mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-21 09:31:19 +02:00
Compare commits
82 Commits
0d00ec7eed
...
v1.9.3
Author | SHA1 | Date | |
---|---|---|---|
|
2f71571305 | ||
|
a182a80f7c | ||
|
89c57487cd | ||
|
bb609cacee | ||
|
e7f6da386f | ||
|
7727f84fe8 | ||
|
5d2676089e | ||
|
9bea8d825b | ||
|
3cc728870a | ||
|
0793b5e9c0 | ||
|
bb423f9350 | ||
|
4d6c8d9b13 | ||
|
b6b1560701 | ||
|
30dbddcc4d | ||
|
c491c22279 | ||
|
5649f0d2b3 | ||
|
7dd726faeb | ||
|
14c979c1b2 | ||
|
6b84a1d72b | ||
|
68424eddf0 | ||
|
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 |
164
.drone.yml
164
.drone.yml
@@ -114,6 +114,17 @@ steps:
|
||||
- push
|
||||
- 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
|
||||
pull: always
|
||||
image: golang:1.12
|
||||
@@ -122,7 +133,7 @@ steps:
|
||||
environment:
|
||||
TAGS: bindata
|
||||
depends_on:
|
||||
- build
|
||||
- tag-pre-condition
|
||||
when:
|
||||
event:
|
||||
- tag
|
||||
@@ -351,7 +362,7 @@ steps:
|
||||
|
||||
- name: static
|
||||
pull: always
|
||||
image: techknowlogick/xgo:latest
|
||||
image: techknowlogick/xgo:go-1.12.x
|
||||
commands:
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make generate
|
||||
@@ -442,7 +453,6 @@ trigger:
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
- translations
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
@@ -453,7 +463,7 @@ steps:
|
||||
|
||||
- name: static
|
||||
pull: always
|
||||
image: techknowlogick/xgo:latest
|
||||
image: techknowlogick/xgo:go-1.12.x
|
||||
commands:
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make generate
|
||||
@@ -548,7 +558,7 @@ steps:
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker
|
||||
name: docker-linux-amd64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
@@ -558,6 +568,15 @@ workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
- "refs/pull/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
@@ -571,56 +590,121 @@ steps:
|
||||
|
||||
- name: dryrun
|
||||
pull: always
|
||||
image: plugins/docker:18.09
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
cache_from: gitea/gitea
|
||||
dry_run: true
|
||||
repo: gitea/gitea
|
||||
tags: linux-amd64
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: release
|
||||
- name: publish
|
||||
pull: always
|
||||
image: plugins/docker:18.09
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
cache_from: gitea/gitea
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
repo: gitea/gitea
|
||||
tags:
|
||||
- "${DRONE_BRANCH##release/v}"
|
||||
environment:
|
||||
DOCKER_PASSWORD:
|
||||
password:
|
||||
from_secret: docker_password
|
||||
DOCKER_USERNAME:
|
||||
username:
|
||||
from_secret: docker_username
|
||||
depends_on:
|
||||
- dryrun
|
||||
when:
|
||||
branch:
|
||||
- "release/*"
|
||||
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
|
||||
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-linux-arm64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
- "refs/pull/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
pull: default
|
||||
image: docker:git
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
when:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: dryrun
|
||||
pull: always
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
dry_run: true
|
||||
repo: gitea/gitea
|
||||
tags: linux-arm64
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
|
||||
- name: publish
|
||||
pull: always
|
||||
image: plugins/docker:linux-arm64
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
repo: gitea/gitea
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker-manifest
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: manifest
|
||||
pull: always
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
spec: docker/manifest.tmpl
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- refs/heads/master
|
||||
- "refs/tags/**"
|
||||
|
||||
depends_on:
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
@@ -644,7 +728,9 @@ depends_on:
|
||||
- translations
|
||||
- release-version
|
||||
- release-master
|
||||
- docker
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
- docker-manifest
|
||||
- docs
|
||||
|
||||
steps:
|
||||
|
100
CHANGELOG.md
100
CHANGELOG.md
@@ -4,9 +4,71 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.9.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.9.0-rc1) - 2019-07-06
|
||||
## [1.9.3](https://github.com/go-gitea/gitea/releases/tag/v1.9.3) - 2019-09-06
|
||||
* BUGFIXES
|
||||
* Fix go get from a private repository with Go 1.13 (#8100)
|
||||
* Strict name matching for Repository.GetTagID() (#8082)
|
||||
* Avoid ambiguity of branch/directory names for the git-diff-tree command (#8070)
|
||||
* Add change title notification for issues (#8064)
|
||||
* Run CORS handler first for /api routes (#7967) (#8053)
|
||||
* Evaluate emojis in commit messages in list view (#8044)
|
||||
* Fix failed to synchronize tags to releases for repository (#7990) (#7994)
|
||||
* Fix adding default Telegram webhook (#7972) (#7992)
|
||||
* Abort synchronization from LDAP source if there is some error (#7965)
|
||||
* Fix deformed emoji in commit message (#8071)
|
||||
* ENHANCEMENT
|
||||
* Keep blame view buttons sequence consistent with normal view when viewing a file (#8007) (#8009)
|
||||
|
||||
## [1.9.2](https://github.com/go-gitea/gitea/releases/tag/v1.9.2) - 2019-08-22
|
||||
* BUGFIXES
|
||||
* Fix wrong sender when send slack webhook (#7918) (#7924)
|
||||
* Upload support text/plain; charset=utf8 (#7899)
|
||||
* Lfs/lock: round locked_at timestamp to second (#7872) (#7875)
|
||||
* Fix non existent milestone with 500 error (#7867) (#7873)
|
||||
* SECURITY
|
||||
* Fix No PGP signature on 1.9.1 tag (#7874)
|
||||
* Release built with go 1.12.9 to fix security fixes in golang std lib, ref: https://groups.google.com/forum/#!msg/golang-announce/oeMaeUnkvVE/a49yvTLqAAAJ
|
||||
* ENHANCEMENT
|
||||
* Fix pull creation with empty changes (#7920) (#7926)
|
||||
* BUILD
|
||||
* Drone/docker: prepare multi-arch release + provide arm64 image (#7571) (#7884)
|
||||
|
||||
## [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
|
||||
* 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
|
||||
* Content API for Creating, Updating, Deleting Files (#6314)
|
||||
* Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
|
||||
@@ -29,6 +91,39 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Implement Default Webhooks (#4299)
|
||||
* Telegram webhook (#4227)
|
||||
* 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)
|
||||
* Handle early git version's lack of get-url (#7065)
|
||||
* Fix icon position in issue view (#7354)
|
||||
@@ -166,6 +261,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Disable benchmarking during tag events on DroneIO (#6365)
|
||||
* Comments list performance optimization (#5305)
|
||||
* ENHANCEMENT
|
||||
* Update Drone docker generation to standard format (#7480) (#7496) (#7504)
|
||||
* Add API Endpoint for Repo Edit (#7006)
|
||||
* Add state param to milestone listing API (#7131)
|
||||
* Make captcha and password optional for external accounts (#6606)
|
||||
@@ -285,8 +381,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
* Refactor: append, build variable and type switch (#4940)
|
||||
* Git statistics in Activity tab (#4724)
|
||||
* Drop the bits argument when generating an ed25519 key (#6504)
|
||||
* SECURITY
|
||||
* Shadow the password on cache and session config on admin panel (#7300)
|
||||
* TESTING
|
||||
* Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
|
||||
* Refactor and improve git test (#7086)
|
||||
|
@@ -96,6 +96,7 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
UserID: userID,
|
||||
GitAlternativeObjectDirectories: os.Getenv(private.GitAlternativeObjectDirectories),
|
||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||
ProtectedBranchID: prID,
|
||||
})
|
||||
switch statusCode {
|
||||
|
@@ -73,7 +73,6 @@ func fail(userMessage, logMessage string, args ...interface{}) {
|
||||
if !setting.ProdMode {
|
||||
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
|
19
docker/manifest.tmpl
vendored
Normal file
19
docker/manifest.tmpl
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
4
go.mod
4
go.mod
@@ -45,7 +45,7 @@ require (
|
||||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect
|
||||
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443
|
||||
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/csrf v0.0.0-20180426211211-503617c6b372
|
||||
github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
|
||||
@@ -135,4 +135,4 @@ require (
|
||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
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-20180314172330-6a30f4e59a44/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44 h1:DWxZh2sImfCFn/79OUBhzFkPTKnsdDzXH/JTxpw5n6w=
|
||||
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/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
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/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/captcha v0.0.0-20151123225153-8aa5919789ab h1:4VFhsA3GE5Wwq1Ymr8KWCmrOWi1wRLEgdj48LPfQjxI=
|
||||
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 h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78=
|
||||
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/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
|
||||
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=
|
||||
|
@@ -104,8 +104,11 @@ func TestAPILFSLocksLogged(t *testing.T) {
|
||||
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks", test.repo.FullName()), map[string]string{"path": test.path})
|
||||
req.Header.Set("Accept", "application/vnd.git-lfs+json")
|
||||
req.Header.Set("Content-Type", "application/vnd.git-lfs+json")
|
||||
session.MakeRequest(t, req, test.httpResult)
|
||||
resp := session.MakeRequest(t, req, test.httpResult)
|
||||
if len(test.addTime) > 0 {
|
||||
var lfsLock api.LFSLockResponse
|
||||
DecodeJSON(t, resp, &lfsLock)
|
||||
assert.EqualValues(t, lfsLock.Lock.LockedAt.Format(time.RFC3339), lfsLock.Lock.LockedAt.Format(time.RFC3339Nano)) //locked at should be rounded to second
|
||||
for _, id := range test.addTime {
|
||||
resultsTests[id].locksTimes = append(resultsTests[id].locksTimes, time.Now())
|
||||
}
|
||||
@@ -124,6 +127,7 @@ func TestAPILFSLocksLogged(t *testing.T) {
|
||||
for i, lock := range lfsLocks.Locks {
|
||||
assert.EqualValues(t, test.locksOwners[i].DisplayName(), lock.Owner.Name)
|
||||
assert.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 3*time.Second)
|
||||
assert.EqualValues(t, lock.LockedAt.Format(time.RFC3339), lock.LockedAt.Format(time.RFC3339Nano)) //locked at should be rounded to second
|
||||
}
|
||||
|
||||
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks/verify", test.repo.FullName()), map[string]string{})
|
||||
|
@@ -24,20 +24,24 @@ import (
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
//Setup ssh wrapper
|
||||
os.Setenv("GIT_SSH_COMMAND",
|
||||
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "+
|
||||
filepath.Join(setting.AppWorkPath, keyFile))
|
||||
"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\"")
|
||||
os.Setenv("GIT_SSH_VARIANT", "ssh")
|
||||
|
||||
callback(keyFile)
|
||||
|
||||
defer os.RemoveAll(keyFile)
|
||||
defer os.RemoveAll(keyFile + ".pub")
|
||||
}
|
||||
|
||||
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) {
|
||||
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")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
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), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
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) {
|
||||
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")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
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), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
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) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||
assert.NoError(t, err)
|
||||
hookTasksLenBefore := len(hookTasks)
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
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), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
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) {
|
||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
hookTasks, err := models.HookTasks(1, 1) //Retrieve previous hook number
|
||||
assert.NoError(t, err)
|
||||
hookTasksLenBefore := len(hookTasks)
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
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), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
@@ -93,3 +94,28 @@ func TestPullCreate_CommitStatus(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPullCreate_EmptyChangesWithCommits(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "status1", "README.md", "status1")
|
||||
testEditFileToNewBranch(t, session, "user1", "repo1", "status1", "status1", "README.md", "# repo1\n\nDescription for repo1")
|
||||
|
||||
url := path.Join("user1", "repo1", "compare", "master...status1")
|
||||
req := NewRequestWithValues(t, "POST", url,
|
||||
map[string]string{
|
||||
"_csrf": GetCSRF(t, session, url),
|
||||
"title": "pull request from status1",
|
||||
},
|
||||
)
|
||||
session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
req = NewRequest(t, "GET", "/user1/repo1/pulls/1")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
text := strings.TrimSpace(doc.doc.Find(".item.text.green").Text())
|
||||
assert.EqualValues(t, "This pull request can be merged automatically.", text)
|
||||
})
|
||||
}
|
||||
|
@@ -5,10 +5,13 @@
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -67,6 +70,29 @@ func doTestRepoCommitWithStatus(t *testing.T, state string, classes ...string) {
|
||||
for _, class := range classes {
|
||||
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) {
|
||||
|
@@ -65,6 +65,7 @@ var (
|
||||
)
|
||||
|
||||
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 {
|
||||
return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
|
||||
@@ -73,7 +74,7 @@ func assembleKeywordsPattern(words []string) string {
|
||||
func init() {
|
||||
issueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueCloseKeywords))
|
||||
issueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueReopenKeywords))
|
||||
issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStr)
|
||||
issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStrNoKeyword)
|
||||
}
|
||||
|
||||
// Action represents user operation type and other information to
|
||||
|
@@ -155,6 +155,25 @@ func TestPushCommits_AvatarLink(t *testing.T) {
|
||||
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) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
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.
|
||||
func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 {
|
||||
reviews, err := GetReviewersByPullID(pr.Issue.ID)
|
||||
reviews, err := GetReviewersByPullID(pr.IssueID)
|
||||
if err != nil {
|
||||
log.Error("GetReviewersByPullID: %v", err)
|
||||
return 0
|
||||
|
@@ -87,7 +87,7 @@ func (status *CommitStatus) loadRepo(e Engine) (err error) {
|
||||
// APIURL returns the absolute APIURL to this commit-status.
|
||||
func (status *CommitStatus) APIURL() string {
|
||||
_ = 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)
|
||||
}
|
||||
|
||||
|
@@ -19,20 +19,25 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||
|
||||
statuses, err := GetCommitStatuses(repo1, sha1, 0)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, statuses, 5) {
|
||||
assert.Equal(t, statuses[0].Context, "ci/awesomeness")
|
||||
assert.Equal(t, statuses[0].State, CommitStatusPending)
|
||||
assert.Len(t, statuses, 5)
|
||||
|
||||
assert.Equal(t, statuses[1].Context, "cov/awesomeness")
|
||||
assert.Equal(t, statuses[1].State, CommitStatusWarning)
|
||||
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
||||
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, statuses[2].State, CommitStatusSuccess)
|
||||
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
|
||||
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, statuses[3].State, CommitStatusFailure)
|
||||
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
|
||||
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, statuses[4].State, CommitStatusError)
|
||||
}
|
||||
assert.Equal(t, "ci/awesomeness", statuses[3].Context)
|
||||
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
|
||||
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
|
||||
func FullPushingEnvironment(author, committer *User, repo *Repository, prID int64) []string {
|
||||
func FullPushingEnvironment(author, committer *User, repo *Repository, repoName string, prID int64) []string {
|
||||
isWiki := "false"
|
||||
if strings.HasSuffix(repo.Name, ".wiki") {
|
||||
if strings.HasSuffix(repoName, ".wiki") {
|
||||
isWiki = "true"
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func FullPushingEnvironment(author, committer *User, repo *Repository, prID int6
|
||||
"GIT_AUTHOR_EMAIL="+authorSig.Email,
|
||||
"GIT_COMMITTER_NAME="+committerSig.Name,
|
||||
"GIT_COMMITTER_EMAIL="+committerSig.Email,
|
||||
EnvRepoName+"="+repo.Name,
|
||||
EnvRepoName+"="+repoName,
|
||||
EnvRepoUsername+"="+repo.MustOwnerName(),
|
||||
EnvRepoIsWiki+"="+isWiki,
|
||||
EnvPusherName+"="+committer.Name,
|
||||
|
@@ -1835,3 +1835,22 @@ func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
|
||||
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
|
||||
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 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) {
|
||||
|
||||
// Update the assignee
|
||||
removed, err := updateIssueAssignee(sess, issue, assigneeID)
|
||||
if err != nil {
|
||||
@@ -209,7 +213,6 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
|
||||
return nil
|
||||
}
|
||||
}
|
||||
go HookQueue.Add(issue.RepoID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -632,12 +632,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
|
||||
act.OpType = ActionReopenPullRequest
|
||||
}
|
||||
|
||||
if opts.Issue.IsPull {
|
||||
_, 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 {
|
||||
if err = opts.Issue.updateClosedNum(e); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -647,12 +642,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
|
||||
act.OpType = ActionClosePullRequest
|
||||
}
|
||||
|
||||
if opts.Issue.IsPull {
|
||||
_, 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 {
|
||||
if err = opts.Issue.updateClosedNum(e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -56,7 +56,7 @@ func (l *LFSLock) APIFormat() *api.LFSLock {
|
||||
return &api.LFSLock{
|
||||
ID: strconv.FormatInt(l.ID, 10),
|
||||
Path: l.Path,
|
||||
LockedAt: l.Created,
|
||||
LockedAt: l.Created.Round(time.Second),
|
||||
Owner: &api.LFSLockOwner{
|
||||
Name: l.Owner.DisplayName(),
|
||||
},
|
||||
|
@@ -62,38 +62,50 @@ func insertIssue(sess *xorm.Session, issue *Issue) error {
|
||||
if _, err := sess.Insert(issueLabels); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cols := make([]string, 0)
|
||||
if !issue.IsPull {
|
||||
sess.ID(issue.RepoID).Incr("num_issues")
|
||||
cols = append(cols, "num_issues")
|
||||
if issue.IsClosed {
|
||||
sess.Incr("num_closed_issues")
|
||||
cols = append(cols, "num_closed_issues")
|
||||
}
|
||||
} else {
|
||||
sess.ID(issue.RepoID).Incr("num_pulls")
|
||||
cols = append(cols, "num_pulls")
|
||||
if issue.IsClosed {
|
||||
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
|
||||
}
|
||||
|
||||
cols = []string{"num_issues"}
|
||||
sess.Incr("num_issues")
|
||||
if issue.IsClosed {
|
||||
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
|
||||
}
|
||||
|
||||
if issue.MilestoneID > 0 {
|
||||
cols = []string{"num_issues"}
|
||||
sess.Incr("num_issues")
|
||||
cl := "num_closed_issues"
|
||||
if issue.IsClosed {
|
||||
sess.Incr("num_closed_issues")
|
||||
cols = append(cols, "num_closed_issues")
|
||||
cl = "(num_closed_issues + 1)"
|
||||
}
|
||||
|
||||
if _, err := sess.ID(issue.MilestoneID).
|
||||
SetExpr("completeness", "num_closed_issues * 100 / num_issues").
|
||||
NoAutoTime().
|
||||
SetExpr("completeness", cl+" * 100 / (num_issues + 1)").
|
||||
NoAutoTime().Cols(cols...).
|
||||
Update(new(Milestone)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -321,11 +321,25 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
|
||||
return err
|
||||
}
|
||||
tableSQL := string(res[0]["sql"])
|
||||
|
||||
// Separate out the column definitions
|
||||
tableSQL = tableSQL[strings.Index(tableSQL, "("):]
|
||||
|
||||
// Remove the required 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)
|
||||
|
||||
tableSQL = fmt.Sprintf("CREATE TABLE `new_%s_new` ", tableName) + tableSQL
|
||||
|
@@ -5,13 +5,7 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
"xorm.io/core"
|
||||
)
|
||||
|
||||
func renameRepoIsBareToIsEmpty(x *xorm.Engine) error {
|
||||
@@ -21,73 +15,28 @@ func renameRepoIsBareToIsEmpty(x *xorm.Engine) error {
|
||||
IsEmpty bool `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
// First remove the index
|
||||
sess := x.NewSession()
|
||||
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 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 {
|
||||
return err
|
||||
}
|
||||
if _, err := sess.Exec("UPDATE repository SET is_empty = is_bare;"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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 {
|
||||
if err := sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if models.DbCfg.Type == core.SQLITE {
|
||||
log.Warn("TABLE repository's COLUMN is_bare should be DROP but sqlite is not supported, you could manually do that.")
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
if err := dropTableColumns(sess, "repository", "is_bare"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
@@ -8,9 +8,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
"xorm.io/core"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/generate"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
@@ -37,41 +35,6 @@ func hashAppToken(x *xorm.Engine) error {
|
||||
// First remove the index
|
||||
sess := x.NewSession()
|
||||
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 {
|
||||
return err
|
||||
@@ -81,7 +44,7 @@ func hashAppToken(x *xorm.Engine) error {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
if err := sess.Commit(); err != nil {
|
||||
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
|
||||
func UsersInTeamsCount(userIDs []int64, teamIDs []int64) (count int64, err error) {
|
||||
if count, err = x.In("uid", userIDs).In("team_id", teamIDs).Count(new(TeamUser)); err != nil {
|
||||
func UsersInTeamsCount(userIDs []int64, teamIDs []int64) (int64, error) {
|
||||
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
|
||||
return int64(len(ids)), nil
|
||||
}
|
||||
|
||||
// ___________ __________
|
||||
|
@@ -370,7 +370,7 @@ func TestUsersInTeamsCount(t *testing.T) {
|
||||
assert.Equal(t, expected, count)
|
||||
}
|
||||
|
||||
test([]int64{2}, []int64{1, 2, 3, 4}, 2)
|
||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2)
|
||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3)
|
||||
test([]int64{2}, []int64{1, 2, 3, 4}, 1) // only userid 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) // userid 2,4,5
|
||||
}
|
||||
|
107
models/pull.go
107
models/pull.go
@@ -189,36 +189,6 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
||||
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 {
|
||||
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{
|
||||
ID: pr.ID,
|
||||
URL: pr.Issue.HTMLURL(),
|
||||
Index: pr.Index,
|
||||
Poster: apiIssue.Poster,
|
||||
Title: apiIssue.Title,
|
||||
@@ -241,13 +212,68 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
|
||||
DiffURL: pr.Issue.DiffURL(),
|
||||
PatchURL: pr.Issue.PatchURL(),
|
||||
HasMerged: pr.HasMerged,
|
||||
Base: apiBaseBranchInfo,
|
||||
Head: apiHeadBranchInfo,
|
||||
MergeBase: pr.MergeBase,
|
||||
Deadline: apiIssue.Deadline,
|
||||
Created: pr.Issue.CreatedUnix.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 {
|
||||
mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
|
||||
@@ -572,7 +598,7 @@ func (pr *PullRequest) testPatch(e Engine) (err error) {
|
||||
if err != nil {
|
||||
for i := range patchConflicts {
|
||||
if strings.Contains(stderr, patchConflicts[i]) {
|
||||
log.Trace("PullRequest[%d].testPatch (apply): has conflict", pr.ID)
|
||||
log.Trace("PullRequest[%d].testPatch (apply): has conflict: %s", pr.ID, stderr)
|
||||
const prefix = "error: patch failed:"
|
||||
pr.Status = PullRequestStatusConflict
|
||||
pr.ConflictedFiles = make([]string, 0, 5)
|
||||
@@ -635,13 +661,16 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
||||
}
|
||||
|
||||
pr.Index = pull.Index
|
||||
if err = repo.savePatch(sess, pr.Index, patch); err != nil {
|
||||
return fmt.Errorf("SavePatch: %v", err)
|
||||
}
|
||||
|
||||
pr.BaseRepo = repo
|
||||
if err = pr.testPatch(sess); err != nil {
|
||||
return fmt.Errorf("testPatch: %v", err)
|
||||
pr.Status = PullRequestStatusChecking
|
||||
if len(patch) > 0 {
|
||||
if err = repo.savePatch(sess, pr.Index, patch); err != nil {
|
||||
return fmt.Errorf("SavePatch: %v", err)
|
||||
}
|
||||
|
||||
if err = pr.testPatch(sess); err != nil {
|
||||
return fmt.Errorf("testPatch: %v", err)
|
||||
}
|
||||
}
|
||||
// No conflict appears after test means mergeable.
|
||||
if pr.Status == PullRequestStatusChecking {
|
||||
|
@@ -31,7 +31,15 @@ func TestPullRequest_LoadIssue(t *testing.T) {
|
||||
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) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
@@ -409,7 +409,7 @@ func UpdateRelease(doer *User, gitRepo *git.Repository, rel *Release, attachment
|
||||
Action: api.HookReleaseUpdated,
|
||||
Release: rel.APIFormat(),
|
||||
Repository: rel.Repo.APIFormat(mode),
|
||||
Sender: rel.Publisher.APIFormat(),
|
||||
Sender: doer.APIFormat(),
|
||||
}); err1 != nil {
|
||||
log.Error("PrepareWebhooks: %v", err)
|
||||
} else {
|
||||
@@ -420,7 +420,7 @@ func UpdateRelease(doer *User, gitRepo *git.Repository, rel *Release, attachment
|
||||
}
|
||||
|
||||
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
|
||||
func DeleteReleaseByID(id int64, u *User, delTag bool) error {
|
||||
func DeleteReleaseByID(id int64, doer *User, delTag bool) error {
|
||||
rel, err := GetReleaseByID(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetReleaseByID: %v", err)
|
||||
@@ -459,12 +459,12 @@ func DeleteReleaseByID(id int64, u *User, delTag bool) error {
|
||||
return fmt.Errorf("LoadAttributes: %v", err)
|
||||
}
|
||||
|
||||
mode, _ := AccessLevel(u, rel.Repo)
|
||||
mode, _ := AccessLevel(doer, rel.Repo)
|
||||
if err := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{
|
||||
Action: api.HookReleaseDeleted,
|
||||
Release: rel.APIFormat(),
|
||||
Repository: rel.Repo.APIFormat(mode),
|
||||
Sender: rel.Publisher.APIFormat(),
|
||||
Sender: doer.APIFormat(),
|
||||
}); err != nil {
|
||||
log.Error("PrepareWebhooks: %v", err)
|
||||
} else {
|
||||
|
@@ -134,8 +134,8 @@ type Repository struct {
|
||||
Owner *User `xorm:"-"`
|
||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"INDEX NOT NULL"`
|
||||
Description string
|
||||
Website string
|
||||
Description string `xorm:"TEXT"`
|
||||
Website string `xorm:"VARCHAR(2048)"`
|
||||
DefaultBranch string
|
||||
|
||||
NumWatches int
|
||||
@@ -1324,7 +1324,6 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
|
||||
}); err != nil {
|
||||
return fmt.Errorf("prepareWebhooks: %v", err)
|
||||
}
|
||||
go HookQueue.Add(repo.ID)
|
||||
} else if err = repo.recalculateAccesses(e); err != nil {
|
||||
// Organization automatically called this in addRepository method.
|
||||
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 {
|
||||
@@ -1783,6 +1791,7 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
|
||||
&HookTask{RepoID: repoID},
|
||||
&Notification{RepoID: repoID},
|
||||
&CommitStatus{RepoID: repoID},
|
||||
&RepoIndexerStatus{RepoID: repoID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
@@ -2327,6 +2336,23 @@ func CheckRepoStats() {
|
||||
}
|
||||
// ***** 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.
|
||||
// ***** 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)")
|
||||
@@ -2461,6 +2487,11 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
|
||||
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 {
|
||||
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 {
|
||||
return fmt.Errorf("Misformatted git cat-file output: %v", err)
|
||||
} else if int64(size) > setting.Indexer.MaxIndexerFileSize {
|
||||
return nil
|
||||
return addDelete(update.Filename, repo, batch)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func isIndexable(entry *git.TreeEntry) bool {
|
||||
return entry.IsRegular() || entry.IsExecutable()
|
||||
}
|
||||
|
||||
// parseGitLsTreeOutput parses the output of a `git ls-tree -r --full-name` command
|
||||
func parseGitLsTreeOutput(stdout []byte) ([]fileUpdate, error) {
|
||||
entries, err := git.ParseTreeEntries(stdout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var idxCount = 0
|
||||
updates := make([]fileUpdate, len(entries))
|
||||
for i, entry := range entries {
|
||||
updates[i] = fileUpdate{
|
||||
Filename: entry.Name(),
|
||||
BlobSha: entry.ID.String(),
|
||||
for _, entry := range entries {
|
||||
if isIndexable(entry) {
|
||||
updates[idxCount] = fileUpdate{
|
||||
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
|
||||
|
@@ -642,12 +642,14 @@ func rewriteAllPublicKeys(e Engine) error {
|
||||
}
|
||||
_, err = t.WriteString(line + "\n")
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer f.Close()
|
||||
f.Close()
|
||||
}
|
||||
|
||||
t.Close()
|
||||
return os.Rename(tmpPath, fPath)
|
||||
}
|
||||
|
||||
|
@@ -195,9 +195,9 @@ func (u *User) UpdateTheme(themeName string) error {
|
||||
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.
|
||||
func (u *User) getEmail() string {
|
||||
func (u *User) GetEmail() string {
|
||||
if u.KeepEmailPrivate {
|
||||
return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress)
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (u *User) APIFormat() *api.User {
|
||||
ID: u.ID,
|
||||
UserName: u.Name,
|
||||
FullName: u.FullName,
|
||||
Email: u.getEmail(),
|
||||
Email: u.GetEmail(),
|
||||
AvatarURL: u.AvatarLink(),
|
||||
Language: u.Language,
|
||||
IsAdmin: u.IsAdmin,
|
||||
@@ -425,7 +425,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) {
|
||||
func (u *User) NewGitSig() *git.Signature {
|
||||
return &git.Signature{
|
||||
Name: u.GitName(),
|
||||
Email: u.getEmail(),
|
||||
Email: u.GetEmail(),
|
||||
When: time.Now(),
|
||||
}
|
||||
}
|
||||
@@ -751,6 +751,7 @@ var (
|
||||
"robots.txt",
|
||||
".",
|
||||
"..",
|
||||
".well-known",
|
||||
}
|
||||
reservedUserPatterns = []string{"*.keys", "*.gpg"}
|
||||
)
|
||||
@@ -1375,9 +1376,7 @@ type SearchUserOptions struct {
|
||||
}
|
||||
|
||||
func (opts *SearchUserOptions) toConds() builder.Cond {
|
||||
|
||||
var cond = builder.NewCond()
|
||||
cond = cond.And(builder.Eq{"type": opts.Type})
|
||||
var cond builder.Cond = builder.Eq{"type": opts.Type}
|
||||
|
||||
if len(opts.Keyword) > 0 {
|
||||
lowerKeyword := strings.ToLower(opts.Keyword)
|
||||
@@ -1646,7 +1645,12 @@ func SyncExternalUsers() {
|
||||
return
|
||||
}
|
||||
|
||||
sr := s.LDAP().SearchEntries()
|
||||
sr, err := s.LDAP().SearchEntries()
|
||||
if err != nil {
|
||||
log.Error("SyncExternalUsers LDAP source failure [%s], skipped", s.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, su := range sr {
|
||||
if len(su.Username) == 0 {
|
||||
continue
|
||||
|
@@ -890,7 +890,6 @@ func DeliverHooks() {
|
||||
for _, t := range tasks {
|
||||
if err = t.deliver(); err != nil {
|
||||
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.
|
||||
func getSlackForkPayload(p *api.ForkPayload, slack *SlackMeta) (*SlackPayload, error) {
|
||||
baseLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
|
||||
forkLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
|
||||
baseLink := 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)
|
||||
return &SlackPayload{
|
||||
Channel: slack.Channel,
|
||||
|
@@ -217,7 +217,13 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
|
||||
if err := git.Push(basePath, git.PushOptions{
|
||||
Remote: "origin",
|
||||
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 {
|
||||
log.Error("%v", err)
|
||||
return fmt.Errorf("Push: %v", err)
|
||||
|
@@ -308,12 +308,12 @@ func (ls *Source) UsePagedSearch() bool {
|
||||
}
|
||||
|
||||
// SearchEntries : search an LDAP source for all users matching userFilter
|
||||
func (ls *Source) SearchEntries() []*SearchResult {
|
||||
func (ls *Source) SearchEntries() ([]*SearchResult, error) {
|
||||
l, err := dial(ls)
|
||||
if err != nil {
|
||||
log.Error("LDAP Connect error, %s:%v", ls.Host, err)
|
||||
ls.Enabled = false
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
@@ -321,7 +321,7 @@ func (ls *Source) SearchEntries() []*SearchResult {
|
||||
err := l.Bind(ls.BindDN, ls.BindPassword)
|
||||
if err != nil {
|
||||
log.Debug("Failed to bind as BindDN[%s]: %v", ls.BindDN, err)
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
log.Trace("Bound as BindDN %s", ls.BindDN)
|
||||
} else {
|
||||
@@ -350,7 +350,7 @@ func (ls *Source) SearchEntries() []*SearchResult {
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("LDAP Search failed unexpectedly! (%v)", err)
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*SearchResult, len(sr.Entries))
|
||||
@@ -368,5 +368,5 @@ func (ls *Source) SearchEntries() []*SearchResult {
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
@@ -249,6 +249,19 @@ func Contexter() macaron.Handler {
|
||||
if ctx.Query("go-get") == "1" {
|
||||
ownerName := c.Params(":username")
|
||||
repoName := c.Params(":reponame")
|
||||
trimmedRepoName := strings.TrimSuffix(repoName, ".git")
|
||||
|
||||
if ownerName == "" || trimmedRepoName == "" {
|
||||
_, _ = c.Write([]byte(`<!doctype html>
|
||||
<html>
|
||||
<body>
|
||||
invalid import path
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
c.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
branchName := "master"
|
||||
|
||||
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
|
||||
@@ -276,7 +289,7 @@ func Contexter() macaron.Handler {
|
||||
</body>
|
||||
</html>
|
||||
`, map[string]string{
|
||||
"GoGetImport": ComposeGoGetImport(ownerName, strings.TrimSuffix(repoName, ".git")),
|
||||
"GoGetImport": ComposeGoGetImport(ownerName, trimmedRepoName),
|
||||
"CloneLink": models.ComposeHTTPSCloneURL(ownerName, repoName),
|
||||
"GoDocDirectory": prefix + "{/dir}",
|
||||
"GoDocFile": prefix + "{/dir}/{file}#L{line}",
|
||||
|
@@ -201,10 +201,14 @@ func ComposeGoGetImport(owner, repo string) string {
|
||||
// .netrc file.
|
||||
func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||
username := ctx.Params(":username")
|
||||
reponame := ctx.Params(":reponame")
|
||||
reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
|
||||
if username == "" || reponame == "" {
|
||||
ctx.PlainText(400, []byte("invalid repository path"))
|
||||
return
|
||||
}
|
||||
ctx.PlainText(200, []byte(com.Expand(`<meta name="go-import" content="{GoGetImport} git {CloneLink}">`,
|
||||
map[string]string{
|
||||
"GoGetImport": ComposeGoGetImport(username, strings.TrimSuffix(reponame, ".git")),
|
||||
"GoGetImport": ComposeGoGetImport(username, reponame),
|
||||
"CloneLink": models.ComposeHTTPSCloneURL(username, reponame),
|
||||
})))
|
||||
}
|
||||
|
@@ -169,6 +169,7 @@ func AddChanges(repoPath string, all bool, files ...string) error {
|
||||
if all {
|
||||
cmd.AddArguments("--all")
|
||||
}
|
||||
cmd.AddArguments("--")
|
||||
_, err := cmd.AddArguments(files...).RunInDir(repoPath)
|
||||
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
|
||||
// YOU MUST ENSURE THAT pastCommit is a valid commit ID.
|
||||
func (c *Commit) FileChangedSinceCommit(filename, pastCommit string) (bool, error) {
|
||||
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
|
||||
// pages to display information about newest commit for a given path.
|
||||
var treeCommit *Commit
|
||||
if rev, ok := revs[""]; ok {
|
||||
if treePath == "" {
|
||||
treeCommit = commit
|
||||
} else if rev, ok := revs[""]; ok {
|
||||
treeCommit = convertCommit(rev)
|
||||
}
|
||||
return commitsInfo, treeCommit, nil
|
||||
|
@@ -28,21 +28,27 @@ func cloneRepo(url, dir, name string) (string, error) {
|
||||
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
|
||||
// these test case are specific to the repo1 test repo
|
||||
testCases := []struct {
|
||||
CommitID string
|
||||
Path string
|
||||
ExpectedIDs map[string]string
|
||||
CommitID string
|
||||
Path string
|
||||
ExpectedIDs map[string]string
|
||||
ExpectedTreeCommit string
|
||||
}{
|
||||
{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
|
||||
"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
|
||||
"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||
}},
|
||||
}, "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2"},
|
||||
{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
|
||||
"file1.txt": "2839944139e0de9737a044f78b0e4b40d989a9e3",
|
||||
"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
|
||||
}},
|
||||
}, "2839944139e0de9737a044f78b0e4b40d989a9e3"},
|
||||
{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
|
||||
"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
|
||||
}},
|
||||
}, "5c80b0245c1c6f8343fa418ec374b13b5d4ee658"},
|
||||
{"feaf4ba6bc635fec442f46ddd4512416ec43c2c2", "", map[string]string{
|
||||
"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
|
||||
"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
|
||||
"foo": "37991dec2c8e592043f47155ce4808d4580f9123",
|
||||
}, "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
commit, err := repo1.GetCommit(testCase.CommitID)
|
||||
@@ -51,7 +57,8 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
|
||||
assert.NoError(t, err)
|
||||
entries, err := tree.ListEntries()
|
||||
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.Len(t, commitsInfo, len(testCase.ExpectedIDs))
|
||||
for _, commitInfo := range commitsInfo {
|
||||
|
@@ -187,8 +187,7 @@ func Pull(repoPath string, opts PullRemoteOptions) error {
|
||||
if opts.All {
|
||||
cmd.AddArguments("--all")
|
||||
} else {
|
||||
cmd.AddArguments(opts.Remote)
|
||||
cmd.AddArguments(opts.Branch)
|
||||
cmd.AddArguments("--", opts.Remote, opts.Branch)
|
||||
}
|
||||
|
||||
if opts.Timeout <= 0 {
|
||||
@@ -213,7 +212,7 @@ func Push(repoPath string, opts PushOptions) error {
|
||||
if opts.Force {
|
||||
cmd.AddArguments("-f")
|
||||
}
|
||||
cmd.AddArguments(opts.Remote, opts.Branch)
|
||||
cmd.AddArguments("--", opts.Remote, opts.Branch)
|
||||
_, err := cmd.RunInDirWithEnv(repoPath, opts.Env)
|
||||
return err
|
||||
}
|
||||
|
@@ -135,7 +135,7 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
|
||||
cmd.AddArguments("-d")
|
||||
}
|
||||
|
||||
cmd.AddArguments(name)
|
||||
cmd.AddArguments("--", name)
|
||||
_, err := cmd.RunInDir(repo.Path)
|
||||
|
||||
return err
|
||||
|
@@ -117,20 +117,26 @@ func (repo *Repository) getCommit(id SHA1) (*Commit, error) {
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
// GetCommit returns commit object of by ID string.
|
||||
func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
|
||||
// ConvertToSHA1 returns a Hash object from a potential ID string
|
||||
func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
|
||||
if len(commitID) != 40 {
|
||||
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 strings.Contains(err.Error(), "unknown revision or path") {
|
||||
return nil, ErrNotExist{commitID, ""}
|
||||
if strings.Contains(err.Error(), "unknown revision or path") ||
|
||||
strings.Contains(err.Error(), "fatal: Needed a single revision") {
|
||||
return SHA1{}, ErrNotExist{commitID, ""}
|
||||
}
|
||||
return nil, err
|
||||
return SHA1{}, err
|
||||
}
|
||||
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 {
|
||||
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
|
||||
// You must ensure that id1 and id2 are valid commit ids.
|
||||
func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) {
|
||||
stdout, err := NewCommand("diff", "--name-only", "-z", id1, id2, "--", filename).RunInDirBytes(repo.Path)
|
||||
if err != nil {
|
||||
|
@@ -55,5 +55,5 @@ func TestGetCommitWithBadCommitID(t *testing.T) {
|
||||
commit, err := bareRepo1.GetCommit("bad_branch")
|
||||
assert.Nil(t, commit)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string)
|
||||
if repo.Path != basePath {
|
||||
// Add a temporary remote
|
||||
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)
|
||||
}
|
||||
defer func() {
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
// ReadTreeToIndex reads a treeish to the index
|
||||
func (repo *Repository) ReadTreeToIndex(treeish string) error {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
@@ -23,12 +23,12 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, code)
|
||||
|
||||
assert.EqualValues(t, 8, code.CommitCount)
|
||||
assert.EqualValues(t, 2, code.AuthorCount)
|
||||
assert.EqualValues(t, 8, code.CommitCountInAllBranches)
|
||||
assert.EqualValues(t, 9, code.CommitCount)
|
||||
assert.EqualValues(t, 3, code.AuthorCount)
|
||||
assert.EqualValues(t, 9, code.CommitCountInAllBranches)
|
||||
assert.EqualValues(t, 10, code.Additions)
|
||||
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.EqualValues(t, 3, code.Authors["tris.git@shoddynet.org"])
|
||||
assert.EqualValues(t, 5, code.Authors[""])
|
||||
|
@@ -29,13 +29,13 @@ func (repo *Repository) IsTagExist(name string) bool {
|
||||
|
||||
// CreateTag create one tag in the repository
|
||||
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
|
||||
}
|
||||
|
||||
// CreateAnnotatedTag create one annotated tag in the repository
|
||||
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
|
||||
}
|
||||
|
||||
@@ -153,15 +153,18 @@ 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)
|
||||
func (repo *Repository) GetTagID(name string) (string, error) {
|
||||
stdout, err := NewCommand("show-ref", name).RunInDir(repo.Path)
|
||||
stdout, err := NewCommand("show-ref", "--tags", "--", name).RunInDir(repo.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fields := strings.Fields(stdout)
|
||||
if len(fields) != 2 {
|
||||
return "", ErrNotExist{ID: name}
|
||||
// Make sure exact match is used: "v1" != "release/v1"
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) == 2 && fields[1] == "refs/tags/"+name {
|
||||
return fields[0], nil
|
||||
}
|
||||
}
|
||||
return fields[0], nil
|
||||
return "", ErrNotExist{ID: name}
|
||||
}
|
||||
|
||||
// GetTag returns a Git tag by given name.
|
||||
|
@@ -62,6 +62,16 @@ func TestRepository_GetTag(t *testing.T) {
|
||||
assert.NotEqual(t, aTagID, aTag.Object.String())
|
||||
assert.EqualValues(t, aTagCommitID, aTag.Object.String())
|
||||
assert.EqualValues(t, "tag", aTag.Type)
|
||||
|
||||
rTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
|
||||
rTagName := "release/" + lTagName
|
||||
bareRepo1.CreateTag(rTagName, rTagCommitID)
|
||||
rTagID, err := bareRepo1.GetTagID(rTagName)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, rTagCommitID, rTagID)
|
||||
oTagID, err := bareRepo1.GetTagID(lTagName)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, lTagCommitID, oTagID)
|
||||
}
|
||||
|
||||
func TestRepository_GetAnnotatedTag(t *testing.T) {
|
||||
|
@@ -28,7 +28,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
|
||||
// GetTree find the tree object in the repository.
|
||||
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
||||
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 {
|
||||
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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
func (te *TreeEntry) Blob() *Blob {
|
||||
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)
|
||||
return body
|
||||
return markup.SanitizeBytes(body)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -111,7 +111,7 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
|
||||
RepoID: g.repo.ID,
|
||||
Name: milestone.Title,
|
||||
Content: milestone.Description,
|
||||
IsClosed: milestone.State == "close",
|
||||
IsClosed: milestone.State == "closed",
|
||||
DeadlineUnix: deadline,
|
||||
}
|
||||
if ms.IsClosed && milestone.Closed != nil {
|
||||
|
@@ -173,6 +173,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
|
||||
var (
|
||||
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{
|
||||
{
|
||||
@@ -208,9 +209,9 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
Number: 7,
|
||||
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",
|
||||
Milestone: "1.x.x",
|
||||
Milestone: "1.10.0",
|
||||
PosterName: "joubertredrat",
|
||||
State: "open",
|
||||
State: "closed",
|
||||
Created: time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC),
|
||||
Labels: []*base.Label{
|
||||
{
|
||||
@@ -232,6 +233,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
|
||||
Heart: 0,
|
||||
Hooray: 0,
|
||||
},
|
||||
Closed: &closed7,
|
||||
},
|
||||
{
|
||||
Number: 8,
|
||||
|
@@ -29,12 +29,13 @@ type HookOptions struct {
|
||||
UserName string
|
||||
GitObjectDirectory string
|
||||
GitAlternativeObjectDirectories string
|
||||
GitQuarantinePath string
|
||||
ProtectedBranchID int64
|
||||
}
|
||||
|
||||
// HookPreReceive check whether the provided commits are allowed
|
||||
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(repoName),
|
||||
url.QueryEscape(opts.OldCommitID),
|
||||
@@ -43,6 +44,7 @@ func HookPreReceive(ownerName, repoName string, opts HookOptions) (int, string)
|
||||
opts.UserID,
|
||||
url.QueryEscape(opts.GitObjectDirectory),
|
||||
url.QueryEscape(opts.GitAlternativeObjectDirectories),
|
||||
url.QueryEscape(opts.GitQuarantinePath),
|
||||
opts.ProtectedBranchID,
|
||||
)
|
||||
|
||||
|
@@ -49,7 +49,6 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
||||
}
|
||||
|
||||
defer func() {
|
||||
go models.HookQueue.Add(pr.BaseRepo.ID)
|
||||
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
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -241,7 +240,13 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
|
||||
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.
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -327,8 +299,7 @@ func getDiffTree(repoPath, baseBranch, headBranch string) (string, error) {
|
||||
getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) {
|
||||
var outbuf, errbuf strings.Builder
|
||||
// Compute the diff-tree for sparse-checkout
|
||||
// The branch argument must be enclosed with double-quotes ("") in case it contains slashes (e.g "feature/test")
|
||||
if err := git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "--root", baseBranch, headBranch).RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
|
||||
if err := git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "--root", baseBranch, headBranch, "--").RunInDirPipeline(repoPath, &outbuf, &errbuf); err != nil {
|
||||
return "", fmt.Errorf("git diff-tree [%s base:%s head:%s]: %s", repoPath, baseBranch, headBranch, errbuf.String())
|
||||
}
|
||||
return outbuf.String(), 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
|
||||
if opts.LastCommitID == "" {
|
||||
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
|
||||
@@ -172,32 +178,6 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo
|
||||
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)
|
||||
if err != nil {
|
||||
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
|
||||
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()
|
||||
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
|
||||
if opts.LastCommitID == "" {
|
||||
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"
|
||||
@@ -387,32 +394,6 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
@@ -177,31 +176,5 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep
|
||||
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...)
|
||||
}
|
||||
|
@@ -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 string `json:"message"`
|
||||
// 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
|
||||
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 Identity `json:"author"`
|
||||
Committer Identity `json:"committer"`
|
||||
|
@@ -694,6 +694,7 @@ editor.delete = Delete '%s'
|
||||
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.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.cancel = Cancel
|
||||
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:hover{color:rgba(0,0,0,.8)}
|
||||
.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).ui.segment{padding:3em}
|
||||
.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 .shatd{text-align:center}
|
||||
.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 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}
|
||||
@@ -664,6 +668,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
||||
.repository .diff-file-box .code-diff-split tbody tr td:nth-child(4){border-left-width:1px;border-left-style:solid}
|
||||
.repository .diff-file-box.file-content{clear:right}
|
||||
.repository .diff-file-box.file-content img{max-width:100%;padding:5px 5px 0 5px}
|
||||
.repository .diff-file-box.file-content img.emoji{padding:0}
|
||||
.repository .code-view{overflow:auto;overflow-x:auto;overflow-y:hidden}
|
||||
.repository .repo-search-result{padding-top:10px;padding-bottom:10px}
|
||||
.repository .repo-search-result .lines-num a{color:inherit}
|
||||
@@ -744,7 +749,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
||||
.repository .segment.reactions .select-reaction{float:none}
|
||||
.repository .segment.reactions .select-reaction:not(.active) a{display:none}
|
||||
.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 .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}
|
||||
@@ -814,8 +819,8 @@ footer .ui.left,footer .ui.right{line-height:40px}
|
||||
.stats-table .table-cell{display:table-cell}
|
||||
.stats-table .table-cell.tiny{height:.5em}
|
||||
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 .commit-status-link{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 .commit-status-link{display:inline-block;vertical-align:middle}
|
||||
.commit-body{white-space:pre-wrap}
|
||||
.git-notes.top{text-align:left}
|
||||
.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}
|
||||
.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 .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.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}
|
||||
|
@@ -10,6 +10,11 @@ function htmlEncode(text) {
|
||||
var csrf;
|
||||
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)
|
||||
if (!Array.from) {
|
||||
Array.from = (function () {
|
||||
@@ -1270,6 +1275,7 @@ function initEditor() {
|
||||
$('.quick-pull-branch-name').hide();
|
||||
$('.quick-pull-branch-name input').prop('required',false);
|
||||
}
|
||||
$('#commit-button').text($(this).attr('button_text'));
|
||||
});
|
||||
|
||||
var $editFilename = $("#file-name");
|
||||
@@ -1968,17 +1974,18 @@ $(document).ready(function () {
|
||||
|
||||
// Highlight JS
|
||||
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
|
||||
var $dropzone = $('#dropzone');
|
||||
const $dropzone = $('#dropzone');
|
||||
if ($dropzone.length > 0) {
|
||||
// Disable auto discover for all elements:
|
||||
Dropzone.autoDiscover = false;
|
||||
const filenameDict = {};
|
||||
|
||||
var filenameDict = {};
|
||||
$dropzone.dropzone({
|
||||
new Dropzone("#dropzone", {
|
||||
url: $dropzone.data('upload-url'),
|
||||
headers: {"X-Csrf-Token": csrf},
|
||||
maxFiles: $dropzone.data('max-file'),
|
||||
@@ -2006,7 +2013,7 @@ $(document).ready(function () {
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2104,12 +2111,16 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
$('.issue-action').click(function () {
|
||||
var action = this.dataset.action
|
||||
var elementId = this.dataset.elementId
|
||||
var issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
|
||||
let action = this.dataset.action;
|
||||
let elementId = this.dataset.elementId;
|
||||
let issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
|
||||
return this.dataset.issueId;
|
||||
}).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);
|
||||
});
|
||||
|
||||
|
@@ -605,7 +605,6 @@ code,
|
||||
.file-comment {
|
||||
font: 12px @monospaced-fonts, monospace;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
|
||||
}
|
||||
|
||||
.ui.floating.dropdown {
|
||||
@@ -877,3 +876,19 @@ footer {
|
||||
.ui.tabular.menu .item.active {
|
||||
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;
|
||||
}
|
||||
|
||||
td.message {
|
||||
text-overflow: unset;
|
||||
}
|
||||
|
||||
&.ui.basic.striped.table tbody tr:nth-child(2n) {
|
||||
background-color: rgba(0, 0, 0, 0.02) !important;
|
||||
}
|
||||
@@ -1540,6 +1544,9 @@
|
||||
max-width: 100%;
|
||||
padding: 5px 5px 0 5px;
|
||||
}
|
||||
img.emoji {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
clear: right;
|
||||
}
|
||||
@@ -1971,6 +1978,8 @@
|
||||
&.user-cards {
|
||||
.list {
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
list-style: none;
|
||||
@@ -2300,12 +2309,12 @@ tbody.commit-list {
|
||||
.commit-list .message-wrapper {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc(100% - 24px);
|
||||
max-width: calc(100% - 50px);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.commit-list .message-wrapper .commit-status-link {
|
||||
.commit-list .commit-status-link {
|
||||
display: inline-block;
|
||||
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(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(5),
|
||||
.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
|
||||
|
||||
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
|
||||
Version: 2.3.1
|
||||
|
9
public/vendor/librejs.html
vendored
9
public/vendor/librejs.html
vendored
@@ -17,8 +17,13 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<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://code.jquery.com/jquery-1.12.4.min.js">jquery-1.12.4.min.js</a></td>
|
||||
<td><a href="https://jquery.org/license/">MIT</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>
|
||||
<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
|
||||
// produces:
|
||||
// - 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:
|
||||
// "200":
|
||||
// "$ref": "#/responses/OrganizationList"
|
||||
@@ -90,7 +99,9 @@ func GetAllOrgs(ctx *context.APIContext) {
|
||||
users, _, err := models.SearchUsers(&models.SearchUserOptions{
|
||||
Type: models.UserTypeOrganization,
|
||||
OrderBy: models.SearchOrderByAlphabetically,
|
||||
PageSize: -1,
|
||||
Page: ctx.QueryInt("page"),
|
||||
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
|
||||
Private: true,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Error(500, "SearchOrganizations", err)
|
||||
|
@@ -91,8 +91,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
|
||||
if form.SendNotify && setting.MailService != nil {
|
||||
models.SendRegisterNotifyMail(ctx.Context.Context, u)
|
||||
}
|
||||
|
||||
ctx.JSON(201, u.APIFormat())
|
||||
ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
ctx.JSON(200, u.APIFormat())
|
||||
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
|
||||
}
|
||||
|
||||
// DeleteUser api for deleting a user
|
||||
@@ -326,7 +325,7 @@ func GetAllUsers(ctx *context.APIContext) {
|
||||
|
||||
results := make([]*api.User, len(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)
|
||||
|
@@ -74,7 +74,6 @@ import (
|
||||
"code.gitea.io/gitea/routers/api/v1/user"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/go-macaron/cors"
|
||||
macaron "gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
@@ -501,12 +500,6 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
m.Get("/swagger", misc.Swagger) //Render V1 by default
|
||||
}
|
||||
|
||||
var handlers []macaron.Handler
|
||||
if setting.EnableCORS {
|
||||
handlers = append(handlers, cors.CORS(setting.CORSConfig))
|
||||
}
|
||||
handlers = append(handlers, securityHeaders(), context.APIContexter(), sudo())
|
||||
|
||||
m.Group("/v1", func() {
|
||||
// Miscellaneous
|
||||
if setting.API.EnableSwagger {
|
||||
@@ -852,7 +845,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
m.Group("/topics", func() {
|
||||
m.Get("/search", repo.TopicSearch)
|
||||
})
|
||||
}, handlers...)
|
||||
}, securityHeaders(), context.APIContexter(), sudo())
|
||||
}
|
||||
|
||||
func securityHeaders() macaron.Handler {
|
||||
|
@@ -229,7 +229,7 @@ func ToTeam(team *models.Team) *api.Team {
|
||||
}
|
||||
|
||||
// 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{
|
||||
ID: user.ID,
|
||||
UserName: user.Name,
|
||||
@@ -239,7 +239,12 @@ func ToUser(user *models.User, signed, admin bool) *api.User {
|
||||
LastLogin: user.LastLoginUnix.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
|
||||
}
|
||||
return result
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||
"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))
|
||||
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)
|
||||
}
|
||||
|
@@ -257,7 +257,7 @@ func GetTeamMembers(ctx *context.APIContext) {
|
||||
}
|
||||
members := make([]*api.User, len(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)
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func GetTeamMember(ctx *context.APIContext) {
|
||||
if ctx.Written() {
|
||||
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
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||
)
|
||||
|
||||
// ListCollaborators list a repository's collaborators
|
||||
@@ -42,7 +43,7 @@ func ListCollaborators(ctx *context.APIContext) {
|
||||
}
|
||||
users := make([]*api.User, len(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)
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ func GetSingleCommit(ctx *context.APIContext) {
|
||||
URL: setting.AppURL + ctx.Link[1:],
|
||||
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{
|
||||
URL: setting.AppURL + ctx.Link[1:],
|
||||
Author: &api.CommitUser{
|
||||
@@ -111,7 +111,7 @@ func GetSingleCommit(ctx *context.APIContext) {
|
||||
},
|
||||
Message: commit.Message(),
|
||||
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(),
|
||||
},
|
||||
},
|
||||
|
@@ -71,19 +71,22 @@ func GetGitRefs(ctx *context.APIContext) {
|
||||
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())
|
||||
if err != nil {
|
||||
ctx.Error(500, "OpenRepository", err)
|
||||
return
|
||||
return nil, "OpenRepository", err
|
||||
}
|
||||
if len(filter) > 0 {
|
||||
filter = "refs/" + 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 {
|
||||
ctx.Error(500, "GetRefsFiltered", err)
|
||||
ctx.Error(500, lastMethodName, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -130,8 +130,8 @@ func TestHook(ctx *context.APIContext) {
|
||||
convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
|
||||
},
|
||||
Repo: ctx.Repo.Repository.APIFormat(models.AccessModeNone),
|
||||
Pusher: ctx.User.APIFormat(),
|
||||
Sender: ctx.User.APIFormat(),
|
||||
Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false),
|
||||
Sender: convert.ToUser(ctx.User, ctx.IsSigned, false),
|
||||
}); err != nil {
|
||||
ctx.Error(500, "PrepareWebhook: ", err)
|
||||
return
|
||||
|
@@ -183,7 +183,8 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
|
||||
allowed := false
|
||||
for _, t := range allowedTypes {
|
||||
t := strings.Trim(t, " ")
|
||||
if t == "*/*" || t == fileType {
|
||||
if t == "*/*" || t == fileType ||
|
||||
strings.HasPrefix(fileType, t+";") {
|
||||
allowed = true
|
||||
break
|
||||
}
|
||||
|
@@ -646,89 +646,102 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
|
||||
})
|
||||
}
|
||||
|
||||
if opts.HasIssues != nil {
|
||||
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.HasIssues == nil {
|
||||
// If HasIssues setting not touched, rewrite existing repo unit
|
||||
if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil {
|
||||
units = append(units, *unit)
|
||||
} else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil {
|
||||
units = append(units, *unit)
|
||||
}
|
||||
} 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 {
|
||||
// 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.HasWiki == nil {
|
||||
// If HasWiki setting not touched, rewrite existing repo unit
|
||||
if unit, err := repo.GetUnit(models.UnitTypeWiki); err == nil {
|
||||
units = append(units, *unit)
|
||||
} else if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err == nil {
|
||||
units = append(units, *unit)
|
||||
}
|
||||
} 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 {
|
||||
// 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 opts.HasPullRequests == nil {
|
||||
// If HasPullRequest setting not touched, rewrite existing repo unit
|
||||
if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil {
|
||||
units = append(units, *unit)
|
||||
}
|
||||
} 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 {
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||
)
|
||||
|
||||
// ListStargazers list a repository's stargazers
|
||||
@@ -38,7 +39,7 @@ func ListStargazers(ctx *context.APIContext) {
|
||||
}
|
||||
users := make([]*api.User, len(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)
|
||||
}
|
||||
|
@@ -46,10 +46,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
|
||||
// "$ref": "#/responses/StatusList"
|
||||
sha := ctx.Params("sha")
|
||||
if len(sha) == 0 {
|
||||
sha = ctx.Params("ref")
|
||||
}
|
||||
if len(sha) == 0 {
|
||||
ctx.Error(400, "ref/sha not given", nil)
|
||||
ctx.Error(400, "sha not given", nil)
|
||||
return
|
||||
}
|
||||
status := &models.CommitStatus{
|
||||
@@ -121,7 +118,38 @@ func GetCommitStatusesByRef(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$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) {
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||
)
|
||||
|
||||
// ListSubscribers list a repo's subscribers (i.e. watchers)
|
||||
@@ -38,7 +39,7 @@ func ListSubscribers(ctx *context.APIContext) {
|
||||
}
|
||||
users := make([]*api.User, len(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)
|
||||
}
|
||||
|
@@ -9,12 +9,13 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/routers/api/v1/convert"
|
||||
)
|
||||
|
||||
func responseAPIUsers(ctx *context.APIContext, users []*models.User) {
|
||||
apiUsers := make([]*api.User, len(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)
|
||||
}
|
||||
|
@@ -22,13 +22,13 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa
|
||||
apiKey.KeyType = "user"
|
||||
|
||||
if defaultUser.ID == key.OwnerID {
|
||||
apiKey.Owner = defaultUser.APIFormat()
|
||||
apiKey.Owner = convert.ToUser(defaultUser, true, true)
|
||||
} else {
|
||||
user, err := models.GetUserByID(key.OwnerID)
|
||||
if err != nil {
|
||||
return apiKey, err
|
||||
}
|
||||
apiKey.Owner = user.APIFormat()
|
||||
apiKey.Owner = convert.ToUser(user, true, true)
|
||||
}
|
||||
} else {
|
||||
apiKey.KeyType = "unknown"
|
||||
|
@@ -104,11 +104,7 @@ func GetInfo(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
// Hide user e-mail when API caller isn't signed in.
|
||||
if !ctx.IsSigned {
|
||||
u.Email = ""
|
||||
}
|
||||
ctx.JSON(200, u.APIFormat())
|
||||
ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.ID == u.ID || ctx.User.IsAdmin))
|
||||
}
|
||||
|
||||
// GetAuthenticatedUser get current user's information
|
||||
@@ -121,7 +117,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) {
|
||||
// responses:
|
||||
// "200":
|
||||
// "$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
|
||||
|
@@ -39,6 +39,7 @@ func Settings(ctx *context.Context) {
|
||||
func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("org.settings")
|
||||
ctx.Data["PageIsSettingsOptions"] = true
|
||||
ctx.Data["CurrentVisibility"] = structs.VisibleType(ctx.Org.Organization.Visibility)
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, tplSettingsOptions)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user