Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/go-gitea/gitea
Browse files Browse the repository at this point in the history
  • Loading branch information
aswild committed Oct 7, 2019
2 parents 10043ac + 51fade4 commit 4320cba
Show file tree
Hide file tree
Showing 52 changed files with 763 additions and 430 deletions.
3 changes: 3 additions & 0 deletions contrib/systemd/gitea.service
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
# If using unix socket: Tells Systemd to create /run/gitea folder to home gitea.sock
# Manual cration would vanish after reboot.
#RuntimeDirectory=gitea
ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
Expand Down
2 changes: 2 additions & 0 deletions docs/content/doc/advanced/ci-cd.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ the purpose is to give a starting point to integrate a CI/CD process with your G
- [Agola](https://agola.io)
- [Buildkite](https://buildkite.com) with [Gitea connector](https://github.com/techknowlogick/gitea-buildkite-connector)
- [AppVeyor](https://www.appveyor.com) with [built-in Gitea support](https://www.appveyor.com/blog/2019/09/05/gitea-receives-first-class-support-in-appveyor/)
- [Buildbot](https://www.buildbot.net/) with [Gitea plugin](https://github.com/lab132/buildbot-gitea)


Others CI/CD solutions that partially can be integrated with Gitea:
- [Concourse](https://www.concourse-ci.org), see more information at [Concourse community forum](https://discuss.concourse-ci.org/t/concourse-ci-and-gitea-oauth/1475)
26 changes: 13 additions & 13 deletions docs/content/doc/installation/from-binary.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ location. When launched manually, Gitea can be killed using `Ctrl+C`.

## Recommended server configuration

**NOTE:** Many of the following directories can be configured using [Environment Variables]({{< relref "doc/advanced/specific-variables.en-us.md" >}}) as well!
**NOTE:** Many of the following directories can be configured using [Environment Variables]({{< relref "doc/advanced/specific-variables.en-us.md" >}}) as well!
Of note, configuring `GITEA_WORK_DIR` will tell Gitea where to base its working directory, as well as ease installation.

### Prepare environment
Expand Down Expand Up @@ -80,7 +80,7 @@ chmod 770 /etc/gitea
**NOTE:** `/etc/gitea` is temporary set with write rights for user `git` so that Web installer could write configuration file. After installation is done, it is recommended to set rights to read-only using:
```
chmod 750 /etc/gitea
chmod 644 /etc/gitea/app.ini
chmod 640 /etc/gitea/app.ini
```
If you don't want the web installer to be able to write the config file at all, it is also possible to make the config file read-only for the gitea user (owner/group `root:root`, mode `0660`), and set `INSTALL_LOCK = true`. In that case all database configuration details must be set beforehand in the config file, as well as the `SECRET_KEY` and `INTERNAL_TOKEN` values. See the [command line documentation]({{< relref "doc/usage/command-line.en-us.md" >}}) for information on using `gitea generate secret INTERNAL_TOKEN`.

Expand Down Expand Up @@ -113,16 +113,16 @@ GITEA_WORK_DIR=/var/lib/gitea/ /usr/local/bin/gitea web -c /etc/gitea/app.ini

## Updating to a new version

You can update to a new version of Gitea by stopping Gitea, replacing the binary at `/usr/local/bin/gitea` and restarting the instance.
The binary file name should not be changed during the update to avoid problems
in existing repositories.
You can update to a new version of Gitea by stopping Gitea, replacing the binary at `/usr/local/bin/gitea` and restarting the instance.
The binary file name should not be changed during the update to avoid problems
in existing repositories.

It is recommended you do a [backup]({{< relref "doc/usage/backup-and-restore.en-us.md" >}}) before updating your installation.

If you have carried out the installation steps as described above, the binary should
have the generic name `gitea`. Do not change this, i.e. to include the version number.
If you have carried out the installation steps as described above, the binary should
have the generic name `gitea`. Do not change this, i.e. to include the version number.

See below for troubleshooting instructions to repair broken repositories after
See below for troubleshooting instructions to repair broken repositories after
an update of your Gitea version.

## Troubleshooting
Expand All @@ -145,7 +145,7 @@ is already running.

### Running Gitea on Raspbian

As of v1.8, there is a problem with the arm7 version of Gitea and it doesn't run on Raspberry Pi and similar devices.
As of v1.8, there is a problem with the arm7 version of Gitea and it doesn't run on Raspberry Pi and similar devices.

It is therefore recommended to switch to the arm6 version which has been tested and shown to work on Raspberry Pi and similar devices.

Expand All @@ -154,18 +154,18 @@ please remove after fixing the arm7 bug
--->
### Git error after updating to a new version of Gitea

If the binary file name has been changed during the update to a new version of Gitea,
git hooks in existing repositories will not work any more. In that case, a git
If the binary file name has been changed during the update to a new version of Gitea,
git hooks in existing repositories will not work any more. In that case, a git
error will be displayed when pushing to the repository.

```
remote: ./hooks/pre-receive.d/gitea: line 2: [...]: No such file or directory
```

The `[...]` part of the error message will contain the path to your previous Gitea
The `[...]` part of the error message will contain the path to your previous Gitea
binary.

To solve this, go to the admin options and run the task `Resynchronize pre-receive,
To solve this, go to the admin options and run the task `Resynchronize pre-receive,
update and post-receive hooks of all repositories` to update all hooks to contain
the new binary path. Please note that this overwrite all git hooks including ones
with customizations made.
Expand Down
26 changes: 26 additions & 0 deletions docs/content/doc/usage/git-lfs-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
date: "2019-10-06T08:00:00+05:00"
title: "Usage: Git LFS setup"
slug: "git-lfs-setup"
weight: 12
toc: true
draft: false
menu:
sidebar:
parent: "usage"
name: "Git LFS setup"
weight: 12
identifier: "git-lfs-setup"
---

# Git Large File Storage setup

To use Gitea's built-in LFS support, you must update the `app.ini` file:

```ini
[server]
; Enables git-lfs support. true or false, default is false.
LFS_START_SERVER = true
; Where your lfs files reside, default is data/lfs.
LFS_CONTENT_PATH = /home/gitea/data/lfs
```
6 changes: 3 additions & 3 deletions docs/content/doc/usage/https-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ To use Gitea's built-in HTTPS support, you must change your `app.ini` file:

```ini
[server]
PROTOCOL=https
ROOT_URL = `https://git.example.com:3000/`
PROTOCOL = https
ROOT_URL = https://git.example.com:3000/
HTTP_PORT = 3000
CERT_FILE = cert.pem
KEY_FILE = key.pem
KEY_FILE = key.pem
```

To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server).
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
github.com/go-redis/redis v6.15.2+incompatible
github.com/go-sql-driver/mysql v1.4.1
github.com/go-swagger/go-swagger v0.20.1
github.com/go-xorm/xorm v0.7.8
github.com/go-xorm/xorm v0.7.9
github.com/gobwas/glob v0.2.3
github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561
github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
Expand All @@ -64,7 +64,7 @@ require (
github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f
github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc // indirect
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 // indirect
github.com/lafriks/xormstore v1.3.0
github.com/lafriks/xormstore v1.3.1
github.com/lib/pq v1.2.0
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/go-xorm/xorm v0.7.8 h1:rKxZJB9mWQ9Nw2TbjsepiThR031jkGePOWXwTtEAU08=
github.com/go-xorm/xorm v0.7.8/go.mod h1:XiVxrMMIhFkwSkh96BW7PACl7UhLtx2iJIHMdmjh5sQ=
github.com/go-xorm/xorm v0.7.9 h1:LZze6n1UvRmM5gpL9/U9Gucwqo6aWlFVlfcHKH10qA0=
github.com/go-xorm/xorm v0.7.9/go.mod h1:XiVxrMMIhFkwSkh96BW7PACl7UhLtx2iJIHMdmjh5sQ=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
Expand Down Expand Up @@ -384,8 +384,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lafriks/xormstore v1.3.0 h1:9A2wAZrdEXtTgfjCFtclPz3pwnmmxY7sJxQgIi62li4=
github.com/lafriks/xormstore v1.3.0/go.mod h1:RAhtOztWBjK9xeZpXwKq59rhUxoRgo1zfYl0H1mtK7A=
github.com/lafriks/xormstore v1.3.1 h1:KpzRUamSV3zmA85Kzw+PZOU9wgMbYsNzuDzLuBMbxpA=
github.com/lafriks/xormstore v1.3.1/go.mod h1:qALRD4Vto2Ic7/A5eplMpu5V62mugtSqFysRwz8FETs=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
Expand Down
2 changes: 1 addition & 1 deletion integrations/api_repo_lfs_locks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func TestAPILFSLocksLogged(t *testing.T) {
assert.Len(t, lfsLocks.Locks, test.totalCount)
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.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 10*time.Second)
assert.EqualValues(t, lock.LockedAt.Format(time.RFC3339), lock.LockedAt.Format(time.RFC3339Nano)) //locked at should be rounded to second
}

Expand Down
15 changes: 15 additions & 0 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,21 @@ func (err ErrIssueLabelTemplateLoad) Error() string {
return fmt.Sprintf("Failed to load label template file '%s': %v", err.TemplateFile, err.OriginalError)
}

// ErrNewIssueInsert is used when the INSERT statement in newIssue fails
type ErrNewIssueInsert struct {
OriginalError error
}

// IsErrNewIssueInsert checks if an error is a ErrNewIssueInsert.
func IsErrNewIssueInsert(err error) bool {
_, ok := err.(ErrNewIssueInsert)
return ok
}

func (err ErrNewIssueInsert) Error() string {
return err.OriginalError.Error()
}

// __________ .__ .__ __________ __
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
Expand Down
52 changes: 29 additions & 23 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (er
}

// Update issue count of milestone
if err = changeMilestoneIssueStats(e, issue); err != nil {
if err := updateMilestoneClosedNum(e, issue.MilestoneID); err != nil {
return err
}

Expand Down Expand Up @@ -1104,21 +1104,10 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
}

// Milestone and assignee validation should happen before insert actual object.

// There's no good way to identify a duplicate key error in database/sql; brute force some retries
dupIndexAttempts := issueMaxDupIndexAttempts
for {
_, err := e.SetExpr("`index`", "coalesce(MAX(`index`),0)+1").
Where("repo_id=?", opts.Issue.RepoID).
Insert(opts.Issue)
if err == nil {
break
}

dupIndexAttempts--
if dupIndexAttempts <= 0 {
return err
}
if _, err := e.SetExpr("`index`", "coalesce(MAX(`index`),0)+1").
Where("repo_id=?", opts.Issue.RepoID).
Insert(opts.Issue); err != nil {
return ErrNewIssueInsert{err}
}

inserted, err := getIssueByID(e, opts.Issue.ID)
Expand All @@ -1130,7 +1119,7 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
opts.Issue.Index = inserted.Index

if opts.Issue.MilestoneID > 0 {
if err = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil {
if _, err = e.Exec("UPDATE `milestone` SET num_issues=num_issues+1 WHERE id=?", opts.Issue.MilestoneID); err != nil {
return err
}
}
Expand Down Expand Up @@ -1201,6 +1190,24 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {

// NewIssue creates new issue with labels for repository.
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []int64, uuids []string) (err error) {
// Retry several times in case INSERT fails due to duplicate key for (repo_id, index); see #7887
i := 0
for {
if err = newIssueAttempt(repo, issue, labelIDs, assigneeIDs, uuids); err == nil {
return nil
}
if !IsErrNewIssueInsert(err) {
return err
}
if i++; i == issueMaxDupIndexAttempts {
break
}
log.Error("NewIssue: error attempting to insert the new issue; will retry. Original error: %v", err)
}
return fmt.Errorf("NewIssue: too many errors attempting to insert the new issue. Last error was: %v", err)
}

func newIssueAttempt(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []int64, uuids []string) (err error) {
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
Expand All @@ -1214,7 +1221,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []in
Attachments: uuids,
AssigneeIDs: assigneeIDs,
}); err != nil {
if IsErrUserDoesNotHaveAccessToRepo(err) {
if IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
return err
}
return fmt.Errorf("newIssue: %v", err)
Expand All @@ -1223,7 +1230,6 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []in
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
sess.Close()

return nil
}
Expand Down Expand Up @@ -1655,14 +1661,14 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
return nil, err
}
case FilterModeAssign:
stats.OpenCount, err = x.Where(cond).And("is_closed = ?", false).
stats.OpenCount, err = x.Where(cond).And("issue.is_closed = ?", false).
Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
And("issue_assignees.assignee_id = ?", opts.UserID).
Count(new(Issue))
if err != nil {
return nil, err
}
stats.ClosedCount, err = x.Where(cond).And("is_closed = ?", true).
stats.ClosedCount, err = x.Where(cond).And("issue.is_closed = ?", true).
Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
And("issue_assignees.assignee_id = ?", opts.UserID).
Count(new(Issue))
Expand All @@ -1683,14 +1689,14 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
return nil, err
}
case FilterModeMention:
stats.OpenCount, err = x.Where(cond).And("is_closed = ?", false).
stats.OpenCount, err = x.Where(cond).And("issue.is_closed = ?", false).
Join("INNER", "issue_user", "issue.id = issue_user.issue_id and issue_user.is_mentioned = ?", true).
And("issue_user.uid = ?", opts.UserID).
Count(new(Issue))
if err != nil {
return nil, err
}
stats.ClosedCount, err = x.Where(cond).And("is_closed = ?", true).
stats.ClosedCount, err = x.Where(cond).And("issue.is_closed = ?", true).
Join("INNER", "issue_user", "issue.id = issue_user.issue_id and issue_user.is_mentioned = ?", true).
And("issue_user.uid = ?", opts.UserID).
Count(new(Issue))
Expand Down
Loading

0 comments on commit 4320cba

Please sign in to comment.