mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-13 02:02:53 +09:00
Compare commits
42 Commits
| 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 |
103
.drone.yml
103
.drone.yml
@@ -362,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
|
||||
@@ -463,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
|
||||
@@ -558,7 +558,7 @@ steps:
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
name: docker
|
||||
name: docker-linux-amd64
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
@@ -594,6 +594,7 @@ steps:
|
||||
settings:
|
||||
dry_run: true
|
||||
repo: gitea/gitea
|
||||
tags: linux-amd64
|
||||
when:
|
||||
event:
|
||||
- pull_request
|
||||
@@ -603,6 +604,7 @@ steps:
|
||||
image: plugins/docker:linux-amd64
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
repo: gitea/gitea
|
||||
password:
|
||||
from_secret: docker_password
|
||||
@@ -613,6 +615,97 @@ steps:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
|
||||
|
||||
---
|
||||
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:
|
||||
event:
|
||||
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
|
||||
name: notify
|
||||
@@ -635,7 +728,9 @@ depends_on:
|
||||
- translations
|
||||
- release-version
|
||||
- release-master
|
||||
- docker
|
||||
- docker-linux-amd64
|
||||
- docker-linux-arm64
|
||||
- docker-manifest
|
||||
- docs
|
||||
|
||||
steps:
|
||||
|
||||
56
CHANGELOG.md
56
CHANGELOG.md
@@ -4,6 +4,62 @@ 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.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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -598,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)
|
||||
@@ -661,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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1791,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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -1376,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)
|
||||
@@ -1647,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,
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
|
||||
@@ -292,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
|
||||
}
|
||||
|
||||
@@ -332,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"`
|
||||
|
||||
@@ -623,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}
|
||||
@@ -667,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}
|
||||
@@ -817,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}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -2302,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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -31,6 +31,7 @@ func HookPreReceive(ctx *macaron.Context) {
|
||||
userID := ctx.QueryInt64("userID")
|
||||
gitObjectDirectory := ctx.QueryTrim("gitObjectDirectory")
|
||||
gitAlternativeObjectDirectories := ctx.QueryTrim("gitAlternativeObjectDirectories")
|
||||
gitQuarantinePath := ctx.QueryTrim("gitQuarantinePath")
|
||||
prID := ctx.QueryInt64("prID")
|
||||
|
||||
branchName := strings.TrimPrefix(refFullName, git.BranchPrefix)
|
||||
@@ -63,11 +64,19 @@ func HookPreReceive(ctx *macaron.Context) {
|
||||
|
||||
// detect force push
|
||||
if git.EmptySHA != oldCommitID {
|
||||
env := append(os.Environ(),
|
||||
private.GitAlternativeObjectDirectories+"="+gitAlternativeObjectDirectories,
|
||||
private.GitObjectDirectory+"="+gitObjectDirectory,
|
||||
private.GitQuarantinePath+"="+gitObjectDirectory,
|
||||
)
|
||||
env := os.Environ()
|
||||
if gitAlternativeObjectDirectories != "" {
|
||||
env = append(env,
|
||||
private.GitAlternativeObjectDirectories+"="+gitAlternativeObjectDirectories)
|
||||
}
|
||||
if gitObjectDirectory != "" {
|
||||
env = append(env,
|
||||
private.GitObjectDirectory+"="+gitObjectDirectory)
|
||||
}
|
||||
if gitQuarantinePath != "" {
|
||||
env = append(env,
|
||||
private.GitQuarantinePath+"="+gitQuarantinePath)
|
||||
}
|
||||
|
||||
output, err := git.NewCommand("rev-list", "--max-count=1", oldCommitID, "^"+newCommitID).RunInDirWithEnv(repo.RepoPath(), env)
|
||||
if err != nil {
|
||||
|
||||
@@ -48,7 +48,8 @@ func UploadAttachment(ctx *context.Context) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -162,6 +162,12 @@ func loadBranches(ctx *context.Context) []*Branch {
|
||||
return nil
|
||||
}
|
||||
|
||||
protectedBranches, err := ctx.Repo.Repository.GetProtectedBranches()
|
||||
if err != nil {
|
||||
ctx.ServerError("GetProtectedBranches", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
branches := make([]*Branch, len(rawBranches))
|
||||
for i := range rawBranches {
|
||||
commit, err := rawBranches[i].GetCommit()
|
||||
@@ -170,11 +176,13 @@ func loadBranches(ctx *context.Context) []*Branch {
|
||||
return nil
|
||||
}
|
||||
|
||||
var isProtected bool
|
||||
branchName := rawBranches[i].Name
|
||||
isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User)
|
||||
if err != nil {
|
||||
ctx.ServerError("IsProtectedBranch", err)
|
||||
return nil
|
||||
for _, b := range protectedBranches {
|
||||
if b.BranchName == branchName {
|
||||
isProtected = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, branchName)
|
||||
|
||||
@@ -292,6 +292,13 @@ func CompareDiff(ctx *context.Context) {
|
||||
}
|
||||
|
||||
if ctx.Data["PageIsComparePull"] == true {
|
||||
headBranches, err := headGitRepo.GetBranches()
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranches", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["HeadBranches"] = headBranches
|
||||
|
||||
pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch)
|
||||
if err != nil {
|
||||
if !models.IsErrPullRequestNotExist(err) {
|
||||
@@ -312,13 +319,6 @@ func CompareDiff(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
headBranches, err := headGitRepo.GetBranches()
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranches", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["HeadBranches"] = headBranches
|
||||
}
|
||||
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
|
||||
afterCommitID := ctx.Data["AfterCommitID"].(string)
|
||||
|
||||
@@ -628,7 +628,8 @@ func UploadFileToServer(ctx *context.Context) {
|
||||
allowed := false
|
||||
for _, t := range setting.Repository.Upload.AllowedTypes {
|
||||
t := strings.Trim(t, " ")
|
||||
if t == "*/*" || t == fileType {
|
||||
if t == "*/*" || t == fileType ||
|
||||
strings.HasPrefix(fileType, t+";") {
|
||||
allowed = true
|
||||
break
|
||||
}
|
||||
|
||||
@@ -1047,11 +1047,14 @@ func UpdateIssueTitle(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
oldTitle := issue.Title
|
||||
if err := issue.ChangeTitle(ctx.User, title); err != nil {
|
||||
ctx.ServerError("ChangeTitle", err)
|
||||
return
|
||||
}
|
||||
|
||||
notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle)
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"title": issue.Title,
|
||||
})
|
||||
|
||||
@@ -253,6 +253,11 @@ func MilestoneIssuesAndPulls(ctx *context.Context) {
|
||||
milestoneID := ctx.ParamsInt64(":id")
|
||||
milestone, err := models.GetMilestoneByID(milestoneID)
|
||||
if err != nil {
|
||||
if models.IsErrMilestoneNotExist(err) {
|
||||
ctx.NotFound("GetMilestoneByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.ServerError("GetMilestoneByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/go-macaron/cache"
|
||||
"github.com/go-macaron/captcha"
|
||||
"github.com/go-macaron/cors"
|
||||
"github.com/go-macaron/csrf"
|
||||
"github.com/go-macaron/i18n"
|
||||
"github.com/go-macaron/session"
|
||||
@@ -440,6 +441,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
|
||||
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
|
||||
m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost)
|
||||
m.Post("/telegram/new", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksNewPost)
|
||||
m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
|
||||
m.Get("/:id", repo.WebHooksEdit)
|
||||
m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
|
||||
@@ -447,6 +449,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
|
||||
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
|
||||
m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost)
|
||||
m.Post("/telegram/:id", bindIgnErr(auth.NewTelegramHookForm{}), repo.TelegramHooksEditPost)
|
||||
m.Post("/msteams/:id", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost)
|
||||
})
|
||||
|
||||
@@ -945,9 +948,14 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||
m.Get("/swagger.v1.json", templates.JSONRenderer(), routers.SwaggerV1Json)
|
||||
}
|
||||
|
||||
var handlers []macaron.Handler
|
||||
if setting.EnableCORS {
|
||||
handlers = append(handlers, cors.CORS(setting.CORSConfig))
|
||||
}
|
||||
handlers = append(handlers, ignSignIn)
|
||||
m.Group("/api", func() {
|
||||
apiv1.RegisterRoutes(m)
|
||||
}, ignSignIn)
|
||||
}, handlers...)
|
||||
|
||||
m.Group("/api/internal", func() {
|
||||
// package name internal is ideal but Golang is not allowed, so we use private as package name.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
<img class="img-13" src="{{AppSubUrl}}/img/discord.png">
|
||||
{{else if eq .HookType "dingtalk"}}
|
||||
<img class="img-13" src="{{AppSubUrl}}/img/dingtalk.ico">
|
||||
{{else if eq .HookType "telegram"}}
|
||||
<img class="img-13" src="{{AppSubUrl}}/img/telegram.png">
|
||||
{{else if eq .HookType "msteams"}}
|
||||
<img class="img-13" src="{{AppSubUrl}}/img/msteams.png">
|
||||
{{end}}
|
||||
@@ -31,6 +33,7 @@
|
||||
{{template "repo/settings/webhook/slack" .}}
|
||||
{{template "repo/settings/webhook/discord" .}}
|
||||
{{template "repo/settings/webhook/dingtalk" .}}
|
||||
{{template "repo/settings/webhook/telegram" .}}
|
||||
{{template "repo/settings/webhook/msteams" .}}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
<div class="eight wide right aligned column">
|
||||
<div class="ui right file-actions">
|
||||
<div class="ui buttons">
|
||||
<a class="ui button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
|
||||
{{if not .IsViewCommit}}
|
||||
<a class="ui button" href="{{.RepoLink}}/src/commit/{{.CommitID}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_permalink"}}</a>
|
||||
{{end}}
|
||||
<a class="ui button" href="{{.RepoLink}}/src/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.normal_view"}}</a>
|
||||
<a class="ui button" href="{{.RepoLink}}/commits/{{EscapePound .BranchNameSubURL}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.file_history"}}</a>
|
||||
<a class="ui button" href="{{EscapePound $.RawFileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
|
||||
</div>
|
||||
{{if .Repository.CanEnableEditor}}
|
||||
{{if .CanEditFile}}
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
<tr>
|
||||
<td class="author">
|
||||
{{if .User}}
|
||||
{{if .User.FullName}}
|
||||
{{if .User.FullName}}
|
||||
<img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/> <a href="{{AppSubUrl}}/{{.User.Name}}">{{.User.FullName}}</a>
|
||||
{{else}}
|
||||
{{else}}
|
||||
<img class="ui avatar image" src="{{.User.RelAvatarLink}}" alt=""/> <a href="{{AppSubUrl}}/{{.User.Name}}">{{.Author.Name}}</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
<img class="ui avatar image" src="{{AvatarLink .Author.Email}}" alt=""/> {{.Author.Name}}
|
||||
{{end}}
|
||||
@@ -71,13 +71,15 @@
|
||||
</td>
|
||||
<td class="message">
|
||||
<span class="message-wrapper">
|
||||
<span class="commit-summary has-emoji{{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary}}</span>
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
|
||||
<pre class="commit-body" style="display: none;">{{RenderCommitBody .Message $.RepoLink $.Repository.ComposeMetas}}</pre>
|
||||
{{end}}
|
||||
<span class="commit-summary has-emoji{{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary}}</span>
|
||||
</span>
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
|
||||
{{end}}
|
||||
{{template "repo/commit_status" .Status}}
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<pre class="commit-body" style="display: none;">{{RenderCommitBody .Message $.RepoLink $.Repository.ComposeMetas}}</pre>
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="grey text right aligned">{{TimeSince .Author.When $.Lang}}</td>
|
||||
</tr>
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
</span>
|
||||
</td>
|
||||
{{end}}
|
||||
<td class="message has-emoji">
|
||||
<span class="truncate">
|
||||
<td class="message">
|
||||
<span class="truncate has-emoji">
|
||||
<a href="{{$.RepoLink}}/commit/{{$commit.ID}}" title="{{$commit.Summary}}">{{$commit.Summary}}</a>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -33,6 +33,20 @@
|
||||
],
|
||||
"summary": "List all organizations",
|
||||
"operationId": "adminGetAllOrgs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page number of results to return (1-based)",
|
||||
"name": "page",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "page size of results, maximum page size is 50",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/OrganizationList"
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
<i class="mega-octicon octicon-key {{if or (eq .ExpiredUnix 0) ($.PageStartTime.Before .ExpiredUnix.AsTime)}}green{{end}}"></i>
|
||||
<i class="mega-octicon octicon-key {{if or .ExpiredUnix.IsZero ($.PageStartTime.Before .ExpiredUnix.AsTime)}}green{{end}}"></i>
|
||||
<div class="content">
|
||||
{{range .Emails}}<strong>{{.Email}} </strong>{{end}}
|
||||
<div class="print meta">
|
||||
|
||||
Reference in New Issue
Block a user