mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-03 08:02:36 +09:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab23e4b7f4 | ||
|
|
1bb88dad20 | ||
|
|
94f0151789 | ||
|
|
1e2fe9f0b4 | ||
|
|
f3496c88b2 | ||
|
|
89915ca8a0 | ||
|
|
24fa56830f | ||
|
|
0fa9ea516a | ||
|
|
9b95b41aa8 | ||
|
|
38e799779f | ||
|
|
4f39e56795 | ||
|
|
7b92f91e88 | ||
|
|
aea49d0b92 | ||
|
|
1b5908fb6a | ||
|
|
65a76b7cb0 | ||
|
|
c6f1825fe9 | ||
|
|
4f5dbc4d00 | ||
|
|
4ee8982e91 | ||
|
|
0d10482168 | ||
|
|
6d441de2bd | ||
|
|
d15e49f7ff | ||
|
|
39da4ac6d4 | ||
|
|
8f29011723 | ||
|
|
ee43d20d3b | ||
|
|
99ffd826e5 | ||
|
|
93bac4e10d | ||
|
|
9fbb898058 | ||
|
|
0a9794a6bc | ||
|
|
d4044b9c98 | ||
|
|
1e6d2e47e9 | ||
|
|
d827b0bfb7 | ||
|
|
d789170e31 | ||
|
|
9bbe3eb0b4 | ||
|
|
650fdceb5a | ||
|
|
4c69e158e5 | ||
|
|
b7e41f7b8f | ||
|
|
5a3d9861ba | ||
|
|
adb43358bc | ||
|
|
d6a980501b | ||
|
|
103a66ae83 | ||
|
|
426fd2a816 | ||
|
|
337f2625ac | ||
|
|
5ebf4990a5 | ||
|
|
3fd07a0be6 | ||
|
|
d372539f79 | ||
|
|
91e24a3a10 | ||
|
|
a29e667eff | ||
|
|
92b993c91f | ||
|
|
33b1027c76 | ||
|
|
b45f9260bf | ||
|
|
ee1a8d7b41 | ||
|
|
ba19a35b6b | ||
|
|
cc8e7dd355 | ||
|
|
f52840623c | ||
|
|
97d4a38e01 | ||
|
|
60ccd87d6e | ||
|
|
2477737fff | ||
|
|
a360daeff9 | ||
|
|
82d4d725ae | ||
|
|
1e585d7991 | ||
|
|
f849766998 | ||
|
|
f4818671e4 |
67
.drone.yml
67
.drone.yml
@@ -114,6 +114,17 @@ steps:
|
|||||||
- push
|
- push
|
||||||
- pull_request
|
- pull_request
|
||||||
|
|
||||||
|
- name: tag-pre-condition
|
||||||
|
pull: always
|
||||||
|
image: alpine/git
|
||||||
|
commands:
|
||||||
|
- git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- tag
|
||||||
|
|
||||||
- name: tag-test
|
- name: tag-test
|
||||||
pull: always
|
pull: always
|
||||||
image: golang:1.12
|
image: golang:1.12
|
||||||
@@ -122,7 +133,7 @@ steps:
|
|||||||
environment:
|
environment:
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- tag-pre-condition
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- tag
|
- tag
|
||||||
@@ -442,7 +453,6 @@ trigger:
|
|||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- testing
|
- testing
|
||||||
- translations
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: fetch-tags
|
- name: fetch-tags
|
||||||
@@ -558,6 +568,15 @@ workspace:
|
|||||||
base: /go
|
base: /go
|
||||||
path: src/code.gitea.io/gitea
|
path: src/code.gitea.io/gitea
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- testing
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/master
|
||||||
|
- "refs/tags/**"
|
||||||
|
- "refs/pull/**"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: fetch-tags
|
- name: fetch-tags
|
||||||
pull: default
|
pull: default
|
||||||
@@ -571,56 +590,28 @@ steps:
|
|||||||
|
|
||||||
- name: dryrun
|
- name: dryrun
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/docker:18.09
|
image: plugins/docker:linux-amd64
|
||||||
settings:
|
settings:
|
||||||
cache_from: gitea/gitea
|
|
||||||
dry_run: true
|
dry_run: true
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
when:
|
when:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
|
||||||
- name: release
|
- name: publish
|
||||||
pull: always
|
pull: always
|
||||||
image: plugins/docker:18.09
|
image: plugins/docker:linux-amd64
|
||||||
settings:
|
settings:
|
||||||
cache_from: gitea/gitea
|
auto_tag: true
|
||||||
repo: gitea/gitea
|
repo: gitea/gitea
|
||||||
tags:
|
password:
|
||||||
- "${DRONE_BRANCH##release/v}"
|
|
||||||
environment:
|
|
||||||
DOCKER_PASSWORD:
|
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
DOCKER_USERNAME:
|
username:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
depends_on:
|
|
||||||
- dryrun
|
|
||||||
when:
|
when:
|
||||||
branch:
|
|
||||||
- "release/*"
|
|
||||||
event:
|
event:
|
||||||
- push
|
exclude:
|
||||||
|
- pull_request
|
||||||
- name: latest
|
|
||||||
pull: always
|
|
||||||
image: plugins/docker:18.09
|
|
||||||
settings:
|
|
||||||
cache_from: gitea/gitea
|
|
||||||
default_tags: true
|
|
||||||
repo: gitea/gitea
|
|
||||||
environment:
|
|
||||||
DOCKER_PASSWORD:
|
|
||||||
from_secret: docker_password
|
|
||||||
DOCKER_USERNAME:
|
|
||||||
from_secret: docker_username
|
|
||||||
depends_on:
|
|
||||||
- dryrun
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- master
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
|
|||||||
71
CHANGELOG.md
71
CHANGELOG.md
@@ -4,9 +4,42 @@ 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.9.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.9.0-rc1) - 2019-07-06
|
## [1.9.1](https://github.com/go-gitea/gitea/releases/tag/v1.9.1) - 2019-08-14
|
||||||
|
* BREAKING
|
||||||
|
* Add pagination for admin api get orgs and fix only list public orgs bug (#7742) (#7752)
|
||||||
|
* SECURITY
|
||||||
|
* Be more strict with git arguments (#7715) (#7762)
|
||||||
|
* Release built with go 1.12.8 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!topic/golang-nuts/fCQWxqxP8aA
|
||||||
|
* BUGFIXES
|
||||||
|
* Fix local runs of ssh-requiring integration tests (#7855) (#7857)
|
||||||
|
* Fix hook problem (#7856) (#7754)
|
||||||
|
* Use .ExpiredUnix.IsZero to display green color of forever valid gpg key (#7850) (#7846)
|
||||||
|
* Do not fetch all refs (#7797) (#7837)
|
||||||
|
* Fix duplicate call of webhook (#7824) (#7821)
|
||||||
|
* Enable switching to a different source branch when PR already exists (#7823)
|
||||||
|
* Rewrite existing repo units if setting is not included in api body (#7811)
|
||||||
|
* Prevent Commit Status and Message From Overflowing On Branch Page (#7800) (#7808)
|
||||||
|
* API: fix multiple bugs with statuses endpoints (Backport #7785) (#7807)
|
||||||
|
* Fix Slack webhook fork message (1.9 release backport) (#7783)
|
||||||
|
* Fix approvals counting (#7757) (#7777)
|
||||||
|
* Fix rename failed when rewrite public keys (#7761) (#7769)
|
||||||
|
* Fix dropTableColumns sqlite implementation (#7710) (#7765)
|
||||||
|
* Fix repo_index_status lingering when deleting a repository (#7738)
|
||||||
|
* Fix milestone completness calculation when migrating (#7725) (#7732)
|
||||||
|
* Fixes indexed repos keeping outdated indexes when files grow too large (#7731)
|
||||||
|
* Skip non-regular files (e.g. submodules) on repo indexing (#7717)
|
||||||
|
* Improve branches list performance and fix protected branch icon when no-login (#7695) (#7704)
|
||||||
|
* Correct wrong datetime format for git (#7689) (#7690)
|
||||||
|
|
||||||
|
## [1.9.0](https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - 2019-07-30
|
||||||
* BREAKING
|
* BREAKING
|
||||||
* Better logging (#6038) (#6095)
|
* Better logging (#6038) (#6095)
|
||||||
|
* SECURITY
|
||||||
|
* Shadow the password on cache and session config on admin panel (#7300)
|
||||||
|
* Fix markdown invoke sequence (#7513) (#7560)
|
||||||
|
* Reserve .well-known username (#7638)
|
||||||
|
* Do not leak secrets via timing side channel (#7364)
|
||||||
|
* Ensure that decryption of cookie actually suceeds (#7363)
|
||||||
* FEATURE
|
* FEATURE
|
||||||
* Content API for Creating, Updating, Deleting Files (#6314)
|
* Content API for Creating, Updating, Deleting Files (#6314)
|
||||||
* Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
|
* Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
|
||||||
@@ -29,6 +62,39 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
|||||||
* Implement Default Webhooks (#4299)
|
* Implement Default Webhooks (#4299)
|
||||||
* Telegram webhook (#4227)
|
* Telegram webhook (#4227)
|
||||||
* BUGFIXES
|
* BUGFIXES
|
||||||
|
* Send webhook after commit when creating issue with assignees (#7681) (#7684)
|
||||||
|
* Upgrade macaron/captcha to fix random error problem (#7407) (#7683)
|
||||||
|
* Move add to hook queue for created repo to outside xorm session. (#7682) (#7675)
|
||||||
|
* Show protection symbol if needed on default branch (#7660) (#7668)
|
||||||
|
* Hide delete/restore button on archived repos (#7660)
|
||||||
|
* Fix bug on migrating milestone from github (#7665) (#7666)
|
||||||
|
* Use flex to fix floating paginate (#7656) (#7662)
|
||||||
|
* Change length of some repository's columns (#7652) (#7655)
|
||||||
|
* Fix wrong email when use gitea as OAuth2 provider (#7640) (#7647)
|
||||||
|
* Fix syntax highlight initialization (#7617) (#7626)
|
||||||
|
* Fix bug create/edit wiki pages when code master branch protected (#7580) (#7623)
|
||||||
|
* Fix panic on push at #7611 (#7615) (#7618)
|
||||||
|
* Handle ErrUserProhibitLogin in http git (#7586, #7591) (#7590)
|
||||||
|
* Fix color of split-diff view in dark theme (#7587) (#7589)
|
||||||
|
* Fix file header overflow in file and blame views (#7562) (#7579)
|
||||||
|
* Malformed URLs in API git/commits response (#7565) (#7567)
|
||||||
|
* Fix empty commits now showing in repo overview (#7521) (#7563)
|
||||||
|
* Fix repository's pull request count error (#7518) (#7524)
|
||||||
|
* Remove duplicated webhook trigger (#7511) (#7516)
|
||||||
|
* Handles all redirects for Web UI File CRUD (#7478) (#7507)
|
||||||
|
* Fix regex for issues in commit messages (#7444) (#7466)
|
||||||
|
* cmd/serv: actually exit after fatal errors (#7458) (#7460)
|
||||||
|
* Fix an issue with some pages throwing 'not defined' js exceptions #7450 (#7453)
|
||||||
|
* Fix Dropzone.js integration (#7445) (#7448)
|
||||||
|
* Create class for inline positioned lists (#7439) (#7393)
|
||||||
|
* Diff: Fix indentation on unhighlighted code (#7435) (#7443)
|
||||||
|
* jQuery 3 (#7442) (#7425)
|
||||||
|
* Only show "New Pull Request" button if repo allows pulls (#7426) (#7432)
|
||||||
|
* Fix vendor references (#7394) (#7396)
|
||||||
|
* Only return head: null if source branch was deleted (#6705) (#7376)
|
||||||
|
* Add missing template variable on organisation settings (#7386) (#7385)
|
||||||
|
* Fix post parameter on issue list which had unset assignee (#7380) (#7383)
|
||||||
|
* Fix migration tests due to issue 7 being resolved (#7375) (#7381)
|
||||||
* Correctly adjust mirror url (#6593)
|
* Correctly adjust mirror url (#6593)
|
||||||
* Handle early git version's lack of get-url (#7065)
|
* Handle early git version's lack of get-url (#7065)
|
||||||
* Fix icon position in issue view (#7354)
|
* Fix icon position in issue view (#7354)
|
||||||
@@ -166,6 +232,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
|||||||
* Disable benchmarking during tag events on DroneIO (#6365)
|
* Disable benchmarking during tag events on DroneIO (#6365)
|
||||||
* Comments list performance optimization (#5305)
|
* Comments list performance optimization (#5305)
|
||||||
* ENHANCEMENT
|
* ENHANCEMENT
|
||||||
|
* Update Drone docker generation to standard format (#7480) (#7496) (#7504)
|
||||||
* Add API Endpoint for Repo Edit (#7006)
|
* Add API Endpoint for Repo Edit (#7006)
|
||||||
* Add state param to milestone listing API (#7131)
|
* Add state param to milestone listing API (#7131)
|
||||||
* Make captcha and password optional for external accounts (#6606)
|
* Make captcha and password optional for external accounts (#6606)
|
||||||
@@ -285,8 +352,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
|||||||
* Refactor: append, build variable and type switch (#4940)
|
* Refactor: append, build variable and type switch (#4940)
|
||||||
* Git statistics in Activity tab (#4724)
|
* Git statistics in Activity tab (#4724)
|
||||||
* Drop the bits argument when generating an ed25519 key (#6504)
|
* Drop the bits argument when generating an ed25519 key (#6504)
|
||||||
* SECURITY
|
|
||||||
* Shadow the password on cache and session config on admin panel (#7300)
|
|
||||||
* TESTING
|
* TESTING
|
||||||
* Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
|
* Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
|
||||||
* Refactor and improve git test (#7086)
|
* Refactor and improve git test (#7086)
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
UserID: userID,
|
UserID: userID,
|
||||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||||
|
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||||
ProtectedBranchID: prID,
|
ProtectedBranchID: prID,
|
||||||
})
|
})
|
||||||
switch statusCode {
|
switch statusCode {
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ func fail(userMessage, logMessage string, args ...interface{}) {
|
|||||||
if !setting.ProdMode {
|
if !setting.ProdMode {
|
||||||
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
4
go.mod
4
go.mod
@@ -45,7 +45,7 @@ require (
|
|||||||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect
|
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect
|
||||||
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443
|
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443
|
||||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776
|
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776
|
||||||
github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab
|
github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df
|
||||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9
|
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9
|
||||||
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372
|
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372
|
||||||
github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
|
github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
|
||||||
@@ -135,4 +135,4 @@ require (
|
|||||||
xorm.io/core v0.6.3
|
xorm.io/core v0.6.3
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/denisenkom/go-mssqldb => github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44
|
replace github.com/denisenkom/go-mssqldb => github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44
|
||||||
|
|||||||
8
go.sum
8
go.sum
@@ -66,8 +66,8 @@ github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44 h1:x0uHqLQTSEL9LKic8sWDt3ASkq07ve5ojIIUl5uF64M=
|
github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44 h1:DWxZh2sImfCFn/79OUBhzFkPTKnsdDzXH/JTxpw5n6w=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
@@ -113,8 +113,8 @@ github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 h1:i801KPR7j76u
|
|||||||
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM=
|
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM=
|
||||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw=
|
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw=
|
||||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok=
|
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok=
|
||||||
github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab h1:4VFhsA3GE5Wwq1Ymr8KWCmrOWi1wRLEgdj48LPfQjxI=
|
github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78=
|
||||||
github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA=
|
github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA=
|
||||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 h1:A0QGzY6UHHEil0I2e7C21JenNNG0mmrj5d9SFWTlgr8=
|
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 h1:A0QGzY6UHHEil0I2e7C21JenNNG0mmrj5d9SFWTlgr8=
|
||||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
|
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
|
||||||
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=
|
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=
|
||||||
|
|||||||
@@ -24,20 +24,24 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func withKeyFile(t *testing.T, keyname string, callback func(string)) {
|
func withKeyFile(t *testing.T, keyname string, callback func(string)) {
|
||||||
keyFile := filepath.Join(setting.AppDataPath, keyname)
|
|
||||||
err := ssh.GenKeyPair(keyFile)
|
tmpDir, err := ioutil.TempDir("", "key-file")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
|
err = os.Chmod(tmpDir, 0700)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
keyFile := filepath.Join(tmpDir, keyname)
|
||||||
|
err = ssh.GenKeyPair(keyFile)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
//Setup ssh wrapper
|
//Setup ssh wrapper
|
||||||
os.Setenv("GIT_SSH_COMMAND",
|
os.Setenv("GIT_SSH_COMMAND",
|
||||||
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+
|
"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\"")
|
||||||
filepath.Join(setting.AppWorkPath, keyFile))
|
|
||||||
os.Setenv("GIT_SSH_VARIANT", "ssh")
|
os.Setenv("GIT_SSH_VARIANT", "ssh")
|
||||||
|
|
||||||
callback(keyFile)
|
callback(keyFile)
|
||||||
|
|
||||||
defer os.RemoveAll(keyFile)
|
|
||||||
defer os.RemoveAll(keyFile + ".pub")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createSSHUrl(gitPath string, u *url.URL) *url.URL {
|
func createSSHUrl(gitPath string, u *url.URL) *url.URL {
|
||||||
|
|||||||
BIN
integrations/migration-test/gitea-v1.3.3.sqlite3.sql.gz
Normal file
BIN
integrations/migration-test/gitea-v1.3.3.sqlite3.sql.gz
Normal file
Binary file not shown.
@@ -54,6 +54,10 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
|
|||||||
|
|
||||||
func TestPullMerge(t *testing.T) {
|
func TestPullMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
|
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||||
|
assert.NoError(t, err)
|
||||||
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -63,11 +67,19 @@ func TestPullMerge(t *testing.T) {
|
|||||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
|
||||||
|
|
||||||
|
hookTasks, err = models.HookTasks(1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebase(t *testing.T) {
|
func TestPullRebase(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
|
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||||
|
assert.NoError(t, err)
|
||||||
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -77,12 +89,21 @@ func TestPullRebase(t *testing.T) {
|
|||||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebase)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebase)
|
||||||
|
|
||||||
|
hookTasks, err = models.HookTasks(1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebaseMerge(t *testing.T) {
|
func TestPullRebaseMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
|
|
||||||
|
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||||
|
assert.NoError(t, err)
|
||||||
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -92,12 +113,21 @@ func TestPullRebaseMerge(t *testing.T) {
|
|||||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebaseMerge)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebaseMerge)
|
||||||
|
|
||||||
|
hookTasks, err = models.HookTasks(1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullSquash(t *testing.T) {
|
func TestPullSquash(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
prepareTestEnv(t)
|
prepareTestEnv(t)
|
||||||
|
|
||||||
|
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||||
|
assert.NoError(t, err)
|
||||||
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||||
@@ -108,6 +138,10 @@ func TestPullSquash(t *testing.T) {
|
|||||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleSquash)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleSquash)
|
||||||
|
|
||||||
|
hookTasks, err = models.HookTasks(1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,13 @@
|
|||||||
package integrations
|
package integrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"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"
|
||||||
@@ -67,6 +70,29 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
|||||||
for _, class := range classes {
|
for _, class := range classes {
|
||||||
assert.True(t, sel.HasClass(class))
|
assert.True(t, sel.HasClass(class))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//By SHA
|
||||||
|
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/"+path.Base(commitURL)+"/statuses")
|
||||||
|
testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), state)
|
||||||
|
//By Ref
|
||||||
|
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/master/statuses")
|
||||||
|
testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), state)
|
||||||
|
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/v1.1/statuses")
|
||||||
|
testRepoCommitsWithStatus(t, session.MakeRequest(t, req, http.StatusOK), state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepoCommitsWithStatus(t *testing.T, resp *httptest.ResponseRecorder, state string) {
|
||||||
|
decoder := json.NewDecoder(resp.Body)
|
||||||
|
statuses := []*api.Status{}
|
||||||
|
assert.NoError(t, decoder.Decode(&statuses))
|
||||||
|
assert.Len(t, statuses, 1)
|
||||||
|
for _, s := range statuses {
|
||||||
|
assert.Equal(t, api.StatusState(state), s.State)
|
||||||
|
assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/statuses/65f1bf27bc3bf70f64657658635e66094edbcb4d", s.URL)
|
||||||
|
assert.Equal(t, "http://test.ci/", s.TargetURL)
|
||||||
|
assert.Equal(t, "", s.Description)
|
||||||
|
assert.Equal(t, "testci", s.Context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRepoCommitsWithStatusPending(t *testing.T) {
|
func TestRepoCommitsWithStatusPending(t *testing.T) {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const issueRefRegexpStr = `(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)+`
|
const issueRefRegexpStr = `(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)+`
|
||||||
|
const issueRefRegexpStrNoKeyword = `(?:\s|^|\(|\[)(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)(?:\s|$|\)|\]|\.(\s|$))`
|
||||||
|
|
||||||
func assembleKeywordsPattern(words []string) string {
|
func assembleKeywordsPattern(words []string) string {
|
||||||
return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
|
return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
|
||||||
@@ -73,7 +74,7 @@ func assembleKeywordsPattern(words []string) string {
|
|||||||
func init() {
|
func init() {
|
||||||
issueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueCloseKeywords))
|
issueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueCloseKeywords))
|
||||||
issueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueReopenKeywords))
|
issueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueReopenKeywords))
|
||||||
issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStr)
|
issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStrNoKeyword)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action represents user operation type and other information to
|
// Action represents user operation type and other information to
|
||||||
|
|||||||
@@ -155,6 +155,25 @@ func TestPushCommits_AvatarLink(t *testing.T) {
|
|||||||
pushCommits.AvatarLink("nonexistent@example.com"))
|
pushCommits.AvatarLink("nonexistent@example.com"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRegExp_issueReferenceKeywordsPat(t *testing.T) {
|
||||||
|
trueTestCases := []string{
|
||||||
|
"#2",
|
||||||
|
"[#2]",
|
||||||
|
"please see go-gitea/gitea#5",
|
||||||
|
}
|
||||||
|
falseTestCases := []string{
|
||||||
|
"kb#2",
|
||||||
|
"#2xy",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range trueTestCases {
|
||||||
|
assert.True(t, issueReferenceKeywordsPat.MatchString(testCase))
|
||||||
|
}
|
||||||
|
for _, testCase := range falseTestCases {
|
||||||
|
assert.False(t, issueReferenceKeywordsPat.MatchString(testCase))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_getIssueFromRef(t *testing.T) {
|
func Test_getIssueFromRef(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
|
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ func (protectBranch *ProtectedBranch) HasEnoughApprovals(pr *PullRequest) bool {
|
|||||||
|
|
||||||
// GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist.
|
// GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist.
|
||||||
func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 {
|
func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 {
|
||||||
reviews, err := GetReviewersByPullID(pr.Issue.ID)
|
reviews, err := GetReviewersByPullID(pr.IssueID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("GetReviewersByPullID: %v", err)
|
log.Error("GetReviewersByPullID: %v", err)
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (status *CommitStatus) loadRepo(e Engine) (err error) {
|
|||||||
// APIURL returns the absolute APIURL to this commit-status.
|
// APIURL returns the absolute APIURL to this commit-status.
|
||||||
func (status *CommitStatus) APIURL() string {
|
func (status *CommitStatus) APIURL() string {
|
||||||
_ = status.loadRepo(x)
|
_ = status.loadRepo(x)
|
||||||
return fmt.Sprintf("%sapi/v1/%s/statuses/%s",
|
return fmt.Sprintf("%sapi/v1/repos/%s/statuses/%s",
|
||||||
setting.AppURL, status.Repo.FullName(), status.SHA)
|
setting.AppURL, status.Repo.FullName(), status.SHA)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,20 +19,25 @@ func TestGetCommitStatuses(t *testing.T) {
|
|||||||
|
|
||||||
statuses, err := GetCommitStatuses(repo1, sha1, 0)
|
statuses, err := GetCommitStatuses(repo1, sha1, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, statuses, 5) {
|
assert.Len(t, statuses, 5)
|
||||||
assert.Equal(t, statuses[0].Context, "ci/awesomeness")
|
|
||||||
assert.Equal(t, statuses[0].State, CommitStatusPending)
|
|
||||||
|
|
||||||
assert.Equal(t, statuses[1].Context, "cov/awesomeness")
|
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
||||||
assert.Equal(t, statuses[1].State, CommitStatusWarning)
|
assert.Equal(t, CommitStatusPending, statuses[0].State)
|
||||||
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, statuses[2].Context, "cov/awesomeness")
|
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
|
||||||
assert.Equal(t, statuses[2].State, CommitStatusSuccess)
|
assert.Equal(t, CommitStatusWarning, statuses[1].State)
|
||||||
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, statuses[3].Context, "ci/awesomeness")
|
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
|
||||||
assert.Equal(t, statuses[3].State, CommitStatusFailure)
|
assert.Equal(t, CommitStatusSuccess, statuses[2].State)
|
||||||
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL())
|
||||||
|
|
||||||
assert.Equal(t, statuses[4].Context, "deploy/awesomeness")
|
assert.Equal(t, "ci/awesomeness", statuses[3].Context)
|
||||||
assert.Equal(t, statuses[4].State, CommitStatusError)
|
assert.Equal(t, CommitStatusFailure, statuses[3].State)
|
||||||
}
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL())
|
||||||
|
|
||||||
|
assert.Equal(t, "deploy/awesomeness", statuses[4].Context)
|
||||||
|
assert.Equal(t, CommitStatusError, statuses[4].State)
|
||||||
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import (
|
|||||||
|
|
||||||
// PushingEnvironment returns an os environment to allow hooks to work on push
|
// PushingEnvironment returns an os environment to allow hooks to work on push
|
||||||
func PushingEnvironment(doer *User, repo *Repository) []string {
|
func PushingEnvironment(doer *User, repo *Repository) []string {
|
||||||
return FullPushingEnvironment(doer, doer, repo, 0)
|
return FullPushingEnvironment(doer, doer, repo, repo.Name, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FullPushingEnvironment returns an os environment to allow hooks to work on push
|
// FullPushingEnvironment returns an os environment to allow hooks to work on push
|
||||||
func FullPushingEnvironment(author, committer *User, repo *Repository, prID int64) []string {
|
func FullPushingEnvironment(author, committer *User, repo *Repository, repoName string, prID int64) []string {
|
||||||
isWiki := "false"
|
isWiki := "false"
|
||||||
if strings.HasSuffix(repo.Name, ".wiki") {
|
if strings.HasSuffix(repoName, ".wiki") {
|
||||||
isWiki = "true"
|
isWiki = "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ func FullPushingEnvironment(author, committer *User, repo *Repository, prID int6
|
|||||||
"GIT_AUTHOR_EMAIL="+authorSig.Email,
|
"GIT_AUTHOR_EMAIL="+authorSig.Email,
|
||||||
"GIT_COMMITTER_NAME="+committerSig.Name,
|
"GIT_COMMITTER_NAME="+committerSig.Name,
|
||||||
"GIT_COMMITTER_EMAIL="+committerSig.Email,
|
"GIT_COMMITTER_EMAIL="+committerSig.Email,
|
||||||
EnvRepoName+"="+repo.Name,
|
EnvRepoName+"="+repoName,
|
||||||
EnvRepoUsername+"="+repo.MustOwnerName(),
|
EnvRepoUsername+"="+repo.MustOwnerName(),
|
||||||
EnvRepoIsWiki+"="+isWiki,
|
EnvRepoIsWiki+"="+isWiki,
|
||||||
EnvPusherName+"="+committer.Name,
|
EnvPusherName+"="+committer.Name,
|
||||||
|
|||||||
@@ -1835,3 +1835,22 @@ func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
|
|||||||
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
|
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
|
||||||
return issue.getBlockingDependencies(x)
|
return issue.getBlockingDependencies(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (issue *Issue) updateClosedNum(e Engine) (err error) {
|
||||||
|
if issue.IsPull {
|
||||||
|
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
|
||||||
|
issue.RepoID,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
issue.RepoID,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
|
||||||
|
issue.RepoID,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
issue.RepoID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -142,11 +142,15 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
if err := sess.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go HookQueue.Add(issue.RepoID)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (err error) {
|
func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (err error) {
|
||||||
|
|
||||||
// Update the assignee
|
// Update the assignee
|
||||||
removed, err := updateIssueAssignee(sess, issue, assigneeID)
|
removed, err := updateIssueAssignee(sess, issue, assigneeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -209,7 +213,6 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
go HookQueue.Add(issue.RepoID)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -632,12 +632,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
|
|||||||
act.OpType = ActionReopenPullRequest
|
act.OpType = ActionReopenPullRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Issue.IsPull {
|
if err = opts.Issue.updateClosedNum(e); err != nil {
|
||||||
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", opts.Repo.ID)
|
|
||||||
} else {
|
|
||||||
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", opts.Repo.ID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,12 +642,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
|
|||||||
act.OpType = ActionClosePullRequest
|
act.OpType = ActionClosePullRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Issue.IsPull {
|
if err = opts.Issue.updateClosedNum(e); err != nil {
|
||||||
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", opts.Repo.ID)
|
|
||||||
} else {
|
|
||||||
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", opts.Repo.ID)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,11 +321,25 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tableSQL := string(res[0]["sql"])
|
tableSQL := string(res[0]["sql"])
|
||||||
|
|
||||||
|
// Separate out the column definitions
|
||||||
tableSQL = tableSQL[strings.Index(tableSQL, "("):]
|
tableSQL = tableSQL[strings.Index(tableSQL, "("):]
|
||||||
|
|
||||||
|
// Remove the required columnNames
|
||||||
for _, name := range columnNames {
|
for _, name := range columnNames {
|
||||||
tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*[,)]").ReplaceAllString(tableSQL, "")
|
tableSQL = regexp.MustCompile(regexp.QuoteMeta("`"+name+"`")+"[^`,)]*?[,)]").ReplaceAllString(tableSQL, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the query is ended properly
|
||||||
|
tableSQL = strings.TrimSpace(tableSQL)
|
||||||
|
if tableSQL[len(tableSQL)-1] != ')' {
|
||||||
|
if tableSQL[len(tableSQL)-1] == ',' {
|
||||||
|
tableSQL = tableSQL[:len(tableSQL)-1]
|
||||||
|
}
|
||||||
|
tableSQL += ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all the columns in the table
|
||||||
columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1)
|
columns := regexp.MustCompile("`([^`]*)`").FindAllString(tableSQL, -1)
|
||||||
|
|
||||||
tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL
|
tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL
|
||||||
|
|||||||
@@ -5,13 +5,7 @@
|
|||||||
package migrations
|
package migrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
"xorm.io/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func renameRepoIsBareToIsEmpty(x *xorm.Engine) error {
|
func renameRepoIsBareToIsEmpty(x *xorm.Engine) error {
|
||||||
@@ -21,73 +15,28 @@ func renameRepoIsBareToIsEmpty(x *xorm.Engine) error {
|
|||||||
IsEmpty bool `xorm:"INDEX"`
|
IsEmpty bool `xorm:"INDEX"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// First remove the index
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
if models.DbCfg.Type == core.POSTGRES || models.DbCfg.Type == core.SQLITE {
|
|
||||||
_, err = sess.Exec("DROP INDEX IF EXISTS IDX_repository_is_bare")
|
|
||||||
} else if models.DbCfg.Type == core.MSSQL {
|
|
||||||
_, err = sess.Exec(`DECLARE @ConstraintName VARCHAR(256)
|
|
||||||
DECLARE @SQL NVARCHAR(256)
|
|
||||||
SELECT @ConstraintName = obj.name FROM sys.columns col LEFT OUTER JOIN sys.objects obj ON obj.object_id = col.default_object_id AND obj.type = 'D' WHERE col.object_id = OBJECT_ID('repository') AND obj.name IS NOT NULL AND col.name = 'is_bare'
|
|
||||||
SET @SQL = N'ALTER TABLE [repository] DROP CONSTRAINT [' + @ConstraintName + N']'
|
|
||||||
EXEC sp_executesql @SQL`)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if models.DbCfg.Type == core.MYSQL {
|
|
||||||
indexes, err := sess.QueryString(`SHOW INDEX FROM repository WHERE KEY_NAME = 'IDX_repository_is_bare'`)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(indexes) >= 1 {
|
|
||||||
_, err = sess.Exec("DROP INDEX IDX_repository_is_bare ON repository")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Drop index failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err = sess.Exec("DROP INDEX IDX_repository_is_bare ON repository")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Drop index failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sess.Sync2(new(Repository)); err != nil {
|
if err := sess.Sync2(new(Repository)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := sess.Exec("UPDATE repository SET is_empty = is_bare;"); err != nil {
|
if _, err := sess.Exec("UPDATE repository SET is_empty = is_bare;"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := sess.Commit(); err != nil {
|
||||||
if models.DbCfg.Type != core.SQLITE {
|
|
||||||
_, err = sess.Exec("ALTER TABLE repository DROP COLUMN is_bare")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Drop column failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if models.DbCfg.Type == core.SQLITE {
|
if err := sess.Begin(); err != nil {
|
||||||
log.Warn("TABLE repository's COLUMN is_bare should be DROP but sqlite is not supported, you could manually do that.")
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
if err := dropTableColumns(sess, "repository", "is_bare"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
"xorm.io/core"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/modules/generate"
|
"code.gitea.io/gitea/modules/generate"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
@@ -37,41 +35,6 @@ func hashAppToken(x *xorm.Engine) error {
|
|||||||
// First remove the index
|
// First remove the index
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err := sess.Begin(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if models.DbCfg.Type == core.POSTGRES || models.DbCfg.Type == core.SQLITE {
|
|
||||||
_, err = sess.Exec("DROP INDEX IF EXISTS UQE_access_token_sha1")
|
|
||||||
} else if models.DbCfg.Type == core.MSSQL {
|
|
||||||
_, err = sess.Exec(`DECLARE @ConstraintName VARCHAR(256)
|
|
||||||
DECLARE @SQL NVARCHAR(256)
|
|
||||||
SELECT @ConstraintName = obj.name FROM sys.columns col LEFT OUTER JOIN sys.objects obj ON obj.object_id = col.default_object_id AND obj.type = 'D' WHERE col.object_id = OBJECT_ID('access_token') AND obj.name IS NOT NULL AND col.name = 'sha1'
|
|
||||||
SET @SQL = N'ALTER TABLE [access_token] DROP CONSTRAINT [' + @ConstraintName + N']'
|
|
||||||
EXEC sp_executesql @SQL`)
|
|
||||||
} else if models.DbCfg.Type == core.MYSQL {
|
|
||||||
indexes, err := sess.QueryString(`SHOW INDEX FROM access_token WHERE KEY_NAME = 'UQE_access_token_sha1'`)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(indexes) >= 1 {
|
|
||||||
_, err = sess.Exec("DROP INDEX UQE_access_token_sha1 ON access_token")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err = sess.Exec("DROP INDEX UQE_access_token_sha1 ON access_token")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Drop index failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -81,7 +44,7 @@ func hashAppToken(x *xorm.Engine) error {
|
|||||||
return fmt.Errorf("Sync2: %v", err)
|
return fmt.Errorf("Sync2: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = sess.Commit(); err != nil {
|
if err := sess.Commit(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -755,11 +755,14 @@ func IsUserInTeams(userID int64, teamIDs []int64) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UsersInTeamsCount counts the number of users which are in userIDs and teamIDs
|
// UsersInTeamsCount counts the number of users which are in userIDs and teamIDs
|
||||||
func UsersInTeamsCount(userIDs []int64, teamIDs []int64) (count int64, err error) {
|
func UsersInTeamsCount(userIDs []int64, teamIDs []int64) (int64, error) {
|
||||||
if count, err = x.In("uid", userIDs).In("team_id", teamIDs).Count(new(TeamUser)); err != nil {
|
var ids []int64
|
||||||
|
if err := x.In("uid", userIDs).In("team_id", teamIDs).
|
||||||
|
Table("team_user").
|
||||||
|
Cols("uid").GroupBy("uid").Find(&ids); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return
|
return int64(len(ids)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ___________ __________
|
// ___________ __________
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ func TestUsersInTeamsCount(t *testing.T) {
|
|||||||
assert.Equal(t, expected, count)
|
assert.Equal(t, expected, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
test([]int64{2}, []int64{1, 2, 3, 4}, 2)
|
test([]int64{2}, []int64{1, 2, 3, 4}, 1) // only userid 2
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2)
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3)
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,36 +189,6 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch); err != nil {
|
|
||||||
log.Error("pr.BaseRepo.GetBranch[%d]: %v", pr.BaseBranch, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if baseCommit, err = baseBranch.GetCommit(); err != nil {
|
|
||||||
log.Error("baseBranch.GetCommit[%d]: %v", pr.ID, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch); err != nil {
|
|
||||||
log.Error("pr.HeadRepo.GetBranch[%d]: %v", pr.HeadBranch, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if headCommit, err = headBranch.GetCommit(); err != nil {
|
|
||||||
log.Error("headBranch.GetCommit[%d]: %v", pr.ID, err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
apiBaseBranchInfo := &api.PRBranchInfo{
|
|
||||||
Name: pr.BaseBranch,
|
|
||||||
Ref: pr.BaseBranch,
|
|
||||||
Sha: baseCommit.ID.String(),
|
|
||||||
RepoID: pr.BaseRepoID,
|
|
||||||
Repository: pr.BaseRepo.innerAPIFormat(e, AccessModeNone, false),
|
|
||||||
}
|
|
||||||
apiHeadBranchInfo := &api.PRBranchInfo{
|
|
||||||
Name: pr.HeadBranch,
|
|
||||||
Ref: pr.HeadBranch,
|
|
||||||
Sha: headCommit.ID.String(),
|
|
||||||
RepoID: pr.HeadRepoID,
|
|
||||||
Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = pr.Issue.loadRepo(e); err != nil {
|
if err = pr.Issue.loadRepo(e); err != nil {
|
||||||
log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
|
log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
|
||||||
@@ -227,6 +197,7 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
|||||||
|
|
||||||
apiPullRequest := &api.PullRequest{
|
apiPullRequest := &api.PullRequest{
|
||||||
ID: pr.ID,
|
ID: pr.ID,
|
||||||
|
URL: pr.Issue.HTMLURL(),
|
||||||
Index: pr.Index,
|
Index: pr.Index,
|
||||||
Poster: apiIssue.Poster,
|
Poster: apiIssue.Poster,
|
||||||
Title: apiIssue.Title,
|
Title: apiIssue.Title,
|
||||||
@@ -241,13 +212,68 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
|||||||
DiffURL: pr.Issue.DiffURL(),
|
DiffURL: pr.Issue.DiffURL(),
|
||||||
PatchURL: pr.Issue.PatchURL(),
|
PatchURL: pr.Issue.PatchURL(),
|
||||||
HasMerged: pr.HasMerged,
|
HasMerged: pr.HasMerged,
|
||||||
Base: apiBaseBranchInfo,
|
|
||||||
Head: apiHeadBranchInfo,
|
|
||||||
MergeBase: pr.MergeBase,
|
MergeBase: pr.MergeBase,
|
||||||
Deadline: apiIssue.Deadline,
|
Deadline: apiIssue.Deadline,
|
||||||
Created: pr.Issue.CreatedUnix.AsTimePtr(),
|
Created: pr.Issue.CreatedUnix.AsTimePtr(),
|
||||||
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
|
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
|
||||||
}
|
}
|
||||||
|
baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch)
|
||||||
|
if err != nil {
|
||||||
|
if git.IsErrBranchNotExist(err) {
|
||||||
|
apiPullRequest.Base = nil
|
||||||
|
} else {
|
||||||
|
log.Error("GetBranch[%s]: %v", pr.BaseBranch, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
apiBaseBranchInfo := &api.PRBranchInfo{
|
||||||
|
Name: pr.BaseBranch,
|
||||||
|
Ref: pr.BaseBranch,
|
||||||
|
RepoID: pr.BaseRepoID,
|
||||||
|
Repository: pr.BaseRepo.innerAPIFormat(e, AccessModeNone, false),
|
||||||
|
}
|
||||||
|
baseCommit, err = baseBranch.GetCommit()
|
||||||
|
if err != nil {
|
||||||
|
if git.IsErrNotExist(err) {
|
||||||
|
apiBaseBranchInfo.Sha = ""
|
||||||
|
} else {
|
||||||
|
log.Error("GetCommit[%s]: %v", baseBranch.Name, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
apiBaseBranchInfo.Sha = baseCommit.ID.String()
|
||||||
|
}
|
||||||
|
apiPullRequest.Base = apiBaseBranchInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch)
|
||||||
|
if err != nil {
|
||||||
|
if git.IsErrBranchNotExist(err) {
|
||||||
|
apiPullRequest.Head = nil
|
||||||
|
} else {
|
||||||
|
log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
apiHeadBranchInfo := &api.PRBranchInfo{
|
||||||
|
Name: pr.HeadBranch,
|
||||||
|
Ref: pr.HeadBranch,
|
||||||
|
RepoID: pr.HeadRepoID,
|
||||||
|
Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
|
||||||
|
}
|
||||||
|
headCommit, err = headBranch.GetCommit()
|
||||||
|
if err != nil {
|
||||||
|
if git.IsErrNotExist(err) {
|
||||||
|
apiHeadBranchInfo.Sha = ""
|
||||||
|
} else {
|
||||||
|
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
apiHeadBranchInfo.Sha = headCommit.ID.String()
|
||||||
|
}
|
||||||
|
apiPullRequest.Head = apiHeadBranchInfo
|
||||||
|
}
|
||||||
|
|
||||||
if pr.Status != PullRequestStatusChecking {
|
if pr.Status != PullRequestStatusChecking {
|
||||||
mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
|
mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
|
||||||
|
|||||||
@@ -31,7 +31,15 @@ func TestPullRequest_LoadIssue(t *testing.T) {
|
|||||||
assert.Equal(t, int64(2), pr.Issue.ID)
|
assert.Equal(t, int64(2), pr.Issue.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO TestPullRequest_APIFormat
|
func TestPullRequest_APIFormat(t *testing.T) {
|
||||||
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest)
|
||||||
|
assert.NoError(t, pr.LoadAttributes())
|
||||||
|
assert.NoError(t, pr.LoadIssue())
|
||||||
|
apiPullRequest := pr.APIFormat()
|
||||||
|
assert.NotNil(t, apiPullRequest)
|
||||||
|
assert.Nil(t, apiPullRequest.Head)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPullRequest_GetBaseRepo(t *testing.T) {
|
func TestPullRequest_GetBaseRepo(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ type Repository struct {
|
|||||||
Owner *User `xorm:"-"`
|
Owner *User `xorm:"-"`
|
||||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||||
Name string `xorm:"INDEX NOT NULL"`
|
Name string `xorm:"INDEX NOT NULL"`
|
||||||
Description string
|
Description string `xorm:"TEXT"`
|
||||||
Website string
|
Website string `xorm:"VARCHAR(2048)"`
|
||||||
DefaultBranch string
|
DefaultBranch string
|
||||||
|
|
||||||
NumWatches int
|
NumWatches int
|
||||||
@@ -1324,7 +1324,6 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return fmt.Errorf("prepareWebhooks: %v", err)
|
return fmt.Errorf("prepareWebhooks: %v", err)
|
||||||
}
|
}
|
||||||
go HookQueue.Add(repo.ID)
|
|
||||||
} else if err = repo.recalculateAccesses(e); err != nil {
|
} else if err = repo.recalculateAccesses(e); err != nil {
|
||||||
// Organization automatically called this in addRepository method.
|
// Organization automatically called this in addRepository method.
|
||||||
return fmt.Errorf("recalculateAccesses: %v", err)
|
return fmt.Errorf("recalculateAccesses: %v", err)
|
||||||
@@ -1393,7 +1392,16 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return repo, sess.Commit()
|
if err = sess.Commit(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to hook queue for created repo after session commit.
|
||||||
|
if u.IsOrganization() {
|
||||||
|
go HookQueue.Add(repo.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func countRepositories(userID int64, private bool) int64 {
|
func countRepositories(userID int64, private bool) int64 {
|
||||||
@@ -1783,6 +1791,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)
|
||||||
}
|
}
|
||||||
@@ -2327,6 +2336,23 @@ func CheckRepoStats() {
|
|||||||
}
|
}
|
||||||
// ***** END: Repository.NumClosedIssues *****
|
// ***** END: Repository.NumClosedIssues *****
|
||||||
|
|
||||||
|
// ***** START: Repository.NumClosedPulls *****
|
||||||
|
desc = "repository count 'num_closed_pulls'"
|
||||||
|
results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Select %s: %v", desc, err)
|
||||||
|
} else {
|
||||||
|
for _, result := range results {
|
||||||
|
id := com.StrTo(result["id"]).MustInt64()
|
||||||
|
log.Trace("Updating %s: %d", desc, id)
|
||||||
|
_, err = x.Exec("UPDATE `repository` SET num_closed_pulls=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, true, id)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Update %s[%d]: %v", desc, id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ***** END: Repository.NumClosedPulls *****
|
||||||
|
|
||||||
// FIXME: use checker when stop supporting old fork repo format.
|
// FIXME: use checker when stop supporting old fork repo format.
|
||||||
// ***** START: Repository.NumForks *****
|
// ***** START: Repository.NumForks *****
|
||||||
results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
|
results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
|
||||||
@@ -2461,6 +2487,11 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
|
|||||||
go HookQueue.Add(oldRepo.ID)
|
go HookQueue.Add(oldRepo.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to hook queue for created repo after session commit.
|
||||||
|
if u.IsOrganization() {
|
||||||
|
go HookQueue.Add(repo.ID)
|
||||||
|
}
|
||||||
|
|
||||||
if err = repo.UpdateSize(); err != nil {
|
if err = repo.UpdateSize(); err != nil {
|
||||||
log.Error("Failed to update size for repository: %v", err)
|
log.Error("Failed to update size for repository: %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).
|
||||||
@@ -231,20 +231,28 @@ func addDelete(filename string, repo *Repository, batch rupture.FlushingBatch) e
|
|||||||
return indexerUpdate.AddToFlushingBatch(batch)
|
return indexerUpdate.AddToFlushingBatch(batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isIndexable(entry *git.TreeEntry) bool {
|
||||||
|
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
|
||||||
func parseGitLsTreeOutput(stdout []byte) ([]fileUpdate, error) {
|
func parseGitLsTreeOutput(stdout []byte) ([]fileUpdate, error) {
|
||||||
entries, err := git.ParseTreeEntries(stdout)
|
entries, err := git.ParseTreeEntries(stdout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
var idxCount = 0
|
||||||
updates := make([]fileUpdate, len(entries))
|
updates := make([]fileUpdate, len(entries))
|
||||||
for i, entry := range entries {
|
for _, entry := range entries {
|
||||||
updates[i] = fileUpdate{
|
if isIndexable(entry) {
|
||||||
Filename: entry.Name(),
|
updates[idxCount] = fileUpdate{
|
||||||
BlobSha: entry.ID.String(),
|
Filename: entry.Name(),
|
||||||
|
BlobSha: entry.ID.String(),
|
||||||
|
}
|
||||||
|
idxCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return updates, nil
|
return updates[:idxCount], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// genesisChanges get changes to add repo to the indexer for the first time
|
// genesisChanges get changes to add repo to the indexer for the first time
|
||||||
|
|||||||
@@ -642,12 +642,14 @@ func rewriteAllPublicKeys(e Engine) error {
|
|||||||
}
|
}
|
||||||
_, err = t.WriteString(line + "\n")
|
_, err = t.WriteString(line + "\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
f.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Close()
|
||||||
return os.Rename(tmpPath, fPath)
|
return os.Rename(tmpPath, fPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,9 +195,9 @@ func (u *User) UpdateTheme(themeName string) error {
|
|||||||
return UpdateUserCols(u, "theme")
|
return UpdateUserCols(u, "theme")
|
||||||
}
|
}
|
||||||
|
|
||||||
// getEmail returns an noreply email, if the user has set to keep his
|
// GetEmail returns an noreply email, if the user has set to keep his
|
||||||
// email address private, otherwise the primary email address.
|
// email address private, otherwise the primary email address.
|
||||||
func (u *User) getEmail() string {
|
func (u *User) GetEmail() string {
|
||||||
if u.KeepEmailPrivate {
|
if u.KeepEmailPrivate {
|
||||||
return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress)
|
return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress)
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ func (u *User) APIFormat() *api.User {
|
|||||||
ID: u.ID,
|
ID: u.ID,
|
||||||
UserName: u.Name,
|
UserName: u.Name,
|
||||||
FullName: u.FullName,
|
FullName: u.FullName,
|
||||||
Email: u.getEmail(),
|
Email: u.GetEmail(),
|
||||||
AvatarURL: u.AvatarLink(),
|
AvatarURL: u.AvatarLink(),
|
||||||
Language: u.Language,
|
Language: u.Language,
|
||||||
IsAdmin: u.IsAdmin,
|
IsAdmin: u.IsAdmin,
|
||||||
@@ -425,7 +425,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) {
|
|||||||
func (u *User) NewGitSig() *git.Signature {
|
func (u *User) NewGitSig() *git.Signature {
|
||||||
return &git.Signature{
|
return &git.Signature{
|
||||||
Name: u.GitName(),
|
Name: u.GitName(),
|
||||||
Email: u.getEmail(),
|
Email: u.GetEmail(),
|
||||||
When: time.Now(),
|
When: time.Now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -751,6 +751,7 @@ var (
|
|||||||
"robots.txt",
|
"robots.txt",
|
||||||
".",
|
".",
|
||||||
"..",
|
"..",
|
||||||
|
".well-known",
|
||||||
}
|
}
|
||||||
reservedUserPatterns = []string{"*.keys", "*.gpg"}
|
reservedUserPatterns = []string{"*.keys", "*.gpg"}
|
||||||
)
|
)
|
||||||
@@ -1375,9 +1376,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)
|
||||||
|
|||||||
@@ -890,7 +890,6 @@ func DeliverHooks() {
|
|||||||
for _, t := range tasks {
|
for _, t := range tasks {
|
||||||
if err = t.deliver(); err != nil {
|
if err = t.deliver(); err != nil {
|
||||||
log.Error("deliver: %v", err)
|
log.Error("deliver: %v", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ func getSlackDeletePayload(p *api.DeletePayload, slack *SlackMeta) (*SlackPayloa
|
|||||||
|
|
||||||
// getSlackForkPayload composes Slack payload for forked by a repository.
|
// getSlackForkPayload composes Slack payload for forked by a repository.
|
||||||
func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, error) {
|
func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||||
baseLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
baseLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
||||||
forkLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
forkLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.FullName)
|
||||||
text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
|
text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
|
||||||
return &SlackPayload{
|
return &SlackPayload{
|
||||||
Channel: slack.Channel,
|
Channel: slack.Channel,
|
||||||
|
|||||||
@@ -217,7 +217,13 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
|
|||||||
if err := git.Push(basePath, git.PushOptions{
|
if err := git.Push(basePath, git.PushOptions{
|
||||||
Remote: "origin",
|
Remote: "origin",
|
||||||
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
|
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
|
||||||
Env: PushingEnvironment(doer, repo),
|
Env: FullPushingEnvironment(
|
||||||
|
doer,
|
||||||
|
doer,
|
||||||
|
repo,
|
||||||
|
repo.Name+".wiki",
|
||||||
|
0,
|
||||||
|
),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error("%v", err)
|
log.Error("%v", err)
|
||||||
return fmt.Errorf("Push: %v", err)
|
return fmt.Errorf("Push: %v", err)
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ func AddChanges(repoPath string, all bool, files ...string) error {
|
|||||||
if all {
|
if all {
|
||||||
cmd.AddArguments("--all")
|
cmd.AddArguments("--all")
|
||||||
}
|
}
|
||||||
|
cmd.AddArguments("--")
|
||||||
_, err := cmd.AddArguments(files...).RunInDir(repoPath)
|
_, err := cmd.AddArguments(files...).RunInDir(repoPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -304,6 +305,7 @@ func (c *Commit) GetFilesChangedSinceCommit(pastCommit string) ([]string, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FileChangedSinceCommit Returns true if the file given has changed since the the past commit
|
// FileChangedSinceCommit Returns true if the file given has changed since the the past commit
|
||||||
|
// YOU MUST ENSURE THAT pastCommit is a valid commit ID.
|
||||||
func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) {
|
func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) {
|
||||||
return c.repo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String())
|
return c.repo.FileChangedBetweenCommits(filename, pastCommit, c.ID.String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCom
|
|||||||
// get it for free during the tree traversal and it's used for listing
|
// get it for free during the tree traversal and it's used for listing
|
||||||
// pages to display information about newest commit for a given path.
|
// pages to display information about newest commit for a given path.
|
||||||
var treeCommit *Commit
|
var treeCommit *Commit
|
||||||
if rev, ok := revs[""]; ok {
|
if treePath == "" {
|
||||||
|
treeCommit = commit
|
||||||
|
} else if rev, ok := revs[""]; ok {
|
||||||
treeCommit = convertCommit(rev)
|
treeCommit = convertCommit(rev)
|
||||||
}
|
}
|
||||||
return commitsInfo, treeCommit, nil
|
return commitsInfo, treeCommit, nil
|
||||||
|
|||||||
@@ -28,21 +28,27 @@ func cloneRepo(url, dir, name string) (string, error) {
|
|||||||
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
|
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
|
||||||
// these test case are specific to the repo1 test repo
|
// these test case are specific to the repo1 test repo
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
CommitID string
|
CommitID string
|
||||||
Path string
|
Path string
|
||||||
ExpectedIDs map[string]string
|
ExpectedIDs map[string]string
|
||||||
|
ExpectedTreeCommit string
|
||||||
}{
|
}{
|
||||||
{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
|
{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
|
||||||
"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
|
"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
|
||||||
"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||||
}},
|
}, "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2"},
|
||||||
{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
|
{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
|
||||||
"file1.txt": "2839944139e0de9737a044f78b0e4b40d989a9e3",
|
"file1.txt": "2839944139e0de9737a044f78b0e4b40d989a9e3",
|
||||||
"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
|
"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
|
||||||
}},
|
}, "2839944139e0de9737a044f78b0e4b40d989a9e3"},
|
||||||
{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
|
{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
|
||||||
"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
|
"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
|
||||||
}},
|
}, "5c80b0245c1c6f8343fa418ec374b13b5d4ee658"},
|
||||||
|
{"feaf4ba6bc635fec442f46ddd4512416ec43c2c2", "", map[string]string{
|
||||||
|
"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
|
||||||
|
"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||||
|
"foo": "37991dec2c8e592043f47155ce4808d4580f9123",
|
||||||
|
}, "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"},
|
||||||
}
|
}
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
commit, err := repo1.GetCommit(testCase.CommitID)
|
commit, err := repo1.GetCommit(testCase.CommitID)
|
||||||
@@ -51,7 +57,8 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
entries, err := tree.ListEntries()
|
entries, err := tree.ListEntries()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
commitsInfo, _, err := entries.GetCommitsInfo(commit, testCase.Path, nil)
|
commitsInfo, treeCommit, err := entries.GetCommitsInfo(commit, testCase.Path, nil)
|
||||||
|
assert.Equal(t, testCase.ExpectedTreeCommit, treeCommit.ID.String())
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, commitsInfo, len(testCase.ExpectedIDs))
|
assert.Len(t, commitsInfo, len(testCase.ExpectedIDs))
|
||||||
for _, commitInfo := range commitsInfo {
|
for _, commitInfo := range commitsInfo {
|
||||||
|
|||||||
@@ -187,8 +187,7 @@ func Pull(repoPath string, opts PullRemoteOptions) error {
|
|||||||
if opts.All {
|
if opts.All {
|
||||||
cmd.AddArguments("--all")
|
cmd.AddArguments("--all")
|
||||||
} else {
|
} else {
|
||||||
cmd.AddArguments(opts.Remote)
|
cmd.AddArguments("--", opts.Remote, opts.Branch)
|
||||||
cmd.AddArguments(opts.Branch)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Timeout <= 0 {
|
if opts.Timeout <= 0 {
|
||||||
@@ -213,7 +212,7 @@ func Push(repoPath string, opts PushOptions) error {
|
|||||||
if opts.Force {
|
if opts.Force {
|
||||||
cmd.AddArguments("-f")
|
cmd.AddArguments("-f")
|
||||||
}
|
}
|
||||||
cmd.AddArguments(opts.Remote, opts.Branch)
|
cmd.AddArguments("--", opts.Remote, opts.Branch)
|
||||||
_, err := cmd.RunInDirWithEnv(repoPath, opts.Env)
|
_, err := cmd.RunInDirWithEnv(repoPath, opts.Env)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
|
|||||||
cmd.AddArguments("-d")
|
cmd.AddArguments("-d")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddArguments(name)
|
cmd.AddArguments("--", name)
|
||||||
_, err := cmd.RunInDir(repo.Path)
|
_, err := cmd.RunInDir(repo.Path)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -117,20 +117,26 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
|
|||||||
return commit, nil
|
return commit, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCommit returns commit object of by ID string.
|
// ConvertToSHA1 returns a Hash object from a potential ID string
|
||||||
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
|
func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
|
||||||
if len(commitID) != 40 {
|
if len(commitID) != 40 {
|
||||||
var err error
|
var err error
|
||||||
actualCommitID, err := NewCommand("rev-parse", commitID).RunInDir(repo.Path)
|
actualCommitID, err := NewCommand("rev-parse", "--verify", commitID).RunInDir(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "unknown revision or path") {
|
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||||
return nil, ErrNotExist{commitID, ""}
|
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
||||||
|
return SHA1{}, ErrNotExist{commitID, ""}
|
||||||
}
|
}
|
||||||
return nil, err
|
return SHA1{}, err
|
||||||
}
|
}
|
||||||
commitID = actualCommitID
|
commitID = actualCommitID
|
||||||
}
|
}
|
||||||
id, err := NewIDFromString(commitID)
|
return NewIDFromString(commitID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCommit returns commit object of by ID string.
|
||||||
|
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
|
||||||
|
id, err := repo.ConvertToSHA1(commitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -243,6 +249,7 @@ func (repo *Repository) getFilesChanged(id1, id2 string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2
|
// FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2
|
||||||
|
// You must ensure that id1 and id2 are valid commit ids.
|
||||||
func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) {
|
func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) {
|
||||||
stdout, err := NewCommand("diff", "--name-only", "-z", id1, id2, "--", filename).RunInDirBytes(repo.Path)
|
stdout, err := NewCommand("diff", "--name-only", "-z", id1, id2, "--", filename).RunInDirBytes(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -55,5 +55,5 @@ func TestGetCommitWithBadCommitID(t *testing.T) {
|
|||||||
commit, err := bareRepo1.GetCommit("bad_branch")
|
commit, err := bareRepo1.GetCommit("bad_branch")
|
||||||
assert.Nil(t, commit)
|
assert.Nil(t, commit)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.EqualError(t, err, "object does not exist [id: bad_branch, rel_path: ]")
|
assert.True(t, IsErrNotExist(err))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout, err := NewCommand("merge-base", base, head).RunInDir(repo.Path)
|
stdout, err := NewCommand("merge-base", "--", base, head).RunInDir(repo.Path)
|
||||||
return strings.TrimSpace(stdout), base, err
|
return strings.TrimSpace(stdout), base, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string)
|
|||||||
if repo.Path != basePath {
|
if repo.Path != basePath {
|
||||||
// Add a temporary remote
|
// Add a temporary remote
|
||||||
tmpRemote = strconv.FormatInt(time.Now().UnixNano(), 10)
|
tmpRemote = strconv.FormatInt(time.Now().UnixNano(), 10)
|
||||||
if err = repo.AddRemote(tmpRemote, basePath, true); err != nil {
|
if err = repo.AddRemote(tmpRemote, basePath, false); err != nil {
|
||||||
return nil, fmt.Errorf("AddRemote: %v", err)
|
return nil, fmt.Errorf("AddRemote: %v", err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
// ReadTreeToIndex reads a treeish to the index
|
// ReadTreeToIndex reads a treeish to the index
|
||||||
func (repo *Repository) ReadTreeToIndex(treeish string) error {
|
func (repo *Repository) ReadTreeToIndex(treeish string) error {
|
||||||
if len(treeish) != 40 {
|
if len(treeish) != 40 {
|
||||||
res, err := NewCommand("rev-parse", treeish).RunInDir(repo.Path)
|
res, err := NewCommand("rev-parse", "--verify", treeish).RunInDir(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, code)
|
assert.NotNil(t, code)
|
||||||
|
|
||||||
assert.EqualValues(t, 8, code.CommitCount)
|
assert.EqualValues(t, 9, code.CommitCount)
|
||||||
assert.EqualValues(t, 2, code.AuthorCount)
|
assert.EqualValues(t, 3, code.AuthorCount)
|
||||||
assert.EqualValues(t, 8, code.CommitCountInAllBranches)
|
assert.EqualValues(t, 9, code.CommitCountInAllBranches)
|
||||||
assert.EqualValues(t, 10, code.Additions)
|
assert.EqualValues(t, 10, code.Additions)
|
||||||
assert.EqualValues(t, 1, code.Deletions)
|
assert.EqualValues(t, 1, code.Deletions)
|
||||||
assert.Len(t, code.Authors, 2)
|
assert.Len(t, code.Authors, 3)
|
||||||
assert.Contains(t, code.Authors, "tris.git@shoddynet.org")
|
assert.Contains(t, code.Authors, "tris.git@shoddynet.org")
|
||||||
assert.EqualValues(t, 3, code.Authors["tris.git@shoddynet.org"])
|
assert.EqualValues(t, 3, code.Authors["tris.git@shoddynet.org"])
|
||||||
assert.EqualValues(t, 5, code.Authors[""])
|
assert.EqualValues(t, 5, code.Authors[""])
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ func (repo *Repository) IsTagExist(name string) bool {
|
|||||||
|
|
||||||
// CreateTag create one tag in the repository
|
// CreateTag create one tag in the repository
|
||||||
func (repo *Repository) CreateTag(name, revision string) error {
|
func (repo *Repository) CreateTag(name, revision string) error {
|
||||||
_, err := NewCommand("tag", name, revision).RunInDir(repo.Path)
|
_, err := NewCommand("tag", "--", name, revision).RunInDir(repo.Path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAnnotatedTag create one annotated tag in the repository
|
// CreateAnnotatedTag create one annotated tag in the repository
|
||||||
func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error {
|
func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error {
|
||||||
_, err := NewCommand("tag", "-a", "-m", message, name, revision).RunInDir(repo.Path)
|
_, err := NewCommand("tag", "-a", "-m", message, "--", name, revision).RunInDir(repo.Path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
|
|||||||
|
|
||||||
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
|
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
|
||||||
func (repo *Repository) GetTagID(name string) (string, error) {
|
func (repo *Repository) GetTagID(name string) (string, error) {
|
||||||
stdout, err := NewCommand("show-ref", name).RunInDir(repo.Path)
|
stdout, err := NewCommand("show-ref", "--", name).RunInDir(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
|
|||||||
// GetTree find the tree object in the repository.
|
// GetTree find the tree object in the repository.
|
||||||
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
||||||
if len(idStr) != 40 {
|
if len(idStr) != 40 {
|
||||||
res, err := NewCommand("rev-parse", idStr).RunInDir(repo.Path)
|
res, err := NewCommand("rev-parse", "--verify", idStr).RunInDir(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ type CommitTreeOpts struct {
|
|||||||
|
|
||||||
// CommitTree creates a commit from a given tree id for the user with provided message
|
// CommitTree creates a commit from a given tree id for the user with provided message
|
||||||
func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
|
func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
|
||||||
commitTimeStr := time.Now().Format(time.UnixDate)
|
commitTimeStr := time.Now().Format(time.RFC3339)
|
||||||
|
|
||||||
// Because this may call hooks we should pass in the environment
|
// Because this may call hooks we should pass in the environment
|
||||||
env := append(os.Environ(),
|
env := append(os.Environ(),
|
||||||
|
|||||||
1
modules/git/tests/repos/repo1_bare/logs/HEAD
Normal file
1
modules/git/tests/repos/repo1_bare/logs/HEAD
Normal file
@@ -0,0 +1 @@
|
|||||||
|
37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200 push
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200 push
|
||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
37991dec2c8e592043f47155ce4808d4580f9123
|
feaf4ba6bc635fec442f46ddd4512416ec43c2c2
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body = blackfriday.Markdown(body, renderer, exts)
|
body = blackfriday.Markdown(body, renderer, exts)
|
||||||
return body
|
return markup.SanitizeBytes(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
|
|||||||
RepoID: g.repo.ID,
|
RepoID: g.repo.ID,
|
||||||
Name: milestone.Title,
|
Name: milestone.Title,
|
||||||
Content: milestone.Description,
|
Content: milestone.Description,
|
||||||
IsClosed: milestone.State == "close",
|
IsClosed: milestone.State == "closed",
|
||||||
DeadlineUnix: deadline,
|
DeadlineUnix: deadline,
|
||||||
}
|
}
|
||||||
if ms.IsClosed && milestone.Closed != nil {
|
if ms.IsClosed && milestone.Closed != nil {
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
closed1 = time.Date(2018, 10, 23, 02, 57, 43, 0, time.UTC)
|
closed1 = time.Date(2018, 10, 23, 02, 57, 43, 0, time.UTC)
|
||||||
|
closed7 = time.Date(2019, 7, 8, 8, 20, 23, 0, time.UTC)
|
||||||
)
|
)
|
||||||
assert.EqualValues(t, []*base.Issue{
|
assert.EqualValues(t, []*base.Issue{
|
||||||
{
|
{
|
||||||
@@ -208,9 +209,9 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
Number: 7,
|
Number: 7,
|
||||||
Title: "display page revisions on wiki",
|
Title: "display page revisions on wiki",
|
||||||
Content: "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991",
|
Content: "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991",
|
||||||
Milestone: "1.x.x",
|
Milestone: "1.10.0",
|
||||||
PosterName: "joubertredrat",
|
PosterName: "joubertredrat",
|
||||||
State: "open",
|
State: "closed",
|
||||||
Created: time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC),
|
Created: time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC),
|
||||||
Labels: []*base.Label{
|
Labels: []*base.Label{
|
||||||
{
|
{
|
||||||
@@ -232,6 +233,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
|||||||
Heart: 0,
|
Heart: 0,
|
||||||
Hooray: 0,
|
Hooray: 0,
|
||||||
},
|
},
|
||||||
|
Closed: &closed7,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Number: 8,
|
Number: 8,
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ type HookOptions struct {
|
|||||||
UserName string
|
UserName string
|
||||||
GitObjectDirectory string
|
GitObjectDirectory string
|
||||||
GitAlternativeObjectDirectories string
|
GitAlternativeObjectDirectories string
|
||||||
|
GitQuarantinePath string
|
||||||
ProtectedBranchID int64
|
ProtectedBranchID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// HookPreReceive check whether the provided commits are allowed
|
// HookPreReceive check whether the provided commits are allowed
|
||||||
func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string) {
|
func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string) {
|
||||||
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&gitObjectDirectory=%s&gitAlternativeObjectDirectories=%s&prID=%d",
|
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s?old=%s&new=%s&ref=%s&userID=%d&gitObjectDirectory=%s&gitAlternativeObjectDirectories=%s&gitQuarantinePath=%s&prID=%d",
|
||||||
url.PathEscape(ownerName),
|
url.PathEscape(ownerName),
|
||||||
url.PathEscape(repoName),
|
url.PathEscape(repoName),
|
||||||
url.QueryEscape(opts.OldCommitID),
|
url.QueryEscape(opts.OldCommitID),
|
||||||
@@ -43,6 +44,7 @@ func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string)
|
|||||||
opts.UserID,
|
opts.UserID,
|
||||||
url.QueryEscape(opts.GitObjectDirectory),
|
url.QueryEscape(opts.GitObjectDirectory),
|
||||||
url.QueryEscape(opts.GitAlternativeObjectDirectories),
|
url.QueryEscape(opts.GitAlternativeObjectDirectories),
|
||||||
|
url.QueryEscape(opts.GitQuarantinePath),
|
||||||
opts.ProtectedBranchID,
|
opts.ProtectedBranchID,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
go models.HookQueue.Add(pr.BaseRepo.ID)
|
|
||||||
go models.AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
|
go models.AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -102,7 +101,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch head branch
|
// Fetch head branch
|
||||||
if err := git.NewCommand("fetch", remoteRepoName).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
|
if err := git.NewCommand("fetch", remoteRepoName, pr.HeadBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
|
||||||
return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
|
return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +240,13 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
|||||||
headUser = doer
|
headUser = doer
|
||||||
}
|
}
|
||||||
|
|
||||||
env := models.FullPushingEnvironment(headUser, doer, pr.BaseRepo, pr.ID)
|
env := models.FullPushingEnvironment(
|
||||||
|
headUser,
|
||||||
|
doer,
|
||||||
|
pr.BaseRepo,
|
||||||
|
pr.BaseRepo.Name,
|
||||||
|
pr.ID,
|
||||||
|
)
|
||||||
|
|
||||||
// Push back to upstream.
|
// Push back to upstream.
|
||||||
if err := git.NewCommand("push", "origin", pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
|
if err := git.NewCommand("push", "origin", pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
|
||||||
@@ -287,39 +292,6 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
|||||||
go models.HookQueue.Add(pr.Issue.Repo.ID)
|
go models.HookQueue.Add(pr.Issue.Repo.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
l, err := baseGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("CommitsBetweenIDs: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is possible that head branch is not fully sync with base branch for merge commits,
|
|
||||||
// so we need to get latest head commit and append merge commit manually
|
|
||||||
// to avoid strange diff commits produced.
|
|
||||||
mergeCommit, err := baseGitRepo.GetBranchCommit(pr.BaseBranch)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GetBranchCommit: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if mergeStyle == models.MergeStyleMerge {
|
|
||||||
l.PushFront(mergeCommit)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := &api.PushPayload{
|
|
||||||
Ref: git.BranchPrefix + pr.BaseBranch,
|
|
||||||
Before: pr.MergeBase,
|
|
||||||
After: mergeCommit.ID.String(),
|
|
||||||
CompareURL: setting.AppURL + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
|
||||||
Commits: models.ListToPushCommits(l).ToAPIPayloadCommits(pr.BaseRepo.HTMLURL()),
|
|
||||||
Repo: pr.BaseRepo.APIFormat(mode),
|
|
||||||
Pusher: pr.HeadRepo.MustOwner().APIFormat(),
|
|
||||||
Sender: doer.APIFormat(),
|
|
||||||
}
|
|
||||||
if err = models.PrepareWebhooks(pr.BaseRepo, models.HookEventPush, p); err != nil {
|
|
||||||
log.Error("PrepareWebhooks: %v", err)
|
|
||||||
} else {
|
|
||||||
go models.HookQueue.Add(pr.BaseRepo.ID)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
|
|||||||
// Assigned LastCommitID in opts if it hasn't been set
|
// Assigned LastCommitID in opts if it hasn't been set
|
||||||
if opts.LastCommitID == "" {
|
if opts.LastCommitID == "" {
|
||||||
opts.LastCommitID = commit.ID.String()
|
opts.LastCommitID = commit.ID.String()
|
||||||
|
} else {
|
||||||
|
lastCommitID, err := t.gitRepo.ConvertToSHA1(opts.LastCommitID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("DeleteRepoFile: Invalid last commit ID: %v", err)
|
||||||
|
}
|
||||||
|
opts.LastCommitID = lastCommitID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the files in the index
|
// Get the files in the index
|
||||||
@@ -172,32 +178,6 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate push event.
|
|
||||||
oldCommitID := opts.LastCommitID
|
|
||||||
if opts.NewBranch != opts.OldBranch {
|
|
||||||
oldCommitID = git.EmptySHA
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = repo.GetOwner(); err != nil {
|
|
||||||
return nil, fmt.Errorf("GetOwner: %v", err)
|
|
||||||
}
|
|
||||||
err = PushUpdate(
|
|
||||||
repo,
|
|
||||||
opts.NewBranch,
|
|
||||||
models.PushUpdateOptions{
|
|
||||||
PusherID: doer.ID,
|
|
||||||
PusherName: doer.Name,
|
|
||||||
RepoUserName: repo.Owner.Name,
|
|
||||||
RepoName: repo.Name,
|
|
||||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
|
||||||
OldCommitID: oldCommitID,
|
|
||||||
NewCommitID: commitHash,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("PushUpdate: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
commit, err = t.GetCommit(commitHash)
|
commit, err = t.GetCommit(commitHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ref string) (string, erro
|
|||||||
|
|
||||||
// CommitTree creates a commit from a given tree for the user with provided message
|
// CommitTree creates a commit from a given tree for the user with provided message
|
||||||
func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, treeHash string, message string) (string, error) {
|
func (t *TemporaryUploadRepository) CommitTree(author, committer *models.User, treeHash string, message string) (string, error) {
|
||||||
commitTimeStr := time.Now().Format(time.UnixDate)
|
commitTimeStr := time.Now().Format(time.RFC3339)
|
||||||
authorSig := author.NewGitSig()
|
authorSig := author.NewGitSig()
|
||||||
committerSig := committer.NewGitSig()
|
committerSig := committer.NewGitSig()
|
||||||
|
|
||||||
|
|||||||
@@ -188,6 +188,13 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
|
|||||||
// Assigned LastCommitID in opts if it hasn't been set
|
// Assigned LastCommitID in opts if it hasn't been set
|
||||||
if opts.LastCommitID == "" {
|
if opts.LastCommitID == "" {
|
||||||
opts.LastCommitID = commit.ID.String()
|
opts.LastCommitID = commit.ID.String()
|
||||||
|
} else {
|
||||||
|
lastCommitID, err := t.gitRepo.ConvertToSHA1(opts.LastCommitID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("DeleteRepoFile: Invalid last commit ID: %v", err)
|
||||||
|
}
|
||||||
|
opts.LastCommitID = lastCommitID.String()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encoding := "UTF-8"
|
encoding := "UTF-8"
|
||||||
@@ -387,32 +394,6 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate push event.
|
|
||||||
oldCommitID := opts.LastCommitID
|
|
||||||
if opts.NewBranch != opts.OldBranch || oldCommitID == "" {
|
|
||||||
oldCommitID = git.EmptySHA
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = repo.GetOwner(); err != nil {
|
|
||||||
return nil, fmt.Errorf("GetOwner: %v", err)
|
|
||||||
}
|
|
||||||
err = PushUpdate(
|
|
||||||
repo,
|
|
||||||
opts.NewBranch,
|
|
||||||
models.PushUpdateOptions{
|
|
||||||
PusherID: doer.ID,
|
|
||||||
PusherName: doer.Name,
|
|
||||||
RepoUserName: repo.Owner.Name,
|
|
||||||
RepoName: repo.Name,
|
|
||||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
|
||||||
OldCommitID: oldCommitID,
|
|
||||||
NewCommitID: commitHash,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("PushUpdate: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
commit, err = t.GetCommit(commitHash)
|
commit, err = t.GetCommit(commitHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/modules/lfs"
|
"code.gitea.io/gitea/modules/lfs"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
@@ -177,31 +176,5 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate push event.
|
|
||||||
oldCommitID := opts.LastCommitID
|
|
||||||
if opts.NewBranch != opts.OldBranch {
|
|
||||||
oldCommitID = git.EmptySHA
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = repo.GetOwner(); err != nil {
|
|
||||||
return fmt.Errorf("GetOwner: %v", err)
|
|
||||||
}
|
|
||||||
err = PushUpdate(
|
|
||||||
repo,
|
|
||||||
opts.NewBranch,
|
|
||||||
models.PushUpdateOptions{
|
|
||||||
PusherID: doer.ID,
|
|
||||||
PusherName: doer.Name,
|
|
||||||
RepoUserName: repo.Owner.Name,
|
|
||||||
RepoName: repo.Name,
|
|
||||||
RefFullName: git.BranchPrefix + opts.NewBranch,
|
|
||||||
OldCommitID: oldCommitID,
|
|
||||||
NewCommitID: commitHash,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("PushUpdate: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.DeleteUploads(uploads...)
|
return models.DeleteUploads(uploads...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ type FileOptions struct {
|
|||||||
// message (optional) for the commit of this file. if not supplied, a default message will be used
|
// message (optional) for the commit of this file. if not supplied, a default message will be used
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
// branch (optional) to base this file from. if not given, the default branch is used
|
// branch (optional) to base this file from. if not given, the default branch is used
|
||||||
BranchName string `json:"branch"`
|
BranchName string `json:"branch" binding:"GitRefName;MaxSize(100)"`
|
||||||
// new_branch (optional) will make a new branch from `branch` before creating the file
|
// new_branch (optional) will make a new branch from `branch` before creating the file
|
||||||
NewBranchName string `json:"new_branch"`
|
NewBranchName string `json:"new_branch" binding:"GitRefName;MaxSize(100)"`
|
||||||
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
|
||||||
Author Identity `json:"author"`
|
Author Identity `json:"author"`
|
||||||
Committer Identity `json:"committer"`
|
Committer Identity `json:"committer"`
|
||||||
|
|||||||
@@ -694,6 +694,7 @@ editor.delete = Delete '%s'
|
|||||||
editor.commit_message_desc = Add an optional extended description…
|
editor.commit_message_desc = Add an optional extended description…
|
||||||
editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
|
editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
|
||||||
editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
|
editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
|
||||||
|
editor.propose_file_change = Propose file change
|
||||||
editor.new_branch_name_desc = New branch name…
|
editor.new_branch_name_desc = New branch name…
|
||||||
editor.cancel = Cancel
|
editor.cancel = Cancel
|
||||||
editor.filename_cannot_be_empty = The filename cannot be empty.
|
editor.filename_cannot_be_empty = The filename cannot be empty.
|
||||||
|
|||||||
@@ -208,6 +208,9 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
|||||||
.ui.tabular.menu .item{color:rgba(0,0,0,.5)}
|
.ui.tabular.menu .item{color:rgba(0,0,0,.5)}
|
||||||
.ui.tabular.menu .item:hover{color:rgba(0,0,0,.8)}
|
.ui.tabular.menu .item:hover{color:rgba(0,0,0,.8)}
|
||||||
.ui.tabular.menu .item.active{color:rgba(0,0,0,.9)}
|
.ui.tabular.menu .item.active{color:rgba(0,0,0,.9)}
|
||||||
|
.inline-grouped-list{display:inline-block;vertical-align:top}
|
||||||
|
.inline-grouped-list>.ui{display:block;margin-top:5px;margin-bottom:10px}
|
||||||
|
.inline-grouped-list>.ui:first-child{margin-top:1px}
|
||||||
.markdown:not(code){overflow:hidden;font-size:16px;line-height:1.6!important;word-wrap:break-word}
|
.markdown:not(code){overflow:hidden;font-size:16px;line-height:1.6!important;word-wrap:break-word}
|
||||||
.markdown:not(code).ui.segment{padding:3em}
|
.markdown:not(code).ui.segment{padding:3em}
|
||||||
.markdown:not(code).file-view{padding:2em 2em 2em!important}
|
.markdown:not(code).file-view{padding:2em 2em 2em!important}
|
||||||
@@ -620,6 +623,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
|||||||
.repository #commits-table thead .sha{width:140px}
|
.repository #commits-table thead .sha{width:140px}
|
||||||
.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 td.message{text-overflow:unset}
|
||||||
.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.isSigned,.repository #repo-files-table .sha.label.isSigned{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.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}
|
||||||
@@ -744,7 +748,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
|||||||
.repository .segment.reactions .select-reaction{float:none}
|
.repository .segment.reactions .select-reaction{float:none}
|
||||||
.repository .segment.reactions .select-reaction:not(.active) a{display:none}
|
.repository .segment.reactions .select-reaction:not(.active) a{display:none}
|
||||||
.repository .segment.reactions:hover .select-reaction a{display:block}
|
.repository .segment.reactions:hover .select-reaction a{display:block}
|
||||||
.user-cards .list{padding:0}
|
.user-cards .list{padding:0;display:flex;flex-wrap:wrap}
|
||||||
.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}
|
.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}
|
||||||
.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}
|
.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}
|
||||||
.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}
|
.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}
|
||||||
@@ -814,8 +818,8 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
|||||||
.stats-table .table-cell{display:table-cell}
|
.stats-table .table-cell{display:table-cell}
|
||||||
.stats-table .table-cell.tiny{height:.5em}
|
.stats-table .table-cell.tiny{height:.5em}
|
||||||
tbody.commit-list{vertical-align:baseline}
|
tbody.commit-list{vertical-align:baseline}
|
||||||
.commit-list .message-wrapper{overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 24px);display:inline-block;vertical-align:middle}
|
.commit-list .message-wrapper{overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - 50px);display:inline-block;vertical-align:middle}
|
||||||
.commit-list .message-wrapper .commit-status-link{display:inline-block;vertical-align:middle}
|
.commit-list .commit-status-link{display:inline-block;vertical-align:middle}
|
||||||
.commit-body{white-space:pre-wrap}
|
.commit-body{white-space:pre-wrap}
|
||||||
.git-notes.top{text-align:left}
|
.git-notes.top{text-align:left}
|
||||||
.git-notes .commit-body{margin:0}
|
.git-notes .commit-body{margin:0}
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ a.ui.label:hover,a.ui.labels .label:hover{background-color:#505667;color:#dbdbdb
|
|||||||
.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}
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6){background-color:#2a2e3a}
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6){background-color:#2a2e3a}
|
||||||
.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(6){background-color:#283e2d!important;border-color:#314a37!important}
|
.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(6){background-color:#283e2d!important;border-color:#314a37!important}
|
||||||
.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3){background-color:#3c2626!important;border-color:#634343!important}
|
.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3){background-color:#3c2626!important;border-color:#634343!important}
|
||||||
.ui.blue.button:active,.ui.blue.buttons .button:active{background-color:#a27558}
|
.ui.blue.button:active,.ui.blue.buttons .button:active{background-color:#a27558}
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ function htmlEncode(text) {
|
|||||||
var csrf;
|
var csrf;
|
||||||
var suburl;
|
var suburl;
|
||||||
|
|
||||||
|
// Disable Dropzone auto-discover because it's manually initialized
|
||||||
|
if (typeof(Dropzone) !== "undefined") {
|
||||||
|
Dropzone.autoDiscover = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Polyfill for IE9+ support (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
|
// Polyfill for IE9+ support (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
|
||||||
if (!Array.from) {
|
if (!Array.from) {
|
||||||
Array.from = (function () {
|
Array.from = (function () {
|
||||||
@@ -1270,6 +1275,7 @@ function initEditor() {
|
|||||||
$('.quick-pull-branch-name').hide();
|
$('.quick-pull-branch-name').hide();
|
||||||
$('.quick-pull-branch-name input').prop('required',false);
|
$('.quick-pull-branch-name input').prop('required',false);
|
||||||
}
|
}
|
||||||
|
$('#commit-button').text($(this).attr('button_text'));
|
||||||
});
|
});
|
||||||
|
|
||||||
var $editFilename = $("#file-name");
|
var $editFilename = $("#file-name");
|
||||||
@@ -1968,17 +1974,18 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
// Highlight JS
|
// Highlight JS
|
||||||
if (typeof hljs != 'undefined') {
|
if (typeof hljs != 'undefined') {
|
||||||
hljs.initHighlightingOnLoad();
|
const nodes = [].slice.call(document.querySelectorAll('pre code') || []);
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
hljs.highlightBlock(nodes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dropzone
|
// Dropzone
|
||||||
var $dropzone = $('#dropzone');
|
const $dropzone = $('#dropzone');
|
||||||
if ($dropzone.length > 0) {
|
if ($dropzone.length > 0) {
|
||||||
// Disable auto discover for all elements:
|
const filenameDict = {};
|
||||||
Dropzone.autoDiscover = false;
|
|
||||||
|
|
||||||
var filenameDict = {};
|
new Dropzone("#dropzone", {
|
||||||
$dropzone.dropzone({
|
|
||||||
url: $dropzone.data('upload-url'),
|
url: $dropzone.data('upload-url'),
|
||||||
headers: {"X-Csrf-Token": csrf},
|
headers: {"X-Csrf-Token": csrf},
|
||||||
maxFiles: $dropzone.data('max-file'),
|
maxFiles: $dropzone.data('max-file'),
|
||||||
@@ -2006,7 +2013,7 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2104,12 +2111,16 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('.issue-action').click(function () {
|
$('.issue-action').click(function () {
|
||||||
var action = this.dataset.action
|
let action = this.dataset.action;
|
||||||
var elementId = this.dataset.elementId
|
let elementId = this.dataset.elementId;
|
||||||
var issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
|
let issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
|
||||||
return this.dataset.issueId;
|
return this.dataset.issueId;
|
||||||
}).get().join();
|
}).get().join();
|
||||||
var url = this.dataset.url
|
let url = this.dataset.url;
|
||||||
|
if (elementId === '0' && url.substr(-9) === '/assignee'){
|
||||||
|
elementId = '';
|
||||||
|
action = 'clear';
|
||||||
|
}
|
||||||
updateIssuesMeta(url, action, issueIDs, elementId).then(reload);
|
updateIssuesMeta(url, action, issueIDs, elementId).then(reload);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -605,7 +605,6 @@ code,
|
|||||||
.file-comment {
|
.file-comment {
|
||||||
font: 12px @monospaced-fonts, monospace;
|
font: 12px @monospaced-fonts, monospace;
|
||||||
color: rgba(0, 0, 0, 0.87);
|
color: rgba(0, 0, 0, 0.87);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.floating.dropdown {
|
.ui.floating.dropdown {
|
||||||
@@ -877,3 +876,19 @@ footer {
|
|||||||
.ui.tabular.menu .item.active {
|
.ui.tabular.menu .item.active {
|
||||||
color: rgba(0, 0, 0, 0.9);
|
color: rgba(0, 0, 0, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* multiple radio or checkboxes as inline element */
|
||||||
|
.inline-grouped-list {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
> .ui {
|
||||||
|
display: block;
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1265,6 +1265,10 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.message {
|
||||||
|
text-overflow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
&.ui.basic.striped.table tbody tr:nth-child(2n) {
|
&.ui.basic.striped.table tbody tr:nth-child(2n) {
|
||||||
background-color: rgba(0, 0, 0, 0.02) !important;
|
background-color: rgba(0, 0, 0, 0.02) !important;
|
||||||
}
|
}
|
||||||
@@ -1971,6 +1975,8 @@
|
|||||||
&.user-cards {
|
&.user-cards {
|
||||||
.list {
|
.list {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
@@ -2300,12 +2306,12 @@ tbody.commit-list {
|
|||||||
.commit-list .message-wrapper {
|
.commit-list .message-wrapper {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
max-width: calc(100% - 24px);
|
max-width: calc(100% - 50px);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.commit-list .message-wrapper .commit-status-link {
|
.commit-list .commit-status-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1082,7 +1082,7 @@ a.ui.labels .label:hover {
|
|||||||
|
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),
|
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),
|
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),
|
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),
|
||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6) {
|
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6) {
|
||||||
|
|||||||
5
public/vendor/VERSIONS
vendored
5
public/vendor/VERSIONS
vendored
@@ -6,7 +6,10 @@ File(s): /vendor/plugins/jquery.areyousure/jquery.are-you-sure.js
|
|||||||
Version: 1.9.0
|
Version: 1.9.0
|
||||||
|
|
||||||
File(s): /vendor/plugins/jquery/jquery.min.js
|
File(s): /vendor/plugins/jquery/jquery.min.js
|
||||||
Version: 1.12.4
|
Version: 3.4.1
|
||||||
|
|
||||||
|
File(s): /vendor/plugins/jquery-migrate/jquery-migrate.min.js
|
||||||
|
Version: 3.0.1
|
||||||
|
|
||||||
File(s): /vendor/plugins/semantic/semantic.min.js
|
File(s): /vendor/plugins/semantic/semantic.min.js
|
||||||
Version: 2.3.1
|
Version: 2.3.1
|
||||||
|
|||||||
9
public/vendor/librejs.html
vendored
9
public/vendor/librejs.html
vendored
@@ -17,8 +17,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="./plugins/jquery/jquery.min.js">jquery.min.js</a></td>
|
<td><a href="./plugins/jquery/jquery.min.js">jquery.min.js</a></td>
|
||||||
<td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
|
<td><a href="https://jquery.org/license/">MIT</a></td>
|
||||||
<td><a href="https://code.jquery.com/jquery-1.12.4.min.js">jquery-1.12.4.min.js</a></td>
|
<td><a href="https://code.jquery.com/jquery-3.4.1.min.js">jquery-3.4.1.min.js</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="./plugins/jquery-migrate/jquery-migrate.min.js">jquery-migrate.min.js</a></td>
|
||||||
|
<td><a href="https://jquery.org/license/">MIT</a></td>
|
||||||
|
<td><a href="https://code.jquery.com/jquery-migrate-3.0.1.min.js">jquery-migrate-3.0.1.min.js</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="./plugins/semantic/semantic.min.js">semantic.min.js</a></td>
|
<td><a href="./plugins/semantic/semantic.min.js">semantic.min.js</a></td>
|
||||||
|
|||||||
215
public/vendor/plugins/jquery-migrate/jquery-migrate.min.js
vendored
Normal file
215
public/vendor/plugins/jquery-migrate/jquery-migrate.min.js
vendored
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
/*! jQuery Migrate v3.0.1 | (c) jQuery Foundation and other contributors | jquery.org/license */
|
||||||
|
|
||||||
|
void 0 === jQuery.migrateMute && (jQuery.migrateMute = !0), function(e) {
|
||||||
|
"function" == typeof define && define.amd ? define([ "jquery" ], window, e) : "object" == typeof module && module.exports ? module.exports = e(require("jquery"), window) : e(jQuery, window);
|
||||||
|
}(function(e, t) {
|
||||||
|
"use strict";
|
||||||
|
function r(r) {
|
||||||
|
var n = t.console;
|
||||||
|
o[r] || (o[r] = !0, e.migrateWarnings.push(r), n && n.warn && !e.migrateMute && (n.warn("JQMIGRATE: " + r),
|
||||||
|
e.migrateTrace && n.trace && n.trace()));
|
||||||
|
}
|
||||||
|
function n(e, t, n, a) {
|
||||||
|
Object.defineProperty(e, t, {
|
||||||
|
configurable: !0,
|
||||||
|
enumerable: !0,
|
||||||
|
get: function() {
|
||||||
|
return r(a), n;
|
||||||
|
},
|
||||||
|
set: function(e) {
|
||||||
|
r(a), n = e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function a(e, t, n, a) {
|
||||||
|
e[t] = function() {
|
||||||
|
return r(a), n.apply(this, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
e.migrateVersion = "3.0.1", function() {
|
||||||
|
var r = /^[12]\./;
|
||||||
|
t.console && t.console.log && (e && !r.test(e.fn.jquery) || t.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED"),
|
||||||
|
e.migrateWarnings && t.console.log("JQMIGRATE: Migrate plugin loaded multiple times"),
|
||||||
|
t.console.log("JQMIGRATE: Migrate is installed" + (e.migrateMute ? "" : " with logging active") + ", version " + e.migrateVersion));
|
||||||
|
}();
|
||||||
|
var o = {};
|
||||||
|
e.migrateWarnings = [], void 0 === e.migrateTrace && (e.migrateTrace = !0), e.migrateReset = function() {
|
||||||
|
o = {}, e.migrateWarnings.length = 0;
|
||||||
|
}, "BackCompat" === t.document.compatMode && r("jQuery is not compatible with Quirks Mode");
|
||||||
|
var i = e.fn.init, s = e.isNumeric, u = e.find, c = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, l = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
|
||||||
|
e.fn.init = function(e) {
|
||||||
|
var t = Array.prototype.slice.call(arguments);
|
||||||
|
return "string" == typeof e && "#" === e && (r("jQuery( '#' ) is not a valid selector"),
|
||||||
|
t[0] = []), i.apply(this, t);
|
||||||
|
}, e.fn.init.prototype = e.fn, e.find = function(e) {
|
||||||
|
var n = Array.prototype.slice.call(arguments);
|
||||||
|
if ("string" == typeof e && c.test(e)) try {
|
||||||
|
t.document.querySelector(e);
|
||||||
|
} catch (a) {
|
||||||
|
e = e.replace(l, function(e, t, r, n) {
|
||||||
|
return "[" + t + r + '"' + n + '"]';
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
t.document.querySelector(e), r("Attribute selector with '#' must be quoted: " + n[0]),
|
||||||
|
n[0] = e;
|
||||||
|
} catch (e) {
|
||||||
|
r("Attribute selector with '#' was not fixed: " + n[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return u.apply(this, n);
|
||||||
|
};
|
||||||
|
var d;
|
||||||
|
for (d in u) Object.prototype.hasOwnProperty.call(u, d) && (e.find[d] = u[d]);
|
||||||
|
e.fn.size = function() {
|
||||||
|
return r("jQuery.fn.size() is deprecated and removed; use the .length property"),
|
||||||
|
this.length;
|
||||||
|
}, e.parseJSON = function() {
|
||||||
|
return r("jQuery.parseJSON is deprecated; use JSON.parse"), JSON.parse.apply(null, arguments);
|
||||||
|
}, e.isNumeric = function(t) {
|
||||||
|
var n = s(t), a = function(t) {
|
||||||
|
var r = t && t.toString();
|
||||||
|
return !e.isArray(t) && r - parseFloat(r) + 1 >= 0;
|
||||||
|
}(t);
|
||||||
|
return n !== a && r("jQuery.isNumeric() should not be called on constructed objects"),
|
||||||
|
a;
|
||||||
|
}, a(e, "holdReady", e.holdReady, "jQuery.holdReady is deprecated"), a(e, "unique", e.uniqueSort, "jQuery.unique is deprecated; use jQuery.uniqueSort"),
|
||||||
|
n(e.expr, "filters", e.expr.pseudos, "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"),
|
||||||
|
n(e.expr, ":", e.expr.pseudos, "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos");
|
||||||
|
var p = e.ajax;
|
||||||
|
e.ajax = function() {
|
||||||
|
var e = p.apply(this, arguments);
|
||||||
|
return e.promise && (a(e, "success", e.done, "jQXHR.success is deprecated and removed"),
|
||||||
|
a(e, "error", e.fail, "jQXHR.error is deprecated and removed"), a(e, "complete", e.always, "jQXHR.complete is deprecated and removed")),
|
||||||
|
e;
|
||||||
|
};
|
||||||
|
var f = e.fn.removeAttr, y = e.fn.toggleClass, m = /\S+/g;
|
||||||
|
e.fn.removeAttr = function(t) {
|
||||||
|
var n = this;
|
||||||
|
return e.each(t.match(m), function(t, a) {
|
||||||
|
e.expr.match.bool.test(a) && (r("jQuery.fn.removeAttr no longer sets boolean properties: " + a),
|
||||||
|
n.prop(a, !1));
|
||||||
|
}), f.apply(this, arguments);
|
||||||
|
}, e.fn.toggleClass = function(t) {
|
||||||
|
return void 0 !== t && "boolean" != typeof t ? y.apply(this, arguments) : (r("jQuery.fn.toggleClass( boolean ) is deprecated"),
|
||||||
|
this.each(function() {
|
||||||
|
var r = this.getAttribute && this.getAttribute("class") || "";
|
||||||
|
r && e.data(this, "__className__", r), this.setAttribute && this.setAttribute("class", r || !1 === t ? "" : e.data(this, "__className__") || "");
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
var h = !1;
|
||||||
|
e.swap && e.each([ "height", "width", "reliableMarginRight" ], function(t, r) {
|
||||||
|
var n = e.cssHooks[r] && e.cssHooks[r].get;
|
||||||
|
n && (e.cssHooks[r].get = function() {
|
||||||
|
var e;
|
||||||
|
return h = !0, e = n.apply(this, arguments), h = !1, e;
|
||||||
|
});
|
||||||
|
}), e.swap = function(e, t, n, a) {
|
||||||
|
var o, i, s = {};
|
||||||
|
h || r("jQuery.swap() is undocumented and deprecated");
|
||||||
|
for (i in t) s[i] = e.style[i], e.style[i] = t[i];
|
||||||
|
o = n.apply(e, a || []);
|
||||||
|
for (i in t) e.style[i] = s[i];
|
||||||
|
return o;
|
||||||
|
};
|
||||||
|
var g = e.data;
|
||||||
|
e.data = function(t, n, a) {
|
||||||
|
var o;
|
||||||
|
if (n && "object" == typeof n && 2 === arguments.length) {
|
||||||
|
o = e.hasData(t) && g.call(this, t);
|
||||||
|
var i = {};
|
||||||
|
for (var s in n) s !== e.camelCase(s) ? (r("jQuery.data() always sets/gets camelCased names: " + s),
|
||||||
|
o[s] = n[s]) : i[s] = n[s];
|
||||||
|
return g.call(this, t, i), n;
|
||||||
|
}
|
||||||
|
return n && "string" == typeof n && n !== e.camelCase(n) && (o = e.hasData(t) && g.call(this, t)) && n in o ? (r("jQuery.data() always sets/gets camelCased names: " + n),
|
||||||
|
arguments.length > 2 && (o[n] = a), o[n]) : g.apply(this, arguments);
|
||||||
|
};
|
||||||
|
var v = e.Tween.prototype.run, j = function(e) {
|
||||||
|
return e;
|
||||||
|
};
|
||||||
|
e.Tween.prototype.run = function() {
|
||||||
|
e.easing[this.easing].length > 1 && (r("'jQuery.easing." + this.easing.toString() + "' should use only one argument"),
|
||||||
|
e.easing[this.easing] = j), v.apply(this, arguments);
|
||||||
|
}, e.fx.interval = e.fx.interval || 13, t.requestAnimationFrame && n(e.fx, "interval", e.fx.interval, "jQuery.fx.interval is deprecated");
|
||||||
|
var Q = e.fn.load, b = e.event.add, w = e.event.fix;
|
||||||
|
e.event.props = [], e.event.fixHooks = {}, n(e.event.props, "concat", e.event.props.concat, "jQuery.event.props.concat() is deprecated and removed"),
|
||||||
|
e.event.fix = function(t) {
|
||||||
|
var n, a = t.type, o = this.fixHooks[a], i = e.event.props;
|
||||||
|
if (i.length) for (r("jQuery.event.props are deprecated and removed: " + i.join()); i.length; ) e.event.addProp(i.pop());
|
||||||
|
if (o && !o._migrated_ && (o._migrated_ = !0, r("jQuery.event.fixHooks are deprecated and removed: " + a),
|
||||||
|
(i = o.props) && i.length)) for (;i.length; ) e.event.addProp(i.pop());
|
||||||
|
return n = w.call(this, t), o && o.filter ? o.filter(n, t) : n;
|
||||||
|
}, e.event.add = function(e, n) {
|
||||||
|
return e === t && "load" === n && "complete" === t.document.readyState && r("jQuery(window).on('load'...) called after load event occurred"),
|
||||||
|
b.apply(this, arguments);
|
||||||
|
}, e.each([ "load", "unload", "error" ], function(t, n) {
|
||||||
|
e.fn[n] = function() {
|
||||||
|
var e = Array.prototype.slice.call(arguments, 0);
|
||||||
|
return "load" === n && "string" == typeof e[0] ? Q.apply(this, e) : (r("jQuery.fn." + n + "() is deprecated"),
|
||||||
|
e.splice(0, 0, n), arguments.length ? this.on.apply(this, e) : (this.triggerHandler.apply(this, e),
|
||||||
|
this));
|
||||||
|
};
|
||||||
|
}), e.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "), function(t, n) {
|
||||||
|
e.fn[n] = function(e, t) {
|
||||||
|
return r("jQuery.fn." + n + "() event shorthand is deprecated"), arguments.length > 0 ? this.on(n, null, e, t) : this.trigger(n);
|
||||||
|
};
|
||||||
|
}), e(function() {
|
||||||
|
e(t.document).triggerHandler("ready");
|
||||||
|
}), e.event.special.ready = {
|
||||||
|
setup: function() {
|
||||||
|
this === t.document && r("'ready' event is deprecated");
|
||||||
|
}
|
||||||
|
}, e.fn.extend({
|
||||||
|
bind: function(e, t, n) {
|
||||||
|
return r("jQuery.fn.bind() is deprecated"), this.on(e, null, t, n);
|
||||||
|
},
|
||||||
|
unbind: function(e, t) {
|
||||||
|
return r("jQuery.fn.unbind() is deprecated"), this.off(e, null, t);
|
||||||
|
},
|
||||||
|
delegate: function(e, t, n, a) {
|
||||||
|
return r("jQuery.fn.delegate() is deprecated"), this.on(t, e, n, a);
|
||||||
|
},
|
||||||
|
undelegate: function(e, t, n) {
|
||||||
|
return r("jQuery.fn.undelegate() is deprecated"), 1 === arguments.length ? this.off(e, "**") : this.off(t, e || "**", n);
|
||||||
|
},
|
||||||
|
hover: function(e, t) {
|
||||||
|
return r("jQuery.fn.hover() is deprecated"), this.on("mouseenter", e).on("mouseleave", t || e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var x = e.fn.offset;
|
||||||
|
e.fn.offset = function() {
|
||||||
|
var n, a = this[0], o = {
|
||||||
|
top: 0,
|
||||||
|
left: 0
|
||||||
|
};
|
||||||
|
return a && a.nodeType ? (n = (a.ownerDocument || t.document).documentElement, e.contains(n, a) ? x.apply(this, arguments) : (r("jQuery.fn.offset() requires an element connected to a document"),
|
||||||
|
o)) : (r("jQuery.fn.offset() requires a valid DOM element"), o);
|
||||||
|
};
|
||||||
|
var k = e.param;
|
||||||
|
e.param = function(t, n) {
|
||||||
|
var a = e.ajaxSettings && e.ajaxSettings.traditional;
|
||||||
|
return void 0 === n && a && (r("jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),
|
||||||
|
n = a), k.call(this, t, n);
|
||||||
|
};
|
||||||
|
var A = e.fn.andSelf || e.fn.addBack;
|
||||||
|
e.fn.andSelf = function() {
|
||||||
|
return r("jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),
|
||||||
|
A.apply(this, arguments);
|
||||||
|
};
|
||||||
|
var S = e.Deferred, q = [ [ "resolve", "done", e.Callbacks("once memory"), e.Callbacks("once memory"), "resolved" ], [ "reject", "fail", e.Callbacks("once memory"), e.Callbacks("once memory"), "rejected" ], [ "notify", "progress", e.Callbacks("memory"), e.Callbacks("memory") ] ];
|
||||||
|
return e.Deferred = function(t) {
|
||||||
|
var n = S(), a = n.promise();
|
||||||
|
return n.pipe = a.pipe = function() {
|
||||||
|
var t = arguments;
|
||||||
|
return r("deferred.pipe() is deprecated"), e.Deferred(function(r) {
|
||||||
|
e.each(q, function(o, i) {
|
||||||
|
var s = e.isFunction(t[o]) && t[o];
|
||||||
|
n[i[1]](function() {
|
||||||
|
var t = s && s.apply(this, arguments);
|
||||||
|
t && e.isFunction(t.promise) ? t.promise().done(r.resolve).fail(r.reject).progress(r.notify) : r[i[0] + "With"](this === a ? r.promise() : this, s ? [ t ] : arguments);
|
||||||
|
});
|
||||||
|
}), t = null;
|
||||||
|
}).promise();
|
||||||
|
}, t && t.call(n, n), n;
|
||||||
|
}, e.Deferred.exceptionHook = S.exceptionHook, e;
|
||||||
|
});
|
||||||
7
public/vendor/plugins/jquery/jquery.min.js
vendored
7
public/vendor/plugins/jquery/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -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)
|
||||||
|
|||||||
@@ -91,8 +91,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
|
|||||||
if form.SendNotify && setting.MailService != nil {
|
if form.SendNotify && setting.MailService != nil {
|
||||||
models.SendRegisterNotifyMail(ctx.Context.Context, u)
|
models.SendRegisterNotifyMail(ctx.Context.Context, u)
|
||||||
}
|
}
|
||||||
|
ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
|
||||||
ctx.JSON(201, u.APIFormat())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EditUser api for modifying a user's information
|
// EditUser api for modifying a user's information
|
||||||
@@ -181,7 +180,7 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) {
|
|||||||
}
|
}
|
||||||
log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
|
log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
|
||||||
|
|
||||||
ctx.JSON(200, u.APIFormat())
|
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser api for deleting a user
|
// DeleteUser api for deleting a user
|
||||||
@@ -326,7 +325,7 @@ func GetAllUsers(ctx *context.APIContext) {
|
|||||||
|
|
||||||
results := make([]*api.User, len(users))
|
results := make([]*api.User, len(users))
|
||||||
for i := range users {
|
for i := range users {
|
||||||
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(200, &results)
|
ctx.JSON(200, &results)
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ func ToTeam(team *models.Team) *api.Team {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ToUser convert models.User to api.User
|
// ToUser convert models.User to api.User
|
||||||
func ToUser(user *models.User, signed, admin bool) *api.User {
|
func ToUser(user *models.User, signed, authed bool) *api.User {
|
||||||
result := &api.User{
|
result := &api.User{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
UserName: user.Name,
|
UserName: user.Name,
|
||||||
@@ -239,7 +239,12 @@ func ToUser(user *models.User, signed, admin bool) *api.User {
|
|||||||
LastLogin: user.LastLoginUnix.AsTime(),
|
LastLogin: user.LastLoginUnix.AsTime(),
|
||||||
Created: user.CreatedUnix.AsTime(),
|
Created: user.CreatedUnix.AsTime(),
|
||||||
}
|
}
|
||||||
if signed && (!user.KeepEmailPrivate || admin) {
|
// hide primary email if API caller isn't user itself or an admin
|
||||||
|
if !signed {
|
||||||
|
result.Email = ""
|
||||||
|
} else if user.KeepEmailPrivate && !authed {
|
||||||
|
result.Email = user.GetEmail()
|
||||||
|
} else {
|
||||||
result.Email = user.Email
|
result.Email = user.Email
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
"code.gitea.io/gitea/routers/api/v1/user"
|
"code.gitea.io/gitea/routers/api/v1/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
|
|||||||
|
|
||||||
apiMembers := make([]*api.User, len(members))
|
apiMembers := make([]*api.User, len(members))
|
||||||
for i, member := range members {
|
for i, member := range members {
|
||||||
apiMembers[i] = member.APIFormat()
|
apiMembers[i] = convert.ToUser(member, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, apiMembers)
|
ctx.JSON(200, apiMembers)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ func GetTeamMembers(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
members := make([]*api.User, len(team.Members))
|
members := make([]*api.User, len(team.Members))
|
||||||
for i, member := range team.Members {
|
for i, member := range team.Members {
|
||||||
members[i] = member.APIFormat()
|
members[i] = convert.ToUser(member, ctx.IsSigned, ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, members)
|
ctx.JSON(200, members)
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ func GetTeamMember(ctx *context.APIContext) {
|
|||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.JSON(200, u.APIFormat())
|
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddTeamMember api for add a member to a team
|
// AddTeamMember api for add a member to a team
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListCollaborators list a repository's collaborators
|
// ListCollaborators list a repository's collaborators
|
||||||
@@ -42,7 +43,7 @@ func ListCollaborators(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
users := make([]*api.User, len(collaborators))
|
users := make([]*api.User, len(collaborators))
|
||||||
for i, collaborator := range collaborators {
|
for i, collaborator := range collaborators {
|
||||||
users[i] = collaborator.APIFormat()
|
users[i] = convert.ToUser(collaborator.User, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, users)
|
ctx.JSON(200, users)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func GetSingleCommit(ctx *context.APIContext) {
|
|||||||
URL: setting.AppURL + ctx.Link[1:],
|
URL: setting.AppURL + ctx.Link[1:],
|
||||||
SHA: commit.ID.String(),
|
SHA: commit.ID.String(),
|
||||||
},
|
},
|
||||||
HTMLURL: ctx.Repo.Repository.HTMLURL() + "/commits/" + commit.ID.String(),
|
HTMLURL: ctx.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(),
|
||||||
RepoCommit: &api.RepoCommit{
|
RepoCommit: &api.RepoCommit{
|
||||||
URL: setting.AppURL + ctx.Link[1:],
|
URL: setting.AppURL + ctx.Link[1:],
|
||||||
Author: &api.CommitUser{
|
Author: &api.CommitUser{
|
||||||
@@ -111,7 +111,7 @@ func GetSingleCommit(ctx *context.APIContext) {
|
|||||||
},
|
},
|
||||||
Message: commit.Message(),
|
Message: commit.Message(),
|
||||||
Tree: &api.CommitMeta{
|
Tree: &api.CommitMeta{
|
||||||
URL: ctx.Repo.Repository.APIURL() + "/trees/" + commit.ID.String(),
|
URL: ctx.Repo.Repository.APIURL() + "/git/trees/" + commit.ID.String(),
|
||||||
SHA: commit.ID.String(),
|
SHA: commit.ID.String(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -71,19 +71,22 @@ func GetGitRefs(ctx *context.APIContext) {
|
|||||||
getGitRefsInternal(ctx, ctx.Params("*"))
|
getGitRefsInternal(ctx, ctx.Params("*"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getGitRefsInternal(ctx *context.APIContext, filter string) {
|
func getGitRefs(ctx *context.APIContext, filter string) ([]*git.Reference, string, error) {
|
||||||
gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath())
|
gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "OpenRepository", err)
|
return nil, "OpenRepository", err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if len(filter) > 0 {
|
if len(filter) > 0 {
|
||||||
filter = "refs/" + filter
|
filter = "refs/" + filter
|
||||||
}
|
}
|
||||||
|
|
||||||
refs, err := gitRepo.GetRefsFiltered(filter)
|
refs, err := gitRepo.GetRefsFiltered(filter)
|
||||||
|
return refs, "GetRefsFiltered", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getGitRefsInternal(ctx *context.APIContext, filter string) {
|
||||||
|
refs, lastMethodName, err := getGitRefs(ctx, filter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(500, "GetRefsFiltered", err)
|
ctx.Error(500, lastMethodName, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,8 +130,8 @@ func TestHook(ctx *context.APIContext) {
|
|||||||
convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
|
convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
|
||||||
},
|
},
|
||||||
Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone),
|
Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone),
|
||||||
Pusher: ctx.User.APIFormat(),
|
Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false),
|
||||||
Sender: ctx.User.APIFormat(),
|
Sender: convert.ToUser(ctx.User, ctx.IsSigned, false),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
ctx.Error(500, "PrepareWebhook: ", err)
|
ctx.Error(500, "PrepareWebhook: ", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -646,89 +646,102 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.HasIssues != nil {
|
if opts.HasIssues == nil {
|
||||||
if *opts.HasIssues {
|
// If HasIssues setting not touched, rewrite existing repo unit
|
||||||
// We don't currently allow setting individual issue settings through the API,
|
if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil {
|
||||||
// only can enable/disable issues, so when enabling issues,
|
units = append(units, *unit)
|
||||||
// we either get the existing config which means it was already enabled,
|
} else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil {
|
||||||
// or create a new config since it doesn't exist.
|
units = append(units, *unit)
|
||||||
unit, err := repo.GetUnit(models.UnitTypeIssues)
|
|
||||||
var config *models.IssuesConfig
|
|
||||||
if err != nil {
|
|
||||||
// Unit type doesn't exist so we make a new config file with default values
|
|
||||||
config = &models.IssuesConfig{
|
|
||||||
EnableTimetracker: true,
|
|
||||||
AllowOnlyContributorsToTrackTime: true,
|
|
||||||
EnableDependencies: true,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
config = unit.IssuesConfig()
|
|
||||||
}
|
|
||||||
units = append(units, models.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: models.UnitTypeIssues,
|
|
||||||
Config: config,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
} else if *opts.HasIssues {
|
||||||
|
// We don't currently allow setting individual issue settings through the API,
|
||||||
|
// only can enable/disable issues, so when enabling issues,
|
||||||
|
// we either get the existing config which means it was already enabled,
|
||||||
|
// or create a new config since it doesn't exist.
|
||||||
|
unit, err := repo.GetUnit(models.UnitTypeIssues)
|
||||||
|
var config *models.IssuesConfig
|
||||||
|
if err != nil {
|
||||||
|
// Unit type doesn't exist so we make a new config file with default values
|
||||||
|
config = &models.IssuesConfig{
|
||||||
|
EnableTimetracker: true,
|
||||||
|
AllowOnlyContributorsToTrackTime: true,
|
||||||
|
EnableDependencies: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config = unit.IssuesConfig()
|
||||||
|
}
|
||||||
|
units = append(units, models.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: models.UnitTypeIssues,
|
||||||
|
Config: config,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.HasWiki != nil {
|
if opts.HasWiki == nil {
|
||||||
if *opts.HasWiki {
|
// If HasWiki setting not touched, rewrite existing repo unit
|
||||||
// We don't currently allow setting individual wiki settings through the API,
|
if unit, err := repo.GetUnit(models.UnitTypeWiki); err == nil {
|
||||||
// only can enable/disable the wiki, so when enabling the wiki,
|
units = append(units, *unit)
|
||||||
// we either get the existing config which means it was already enabled,
|
} else if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err == nil {
|
||||||
// or create a new config since it doesn't exist.
|
units = append(units, *unit)
|
||||||
config := &models.UnitConfig{}
|
|
||||||
units = append(units, models.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: models.UnitTypeWiki,
|
|
||||||
Config: config,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
} else if *opts.HasWiki {
|
||||||
|
// We don't currently allow setting individual wiki settings through the API,
|
||||||
|
// only can enable/disable the wiki, so when enabling the wiki,
|
||||||
|
// we either get the existing config which means it was already enabled,
|
||||||
|
// or create a new config since it doesn't exist.
|
||||||
|
config := &models.UnitConfig{}
|
||||||
|
units = append(units, models.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: models.UnitTypeWiki,
|
||||||
|
Config: config,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.HasPullRequests != nil {
|
if opts.HasPullRequests == nil {
|
||||||
if *opts.HasPullRequests {
|
// If HasPullRequest setting not touched, rewrite existing repo unit
|
||||||
// We do allow setting individual PR settings through the API, so
|
if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil {
|
||||||
// we get the config settings and then set them
|
units = append(units, *unit)
|
||||||
// if those settings were provided in the opts.
|
|
||||||
unit, err := repo.GetUnit(models.UnitTypePullRequests)
|
|
||||||
var config *models.PullRequestsConfig
|
|
||||||
if err != nil {
|
|
||||||
// Unit type doesn't exist so we make a new config file with default values
|
|
||||||
config = &models.PullRequestsConfig{
|
|
||||||
IgnoreWhitespaceConflicts: false,
|
|
||||||
AllowMerge: true,
|
|
||||||
AllowRebase: true,
|
|
||||||
AllowRebaseMerge: true,
|
|
||||||
AllowSquash: true,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
config = unit.PullRequestsConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.IgnoreWhitespaceConflicts != nil {
|
|
||||||
config.IgnoreWhitespaceConflicts = *opts.IgnoreWhitespaceConflicts
|
|
||||||
}
|
|
||||||
if opts.AllowMerge != nil {
|
|
||||||
config.AllowMerge = *opts.AllowMerge
|
|
||||||
}
|
|
||||||
if opts.AllowRebase != nil {
|
|
||||||
config.AllowRebase = *opts.AllowRebase
|
|
||||||
}
|
|
||||||
if opts.AllowRebaseMerge != nil {
|
|
||||||
config.AllowRebaseMerge = *opts.AllowRebaseMerge
|
|
||||||
}
|
|
||||||
if opts.AllowSquash != nil {
|
|
||||||
config.AllowSquash = *opts.AllowSquash
|
|
||||||
}
|
|
||||||
|
|
||||||
units = append(units, models.RepoUnit{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Type: models.UnitTypePullRequests,
|
|
||||||
Config: config,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
} else if *opts.HasPullRequests {
|
||||||
|
// We do allow setting individual PR settings through the API, so
|
||||||
|
// we get the config settings and then set them
|
||||||
|
// if those settings were provided in the opts.
|
||||||
|
unit, err := repo.GetUnit(models.UnitTypePullRequests)
|
||||||
|
var config *models.PullRequestsConfig
|
||||||
|
if err != nil {
|
||||||
|
// Unit type doesn't exist so we make a new config file with default values
|
||||||
|
config = &models.PullRequestsConfig{
|
||||||
|
IgnoreWhitespaceConflicts: false,
|
||||||
|
AllowMerge: true,
|
||||||
|
AllowRebase: true,
|
||||||
|
AllowRebaseMerge: true,
|
||||||
|
AllowSquash: true,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config = unit.PullRequestsConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.IgnoreWhitespaceConflicts != nil {
|
||||||
|
config.IgnoreWhitespaceConflicts = *opts.IgnoreWhitespaceConflicts
|
||||||
|
}
|
||||||
|
if opts.AllowMerge != nil {
|
||||||
|
config.AllowMerge = *opts.AllowMerge
|
||||||
|
}
|
||||||
|
if opts.AllowRebase != nil {
|
||||||
|
config.AllowRebase = *opts.AllowRebase
|
||||||
|
}
|
||||||
|
if opts.AllowRebaseMerge != nil {
|
||||||
|
config.AllowRebaseMerge = *opts.AllowRebaseMerge
|
||||||
|
}
|
||||||
|
if opts.AllowSquash != nil {
|
||||||
|
config.AllowSquash = *opts.AllowSquash
|
||||||
|
}
|
||||||
|
|
||||||
|
units = append(units, models.RepoUnit{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Type: models.UnitTypePullRequests,
|
||||||
|
Config: config,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := models.UpdateRepositoryUnits(repo, units); err != nil {
|
if err := models.UpdateRepositoryUnits(repo, units); err != nil {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListStargazers list a repository's stargazers
|
// ListStargazers list a repository's stargazers
|
||||||
@@ -38,7 +39,7 @@ func ListStargazers(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
users := make([]*api.User, len(stargazers))
|
users := make([]*api.User, len(stargazers))
|
||||||
for i, stargazer := range stargazers {
|
for i, stargazer := range stargazers {
|
||||||
users[i] = stargazer.APIFormat()
|
users[i] = convert.ToUser(stargazer, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, users)
|
ctx.JSON(200, users)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
|
|||||||
// "$ref": "#/responses/StatusList"
|
// "$ref": "#/responses/StatusList"
|
||||||
sha := ctx.Params("sha")
|
sha := ctx.Params("sha")
|
||||||
if len(sha) == 0 {
|
if len(sha) == 0 {
|
||||||
sha = ctx.Params("ref")
|
ctx.Error(400, "sha not given", nil)
|
||||||
}
|
|
||||||
if len(sha) == 0 {
|
|
||||||
ctx.Error(400, "ref/sha not given", nil)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
status := &models.CommitStatus{
|
status := &models.CommitStatus{
|
||||||
@@ -121,7 +118,38 @@ func GetCommitStatusesByRef(ctx *context.APIContext) {
|
|||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/StatusList"
|
// "$ref": "#/responses/StatusList"
|
||||||
getCommitStatuses(ctx, ctx.Params("ref"))
|
|
||||||
|
filter := ctx.Params("ref")
|
||||||
|
if len(filter) == 0 {
|
||||||
|
ctx.Error(400, "ref not given", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, reftype := range []string{"heads", "tags"} { //Search branches and tags
|
||||||
|
refSHA, lastMethodName, err := searchRefCommitByType(ctx, reftype, filter)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(500, lastMethodName, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if refSHA != "" {
|
||||||
|
filter = refSHA
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
getCommitStatuses(ctx, filter) //By default filter is maybe the raw SHA
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (string, string, error) {
|
||||||
|
refs, lastMethodName, err := getGitRefs(ctx, refType+"/"+filter) //Search by type
|
||||||
|
if err != nil {
|
||||||
|
return "", lastMethodName, err
|
||||||
|
}
|
||||||
|
if len(refs) > 0 {
|
||||||
|
return refs[0].Object.String(), "", nil //Return found SHA
|
||||||
|
}
|
||||||
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCommitStatuses(ctx *context.APIContext, sha string) {
|
func getCommitStatuses(ctx *context.APIContext, sha string) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListSubscribers list a repo's subscribers (i.e. watchers)
|
// ListSubscribers list a repo's subscribers (i.e. watchers)
|
||||||
@@ -38,7 +39,7 @@ func ListSubscribers(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
users := make([]*api.User, len(subscribers))
|
users := make([]*api.User, len(subscribers))
|
||||||
for i, subscriber := range subscribers {
|
for i, subscriber := range subscribers {
|
||||||
users[i] = subscriber.APIFormat()
|
users[i] = convert.ToUser(subscriber, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, users)
|
ctx.JSON(200, users)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func responseAPIUsers(ctx *context.APIContext, users []*models.User) {
|
func responseAPIUsers(ctx *context.APIContext, users []*models.User) {
|
||||||
apiUsers := make([]*api.User, len(users))
|
apiUsers := make([]*api.User, len(users))
|
||||||
for i := range users {
|
for i := range users {
|
||||||
apiUsers[i] = users[i].APIFormat()
|
apiUsers[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
|
||||||
}
|
}
|
||||||
ctx.JSON(200, &apiUsers)
|
ctx.JSON(200, &apiUsers)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa
|
|||||||
apiKey.KeyType = "user"
|
apiKey.KeyType = "user"
|
||||||
|
|
||||||
if defaultUser.ID == key.OwnerID {
|
if defaultUser.ID == key.OwnerID {
|
||||||
apiKey.Owner = defaultUser.APIFormat()
|
apiKey.Owner = convert.ToUser(defaultUser, true, true)
|
||||||
} else {
|
} else {
|
||||||
user, err := models.GetUserByID(key.OwnerID)
|
user, err := models.GetUserByID(key.OwnerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apiKey, err
|
return apiKey, err
|
||||||
}
|
}
|
||||||
apiKey.Owner = user.APIFormat()
|
apiKey.Owner = convert.ToUser(user, true, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
apiKey.KeyType = "unknown"
|
apiKey.KeyType = "unknown"
|
||||||
|
|||||||
@@ -104,11 +104,7 @@ func GetInfo(ctx *context.APIContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide user e-mail when API caller isn't signed in.
|
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.ID == u.ID || ctx.User.IsAdmin))
|
||||||
if !ctx.IsSigned {
|
|
||||||
u.Email = ""
|
|
||||||
}
|
|
||||||
ctx.JSON(200, u.APIFormat())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAuthenticatedUser get current user's information
|
// GetAuthenticatedUser get current user's information
|
||||||
@@ -121,7 +117,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) {
|
|||||||
// responses:
|
// responses:
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/User"
|
// "$ref": "#/responses/User"
|
||||||
ctx.JSON(200, ctx.User.APIFormat())
|
ctx.JSON(200, convert.ToUser(ctx.User, ctx.IsSigned, ctx.User != nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserHeatmapData is the handler to get a users heatmap
|
// GetUserHeatmapData is the handler to get a users heatmap
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ func Settings(ctx *context.Context) {
|
|||||||
func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
||||||
ctx.Data["Title"] = ctx.Tr("org.settings")
|
ctx.Data["Title"] = ctx.Tr("org.settings")
|
||||||
ctx.Data["PageIsSettingsOptions"] = true
|
ctx.Data["PageIsSettingsOptions"] = true
|
||||||
|
ctx.Data["CurrentVisibility"] = structs.VisibleType(ctx.Org.Organization.Visibility)
|
||||||
|
|
||||||
if ctx.HasError() {
|
if ctx.HasError() {
|
||||||
ctx.HTML(200, tplSettingsOptions)
|
ctx.HTML(200, tplSettingsOptions)
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func HookPreReceive(ctx *macaron.Context) {
|
|||||||
userID := ctx.QueryInt64("userID")
|
userID := ctx.QueryInt64("userID")
|
||||||
gitObjectDirectory := ctx.QueryTrim("gitObjectDirectory")
|
gitObjectDirectory := ctx.QueryTrim("gitObjectDirectory")
|
||||||
gitAlternativeObjectDirectories := ctx.QueryTrim("gitAlternativeObjectDirectories")
|
gitAlternativeObjectDirectories := ctx.QueryTrim("gitAlternativeObjectDirectories")
|
||||||
|
gitQuarantinePath := ctx.QueryTrim("gitQuarantinePath")
|
||||||
prID := ctx.QueryInt64("prID")
|
prID := ctx.QueryInt64("prID")
|
||||||
|
|
||||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||||
@@ -63,11 +64,19 @@ func HookPreReceive(ctx *macaron.Context) {
|
|||||||
|
|
||||||
// detect force push
|
// detect force push
|
||||||
if git.EmptySHA != oldCommitID {
|
if git.EmptySHA != oldCommitID {
|
||||||
env := append(os.Environ(),
|
env := os.Environ()
|
||||||
private.GitAlternativeObjectDirectories+"="+gitAlternativeObjectDirectories,
|
if gitAlternativeObjectDirectories != "" {
|
||||||
private.GitObjectDirectory+"="+gitObjectDirectory,
|
env = append(env,
|
||||||
private.GitQuarantinePath+"="+gitObjectDirectory,
|
private.GitAlternativeObjectDirectories+"="+gitAlternativeObjectDirectories)
|
||||||
)
|
}
|
||||||
|
if gitObjectDirectory != "" {
|
||||||
|
env = append(env,
|
||||||
|
private.GitObjectDirectory+"="+gitObjectDirectory)
|
||||||
|
}
|
||||||
|
if gitQuarantinePath != "" {
|
||||||
|
env = append(env,
|
||||||
|
private.GitQuarantinePath+"="+gitQuarantinePath)
|
||||||
|
}
|
||||||
|
|
||||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDirWithEnv(repo.RepoPath(), env)
|
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDirWithEnv(repo.RepoPath(), env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ func Branches(ctx *context.Context) {
|
|||||||
ctx.Data["Title"] = "Branches"
|
ctx.Data["Title"] = "Branches"
|
||||||
ctx.Data["IsRepoToolbarBranches"] = true
|
ctx.Data["IsRepoToolbarBranches"] = true
|
||||||
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
|
ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
|
||||||
|
ctx.Data["AllowsPulls"] = ctx.Repo.Repository.AllowsPulls()
|
||||||
ctx.Data["IsWriter"] = ctx.Repo.CanWrite(models.UnitTypeCode)
|
ctx.Data["IsWriter"] = ctx.Repo.CanWrite(models.UnitTypeCode)
|
||||||
ctx.Data["IsMirror"] = ctx.Repo.Repository.IsMirror
|
ctx.Data["IsMirror"] = ctx.Repo.Repository.IsMirror
|
||||||
ctx.Data["PageIsViewCode"] = true
|
ctx.Data["PageIsViewCode"] = true
|
||||||
@@ -161,6 +162,12 @@ func loadBranches(ctx *context.Context) []*Branch {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protectedBranches, err := ctx.Repo.Repository.GetProtectedBranches()
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetProtectedBranches", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
branches := make([]*Branch, len(rawBranches))
|
branches := make([]*Branch, len(rawBranches))
|
||||||
for i := range rawBranches {
|
for i := range rawBranches {
|
||||||
commit, err := rawBranches[i].GetCommit()
|
commit, err := rawBranches[i].GetCommit()
|
||||||
@@ -169,11 +176,13 @@ func loadBranches(ctx *context.Context) []*Branch {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isProtected bool
|
||||||
branchName := rawBranches[i].Name
|
branchName := rawBranches[i].Name
|
||||||
isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User)
|
for _, b := range protectedBranches {
|
||||||
if err != nil {
|
if b.BranchName == branchName {
|
||||||
ctx.ServerError("IsProtectedBranch", err)
|
isProtected = true
|
||||||
return nil
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, branchName)
|
divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, branchName)
|
||||||
|
|||||||
@@ -292,6 +292,13 @@ func CompareDiff(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Data["PageIsComparePull"] == true {
|
if ctx.Data["PageIsComparePull"] == true {
|
||||||
|
headBranches, err := headGitRepo.GetBranches()
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetBranches", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["HeadBranches"] = headBranches
|
||||||
|
|
||||||
pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch)
|
pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !models.IsErrPullRequestNotExist(err) {
|
if !models.IsErrPullRequestNotExist(err) {
|
||||||
@@ -312,13 +319,6 @@ func CompareDiff(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headBranches, err := headGitRepo.GetBranches()
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("GetBranches", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["HeadBranches"] = headBranches
|
|
||||||
}
|
}
|
||||||
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
|
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
|
||||||
afterCommitID := ctx.Data["AfterCommitID"].(string)
|
afterCommitID := ctx.Data["AfterCommitID"].(string)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -137,7 +138,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
||||||
}
|
}
|
||||||
ctx.Data["new_branch_name"] = ""
|
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
|
||||||
ctx.Data["last_commit"] = ctx.Repo.CommitID
|
ctx.Data["last_commit"] = ctx.Repo.CommitID
|
||||||
ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
|
ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
|
||||||
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
|
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
|
||||||
@@ -266,6 +267,10 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
|
|||||||
} else {
|
} else {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, err), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, err), tplEditFile, &form)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.CommitChoice == frmCommitChoiceNewBranch {
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
|
||||||
} else {
|
} else {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
|
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
|
||||||
}
|
}
|
||||||
@@ -335,7 +340,7 @@ func DeleteFile(ctx *context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
||||||
}
|
}
|
||||||
ctx.Data["new_branch_name"] = ""
|
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
|
||||||
|
|
||||||
ctx.HTML(200, tplDeleteFile)
|
ctx.HTML(200, tplDeleteFile)
|
||||||
}
|
}
|
||||||
@@ -362,7 +367,7 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if branchName != ctx.Repo.BranchName && !canCommit {
|
if branchName == ctx.Repo.BranchName && !canCommit {
|
||||||
ctx.Data["Err_NewBranchName"] = true
|
ctx.Data["Err_NewBranchName"] = true
|
||||||
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.cannot_commit_to_protected_branch", branchName), tplDeleteFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.cannot_commit_to_protected_branch", branchName), tplDeleteFile, &form)
|
||||||
@@ -387,20 +392,20 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
|
// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
|
||||||
if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
|
if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplDeleteFile, &form)
|
||||||
} else if models.IsErrFilenameInvalid(err) {
|
} else if models.IsErrFilenameInvalid(err) {
|
||||||
ctx.Data["Err_TreePath"] = true
|
ctx.Data["Err_TreePath"] = true
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplDeleteFile, &form)
|
||||||
} else if models.IsErrFilePathInvalid(err) {
|
} else if models.IsErrFilePathInvalid(err) {
|
||||||
ctx.Data["Err_TreePath"] = true
|
ctx.Data["Err_TreePath"] = true
|
||||||
if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
|
if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
|
||||||
switch fileErr.Type {
|
switch fileErr.Type {
|
||||||
case git.EntryModeSymlink:
|
case git.EntryModeSymlink:
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplDeleteFile, &form)
|
||||||
case git.EntryModeTree:
|
case git.EntryModeTree:
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplDeleteFile, &form)
|
||||||
case git.EntryModeBlob:
|
case git.EntryModeBlob:
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplDeleteFile, &form)
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("DeleteRepoFile", err)
|
ctx.ServerError("DeleteRepoFile", err)
|
||||||
}
|
}
|
||||||
@@ -410,25 +415,44 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
|
|||||||
} else if git.IsErrBranchNotExist(err) {
|
} else if git.IsErrBranchNotExist(err) {
|
||||||
// For when a user deletes a file to a branch that no longer exists
|
// For when a user deletes a file to a branch that no longer exists
|
||||||
if branchErr, ok := err.(git.ErrBranchNotExist); ok {
|
if branchErr, ok := err.(git.ErrBranchNotExist); ok {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name), tplDeleteFile, &form)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(500, err.Error())
|
ctx.Error(500, err.Error())
|
||||||
}
|
}
|
||||||
} else if models.IsErrBranchAlreadyExists(err) {
|
} else if models.IsErrBranchAlreadyExists(err) {
|
||||||
// For when a user specifies a new branch that already exists
|
// For when a user specifies a new branch that already exists
|
||||||
if branchErr, ok := err.(models.ErrBranchAlreadyExists); ok {
|
if branchErr, ok := err.(models.ErrBranchAlreadyExists); ok {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplDeleteFile, &form)
|
||||||
} else {
|
} else {
|
||||||
ctx.Error(500, err.Error())
|
ctx.Error(500, err.Error())
|
||||||
}
|
}
|
||||||
} else if models.IsErrCommitIDDoesNotMatch(err) {
|
} else if models.IsErrCommitIDDoesNotMatch(err) {
|
||||||
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplEditFile, &form)
|
ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplDeleteFile, &form)
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("DeleteRepoFile", err)
|
ctx.ServerError("DeleteRepoFile", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
|
||||||
|
if form.CommitChoice == frmCommitChoiceNewBranch {
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
|
||||||
} else {
|
} else {
|
||||||
ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
|
treePath := filepath.Dir(ctx.Repo.TreePath)
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName))
|
if treePath == "." {
|
||||||
|
treePath = "" // the file deleted was in the root, so we return the user to the root directory
|
||||||
|
}
|
||||||
|
if len(treePath) > 0 {
|
||||||
|
// Need to get the latest commit since it changed
|
||||||
|
commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName)
|
||||||
|
if err == nil && commit != nil {
|
||||||
|
// We have the comment, now find what directory we can return the user to
|
||||||
|
// (must have entries)
|
||||||
|
treePath = GetClosestParentWithFiles(treePath, commit)
|
||||||
|
} else {
|
||||||
|
treePath = "" // otherwise return them to the root of the repo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(treePath))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +491,7 @@ func UploadFile(ctx *context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
|
||||||
}
|
}
|
||||||
ctx.Data["new_branch_name"] = ""
|
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
|
||||||
|
|
||||||
ctx.HTML(200, tplUploadFile)
|
ctx.HTML(200, tplUploadFile)
|
||||||
}
|
}
|
||||||
@@ -565,7 +589,11 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
|
if form.CommitChoice == frmCommitChoiceNewBranch {
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
|
||||||
|
} else {
|
||||||
|
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanUploadFileName(name string) string {
|
func cleanUploadFileName(name string) string {
|
||||||
@@ -645,3 +673,40 @@ func RemoveUploadFileFromServer(ctx *context.Context, form auth.RemoveUploadFile
|
|||||||
log.Trace("Upload file removed: %s", form.File)
|
log.Trace("Upload file removed: %s", form.File)
|
||||||
ctx.Status(204)
|
ctx.Status(204)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUniquePatchBranchName Gets a unique branch name for a new patch branch
|
||||||
|
// It will be in the form of <username>-patch-<num> where <num> is the first branch of this format
|
||||||
|
// that doesn't already exist. If we exceed 1000 tries or an error is thrown, we just return "" so the user has to
|
||||||
|
// type in the branch name themselves (will be an empty field)
|
||||||
|
func GetUniquePatchBranchName(ctx *context.Context) string {
|
||||||
|
prefix := ctx.User.LowerName + "-patch-"
|
||||||
|
for i := 1; i <= 1000; i++ {
|
||||||
|
branchName := fmt.Sprintf("%s%d", prefix, i)
|
||||||
|
if _, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
|
||||||
|
if git.IsErrBranchNotExist(err) {
|
||||||
|
return branchName
|
||||||
|
}
|
||||||
|
log.Error("GetUniquePatchBranchName: %v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetClosestParentWithFiles Recursively gets the path of parent in a tree that has files (used when file in a tree is
|
||||||
|
// deleted). Returns "" for the root if no parents other than the root have files. If the given treePath isn't a
|
||||||
|
// SubTree or it has no entries, we go up one dir and see if we can return the user to that listing.
|
||||||
|
func GetClosestParentWithFiles(treePath string, commit *git.Commit) string {
|
||||||
|
if len(treePath) == 0 || treePath == "." {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// see if the tree has entries
|
||||||
|
if tree, err := commit.SubTree(treePath); err != nil {
|
||||||
|
// failed to get tree, going up a dir
|
||||||
|
return GetClosestParentWithFiles(filepath.Dir(treePath), commit)
|
||||||
|
} else if entries, err := tree.ListEntries(); err != nil || len(entries) == 0 {
|
||||||
|
// no files in this dir, going up a dir
|
||||||
|
return GetClosestParentWithFiles(filepath.Dir(treePath), commit)
|
||||||
|
}
|
||||||
|
return treePath
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
@@ -37,3 +39,40 @@ func TestCleanUploadName(t *testing.T) {
|
|||||||
assert.EqualValues(t, cleanUploadFileName(k), v)
|
assert.EqualValues(t, cleanUploadFileName(k), v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetUniquePatchBranchName(t *testing.T) {
|
||||||
|
models.PrepareTestEnv(t)
|
||||||
|
ctx := test.MockContext(t, "user2/repo1")
|
||||||
|
ctx.SetParams(":id", "1")
|
||||||
|
test.LoadRepo(t, ctx, 1)
|
||||||
|
test.LoadRepoCommit(t, ctx)
|
||||||
|
test.LoadUser(t, ctx, 2)
|
||||||
|
test.LoadGitRepo(t, ctx)
|
||||||
|
expectedBranchName := "user2-patch-1"
|
||||||
|
branchName := GetUniquePatchBranchName(ctx)
|
||||||
|
assert.Equal(t, expectedBranchName, branchName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetClosestParentWithFiles(t *testing.T) {
|
||||||
|
models.PrepareTestEnv(t)
|
||||||
|
ctx := test.MockContext(t, "user2/repo1")
|
||||||
|
ctx.SetParams(":id", "1")
|
||||||
|
test.LoadRepo(t, ctx, 1)
|
||||||
|
test.LoadRepoCommit(t, ctx)
|
||||||
|
test.LoadUser(t, ctx, 2)
|
||||||
|
test.LoadGitRepo(t, ctx)
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
branch := repo.DefaultBranch
|
||||||
|
gitRepo, _ := git.OpenRepository(repo.RepoPath())
|
||||||
|
commit, _ := gitRepo.GetBranchCommit(branch)
|
||||||
|
expectedTreePath := ""
|
||||||
|
|
||||||
|
expectedTreePath = "" // Should return the root dir, empty string, since there are no subdirs in this repo
|
||||||
|
for _, deletedFile := range []string{
|
||||||
|
"dir1/dir2/dir3/file.txt",
|
||||||
|
"file.txt",
|
||||||
|
} {
|
||||||
|
treePath := GetClosestParentWithFiles(deletedFile, commit)
|
||||||
|
assert.Equal(t, expectedTreePath, treePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -215,7 +215,10 @@ func HTTP(ctx *context.Context) {
|
|||||||
// Check username and password
|
// Check username and password
|
||||||
authUser, err = models.UserSignIn(authUsername, authPasswd)
|
authUser, err = models.UserSignIn(authUsername, authPasswd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !models.IsErrUserNotExist(err) {
|
if models.IsErrUserProhibitLogin(err) {
|
||||||
|
ctx.HandleText(http.StatusForbidden, "User is not permitted to login")
|
||||||
|
return
|
||||||
|
} else if !models.IsErrUserNotExist(err) {
|
||||||
ctx.ServerError("UserSignIn error: %v", err)
|
ctx.ServerError("UserSignIn error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -665,7 +665,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||||||
}, func(ctx *context.Context) {
|
}, func(ctx *context.Context) {
|
||||||
ctx.Data["PageIsSettings"] = true
|
ctx.Data["PageIsSettings"] = true
|
||||||
})
|
})
|
||||||
}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.UnitTypes(), context.RepoRef())
|
}, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef())
|
||||||
|
|
||||||
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
|
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
{{template "base/footer_content" .}}
|
{{template "base/footer_content" .}}
|
||||||
|
|
||||||
<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js"></script>
|
<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1"></script>
|
||||||
|
<script src="{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1"></script>
|
||||||
<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
|
<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
|
||||||
{{if .RequireSimpleMDE}}
|
{{if .RequireSimpleMDE}}
|
||||||
<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script>
|
<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script>
|
||||||
|
|||||||
@@ -17,23 +17,19 @@
|
|||||||
|
|
||||||
<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
|
<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
|
||||||
<span class="inline required field"><label for="visibility">{{.i18n.Tr "org.settings.visibility"}}</label></span>
|
<span class="inline required field"><label for="visibility">{{.i18n.Tr "org.settings.visibility"}}</label></span>
|
||||||
<div class="ui radio checkbox">
|
<div class="inline-grouped-list">
|
||||||
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="0" {{if .DefaultOrgVisibilityMode.IsPublic}}checked{{end}}/>
|
<div class="ui radio checkbox">
|
||||||
<label>{{.i18n.Tr "org.settings.visibility.public"}}</label>
|
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="0" {{if .DefaultOrgVisibilityMode.IsPublic}}checked{{end}}/>
|
||||||
</div>
|
<label>{{.i18n.Tr "org.settings.visibility.public"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
|
<div class="ui radio checkbox">
|
||||||
<label> </label>
|
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="1" {{if .DefaultOrgVisibilityMode.IsLimited}}checked{{end}}/>
|
||||||
<div class="ui radio checkbox">
|
<label>{{.i18n.Tr "org.settings.visibility.limited"}}</label>
|
||||||
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="1" {{if .DefaultOrgVisibilityMode.IsLimited}}checked{{end}}/>
|
</div>
|
||||||
<label>{{.i18n.Tr "org.settings.visibility.limited"}}</label>
|
<div class="ui radio checkbox">
|
||||||
</div>
|
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="2" {{if .DefaultOrgVisibilityMode.IsPrivate}}checked{{end}}/>
|
||||||
</div>
|
<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
|
||||||
<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
|
</div>
|
||||||
<label> </label>
|
|
||||||
<div class="ui radio checkbox">
|
|
||||||
<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="2" {{if .DefaultOrgVisibilityMode.IsPrivate}}checked{{end}}/>
|
|
||||||
<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ var STATIC_CACHE = 'static-cache-v1';
|
|||||||
var urlsToCache = [
|
var urlsToCache = [
|
||||||
// js
|
// js
|
||||||
'{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js',
|
'{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js',
|
||||||
'{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js',
|
'{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1',
|
||||||
|
'{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1',
|
||||||
'{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js',
|
'{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js',
|
||||||
'{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}',
|
'{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}',
|
||||||
'{{AppSubUrl}}/js/draw.js',
|
'{{AppSubUrl}}/js/draw.js',
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
<h4 class="ui top attached header" id="repo-read-file">
|
<h4 class="ui top attached header" id="repo-read-file">
|
||||||
<div class="ui stackable grid">
|
<div class="ui stackable grid">
|
||||||
<div class="ten wide column">
|
<div class="eight wide column">
|
||||||
<i class="file text outline icon ui left"></i>
|
<i class="file text outline icon ui left"></i>
|
||||||
<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
|
<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="six wide right aligned column">
|
<div class="eight wide right aligned column">
|
||||||
<div class="ui right file-actions">
|
<div class="ui right file-actions">
|
||||||
<div class="ui buttons">
|
<div class="ui buttons">
|
||||||
{{if not .IsViewCommit}}
|
{{if not .IsViewCommit}}
|
||||||
@@ -48,4 +48,4 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user