diff --git a/.drone.yml b/.drone.yml
index 011d4fefd..9a27e1c21 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -4,7 +4,7 @@ workspace:
clone:
git:
- image: plugins/git:1
+ image: plugins/git:next
depth: 50
tags: true
@@ -75,6 +75,7 @@ pipeline:
- make lint
- make fmt-check
- make swagger-check
+ - make swagger-validate
- make misspell-check
- make test-vendor
- make build
@@ -254,6 +255,18 @@ pipeline:
when:
event: [ push, tag ]
+ gpg-sign:
+ image: plugins/gpgsign:1
+ pull: true
+ secrets: [ gpgsign_key, gpgsign_passphrase ]
+ detach_sign: true
+ files:
+ - dist/release/*
+ excludes:
+ - dist/release/*.sha256
+ when:
+ event: [ push, tag ]
+
release:
image: plugins/s3:1
pull: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 373ce00e6..b31730a09 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,18 @@ 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.4.3](https://github.com/go-gitea/gitea/releases/tag/v1.4.3) - 2018-06-26
+* SECURITY
+ * HTML-escape plain-text READMEs (#4192) (#4214)
+ * Fix open redirect vulnerability on login screen (#4312) (#4312)
+* BUGFIXES
+ * Fix broken monitoring page when running processes are shown (#4203) (#4208)
+ * Fix delete comment bug (#4216) (#4228)
+ * Delete reactions added to issues and comments when deleting repository (#4232) (#4237)
+ * Fix wiki URL encoding bug (#4091) (#4254)
+ * Fix code tab link when viewing tags (#3908) (#4263)
+ * Fix webhook type conflation (#4285) (#4285)
+
## [1.4.2](https://github.com/go-gitea/gitea/releases/tag/v1.4.2) - 2018-06-04
* BUGFIXES
* Adjust z-index for floating labels (#3939) (#3950)
diff --git a/cmd/admin.go b/cmd/admin.go
index 6c79141ea..4fb0810c6 100644
--- a/cmd/admin.go
+++ b/cmd/admin.go
@@ -73,6 +73,11 @@ var (
Value: "",
Usage: "New password to set for user",
},
+ cli.StringFlag{
+ Name: "config, c",
+ Value: "custom/conf/app.ini",
+ Usage: "Custom configuration file path",
+ },
},
}
@@ -123,6 +128,10 @@ func runChangePassword(c *cli.Context) error {
return err
}
+ if c.IsSet("config") {
+ setting.CustomConf = c.String("config")
+ }
+
if err := initDB(); err != nil {
return err
}
diff --git a/contrib/init/sunos/gitea.xml b/contrib/init/sunos/gitea.xml
new file mode 100644
index 000000000..4b8cc3a38
--- /dev/null
+++ b/contrib/init/sunos/gitea.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A painless, self-hosted Git service
+
+
+
+
+
diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample
index ef88e5c32..f823f68e4 100644
--- a/custom/conf/app.ini.sample
+++ b/custom/conf/app.ini.sample
@@ -601,9 +601,9 @@ ko-KR = ko
[U2F]
; Two Factor authentication with security keys
; https://developers.yubico.com/U2F/App_ID.html
-APP_ID = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s
+APP_ID = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
; Comma seperated list of truisted facets
-TRUSTED_FACETS = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s
+TRUSTED_FACETS = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
; Extension mapping to highlight class
; e.g. .toml=ini
diff --git a/docker/etc/s6/gitea/setup b/docker/etc/s6/gitea/setup
index 500cca584..03758ed81 100755
--- a/docker/etc/s6/gitea/setup
+++ b/docker/etc/s6/gitea/setup
@@ -1,7 +1,5 @@
#!/bin/bash
-/usr/sbin/update-ca-certificates
-
if [ ! -d /data/git/.ssh ]; then
mkdir -p /data/git/.ssh
chmod 700 /data/git/.ssh
diff --git a/docs/content/doc/advanced/api-usage.en-us.md b/docs/content/doc/advanced/api-usage.en-us.md
new file mode 100644
index 000000000..f04a99f14
--- /dev/null
+++ b/docs/content/doc/advanced/api-usage.en-us.md
@@ -0,0 +1,75 @@
+---
+date: "2018-06-24:00:00+02:00"
+title: "API Usage"
+slug: "api-usage"
+weight: 40
+toc: true
+draft: false
+menu:
+ sidebar:
+ parent: "advanced"
+ name: "API Usage"
+ weight: 40
+ identifier: "api-usage"
+---
+
+# Gitea API Usage
+
+## Enabling/configuring API access
+
+By default, `ENABLE_SWAGGER_ENDPOINT` is true, and
+`MAX_RESPONSE_ITEMS` is set to 50. See [Config Cheat
+Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for more
+information.
+
+## Authentication via the API
+
+Gitea supports these methods of API authentication:
+
+- HTTP basic authentication
+- `token=...` parameter in URL query string
+- `access_token=...` parameter in URL query string
+- `Authorization: token ...` header in HTTP headers
+
+All of these methods accept the same apiKey token type. You can
+better understand this by looking at the code -- as of this writing,
+Gitea parses queries and headers to find the token in
+[modules/auth/auth.go](https://github.com/go-gitea/gitea/blob/6efdcaed86565c91a3dc77631372a9cc45a58e89/modules/auth/auth.go#L47).
+
+You can create an apiKey token via your gitea install's web interface:
+`Settings | Applications | Generate New Token`.
+
+### More on the `Authorization:` header
+
+For historical reasons, Gitea needs the word `token` included before
+the apiKey token in an authorization header, like this:
+
+```
+Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675
+```
+
+In a `curl` command, for instance, this would look like:
+
+```
+curl -X POST "http://localhost:4000/api/v1/repos/test1/test1/issues" \
+ -H "accept: application/json" \
+ -H "Authorization: token 65eaa9c8ef52460d22a93307fe0aee76289dc675" \
+ -H "Content-Type: application/json" -d "{ \"body\": \"testing\", \"title\": \"test 20\"}" -i
+```
+
+As mentioned above, the token used is the same one you would use in
+the `token=` string in a GET request.
+
+## Listing your issued tokens via the API
+
+As mentioned in
+[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346),
+`/users/:name/tokens` is special and requires you to authenticate
+using BasicAuth, as follows:
+
+### Using basic authentication:
+
+```
+$ curl --request GET --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens
+[{"name":"test","sha1":"..."},{"name":"dev","sha1":"..."}]
+```
diff --git a/docs/content/doc/features/comparison.en-us.md b/docs/content/doc/features/comparison.en-us.md
index 981365c71..698de4f46 100644
--- a/docs/content/doc/features/comparison.en-us.md
+++ b/docs/content/doc/features/comparison.en-us.md
@@ -27,659 +27,93 @@ _Symbols used in table:_
* _✘ - unsupported_
-
-
-
- Feature |
- Gitea |
- Gogs |
- GitHub EE |
- GitLab CE |
- GitLab EE |
- BitBucket |
- RhodeCode CE |
-
-
-
-
- Open source and free |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
- ✘ |
- ✘ |
- ✓ |
-
-
- Issue tracker |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Pull/Merge requests |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Squash merging |
- ✓ |
- ✘ |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Rebase merging |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ⁄ |
- ✘ |
- ✓ |
-
-
- Pull/Merge request inline comments |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Pull/Merge request approval |
- ✘ |
- ✘ |
- ⁄ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Merge conflict resolution |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Restrict push and merge access to certain users |
- ✓ |
- ✘ |
- ✓ |
- ⁄ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Markdown support |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Issues and pull/merge requests templates |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Revert specific commits or a merge request |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Labels |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Time tracking |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Multiple assignees for issues |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Related issues |
- ✘ |
- ✘ |
- ⁄ |
- ✘ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Confidential issues |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Comment reactions |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Lock Discussion |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Batch issue handling |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Issue Boards |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Create new branches from issues |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Commit graph |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Web code editor |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Branch manager |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Create new branches |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Repository topics |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Repository code search |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Global code search |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Issue search |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Global issue search |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Git LFS 2.0 |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ⁄ |
- ✓ |
-
-
- Integrated Git-powered wiki |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Static Git-powered pages |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Group Milestones |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Granular user roles (Code, Issues, Wiki etc) |
- ✓ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- Cherry-picking changes |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- GPG Signed Commits |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Reject unsigned commits |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
-
-
- Verified Committer |
- ✘ |
- ✘ |
- ? |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Subgroups: groups within groups |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
-
-
- Custom Git Hooks |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Repository Activity page |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Deploy Tokens |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Repository Tokens with write rights |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
-
-
- Easy upgrade process |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✓ |
-
-
- Built-in Container Registry |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- External git mirroring |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
-
-
- AD / LDAP integration |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Multiple LDAP / AD server support |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
-
-
- LDAP user synchronization |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- OpenId Connect support |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ? |
- ✘ |
-
-
- OAuth 2.0 integration (external authorization) |
- ✓ |
- ✘ |
- ⁄ |
- ✓ |
- ✓ |
- ? |
- ✓ |
-
-
- Act as OAuth 2.0 provider |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Two factor authentication (2FA) |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- FIDO U2F (2FA) |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
-
-
- Webhook support |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Mattermost/Slack integration |
- ✓ |
- ✓ |
- ⁄ |
- ✓ |
- ✓ |
- ⁄ |
- ✓ |
-
-
- Discord integration |
- ✓ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
- ✘ |
- ✘ |
-
-
- Built-in CI/CD |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
-
-
- External CI/CD status display |
- ✓ |
- ✘ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
- ✓ |
-
-
- Multiple database support |
- ✓ |
- ✓ |
- ✘ |
- ⁄ |
- ⁄ |
- ✓ |
- ✓ |
-
-
- Multiple OS support |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
- ✘ |
- ✘ |
- ✓ |
-
-
- Low resource usage (RAM/CPU) |
- ✓ |
- ✓ |
- ✘ |
- ✘ |
- ✘ |
- ✘ |
- ✘ |
-
-
-
+#### General Features
+
+| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
+|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
+| Open source and free | ✓ | ✓ | ✘| ✓ | ✘ | ✘ | ✓ |
+| Low resource usage (RAM/CPU) | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ |
+| Multiple database support | ✓ | ✓ | ✘ | ⁄ | ⁄ | ✓ | ✓ |
+| Multiple OS support | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ |
+| Easy upgrade process | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ |
+| Markdown support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Static Git-powered pages | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Integrated Git-powered wiki | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
+| Built-in Container Registry | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| External git mirroring | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
+| FIDO U2F (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Built-in CI/CD | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Subgroups: groups within groups | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ |
+
+#### Code management
+
+| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
+|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
+| Repository topics | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Repository code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Global code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ⁄ | ✓ |
+| Group Milestones | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Verified Committer | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
+| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Reject unsigned commits | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
+| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Branch manager | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Create new branches | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Web code editor | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Commit graph | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+
+#### Issue Tracker
+
+| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
+|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
+| Issue tracker | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Issue templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Labels | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Time tracking | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Multiple assignees for issues | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Related issues | ✘ | ✘ | ⁄ | ✘ | ✓ | ✘ | ✘ |
+| Confidential issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Comment reactions | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Lock Discussion | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Batch issue handling | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Issue Boards | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Create new branches from issues | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+| Issue search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Global issue search | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+
+#### Pull/Merge requests
+
+| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
+|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
+| Pull/Merge requests | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Squash merging | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ |
+| Rebase merging | ✓ | ✓ | ✓ | ✘ | ⁄ | ✘ | ✓ |
+| Pull/Merge request inline comments | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Pull/Merge request approval | ✘ | ✘ | ⁄ | ✓ | ✓ | ✓ | ✓ |
+| Merge conflict resolution | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Restrict push and merge access to certain users | ✓ | ✘ | ✓ | ⁄ | ✓ | ✓ | ✓ |
+| Revert specific commits or a merge request | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Pull/Merge requests templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ |
+| Cherry-picking changes | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
+
+
+#### 3rd-party integrations
+
+| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE |
+|---------|-------|------|-----------|-----------|-----------|-----------|--------------|
+| Webhook support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Custom Git Hooks | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| AD / LDAP integration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Multiple LDAP / AD server support | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
+| LDAP user synchronization | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
+| OpenId Connect support | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ |
+| OAuth 2.0 integration (external authorization) | ✓ | ✘ | ⁄ | ✓ | ✓ | ? | ✓ |
+| Act as OAuth 2.0 provider | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Two factor authentication (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ |
+| Mattermost/Slack integration | ✓ | ✓ | ⁄ | ✓ | ✓ | ⁄ | ✓ |
+| Discord integration | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ |
+| External CI/CD status display | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
diff --git a/docs/content/doc/installation/with-docker.en-us.md b/docs/content/doc/installation/with-docker.en-us.md
index c672393cc..aa4337e08 100644
--- a/docs/content/doc/installation/with-docker.en-us.md
+++ b/docs/content/doc/installation/with-docker.en-us.md
@@ -245,6 +245,8 @@ You can configure some of Gitea's settings via environment variables:
* `SECRET_KEY`: **""**: Global secret key. This should be changed. If this has a value and `INSTALL_LOCK` is empty, `INSTALL_LOCK` will automatically set to `true`.
* `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create accounts for users.
* `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page.
+* `USER_UID`: **1000**: The UID (Unix user ID) of the user that runs Gitea within the container. Match this to the UID of the owner of the `/data` volume if using host volumes (this is not necessary with named volumes).
+* `USER_GID`: **1000**: The GID (Unix group ID) of the user that runs Gitea within the container. Match this to the GID of the owner of the `/data` volume if using host volumes (this is not necessary with named volumes).
# Customization
diff --git a/docs/content/doc/usage/backup-and-restore.en-us.md b/docs/content/doc/usage/backup-and-restore.en-us.md
index fa73c38bc..a0816ebe4 100644
--- a/docs/content/doc/usage/backup-and-restore.en-us.md
+++ b/docs/content/doc/usage/backup-and-restore.en-us.md
@@ -20,7 +20,7 @@ file can be unpacked and used to restore an instance.
## Backup Command (`dump`)
-Switch to the user running gitea: `su git`. Run `./gitea dump` in the gitea installation
+Switch to the user running gitea: `su git`. Run `./gitea dump -c /path/to/app.ini` in the gitea installation
directory. There should be some output similar to the following:
```
diff --git a/docs/content/doc/usage/command-line.md b/docs/content/doc/usage/command-line.md
index 9c16d4904..a7a10b4e4 100644
--- a/docs/content/doc/usage/command-line.md
+++ b/docs/content/doc/usage/command-line.md
@@ -62,6 +62,7 @@ Admin operations:
- Options:
- `--username value`, `-u value`: Username. Required.
- `--password value`, `-p value`: New password. Required.
+ - `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
- Examples:
- `gitea admin change-password --username myname --password asecurepassword`
- `regenerate`
diff --git a/integrations/README.md b/integrations/README.md
index 64041b546..927368818 100644
--- a/integrations/README.md
+++ b/integrations/README.md
@@ -13,7 +13,7 @@ Make sure to perform a clean build before running tests:
## Run all tests via local drone
```
-drone exec --local --build.event "pull_request"
+drone exec --local --build-event "pull_request"
```
## Run sqlite integrations tests
diff --git a/integrations/api_repo_test.go b/integrations/api_repo_test.go
index b766dd584..12429c88a 100644
--- a/integrations/api_repo_test.go
+++ b/integrations/api_repo_test.go
@@ -67,9 +67,9 @@ func TestAPISearchRepo(t *testing.T) {
expectedResults
}{
{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
- nil: {count: 15},
- user: {count: 15},
- user2: {count: 15}},
+ nil: {count: 16},
+ user: {count: 16},
+ user2: {count: 16}},
},
{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
nil: {count: 10},
diff --git a/integrations/setting_test.go b/integrations/setting_test.go
index a8d1f01e8..2aac8e90e 100644
--- a/integrations/setting_test.go
+++ b/integrations/setting_test.go
@@ -68,3 +68,25 @@ func TestSettingShowUserEmailProfile(t *testing.T) {
setting.UI.ShowUserEmail = showUserEmail
}
+
+func TestSettingLandingPage(t *testing.T) {
+ prepareTestEnv(t)
+
+ landingPage := setting.LandingPageURL
+
+ setting.LandingPageURL = setting.LandingPageHome
+ req := NewRequest(t, "GET", "/")
+ MakeRequest(t, req, http.StatusOK)
+
+ setting.LandingPageURL = setting.LandingPageExplore
+ req = NewRequest(t, "GET", "/")
+ resp := MakeRequest(t, req, http.StatusFound)
+ assert.Equal(t, "/explore", resp.Header().Get("Location"))
+
+ setting.LandingPageURL = setting.LandingPageOrganizations
+ req = NewRequest(t, "GET", "/")
+ resp = MakeRequest(t, req, http.StatusFound)
+ assert.Equal(t, "/explore/organizations", resp.Header().Get("Location"))
+
+ setting.LandingPageURL = landingPage
+}
diff --git a/models/access_test.go b/models/access_test.go
index 59575acb7..46d6f723e 100644
--- a/models/access_test.go
+++ b/models/access_test.go
@@ -22,8 +22,12 @@ func TestAccessLevel(t *testing.T) {
user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
- repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository)
- repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository)
+ // A public repository owned by User 2
+ repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
+ assert.False(t, repo1.IsPrivate)
+ // A private repository owned by Org 3
+ repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
+ assert.True(t, repo2.IsPrivate)
level, err := AccessLevel(user1.ID, repo1)
assert.NoError(t, err)
@@ -47,8 +51,12 @@ func TestHasAccess(t *testing.T) {
user1 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
user2 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
- repo1 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 2, IsPrivate: false}).(*Repository)
- repo2 := AssertExistsAndLoadBean(t, &Repository{OwnerID: 3, IsPrivate: true}).(*Repository)
+ // A public repository owned by User 2
+ repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
+ assert.False(t, repo1.IsPrivate)
+ // A private repository owned by Org 3
+ repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository)
+ assert.True(t, repo2.IsPrivate)
for _, accessMode := range accessModes {
has, err := HasAccess(user1.ID, repo1, accessMode)
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index c7d73fe17..3238b65ea 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -351,7 +351,7 @@
is_mirror: true
num_forks: 1
is_fork: false
-
+
-
id: 29
fork_id: 27
@@ -365,7 +365,7 @@
num_closed_pulls: 0
is_mirror: false
is_fork: true
-
+
-
id: 30
fork_id: 28
@@ -389,3 +389,14 @@
num_forks: 0
num_issues: 0
is_mirror: false
+
+-
+ id: 32
+ owner_id: 3
+ lower_name: repo21
+ name: repo21
+ is_private: false
+ num_stars: 0
+ num_forks: 0
+ num_issues: 0
+ is_mirror: false
diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml
index 1d242cb5b..4b4a1d798 100644
--- a/models/fixtures/team.yml
+++ b/models/fixtures/team.yml
@@ -4,9 +4,8 @@
lower_name: owners
name: Owners
authorize: 4 # owner
- num_repos: 2
+ num_repos: 3
num_members: 1
- unit_types: '[1,2,3,4,5,6,7]'
-
id: 2
@@ -16,7 +15,6 @@
authorize: 2 # write
num_repos: 1
num_members: 2
- unit_types: '[1,2,3,4,5,6,7]'
-
id: 3
@@ -26,7 +24,6 @@
authorize: 4 # owner
num_repos: 0
num_members: 1
- unit_types: '[1,2,3,4,5,6,7]'
-
id: 4
@@ -36,7 +33,6 @@
authorize: 4 # owner
num_repos: 0
num_members: 1
- unit_types: '[1,2,3,4,5,6,7]'
-
id: 5
@@ -46,7 +42,6 @@
authorize: 4 # owner
num_repos: 2
num_members: 2
- unit_types: '[1,2,3,4,5,6,7]'
-
id: 6
@@ -56,4 +51,3 @@
authorize: 4 # owner
num_repos: 2
num_members: 1
- unit_types: '[1,2,3,4,5,6,7]'
\ No newline at end of file
diff --git a/models/fixtures/team_repo.yml b/models/fixtures/team_repo.yml
index 9e6d74553..b324e0941 100644
--- a/models/fixtures/team_repo.yml
+++ b/models/fixtures/team_repo.yml
@@ -33,9 +33,15 @@
org_id: 19
team_id: 6
repo_id: 27
-
+
-
id: 7
org_id: 19
team_id: 6
- repo_id: 28
\ No newline at end of file
+ repo_id: 28
+
+-
+ id: 8
+ org_id: 3
+ team_id: 1
+ repo_id: 32
diff --git a/models/fixtures/team_unit.yml b/models/fixtures/team_unit.yml
new file mode 100644
index 000000000..ad5466a5c
--- /dev/null
+++ b/models/fixtures/team_unit.yml
@@ -0,0 +1,209 @@
+-
+ id: 1
+ team_id: 1
+ type: 1
+
+-
+ id: 2
+ team_id: 1
+ type: 2
+
+-
+ id: 3
+ team_id: 1
+ type: 3
+
+-
+ id: 4
+ team_id: 1
+ type: 4
+
+-
+ id: 5
+ team_id: 1
+ type: 5
+
+-
+ id: 6
+ team_id: 1
+ type: 6
+
+-
+ id: 7
+ team_id: 1
+ type: 7
+
+-
+ id: 8
+ team_id: 2
+ type: 1
+
+-
+ id: 9
+ team_id: 2
+ type: 2
+
+-
+ id: 10
+ team_id: 2
+ type: 3
+
+-
+ id: 11
+ team_id: 2
+ type: 4
+
+-
+ id: 12
+ team_id: 2
+ type: 5
+
+-
+ id: 13
+ team_id: 2
+ type: 6
+
+-
+ id: 14
+ team_id: 2
+ type: 7
+
+-
+ id: 15
+ team_id: 3
+ type: 1
+
+-
+ id: 16
+ team_id: 3
+ type: 2
+
+-
+ id: 17
+ team_id: 3
+ type: 3
+
+-
+ id: 18
+ team_id: 3
+ type: 4
+
+-
+ id: 19
+ team_id: 3
+ type: 5
+
+-
+ id: 20
+ team_id: 3
+ type: 6
+
+-
+ id: 21
+ team_id: 3
+ type: 7
+
+-
+ id: 22
+ team_id: 4
+ type: 1
+
+-
+ id: 23
+ team_id: 4
+ type: 2
+
+-
+ id: 24
+ team_id: 4
+ type: 3
+
+-
+ id: 25
+ team_id: 4
+ type: 4
+
+-
+ id: 26
+ team_id: 4
+ type: 5
+
+-
+ id: 27
+ team_id: 4
+ type: 6
+
+-
+ id: 28
+ team_id: 4
+ type: 7
+
+-
+ id: 29
+ team_id: 5
+ type: 1
+
+-
+ id: 30
+ team_id: 5
+ type: 2
+
+-
+ id: 31
+ team_id: 5
+ type: 3
+
+-
+ id: 32
+ team_id: 5
+ type: 4
+
+-
+ id: 33
+ team_id: 5
+ type: 5
+
+-
+ id: 34
+ team_id: 5
+ type: 6
+
+-
+ id: 35
+ team_id: 5
+ type: 7
+
+-
+ id: 36
+ team_id: 6
+ type: 1
+
+-
+ id: 37
+ team_id: 6
+ type: 2
+
+-
+ id: 38
+ team_id: 6
+ type: 3
+
+-
+ id: 39
+ team_id: 6
+ type: 4
+
+-
+ id: 40
+ team_id: 6
+ type: 5
+
+-
+ id: 41
+ team_id: 6
+ type: 6
+
+-
+ id: 42
+ team_id: 6
+ type: 7
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index 7ad48f7fb..a2e3b88d7 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -45,7 +45,7 @@
is_admin: false
avatar: avatar3
avatar_email: user3@example.com
- num_repos: 2
+ num_repos: 3
num_members: 2
num_teams: 2
diff --git a/models/issue_comment.go b/models/issue_comment.go
index a829c8066..1c7c57dd0 100644
--- a/models/issue_comment.go
+++ b/models/issue_comment.go
@@ -147,6 +147,10 @@ func (c *Comment) AfterLoad(session *xorm.Session) {
// AfterDelete is invoked from XORM after the object is deleted.
func (c *Comment) AfterDelete() {
+ if c.ID <= 0 {
+ return
+ }
+
_, err := DeleteAttachmentsByComment(c.ID, true)
if err != nil {
diff --git a/models/issue_watch.go b/models/issue_watch.go
index 69e218af0..3e7d24821 100644
--- a/models/issue_watch.go
+++ b/models/issue_watch.go
@@ -71,3 +71,15 @@ func getIssueWatchers(e Engine, issueID int64) (watches []*IssueWatch, err error
Find(&watches)
return
}
+
+func removeIssueWatchersByRepoID(e Engine, userID int64, repoID int64) error {
+ iw := &IssueWatch{
+ IsWatching: false,
+ }
+ _, err := e.
+ Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", repoID).
+ Cols("is_watching", "updated_unix").
+ Where("`issue_watch`.user_id = ?", userID).
+ Update(iw)
+ return err
+}
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 1300065ab..cc262d810 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -186,6 +186,12 @@ var migrations = []Migration{
NewMigration("add u2f", addU2FReg),
// v66 -> v67
NewMigration("add login source id column for public_key table", addLoginSourceIDToPublicKeyTable),
+ // v67 -> v68
+ NewMigration("remove stale watches", removeStaleWatches),
+ // v68 -> V69
+ NewMigration("Reformat and remove incorrect topics", reformatAndRemoveIncorrectTopics),
+ // v69 -> v70
+ NewMigration("move team units to team_unit table", moveTeamUnitsToTeamUnitTable),
}
// Migrate database to current version
diff --git a/models/migrations/v38.go b/models/migrations/v38.go
index 6f66484b0..eb90f9fbf 100644
--- a/models/migrations/v38.go
+++ b/models/migrations/v38.go
@@ -25,10 +25,15 @@ func removeCommitsUnitType(x *xorm.Engine) (err error) {
Created time.Time `xorm:"-"`
}
+ type Team struct {
+ ID int64
+ UnitTypes []int `xorm:"json"`
+ }
+
// Update team unit types
const batchSize = 100
for start := 0; ; start += batchSize {
- teams := make([]*models.Team, 0, batchSize)
+ teams := make([]*Team, 0, batchSize)
if err := x.Limit(batchSize, start).Find(&teams); err != nil {
return err
}
@@ -36,7 +41,7 @@ func removeCommitsUnitType(x *xorm.Engine) (err error) {
break
}
for _, team := range teams {
- ut := make([]models.UnitType, 0, len(team.UnitTypes))
+ ut := make([]int, 0, len(team.UnitTypes))
for _, u := range team.UnitTypes {
if u < V16UnitTypeCommits {
ut = append(ut, u)
diff --git a/models/migrations/v67.go b/models/migrations/v67.go
new file mode 100644
index 000000000..278221919
--- /dev/null
+++ b/models/migrations/v67.go
@@ -0,0 +1,158 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "code.gitea.io/gitea/modules/setting"
+
+ "github.com/go-xorm/xorm"
+)
+
+func removeStaleWatches(x *xorm.Engine) error {
+ type Watch struct {
+ ID int64
+ UserID int64
+ RepoID int64
+ }
+
+ type IssueWatch struct {
+ ID int64
+ UserID int64
+ RepoID int64
+ IsWatching bool
+ }
+
+ type Repository struct {
+ ID int64
+ IsPrivate bool
+ OwnerID int64
+ }
+
+ type Access struct {
+ UserID int64
+ RepoID int64
+ Mode int
+ }
+
+ const (
+ // AccessModeNone no access
+ AccessModeNone int = iota // 0
+ // AccessModeRead read access
+ AccessModeRead // 1
+ )
+
+ accessLevel := func(userID int64, repo *Repository) (int, error) {
+ mode := AccessModeNone
+ if !repo.IsPrivate {
+ mode = AccessModeRead
+ }
+
+ if userID == 0 {
+ return mode, nil
+ }
+
+ if userID == repo.OwnerID {
+ return 4, nil
+ }
+
+ a := &Access{UserID: userID, RepoID: repo.ID}
+ if has, err := x.Get(a); !has || err != nil {
+ return mode, err
+ }
+ return a.Mode, nil
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ repoCache := make(map[int64]*Repository)
+ err := x.BufferSize(setting.IterateBufferSize).Iterate(new(Watch),
+ func(idx int, bean interface{}) error {
+ watch := bean.(*Watch)
+
+ repo := repoCache[watch.RepoID]
+ if repo == nil {
+ repo = &Repository{
+ ID: watch.RepoID,
+ }
+ if _, err := x.Get(repo); err != nil {
+ return err
+ }
+ repoCache[watch.RepoID] = repo
+ }
+
+ // Remove watches from now unaccessible repositories
+ mode, err := accessLevel(watch.UserID, repo)
+ if err != nil {
+ return err
+ }
+ has := AccessModeRead <= mode
+ if has {
+ return nil
+ }
+
+ if _, err = sess.Delete(&Watch{0, watch.UserID, repo.ID}); err != nil {
+ return err
+ }
+ _, err = sess.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repo.ID)
+
+ return err
+ })
+ if err != nil {
+ return err
+ }
+
+ repoCache = make(map[int64]*Repository)
+ err = x.BufferSize(setting.IterateBufferSize).
+ Distinct("issue_watch.user_id", "issue.repo_id").
+ Join("INNER", "issue", "issue_watch.issue_id = issue.id").
+ Where("issue_watch.is_watching = ?", true).
+ Iterate(new(IssueWatch),
+ func(idx int, bean interface{}) error {
+ watch := bean.(*IssueWatch)
+
+ repo := repoCache[watch.RepoID]
+ if repo == nil {
+ repo = &Repository{
+ ID: watch.RepoID,
+ }
+ if _, err := x.Get(repo); err != nil {
+ return err
+ }
+ repoCache[watch.RepoID] = repo
+ }
+
+ // Remove issue watches from now unaccssible repositories
+ mode, err := accessLevel(watch.UserID, repo)
+ if err != nil {
+ return err
+ }
+ has := AccessModeRead <= mode
+ if has {
+ return nil
+ }
+
+ iw := &IssueWatch{
+ IsWatching: false,
+ }
+
+ _, err = sess.
+ Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", watch.RepoID).
+ Cols("is_watching", "updated_unix").
+ Where("`issue_watch`.user_id = ?", watch.UserID).
+ Update(iw)
+
+ return err
+
+ })
+ if err != nil {
+ return err
+ }
+
+ return sess.Commit()
+}
diff --git a/models/migrations/v68.go b/models/migrations/v68.go
new file mode 100644
index 000000000..e27b896c8
--- /dev/null
+++ b/models/migrations/v68.go
@@ -0,0 +1,213 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "fmt"
+ "regexp"
+ "strings"
+
+ "code.gitea.io/gitea/modules/log"
+
+ "github.com/go-xorm/xorm"
+)
+
+var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
+
+func validateTopic(topic string) bool {
+ return len(topic) <= 35 && topicPattern.MatchString(topic)
+}
+
+func reformatAndRemoveIncorrectTopics(x *xorm.Engine) (err error) {
+ log.Info("This migration could take up to minutes, please be patient.")
+
+ type Topic struct {
+ ID int64
+ Name string `xorm:"UNIQUE"`
+ RepoCount int
+ CreatedUnix int64 `xorm:"INDEX created"`
+ UpdatedUnix int64 `xorm:"INDEX updated"`
+ }
+
+ type RepoTopic struct {
+ RepoID int64 `xorm:"UNIQUE(s)"`
+ TopicID int64 `xorm:"UNIQUE(s)"`
+ }
+
+ type Repository struct {
+ ID int64 `xorm:"pk autoincr"`
+ Topics []string `xorm:"TEXT JSON"`
+ }
+
+ if err := x.Sync2(new(Topic)); err != nil {
+ return fmt.Errorf("Sync2: %v", err)
+ }
+ if err := x.Sync2(new(RepoTopic)); err != nil {
+ return fmt.Errorf("Sync2: %v", err)
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ const batchSize = 100
+ touchedRepo := make(map[int64]struct{})
+ delTopicIDs := make([]int64, 0, batchSize)
+
+ log.Info("Validating existed topics...")
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ for start := 0; ; start += batchSize {
+ topics := make([]*Topic, 0, batchSize)
+ if err := x.Cols("id", "name").Asc("id").Limit(batchSize, start).Find(&topics); err != nil {
+ return err
+ }
+ if len(topics) == 0 {
+ break
+ }
+ for _, topic := range topics {
+ if validateTopic(topic.Name) {
+ continue
+ }
+ log.Info("Incorrect topic: id = %v, name = %q", topic.ID, topic.Name)
+
+ topic.Name = strings.Replace(strings.TrimSpace(strings.ToLower(topic.Name)), " ", "-", -1)
+
+ ids := make([]int64, 0, 30)
+ if err := sess.Table("repo_topic").Cols("repo_id").
+ Where("topic_id = ?", topic.ID).Find(&ids); err != nil {
+ return err
+ }
+ log.Info("Touched repo ids: %v", ids)
+ for _, id := range ids {
+ touchedRepo[id] = struct{}{}
+ }
+
+ if validateTopic(topic.Name) {
+ unifiedTopic := Topic{Name: topic.Name}
+ exists, err := sess.Cols("id", "name").Get(&unifiedTopic)
+ log.Info("Exists topic with the name %q? %v, id = %v", topic.Name, exists, unifiedTopic.ID)
+ if err != nil {
+ return err
+ }
+ if exists {
+ log.Info("Updating repo_topic rows with topic_id = %v to topic_id = %v", topic.ID, unifiedTopic.ID)
+ if _, err := sess.Where("topic_id = ? AND repo_id NOT IN "+
+ "(SELECT rt1.repo_id FROM repo_topic rt1 INNER JOIN repo_topic rt2 "+
+ "ON rt1.repo_id = rt2.repo_id WHERE rt1.topic_id = ? AND rt2.topic_id = ?)",
+ topic.ID, topic.ID, unifiedTopic.ID).Update(&RepoTopic{TopicID: unifiedTopic.ID}); err != nil {
+ return err
+ }
+ log.Info("Updating topic `repo_count` field")
+ if _, err := sess.Exec(
+ "UPDATE topic SET repo_count = (SELECT COUNT(*) FROM repo_topic WHERE topic_id = ? GROUP BY topic_id) WHERE id = ?",
+ unifiedTopic.ID, unifiedTopic.ID); err != nil {
+ return err
+ }
+ } else {
+ log.Info("Updating topic: id = %v, name = %q", topic.ID, topic.Name)
+ if _, err := sess.Table("topic").ID(topic.ID).
+ Update(&Topic{Name: topic.Name}); err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ delTopicIDs = append(delTopicIDs, topic.ID)
+ }
+ }
+ if err := sess.Commit(); err != nil {
+ return err
+ }
+
+ sess.Init()
+
+ log.Info("Deleting incorrect topics...")
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ log.Info("Deleting 'repo_topic' rows for topics with ids = %v", delTopicIDs)
+ if _, err := sess.In("topic_id", delTopicIDs).Delete(&RepoTopic{}); err != nil {
+ return err
+ }
+ log.Info("Deleting topics with id = %v", delTopicIDs)
+ if _, err := sess.In("id", delTopicIDs).Delete(&Topic{}); err != nil {
+ return err
+ }
+ if err := sess.Commit(); err != nil {
+ return err
+ }
+
+ delRepoTopics := make([]*RepoTopic, 0, batchSize)
+
+ log.Info("Checking the number of topics in the repositories...")
+ for start := 0; ; start += batchSize {
+ repoTopics := make([]*RepoTopic, 0, batchSize)
+ if err := x.Cols("repo_id").Asc("repo_id").Limit(batchSize, start).
+ GroupBy("repo_id").Having("COUNT(*) > 25").Find(&repoTopics); err != nil {
+ return err
+ }
+ if len(repoTopics) == 0 {
+ break
+ }
+
+ log.Info("Number of repositories with more than 25 topics: %v", len(repoTopics))
+ for _, repoTopic := range repoTopics {
+ touchedRepo[repoTopic.RepoID] = struct{}{}
+
+ tmpRepoTopics := make([]*RepoTopic, 0, 30)
+ if err := x.Where("repo_id = ?", repoTopic.RepoID).Find(&tmpRepoTopics); err != nil {
+ return err
+ }
+
+ log.Info("Repository with id = %v has %v topics", repoTopic.RepoID, len(tmpRepoTopics))
+
+ for i := len(tmpRepoTopics) - 1; i > 24; i-- {
+ delRepoTopics = append(delRepoTopics, tmpRepoTopics[i])
+ }
+ }
+ }
+
+ sess.Init()
+
+ log.Info("Deleting superfluous topics for repositories (more than 25 topics)...")
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ for _, repoTopic := range delRepoTopics {
+ log.Info("Deleting 'repo_topic' rows for 'repository' with id = %v. Topic id = %v",
+ repoTopic.RepoID, repoTopic.TopicID)
+
+ if _, err := sess.Where("repo_id = ? AND topic_id = ?", repoTopic.RepoID,
+ repoTopic.TopicID).Delete(&RepoTopic{}); err != nil {
+ return err
+ }
+ if _, err := sess.Exec(
+ "UPDATE topic SET repo_count = (SELECT repo_count FROM topic WHERE id = ?) - 1 WHERE id = ?",
+ repoTopic.TopicID, repoTopic.TopicID); err != nil {
+ return err
+ }
+ }
+
+ log.Info("Updating repositories 'topics' fields...")
+ for repoID := range touchedRepo {
+ topicNames := make([]string, 0, 30)
+ if err := sess.Table("topic").Cols("name").
+ Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
+ Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
+ return err
+ }
+ log.Info("Updating 'topics' field for repository with id = %v", repoID)
+ if _, err := sess.ID(repoID).Cols("topics").
+ Update(&Repository{Topics: topicNames}); err != nil {
+ return err
+ }
+ }
+ if err := sess.Commit(); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/models/migrations/v69.go b/models/migrations/v69.go
new file mode 100644
index 000000000..8d964688a
--- /dev/null
+++ b/models/migrations/v69.go
@@ -0,0 +1,80 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "fmt"
+
+ "github.com/go-xorm/xorm"
+)
+
+func moveTeamUnitsToTeamUnitTable(x *xorm.Engine) error {
+ // Team see models/team.go
+ type Team struct {
+ ID int64
+ OrgID int64
+ UnitTypes []int `xorm:"json"`
+ }
+
+ // TeamUnit see models/org_team.go
+ type TeamUnit struct {
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ TeamID int64 `xorm:"UNIQUE(s)"`
+ Type int `xorm:"UNIQUE(s)"`
+ }
+
+ if err := x.Sync2(new(TeamUnit)); err != nil {
+ return fmt.Errorf("Sync2: %v", err)
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ // Update team unit types
+ const batchSize = 100
+ for start := 0; ; start += batchSize {
+ teams := make([]*Team, 0, batchSize)
+ if err := x.Limit(batchSize, start).Find(&teams); err != nil {
+ return err
+ }
+ if len(teams) == 0 {
+ break
+ }
+
+ for _, team := range teams {
+ var unitTypes []int
+ if len(team.UnitTypes) == 0 {
+ unitTypes = allUnitTypes
+ } else {
+ unitTypes = team.UnitTypes
+ }
+
+ // insert units for team
+ var units = make([]TeamUnit, 0, len(unitTypes))
+ for _, tp := range unitTypes {
+ units = append(units, TeamUnit{
+ OrgID: team.OrgID,
+ TeamID: team.ID,
+ Type: tp,
+ })
+ }
+
+ if _, err := sess.Insert(&units); err != nil {
+ return fmt.Errorf("Insert team units: %v", err)
+ }
+
+ }
+ }
+
+ if err := dropTableColumns(sess, "team", "unit_types"); err != nil {
+ return err
+ }
+ return sess.Commit()
+}
diff --git a/models/models.go b/models/models.go
index ddf784dee..aaf1370fd 100644
--- a/models/models.go
+++ b/models/models.go
@@ -1,4 +1,5 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
+// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
@@ -121,6 +122,7 @@ func init() {
new(Reaction),
new(IssueAssignees),
new(U2FRegistration),
+ new(TeamUnit),
)
gonicNames := []string{"SSL", "UID"}
@@ -184,6 +186,18 @@ func parsePostgreSQLHostPort(info string) (string, string) {
return host, port
}
+func getPostgreSQLConnectionString(DBHost, DBUser, DBPasswd, DBName, DBParam, DBSSLMode string) (connStr string) {
+ host, port := parsePostgreSQLHostPort(DBHost)
+ if host[0] == '/' { // looks like a unix socket
+ connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
+ url.PathEscape(DBUser), url.PathEscape(DBPasswd), port, DBName, DBParam, DBSSLMode, host)
+ } else {
+ connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
+ url.PathEscape(DBUser), url.PathEscape(DBPasswd), host, port, DBName, DBParam, DBSSLMode)
+ }
+ return
+}
+
func parseMSSQLHostPort(info string) (string, string) {
host, port := "127.0.0.1", "1433"
if strings.Contains(info, ":") {
@@ -214,14 +228,7 @@ func getEngine() (*xorm.Engine, error) {
DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name, Param)
}
case "postgres":
- host, port := parsePostgreSQLHostPort(DbCfg.Host)
- if host[0] == '/' { // looks like a unix socket
- connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
- url.QueryEscape(DbCfg.User), url.QueryEscape(DbCfg.Passwd), port, DbCfg.Name, Param, DbCfg.SSLMode, host)
- } else {
- connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
- url.QueryEscape(DbCfg.User), url.QueryEscape(DbCfg.Passwd), host, port, DbCfg.Name, Param, DbCfg.SSLMode)
- }
+ connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode)
case "mssql":
host, port := parseMSSQLHostPort(DbCfg.Host)
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd)
diff --git a/models/models_test.go b/models/models_test.go
index 649b1e02e..7016fdb4b 100644
--- a/models/models_test.go
+++ b/models/models_test.go
@@ -1,4 +1,5 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
+// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
@@ -53,3 +54,42 @@ func Test_parsePostgreSQLHostPort(t *testing.T) {
assert.Equal(t, test.Port, port)
}
}
+
+func Test_getPostgreSQLConnectionString(t *testing.T) {
+ tests := []struct {
+ Host string
+ Port string
+ User string
+ Passwd string
+ Name string
+ Param string
+ SSLMode string
+ Output string
+ }{
+ {
+ Host: "/tmp/pg.sock",
+ Port: "4321",
+ User: "testuser",
+ Passwd: "space space !#$%^^%^```-=?=",
+ Name: "gitea",
+ Param: "",
+ SSLMode: "false",
+ Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock",
+ },
+ {
+ Host: "localhost",
+ Port: "1234",
+ User: "pgsqlusername",
+ Passwd: "I love Gitea!",
+ Name: "gitea",
+ Param: "",
+ SSLMode: "true",
+ Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true",
+ },
+ }
+
+ for _, test := range tests {
+ connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode)
+ assert.Equal(t, test.Output, connStr)
+ }
+}
diff --git a/models/notification.go b/models/notification.go
index c8376a857..8c36c0c5c 100644
--- a/models/notification.go
+++ b/models/notification.go
@@ -119,7 +119,17 @@ func createOrUpdateIssueNotifications(e Engine, issue *Issue, notificationAuthor
}
}
+ issue.loadRepo(e)
+
for _, watch := range watches {
+ issue.Repo.Units = nil
+ if issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypePullRequests) {
+ continue
+ }
+ if !issue.IsPull && !issue.Repo.CheckUnitUser(watch.UserID, false, UnitTypeIssues) {
+ continue
+ }
+
if err := notifyUser(watch.UserID); err != nil {
return err
}
diff --git a/models/org.go b/models/org.go
index ed0d58306..23f6c58bf 100644
--- a/models/org.go
+++ b/models/org.go
@@ -154,12 +154,26 @@ func CreateOrganization(org, owner *User) (err error) {
Name: ownerTeamName,
Authorize: AccessModeOwner,
NumMembers: 1,
- UnitTypes: allRepUnitTypes,
}
if _, err = sess.Insert(t); err != nil {
return fmt.Errorf("insert owner team: %v", err)
}
+ // insert units for team
+ var units = make([]TeamUnit, 0, len(allRepUnitTypes))
+ for _, tp := range allRepUnitTypes {
+ units = append(units, TeamUnit{
+ OrgID: org.ID,
+ TeamID: t.ID,
+ Type: tp,
+ })
+ }
+
+ if _, err = sess.Insert(&units); err != nil {
+ sess.Rollback()
+ return err
+ }
+
if _, err = sess.Insert(&TeamUser{
UID: owner.ID,
OrgID: org.ID,
@@ -238,6 +252,7 @@ func deleteOrg(e *xorm.Session, u *User) error {
&Team{OrgID: u.ID},
&OrgUser{OrgID: u.ID},
&TeamUser{OrgID: u.ID},
+ &TeamUnit{OrgID: u.ID},
); err != nil {
return fmt.Errorf("deleteBeans: %v", err)
}
diff --git a/models/org_team.go b/models/org_team.go
index 9d8a03141..3b37f936f 100644
--- a/models/org_team.go
+++ b/models/org_team.go
@@ -1,3 +1,4 @@
+// Copyright 2018 The Gitea Authors. All rights reserved.
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
@@ -10,7 +11,6 @@ import (
"strings"
"code.gitea.io/gitea/modules/log"
-
"github.com/go-xorm/xorm"
)
@@ -28,15 +28,16 @@ type Team struct {
Members []*User `xorm:"-"`
NumRepos int
NumMembers int
- UnitTypes []UnitType `xorm:"json"`
+ Units []*TeamUnit `xorm:"-"`
}
-// GetUnitTypes returns unit types the team owned, empty means all the unit types
-func (t *Team) GetUnitTypes() []UnitType {
- if len(t.UnitTypes) == 0 {
- return allRepUnitTypes
+func (t *Team) getUnits(e Engine) (err error) {
+ if t.Units != nil {
+ return nil
}
- return t.UnitTypes
+
+ t.Units, err = getUnitsByTeamID(e, t.ID)
+ return err
}
// HasWriteAccess returns true if team has at least write level access mode.
@@ -178,6 +179,11 @@ func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (e
if err = watchRepo(e, teamUser.UID, repo.ID, false); err != nil {
return err
}
+
+ // Remove all IssueWatches a user has subscribed to in the repositories
+ if err := removeIssueWatchersByRepoID(e, teamUser.UID, repo.ID); err != nil {
+ return err
+ }
}
return nil
@@ -209,11 +215,12 @@ func (t *Team) RemoveRepository(repoID int64) error {
// UnitEnabled returns if the team has the given unit type enabled
func (t *Team) UnitEnabled(tp UnitType) bool {
- if len(t.UnitTypes) == 0 {
- return true
+ if err := t.getUnits(x); err != nil {
+ log.Warn("Error loading repository (ID: %d) units: %s", t.ID, err.Error())
}
- for _, u := range t.UnitTypes {
- if u == tp {
+
+ for _, unit := range t.Units {
+ if unit.Type == tp {
return true
}
}
@@ -270,6 +277,17 @@ func NewTeam(t *Team) (err error) {
return err
}
+ // insert units for team
+ if len(t.Units) > 0 {
+ for _, unit := range t.Units {
+ unit.TeamID = t.ID
+ }
+ if _, err = sess.Insert(&t.Units); err != nil {
+ sess.Rollback()
+ return err
+ }
+ }
+
// Update organization number of teams.
if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil {
sess.Rollback()
@@ -374,11 +392,34 @@ func DeleteTeam(t *Team) error {
return err
}
+ if err := t.getMembers(sess); err != nil {
+ return err
+ }
+
// Delete all accesses.
for _, repo := range t.Repos {
if err := repo.recalculateTeamAccesses(sess, t.ID); err != nil {
return err
}
+
+ // Remove watches from all users and now unaccessible repos
+ for _, user := range t.Members {
+ has, err := hasAccess(sess, user.ID, repo, AccessModeRead)
+ if err != nil {
+ return err
+ } else if has {
+ continue
+ }
+
+ if err = watchRepo(sess, user.ID, repo.ID, false); err != nil {
+ return err
+ }
+
+ // Remove all IssueWatches a user has subscribed to in the repositories
+ if err = removeIssueWatchersByRepoID(sess, user.ID, repo.ID); err != nil {
+ return err
+ }
+ }
}
// Delete team-repo
@@ -396,6 +437,13 @@ func DeleteTeam(t *Team) error {
return err
}
+ // Delete team-unit.
+ if _, err := sess.
+ Where("team_id=?", t.ID).
+ Delete(new(TeamUnit)); err != nil {
+ return err
+ }
+
// Delete team.
if _, err := sess.ID(t.ID).Delete(new(Team)); err != nil {
return err
@@ -518,6 +566,10 @@ func AddTeamMember(team *Team, userID int64) error {
if err := repo.recalculateTeamAccesses(sess, 0); err != nil {
return err
}
+
+ if err = watchRepo(sess, userID, repo.ID, true); err != nil {
+ return err
+ }
}
return sess.Commit()
@@ -558,6 +610,23 @@ func removeTeamMember(e *xorm.Session, team *Team, userID int64) error {
if err := repo.recalculateTeamAccesses(e, 0); err != nil {
return err
}
+
+ // Remove watches from now unaccessible
+ has, err := hasAccess(e, userID, repo, AccessModeRead)
+ if err != nil {
+ return err
+ } else if has {
+ continue
+ }
+
+ if err = watchRepo(e, userID, repo.ID, false); err != nil {
+ return err
+ }
+
+ // Remove all IssueWatches a user has subscribed to in the repositories
+ if err := removeIssueWatchersByRepoID(e, userID, repo.ID); err != nil {
+ return err
+ }
}
// Check if the user is a member of any team in the organization.
@@ -646,3 +715,47 @@ func GetTeamsWithAccessToRepo(orgID, repoID int64, mode AccessMode) ([]*Team, er
And("team_repo.repo_id = ?", repoID).
Find(&teams)
}
+
+// ___________ ____ ___ .__ __
+// \__ ___/___ _____ _____ | | \____ |__|/ |_
+// | |_/ __ \\__ \ / \| | / \| \ __\
+// | |\ ___/ / __ \| Y Y \ | / | \ || |
+// |____| \___ >____ /__|_| /______/|___| /__||__|
+// \/ \/ \/ \/
+
+// TeamUnit describes all units of a repository
+type TeamUnit struct {
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ TeamID int64 `xorm:"UNIQUE(s)"`
+ Type UnitType `xorm:"UNIQUE(s)"`
+}
+
+// Unit returns Unit
+func (t *TeamUnit) Unit() Unit {
+ return Units[t.Type]
+}
+
+func getUnitsByTeamID(e Engine, teamID int64) (units []*TeamUnit, err error) {
+ return units, e.Where("team_id = ?", teamID).Find(&units)
+}
+
+// UpdateTeamUnits updates a teams's units
+func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return err
+ }
+
+ if _, err = sess.Where("team_id = ?", team.ID).Delete(new(TeamUnit)); err != nil {
+ return err
+ }
+
+ if _, err = sess.Insert(units); err != nil {
+ sess.Rollback()
+ return err
+ }
+
+ return sess.Commit()
+}
diff --git a/models/org_test.go b/models/org_test.go
index 42ab4a2a4..c54e7a93b 100644
--- a/models/org_test.go
+++ b/models/org_test.go
@@ -489,8 +489,8 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) {
assert.NoError(t, err)
assert.EqualValues(t, expectedCount, count)
}
- testSuccess(2, 2)
- testSuccess(4, 1)
+ testSuccess(2, 3)
+ testSuccess(4, 2)
}
func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
@@ -503,8 +503,8 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expectedRepoIDs, repoIDs)
}
- testSuccess(2, 1, 100, []int64{3, 5})
- testSuccess(4, 0, 100, []int64{3})
+ testSuccess(2, 1, 100, []int64{3, 5, 32})
+ testSuccess(4, 0, 100, []int64{3, 32})
}
func TestAccessibleReposEnv_Repos(t *testing.T) {
@@ -522,8 +522,8 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
}
assert.Equal(t, expectedRepos, repos)
}
- testSuccess(2, []int64{3, 5})
- testSuccess(4, []int64{3})
+ testSuccess(2, []int64{3, 5, 32})
+ testSuccess(4, []int64{3, 32})
}
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
diff --git a/models/release.go b/models/release.go
index 630995a74..e3760e9ef 100644
--- a/models/release.go
+++ b/models/release.go
@@ -448,6 +448,11 @@ func DeleteReleaseByID(id int64, u *User, delTag bool) error {
}
}
+ rel.Repo = repo
+ if err = rel.LoadAttributes(); err != nil {
+ return fmt.Errorf("LoadAttributes: %v", err)
+ }
+
mode, _ := accessLevel(x, u.ID, rel.Repo)
if err := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{
Action: api.HookReleaseDeleted,
diff --git a/models/repo.go b/models/repo.go
index c95c867f3..d1cc290c4 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -365,22 +365,14 @@ func (repo *Repository) getUnitsByUserID(e Engine, userID int64, isAdmin bool) (
return err
}
- var allTypes = make(map[UnitType]struct{}, len(allRepUnitTypes))
- for _, team := range teams {
- // Administrators can not be limited
- if team.Authorize >= AccessModeAdmin {
- return nil
- }
- for _, unitType := range team.UnitTypes {
- allTypes[unitType] = struct{}{}
- }
- }
-
// unique
var newRepoUnits = make([]*RepoUnit, 0, len(repo.Units))
for _, u := range repo.Units {
- if _, ok := allTypes[u.Type]; ok {
- newRepoUnits = append(newRepoUnits, u)
+ for _, team := range teams {
+ if team.UnitEnabled(u.Type) {
+ newRepoUnits = append(newRepoUnits, u)
+ break
+ }
}
}
@@ -1848,6 +1840,12 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
if _, err = sess.In("issue_id", issueIDs).Delete(&IssueUser{}); err != nil {
return err
}
+ if _, err = sess.In("issue_id", issueIDs).Delete(&Reaction{}); err != nil {
+ return err
+ }
+ if _, err = sess.In("issue_id", issueIDs).Delete(&IssueWatch{}); err != nil {
+ return err
+ }
attachments := make([]*Attachment, 0, 5)
if err = sess.
diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go
index 0448149e6..9d2935d58 100644
--- a/models/repo_collaboration.go
+++ b/models/repo_collaboration.go
@@ -172,5 +172,14 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) {
return err
}
+ if err = watchRepo(sess, uid, repo.ID, false); err != nil {
+ return err
+ }
+
+ // Remove all IssueWatches a user has subscribed to in the repository
+ if err := removeIssueWatchersByRepoID(sess, uid, repo.ID); err != nil {
+ return err
+ }
+
return sess.Commit()
}
diff --git a/models/repo_list_test.go b/models/repo_list_test.go
index 3bccb1aeb..164bc19bf 100644
--- a/models/repo_list_test.go
+++ b/models/repo_list_test.go
@@ -147,10 +147,10 @@ func TestSearchRepositoryByName(t *testing.T) {
count: 14},
{name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, AllPublic: true},
- count: 15},
+ count: 16},
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
- count: 19},
+ count: 20},
{name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
opts: &SearchRepoOptions{Keyword: "test", Page: 1, PageSize: 10, OwnerID: 15, Private: true, AllPublic: true},
count: 13},
@@ -159,7 +159,7 @@ func TestSearchRepositoryByName(t *testing.T) {
count: 11},
{name: "AllPublic/PublicRepositoriesOfOrganization",
opts: &SearchRepoOptions{Page: 1, PageSize: 10, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse},
- count: 15},
+ count: 16},
}
for _, testCase := range testCases {
diff --git a/models/repo_watch.go b/models/repo_watch.go
index fb89a55a1..8019027c1 100644
--- a/models/repo_watch.go
+++ b/models/repo_watch.go
@@ -109,6 +109,23 @@ func notifyWatchers(e Engine, act *Action) error {
act.ID = 0
act.UserID = watches[i].UserID
+ act.Repo.Units = nil
+
+ switch act.OpType {
+ case ActionCommitRepo, ActionPushTag, ActionDeleteTag, ActionDeleteBranch:
+ if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypeCode) {
+ continue
+ }
+ case ActionCreateIssue, ActionCommentIssue, ActionCloseIssue, ActionReopenIssue:
+ if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypeIssues) {
+ continue
+ }
+ case ActionCreatePullRequest, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest:
+ if !act.Repo.CheckUnitUser(act.UserID, false, UnitTypePullRequests) {
+ continue
+ }
+ }
+
if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
diff --git a/models/topic.go b/models/topic.go
index 3b1737f8a..678795a3d 100644
--- a/models/topic.go
+++ b/models/topic.go
@@ -6,6 +6,7 @@ package models
import (
"fmt"
+ "regexp"
"strings"
"code.gitea.io/gitea/modules/util"
@@ -20,10 +21,12 @@ func init() {
)
}
+var topicPattern = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*$`)
+
// Topic represents a topic of repositories
type Topic struct {
ID int64
- Name string `xorm:"unique"`
+ Name string `xorm:"UNIQUE"`
RepoCount int
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
@@ -31,8 +34,8 @@ type Topic struct {
// RepoTopic represents associated repositories and topics
type RepoTopic struct {
- RepoID int64 `xorm:"unique(s)"`
- TopicID int64 `xorm:"unique(s)"`
+ RepoID int64 `xorm:"UNIQUE(s)"`
+ TopicID int64 `xorm:"UNIQUE(s)"`
}
// ErrTopicNotExist represents an error that a topic is not exist
@@ -51,6 +54,11 @@ func (err ErrTopicNotExist) Error() string {
return fmt.Sprintf("topic is not exist [name: %s]", err.Name)
}
+// ValidateTopic checks topics by length and match pattern rules
+func ValidateTopic(topic string) bool {
+ return len(topic) <= 35 && topicPattern.MatchString(topic)
+}
+
// GetTopicByName retrieves topic by name
func GetTopicByName(name string) (*Topic, error) {
var topic Topic
@@ -182,6 +190,13 @@ func SaveTopics(repoID int64, topicNames ...string) error {
}
}
+ topicNames = make([]string, 0, 25)
+ if err := sess.Table("topic").Cols("name").
+ Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
+ Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
+ return err
+ }
+
if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
Topics: topicNames,
}); err != nil {
diff --git a/models/topic_test.go b/models/topic_test.go
index 472f4e52d..ef374e557 100644
--- a/models/topic_test.go
+++ b/models/topic_test.go
@@ -55,3 +55,16 @@ func TestAddTopic(t *testing.T) {
assert.NoError(t, err)
assert.EqualValues(t, 2, len(topics))
}
+
+func TestTopicValidator(t *testing.T) {
+ assert.True(t, ValidateTopic("12345"))
+ assert.True(t, ValidateTopic("2-test"))
+ assert.True(t, ValidateTopic("test-3"))
+ assert.True(t, ValidateTopic("first"))
+ assert.True(t, ValidateTopic("second-test-topic"))
+ assert.True(t, ValidateTopic("third-project-topic-with-max-length"))
+
+ assert.False(t, ValidateTopic("$fourth-test,topic"))
+ assert.False(t, ValidateTopic("-fifth-test-topic"))
+ assert.False(t, ValidateTopic("sixth-go-project-topic-with-excess-length"))
+}
diff --git a/models/user.go b/models/user.go
index 4eeb3e22a..59a27e129 100644
--- a/models/user.go
+++ b/models/user.go
@@ -546,28 +546,46 @@ func (u *User) GetRepositories(page, pageSize int) (err error) {
return err
}
-// GetRepositoryIDs returns repositories IDs where user owned
-func (u *User) GetRepositoryIDs() ([]int64, error) {
+// GetRepositoryIDs returns repositories IDs where user owned and has unittypes
+func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
var ids []int64
- return ids, x.Table("repository").Cols("id").Where("owner_id = ?", u.ID).Find(&ids)
+
+ sess := x.Table("repository").Cols("repository.id")
+
+ if len(units) > 0 {
+ sess = sess.Join("INNER", "repo_unit", "repository.id = repo_unit.repo_id")
+ sess = sess.In("repo_unit.type", units)
+ }
+
+ return ids, sess.Where("owner_id = ?", u.ID).Find(&ids)
}
-// GetOrgRepositoryIDs returns repositories IDs where user's team owned
-func (u *User) GetOrgRepositoryIDs() ([]int64, error) {
+// GetOrgRepositoryIDs returns repositories IDs where user's team owned and has unittypes
+func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
var ids []int64
- return ids, x.Table("repository").
+
+ sess := x.Table("repository").
Cols("repository.id").
- Join("INNER", "team_user", "repository.owner_id = team_user.org_id AND team_user.uid = ?", u.ID).
+ Join("INNER", "team_user", "repository.owner_id = team_user.org_id").
+ Join("INNER", "team_repo", "repository.is_private != ? OR (team_user.team_id = team_repo.team_id AND repository.id = team_repo.repo_id)", true)
+
+ if len(units) > 0 {
+ sess = sess.Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id")
+ sess = sess.In("team_unit.type", units)
+ }
+
+ return ids, sess.
+ Where("team_user.uid = ?", u.ID).
GroupBy("repository.id").Find(&ids)
}
// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
-func (u *User) GetAccessRepoIDs() ([]int64, error) {
- ids, err := u.GetRepositoryIDs()
+func (u *User) GetAccessRepoIDs(units ...UnitType) ([]int64, error) {
+ ids, err := u.GetRepositoryIDs(units...)
if err != nil {
return nil, err
}
- ids2, err := u.GetOrgRepositoryIDs()
+ ids2, err := u.GetOrgRepositoryIDs(units...)
if err != nil {
return nil, err
}
diff --git a/models/user_test.go b/models/user_test.go
index 4fd0bc0fa..20de1a64b 100644
--- a/models/user_test.go
+++ b/models/user_test.go
@@ -159,3 +159,25 @@ func BenchmarkHashPassword(b *testing.B) {
u.HashPassword(pass)
}
}
+
+func TestGetOrgRepositoryIDs(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ user2 := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
+ user4 := AssertExistsAndLoadBean(t, &User{ID: 4}).(*User)
+ user5 := AssertExistsAndLoadBean(t, &User{ID: 5}).(*User)
+
+ accessibleRepos, err := user2.GetOrgRepositoryIDs()
+ assert.NoError(t, err)
+ // User 2's team has access to private repos 3, 5, repo 32 is a public repo of the organization
+ assert.Equal(t, []int64{3, 5, 32}, accessibleRepos)
+
+ accessibleRepos, err = user4.GetOrgRepositoryIDs()
+ assert.NoError(t, err)
+ // User 4's team has access to private repo 3, repo 32 is a public repo of the organization
+ assert.Equal(t, []int64{3, 32}, accessibleRepos)
+
+ accessibleRepos, err = user5.GetOrgRepositoryIDs()
+ assert.NoError(t, err)
+ // User 5's team has no access to any repo
+ assert.Len(t, accessibleRepos, 0)
+}
diff --git a/modules/context/auth.go b/modules/context/auth.go
index 372bcb187..c38cc3948 100644
--- a/modules/context/auth.go
+++ b/modules/context/auth.go
@@ -37,12 +37,6 @@ func Toggle(options *ToggleOptions) macaron.Handler {
return
}
- // Check non-logged users landing page.
- if !ctx.IsSigned && ctx.Req.RequestURI == "/" && setting.LandingPageURL != setting.LandingPageHome {
- ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
- return
- }
-
// Redirect to dashboard if user tries to visit any non-login page.
if options.SignOutRequired && ctx.IsSigned && ctx.Req.RequestURI != "/" {
ctx.Redirect(setting.AppSubURL + "/")
diff --git a/modules/markup/html.go b/modules/markup/html.go
index 4f9d02a8f..a4ef86de2 100644
--- a/modules/markup/html.go
+++ b/modules/markup/html.go
@@ -469,6 +469,9 @@ func shortLinkProcessorFull(ctx *postProcessCtx, node *html.Node, noLink bool) {
} else {
link = strings.Replace(link, " ", "-", -1)
}
+ if !strings.Contains(link, "/") {
+ link = url.PathEscape(link)
+ }
}
urlPrefix := ctx.urlPrefix
if image {
diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go
index fc11532d1..bf7606e1d 100644
--- a/modules/markup/html_test.go
+++ b/modules/markup/html_test.go
@@ -82,12 +82,18 @@ func TestRender_ShortLinks(t *testing.T) {
rawtree := util.URLJoin(AppSubURL, "raw", "master")
url := util.URLJoin(tree, "Link")
otherURL := util.URLJoin(tree, "Other-Link")
+ encodedURL := util.URLJoin(tree, "Link%3F")
imgurl := util.URLJoin(rawtree, "Link.jpg")
otherImgurl := util.URLJoin(rawtree, "Link+Other.jpg")
+ encodedImgurl := util.URLJoin(rawtree, "Link+%23.jpg")
+ notencodedImgurl := util.URLJoin(rawtree, "some", "path", "Link+#.jpg")
urlWiki := util.URLJoin(AppSubURL, "wiki", "Link")
otherURLWiki := util.URLJoin(AppSubURL, "wiki", "Other-Link")
+ encodedURLWiki := util.URLJoin(AppSubURL, "wiki", "Link%3F")
imgurlWiki := util.URLJoin(AppSubURL, "wiki", "raw", "Link.jpg")
otherImgurlWiki := util.URLJoin(AppSubURL, "wiki", "raw", "Link+Other.jpg")
+ encodedImgurlWiki := util.URLJoin(AppSubURL, "wiki", "raw", "Link+%23.jpg")
+ notencodedImgurlWiki := util.URLJoin(AppSubURL, "wiki", "raw", "some", "path", "Link+#.jpg")
favicon := "http://google.com/favicon.ico"
test(
@@ -134,4 +140,24 @@ func TestRender_ShortLinks(t *testing.T) {
"[[Link]] [[Other Link]]",
`Link Other Link
`,
`Link Other Link
`)
+ test(
+ "[[Link?]]",
+ `Link?
`,
+ `Link?
`)
+ test(
+ "[[Link]] [[Other Link]] [[Link?]]",
+ `Link Other Link Link?
`,
+ `Link Other Link Link?
`)
+ test(
+ "[[Link #.jpg]]",
+ `
`,
+ `
`)
+ test(
+ "[[Name|Link #.jpg|alt=\"AltName\"|title='Title']]",
+ `
`,
+ `
`)
+ test(
+ "[[some/path/Link #.jpg]]",
+ `
`,
+ `
`)
}
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index bf5c0130b..b6c835ad4 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -323,7 +323,7 @@ func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.H
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines.
func IsMultilineCommitMessage(msg string) bool {
- return strings.Count(strings.TrimSpace(msg), "\n") > 1
+ return strings.Count(strings.TrimSpace(msg), "\n") >= 1
}
// Actioner describes an action
diff --git a/modules/util/util.go b/modules/util/util.go
index b6acb9796..5dcbe448f 100644
--- a/modules/util/util.go
+++ b/modules/util/util.go
@@ -10,6 +10,7 @@ import (
"strings"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
)
// OptionalBool a boolean that can be "null"
@@ -78,6 +79,18 @@ func URLJoin(base string, elems ...string) string {
return joinedURL
}
+// IsExternalURL checks if rawURL points to an external URL like http://example.com
+func IsExternalURL(rawURL string) bool {
+ parsed, err := url.Parse(rawURL)
+ if err != nil {
+ return true
+ }
+ if len(parsed.Host) != 0 && strings.Replace(parsed.Host, "www.", "", 1) != strings.Replace(setting.Domain, "www.", "", 1) {
+ return true
+ }
+ return false
+}
+
// Min min of two ints
func Min(a, b int) int {
if a > b {
diff --git a/modules/util/util_test.go b/modules/util/util_test.go
index 0d79df605..d9357ffa3 100644
--- a/modules/util/util_test.go
+++ b/modules/util/util_test.go
@@ -7,6 +7,8 @@ package util
import (
"testing"
+ "code.gitea.io/gitea/modules/setting"
+
"github.com/stretchr/testify/assert"
)
@@ -42,3 +44,36 @@ func TestURLJoin(t *testing.T) {
assert.Equal(t, test.Expected, URLJoin(test.Base, test.Elements...))
}
}
+
+func TestIsExternalURL(t *testing.T) {
+ setting.Domain = "try.gitea.io"
+ type test struct {
+ Expected bool
+ RawURL string
+ }
+ newTest := func(expected bool, rawURL string) test {
+ return test{Expected: expected, RawURL: rawURL}
+ }
+ for _, test := range []test{
+ newTest(false,
+ "https://try.gitea.io"),
+ newTest(true,
+ "https://example.com/"),
+ newTest(true,
+ "//example.com"),
+ newTest(true,
+ "http://example.com"),
+ newTest(false,
+ "a/"),
+ newTest(false,
+ "https://try.gitea.io/test?param=false"),
+ newTest(false,
+ "test?param=false"),
+ newTest(false,
+ "//try.gitea.io/test?param=false"),
+ newTest(false,
+ "/hey/hey/hey#3244"),
+ } {
+ assert.Equal(t, test.Expected, IsExternalURL(test.RawURL))
+ }
+}
diff --git a/options/locale/locale_bg-BG.ini b/options/locale/locale_bg-BG.ini
index 810e8d471..f0d6b1c0a 100644
--- a/options/locale/locale_bg-BG.ini
+++ b/options/locale/locale_bg-BG.ini
@@ -79,7 +79,6 @@ has_unconfirmed_mail=Здравейте %s, имате непотвърден а
resend_mail=Щракнете тук, за да се изпрати ново писмо за потвърждение
reset_password=Нулиране на паролата
reset_password_helper=Щракнете тук, за да нулирате паролата си
-password_too_short=Размерът на паролата не може да бъде по-малък от %d знака.
[mail]
activate_account=Моля активирайте Вашия профил
diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini
index 818611ee2..1fc7e193d 100644
--- a/options/locale/locale_cs-CZ.ini
+++ b/options/locale/locale_cs-CZ.ini
@@ -79,7 +79,6 @@ has_unconfirmed_mail=Zdravím, %s, máte nepotvrzenou e-mailovou adresu (%s
resend_mail=Klikněte zde pro odeslání aktivačního e-mailu
reset_password=Obnova vašeho hesla
reset_password_helper=Klikněte zde pro obnovu vašeho hesla
-password_too_short=Délka hesla musí být minimálně %d znaků.
[mail]
activate_account=Prosíme, aktivujte si váš účet
diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini
index 7895827ba..972b62261 100644
--- a/options/locale/locale_de-DE.ini
+++ b/options/locale/locale_de-DE.ini
@@ -83,12 +83,12 @@ host=Host
user=Benutzername
password=Passwort
db_name=Datenbankname
-db_helper=Hinweis für MySQL-Benutzer: Bitte verwende das InnoDB Speichersubsystem und den Zeichensatz "utf8_general_ci".
+db_helper=Hinweis für MySQL-Benutzer: Bitte verwende das InnoDB-Speichersubsystem und den Zeichensatz „utf8_general_ci“.
ssl_mode=SSL
path=Pfad
sqlite_helper=Der Dateipfad zur SQLite3- oder TiDB-Datenbank.
Bitte verwende einen absoluten Pfad, wenn Gitea als Service gestartet wird.
-err_empty_db_path=Der SQLite3 oder TiDB Datenbankpfad darf nicht leer sein.
-err_invalid_tidb_name=Der TiDB Datenbankname darf nicht die Zeichen "." und "-" enthalten.
+err_empty_db_path=Der SQLite3- oder TiDB-Datenbankpfad darf nicht leer sein.
+err_invalid_tidb_name=Der TiDB-Datenbankname darf nicht die Zeichen „.“ und „-“ enthalten.
no_admin_and_disable_registration=Du kannst Selbst-Registrierungen nicht deaktivieren, ohne ein Administratorkonto zu erstellen.
err_empty_admin_password=Das Administrator-Passwort darf nicht leer sein.
@@ -97,17 +97,17 @@ app_name=Seitentitel
app_name_helper=Du kannst hier den Namen deines Unternehmens eingeben.
repo_path=Repository-Verzeichnis
repo_path_helper=Remote-Git-Repositories werden in diesem Verzeichnis gespeichert.
-lfs_path=Git LFS-Wurzelpfad
+lfs_path=Git-LFS-Wurzelpfad
lfs_path_helper=In diesem Verzeichnis werden die Dateien von Git LFS abgespeichert. Leer lassen um LFS zu deaktivieren.
run_user=Ausführen als
run_user_helper=Gebe den Betriebssystem-Benutzernamen ein, unter welchem Gitea laufen soll. Beachte, dass dieser Nutzer Zugriff auf den Repository-Ordner haben muss.
-domain=SSH Server-Domain
+domain=SSH-Server-Domain
domain_helper=Domain oder Host-Adresse für die SSH-URL.
-ssh_port=SSH Server Port
+ssh_port=SSH-Server-Port
ssh_port_helper=Der Port deines SSH-Servers. Leer lassen um SSH zu deaktivieren.
-http_port=Gitea HTTP-Listen-Port
-http_port_helper=Port unter dem der Gitea Web Server laufen soll.
-app_url=Gitea Basis-URL
+http_port=Gitea-HTTP-Listen-Port
+http_port_helper=Port, unter dem der Gitea-Webserver laufen soll.
+app_url=Gitea-Basis-URL
app_url_helper=Adresse für HTTP(S)-Klon-URLs und E-Mail-Benachrichtigungen.
log_root_path=Logdateipfad
log_root_path_helper=Log-Dateien werden in diesem Verzeichnis gespeichert.
@@ -117,8 +117,8 @@ email_title=E-Mail-Einstellungen
smtp_host=SMTP-Server
smtp_from=E-Mail senden als
smtp_from_helper=E-Mail-Adresse, die von Gitea genutzt werden soll. Bitte gib die E-Mail-Adresse im '"Name" '-Format ein.
-mailer_user=SMTP Benutzername
-mailer_password=SMTP Passwort
+mailer_user=SMTP-Benutzername
+mailer_password=SMTP-Passwort
register_confirm=E-Mail-Bestätigung benötigt zum Registrieren
mail_notify=E-Mail-Benachrichtigungen aktivieren
server_service_title=Sonstige Server- und Drittserviceeinstellungen
@@ -131,9 +131,9 @@ federated_avatar_lookup_popup=Föderierte Profilbilder via Libravatar aktivieren
disable_registration=Registrierung deaktivieren
disable_registration_popup=Registrierung neuer Benutzer deaktivieren. Nur Administratoren werden neue Benutzerkonten anlegen können.
allow_only_external_registration_popup=Registrierung nur über externe Services aktiveren.
-openid_signin=OpenID Anmeldung aktivieren
+openid_signin=OpenID-Anmeldung aktivieren
openid_signin_popup=Benutzeranmeldung via OpenID aktivieren.
-openid_signup=OpenID Selbstregistrierung aktivieren
+openid_signup=OpenID-Selbstregistrierung aktivieren
openid_signup_popup=OpenID-basierte Selbstregistrierung aktivieren.
enable_captcha=CAPTCHA aktivieren
enable_captcha_popup=Captcha-Eingabe bei der Registrierung erforderlich.
@@ -147,10 +147,10 @@ confirm_password=Passwort bestätigen
admin_email=E-Mail-Adresse
install_btn_confirm=Gitea installieren
test_git_failed=Fehler beim Test des 'git' Kommandos: %v
-sqlite3_not_available=Diese Gitea-Version unterstützt SQLite3 nicht. Bitte lade die offizielle binäre Version von %s herunter (nicht die 'gobuild'-Version).
+sqlite3_not_available=Diese Gitea-Version unterstützt SQLite3 nicht. Bitte lade die offizielle binäre Version von %s herunter (nicht die „gobuild“-Version).
invalid_db_setting=Datenbankeinstellungen sind ungültig: %v
invalid_repo_path=Repository-Verzeichnis ist ungültig: %v
-run_user_not_match=Der "Ausführen als" Benutzer ist nicht der aktuelle Benutzer: %s -> %s
+run_user_not_match=Der „Ausführen als“-Benutzername ist nicht der aktuelle Benutzername: %s -> %s
save_config_failed=Fehler beim Speichern der Konfiguration: %v
invalid_admin_setting=Administrator-Konto Einstellungen sind ungültig: %v
install_success=Willkommen! Danke, dass du Gitea gewählt hast. Viel Spaß!
@@ -162,7 +162,7 @@ default_allow_create_organization_popup=Neuen Nutzern das Erstellen von Organisa
default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
default_enable_timetracking_popup=Zeiterfassung standardmäßig für neue Repositories aktivieren.
no_reply_address=Versteckte E-Mail-Domain
-no_reply_address_helper=Domain-Namen für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername "Joe" in Git als "joe@noreply.example.org" protokolliert, wenn die versteckte E-Mail-Domäne "noreply.example.org" festgelegt ist.
+no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist.
[home]
uname_holder=E-Mail-Adresse oder Benutzername
@@ -213,7 +213,7 @@ send_reset_mail=E-Mail zum Passwort-zurücksetzen erneut verschicken
reset_password=Passwort zurücksetzen
invalid_code=Dein Bestätigungs-Code ist ungültig oder abgelaufen.
reset_password_helper=Passwort zurückzusetzen
-password_too_short=Das Passwort muss mindenstens %d Zeichen lang sein.
+password_too_short=Das Passwort muss mindestens %d Zeichen lang sein.
non_local_account=Benutzer, die nicht von Gitea verwaltet werden können ihre Passwörter nicht über das Web Interface ändern.
verify=Verifizieren
scratch_code=Einmalpasswort
@@ -225,9 +225,9 @@ login_userpass=Anmelden
login_openid=OpenID
openid_connect_submit=Verbinden
openid_connect_title=Mit bestehendem Konto verbinden
-openid_connect_desc=Die gewählte OpenID URI ist unbekannt. Ordne sie hier einem neuen Account zu.
+openid_connect_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu.
openid_register_title=Neues Konto einrichten
-openid_register_desc=Die gewählte OpenID URI ist unbekannt. Ordne sie hier einem neuen Account zu.
+openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu.
openid_signin_desc=Gib deine OpenID-URI ein. Zum Beispiel: https://anne.me, bob.openid.org.cn oder gnusocial.net/carry.
disable_forgot_password_mail=Das Zurücksetzen von Passwörtern wurde deaktiviert. Bitte wende dich an den Administrator.
@@ -264,8 +264,8 @@ TreeName=Dateipfad
Content=Inhalt
require_error=` darf nicht leer sein.`
-alpha_dash_error=` sollte nur Buchstaben, Zahlen, Bindestriche ('-') und Unterstriche ('_') enthalten`
-alpha_dash_dot_error=` sollte nur Buchstaben, Zahlen, Bindestriche ('-'), Unterstriche ('_') und Punkte ('.') enthalten`
+alpha_dash_error=` sollte nur Buchstaben, Zahlen, Bindestriche („-“) und Unterstriche („_“) enthalten.`
+alpha_dash_dot_error=` sollte nur Buchstaben, Zahlen, Bindestriche („-“), Unterstriche („_“) und Punkte („.“) enthalten.`
git_ref_name_error=` muss ein wohlgeformter Git-Referenzname sein.`
size_error=` muss die Größe %s haben.`
min_size_error=` muss mindestens %s Zeichen enthalten.`
@@ -283,13 +283,13 @@ org_name_been_taken=Der Organisationsname ist bereits vergeben.
team_name_been_taken=Der Teamname ist bereits vergeben.
team_no_units_error=Das Team muss auf mindestens einen Bereich Zugriff haben.
email_been_used=Die E-Mail-Adresse wird bereits verwendet.
-openid_been_used=Die OpenID-Adresse "%s" wird bereits verwendet.
+openid_been_used=Die OpenID-Adresse „%s“ wird bereits verwendet.
username_password_incorrect=Benutzername oder Passwort ist falsch.
enterred_invalid_repo_name=Der eingegebenen Repository-Name ist falsch.
-enterred_invalid_owner_name=Der Name des neuen Besitzers ist invalid.
+enterred_invalid_owner_name=Der Name des neuen Besitzers ist ungültig.
enterred_invalid_password=Das eingegebene Passwort ist falsch.
user_not_exist=Dieser Benutzer ist nicht vorhanden.
-last_org_owner=Du kannst den letzten Benutzer nicht aus dem "Besitzer"-Team entferenen. Es muss mindestens ein Besitzer in einer Organisation geben.
+last_org_owner=Du kannst den letzten Benutzer nicht aus dem „Besitzer“-Team entfernen. Es muss mindestens einen Besitzer in einer Organisation geben.
cannot_add_org_to_team=Eine Organisation kann nicht als Teammitglied hinzugefügt werden.
invalid_ssh_key=Dein SSH-Key kann nicht überprüft werden: %s
@@ -349,7 +349,7 @@ continue=Weiter
cancel=Abbrechen
language=Sprache
-lookup_avatar_by_mail=Avatar anhand der E-Mail-Addresse suchen
+lookup_avatar_by_mail=Profilbild anhand der E-Mail-Addresse suchen
federated_avatar_lookup=Suche nach föderierten Profilbildern
enable_custom_avatar=Benutzerdefiniertes Profilbild benutzen
choose_new_avatar=Neues Profilbild auswählen
@@ -364,7 +364,7 @@ new_password=Neues Passwort
retype_new_password=Neues Passwort erneut eingeben
password_incorrect=Das aktuelle Passwort ist falsch.
change_password_success=Dein Passwort wurde aktualisiert. Bitte verwende dieses beim nächsten Einloggen.
-password_change_disabled=Benutzer, die nicht von Gitea verwaltet werden, können ihr Passwort im Web Interface nicht ändern.
+password_change_disabled=Benutzer, die nicht von Gitea verwaltet werden, können ihr Passwort im Web-Interface nicht ändern.
emails=E-Mail-Adressen
manage_emails=E-Mail-Adressen verwalten
@@ -383,7 +383,7 @@ add_new_email=Neue E-Mail-Adresse hinzufügen
add_new_openid=Neue OpenID-URI hinzufügen
add_email=E-Mail-Adresse hinzufügen
add_openid=OpenID-URI hinzufügen
-add_email_confirmation_sent=Eine Bestätigungs-E-Mail wurde an '%s' gesendet. Bitte überprüfe dein Postfach innerhalb der nächsten %s, um die E-Mail-Adresse zu bestätigen.
+add_email_confirmation_sent=Eine Bestätigungs-E-Mail wurde an „%s“ gesendet. Bitte überprüfe dein Postfach innerhalb der nächsten %s, um die E-Mail-Adresse zu bestätigen.
add_email_success=Die neue E-Mail-Addresse wurde hinzugefügt.
add_openid_success=Die neue OpenID-Adresse wurde hinzugefügt.
keep_email_private=E-Mail-Adresse verbergen
@@ -394,8 +394,8 @@ manage_ssh_keys=SSH-Schlüssel verwalten
manage_gpg_keys=GPG-Schlüssel verwalten
add_key=Schlüssel hinzufügen
ssh_desc=Diese öffentlichen SSH-Keys sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Keys geben dir vollen Zugriff auf deine Repositories.
-gpg_desc=Diese öffentlichen GPG-Keys sind mit deinem Account verbunden. Halte die dazugehörigen privaten SSH-Keys geheim, da diese deine Commits signieren.
-ssh_helper=Brauchst du Hilfe? Hier ist Githubs Anleitung zum Erzeugen von SSH-Schlüsseln oder Lösen einfacher SSH-Probleme.
+gpg_desc=Diese öffentlichen GPG-Keys sind mit deinem Account verbunden. Halte die dazugehörigen privaten GPG-Keys geheim, da diese deine Commits signieren.
+ssh_helper=Brauchst du Hilfe? Hier ist GitHubs Anleitung zum Erzeugen von SSH-Schlüsseln oder zum Lösen einfacher SSH-Probleme.
gpg_helper=Brauchst du Hilfe? Hier ist GitHubs Anleitung über GPG.
add_new_key=SSH-Schlüssel hinzufügen
add_new_gpg_key=GPG-Schlüssel hinzufügen
@@ -407,8 +407,8 @@ subkeys=Unterschlüssel
key_id=Schlüssel-ID
key_name=Schlüsselname
key_content=Inhalt
-add_key_success=Der SSH-Schlüssel "%s" wurde hinzugefügt.
-add_gpg_key_success=Der GPG-Key "%s" wurde hinzugefügt.
+add_key_success=Der SSH-Schlüssel „%s“ wurde hinzugefügt.
+add_gpg_key_success=Der GPG-Key „%s“ wurde hinzugefügt.
delete_key=Entfernen
ssh_key_deletion=SSH-Schlüssel entfernen
gpg_key_deletion=GPG-Schlüssel entfernen
@@ -511,10 +511,10 @@ create_repo=Repository erstellen
default_branch=Standardbranch
mirror_prune=Entfernen
mirror_prune_desc=Entferne veraltete remote-tracking Referenzen
-mirror_interval=Spiegelintervall (gültige Zeiteinheiten sind 'h', 'm', 's')
+mirror_interval=Spiegelintervall (gültige Zeiteinheiten sind „h“, „m“, „s“)
mirror_interval_invalid=Das Spiegel-Intervall ist ungültig.
mirror_address=Klonen via URL
-mirror_address_desc=Bitte gebe alle benötigten Zugangsdaten in der URL an.
+mirror_address_desc=Bitte gib alle benötigten Zugangsdaten in der URL an.
mirror_last_synced=Zuletzt synchronisiert
watchers=Beobachter
stargazers=Favorisiert von
@@ -523,7 +523,7 @@ pick_reaction=Wähle eine Reaktion
reactions_more=und %d weitere
form.reach_limit_of_creation=Du hast bereits dein Limit von %d Repositories erreicht.
-form.name_reserved=Der Repository-Name '%s' ist reserviert.
+form.name_reserved=Der Repository-Name „%s“ ist reserviert.
form.name_pattern_not_allowed='%s' ist nicht erlaubt für Repository-Namen.
need_auth=Authentifizierung zum Klonen benötigt
@@ -588,7 +588,7 @@ editor.edit_file=Datei bearbeiten
editor.preview_changes=Vorschau der Änderungen
editor.cannot_edit_non_text_files=Binärdateien können nicht im Webinterface bearbeitet werden.
editor.edit_this_file=Datei bearbeiten
-editor.must_be_on_a_branch=Du musst dich in einer Branch befinden, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
+editor.must_be_on_a_branch=Du musst dich in einem Branch befinden, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
editor.fork_before_edit=Du musst dieses Repository forken, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
editor.delete_this_file=Datei löschen
editor.must_have_write_access=Du benötigst Schreibzugriff, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
@@ -598,31 +598,31 @@ editor.filename_help=Füge einen Ordner hinzu, indem du seinen Namen und anschli
editor.or=oder
editor.cancel_lower=Abbrechen
editor.commit_changes=Änderungen committen
-editor.add_tmpl='%s/' hinzufügen
-editor.add='%s' hinzufügen
-editor.update='%s' ändern
-editor.delete='%s' löschen
+editor.add_tmpl=„%s/“ hinzufügen
+editor.add=„%s“ hinzufügen
+editor.update=„%s“ ändern
+editor.delete=„%s“ löschen
editor.commit_message_desc=Eine ausführlichere (optionale) Beschreibung hinzufügen…
-editor.commit_directly_to_this_branch=Direkt in die %s-Branch einchecken.
-editor.create_new_branch=Einen neue Branch für diesen Commit erstellen und einen Pull Request starten.
+editor.commit_directly_to_this_branch=Direkt in den Branch „%s“ einchecken.
+editor.create_new_branch=Einen neuen Branch für diesen Commit erstellen und einen Pull Request starten.
editor.new_branch_name_desc=Neuer Branchname…
editor.cancel=Abbrechen
editor.filename_cannot_be_empty=Der Dateiname darf nicht leer sein.
editor.branch_already_exists=Branch '%s' existiert bereits in diesem Repository.
-editor.directory_is_a_file=Der Verzeichnisname '%s' wird bereits als Dateiname in diesem Repository verwendet.
+editor.directory_is_a_file=Der Verzeichnisname „%s“ wird bereits als Dateiname in diesem Repository verwendet.
editor.file_is_a_symlink='%s' ist ein symolischer Link. Symbolische Links können mit dem Web Editor nicht bearbeitet werden.
-editor.filename_is_a_directory=Der Dateiname '%s' wird bereits als Verzeichnisname in diesem Repository verwendet.
-editor.file_editing_no_longer_exists=Die bearbeitete Datei '%s' existiert nicht mehr in diesem Repository.
-editor.file_changed_while_editing=Der Inhalt der Datei hat sich seit dem Beginn der Bearbeitung geändert. Hier klicken um die Änderungen anzusehen, oder Änderungen erneut comitten um sie zu überschreiben.
-editor.file_already_exists=Eine Datei mit dem Namen '%s' ist bereits in diesem Repository vorhanden.
+editor.filename_is_a_directory=Der Dateiname „%s“ wird bereits als Verzeichnisname in diesem Repository verwendet.
+editor.file_editing_no_longer_exists=Die bearbeitete Datei „%s“ existiert nicht mehr in diesem Repository.
+editor.file_changed_while_editing=Der Inhalt der Datei hat sich seit dem Beginn der Bearbeitung geändert. Hier klicken, um die Änderungen anzusehen, oder Änderungen erneut comitten, um sie zu überschreiben.
+editor.file_already_exists=Eine Datei mit dem Namen „%s“ ist bereits in diesem Repository vorhanden.
editor.no_changes_to_show=Keine Änderungen vorhanden.
editor.fail_to_update_file=Fehler beim Ändern/Erstellen der Datei '%s'. Fehler: %v
editor.add_subdir=Verzeichnis erstellen…
-editor.unable_to_upload_files=Fehler beim Hochladen der Dateien nach '%s'. Fehler: %v
+editor.unable_to_upload_files=Fehler beim Hochladen der Dateien nach „%s“. Fehler: %v
editor.upload_files_to_dir=Dateien hochladen nach '%s'
-editor.cannot_commit_to_protected_branch=Commit in den geschützten Branch '%s' ist nicht möglich.
+editor.cannot_commit_to_protected_branch=Commit in den geschützten Branch „%s“ ist nicht möglich.
-commits.desc=Durchsuche die Quellcode Änderungshistorie.
+commits.desc=Durchsuche die Quellcode-Änderungshistorie.
commits.commits=Commits
commits.search=Commits durchsuchen…
commits.find=Suchen
@@ -633,7 +633,7 @@ commits.date=Datum
commits.older=Älter
commits.newer=Neuer
commits.signed_by=Signiert von
-commits.gpg_key_id=GPG Schlüssel-ID
+commits.gpg_key_id=GPG-Schlüssel-ID
ext_issues=Externe Issues
ext_issues.desc=Link zu externem Issuetracker.
@@ -658,7 +658,7 @@ issues.new_label_placeholder=Labelname
issues.new_label_desc_placeholder=Beschreibung
issues.create_label=Label erstellen
issues.label_templates.title=Lade vordefinierte Label
-issues.label_templates.info=Es existieren noch keine Labels. Erstelle ein neues Label ("Neues Label") oder verwende das Standard Label-Set:
+issues.label_templates.info=Es existieren noch keine Label. Erstelle ein neues Label („Neues Label“) oder verwende das Standard-Label-Set:
issues.label_templates.helper=Wähle ein Label
issues.label_templates.use=Label-Set verwenden
issues.label_templates.fail_to_load_file=Fehler beim Laden der Label Template Datei '%s': %v
@@ -676,7 +676,7 @@ issues.delete_branch_at=`löschte die Branch %s %s`
issues.open_tab=%d offen
issues.close_tab=%d geschlossen
issues.filter_label=Label
-issues.filter_label_no_select=Alle Labels
+issues.filter_label_no_select=Alle Label
issues.filter_milestone=Meilenstein
issues.filter_milestone_no_select=Alle Meilensteine
issues.filter_assignee=Zuständig
@@ -768,10 +768,10 @@ issues.cancel_tracking_history=hat die Zeiterfassung %s abgebrochen
issues.time_spent_total=Zeitaufwand insgesamt
issues.time_spent_from_all_authors=`Aufgewendete Zeit: %s`
issues.due_date=Fällig am
-issues.invalid_due_date_format=Das Fälligkeitsdatum muss das Format 'JJJJ-MM-TT' haben.
+issues.invalid_due_date_format=Das Fälligkeitsdatum muss das Format „JJJJ-MM-TT“ haben.
issues.error_modifying_due_date=Fehler beim Ändern des Fälligkeitsdatums.
issues.error_removing_due_date=Fehler beim Entfernen des Fälligkeitsdatums.
-issues.due_date_form=jjjj-mm-tt
+issues.due_date_form=JJJJ-MM-TT
issues.due_date_form_add=Fälligkeitsdatum hinzufügen
issues.due_date_form_update=Fälligkeitsdatum ändern
issues.due_date_form_remove=Fälligkeitsdatum löschen
@@ -787,7 +787,7 @@ pulls.new=Neuer Pull-Request
pulls.compare_changes=Neuer Pull-Request
pulls.compare_changes_desc=Wähle die Ziel- und Quellbranch aus.
pulls.compare_base=Ziel
-pulls.compare_compare=pull von
+pulls.compare_compare=pullen von
pulls.filter_branch=Branch filtern
pulls.no_results=Keine Ergebnisse verfügbar.
pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden.
@@ -827,13 +827,13 @@ milestones.title=Titel
milestones.desc=Beschreibung
milestones.due_date=Fälligkeitsdatum (optional)
milestones.clear=Feld leeren
-milestones.invalid_due_date_format=Das Fälligkeitsdatum muss das Format 'JJJJ-MM-TT' haben.
-milestones.create_success=Der Meilenstein '%s' wurde erstellt.
+milestones.invalid_due_date_format=Das Fälligkeitsdatum muss das Format „JJJJ-MM-TT“ haben.
+milestones.create_success=Der Meilenstein „%s“ wurde erstellt.
milestones.edit=Meilenstein bearbeiten
milestones.edit_subheader=Benutze Meilensteine, um Issues zu organisieren und den Fortschritt darzustellen.
milestones.cancel=Abbrechen
milestones.modify=Meilenstein bearbeiten
-milestones.edit_success=Die Änderungen am Meilenstein "%s" wurden gespeichert.
+milestones.edit_success=Die Änderungen am Meilenstein „%s“ wurden gespeichert.
milestones.deletion=Meilenstein löschen
milestones.deletion_desc=Das Löschen des Meilensteins entfernt ihn von allen Issues. Fortfahren?
milestones.deletion_success=Der Meilenstein wurde gelöscht.
@@ -849,7 +849,7 @@ ext_wiki.desc=Verweis auf externes Wiki.
wiki=Wiki
wiki.welcome=Willkommen im Wiki.
-wiki.welcome_desc=Im Wiki kannst Dokumentation schreiben und mit Mitarbeitern teilen.
+wiki.welcome_desc=Im Wiki kannst du Dokumentation schreiben und sie mit Mitarbeitern teilen.
wiki.desc=Schreibe und teile Dokumentation mit Mitarbeitern.
wiki.create_first_page=Erstelle die erste Seite
wiki.page=Seite
@@ -861,9 +861,9 @@ wiki.last_commit_info=%s hat diese Seite bearbeitet %s
wiki.edit_page_button=Bearbeiten
wiki.new_page_button=Neue Seite
wiki.delete_page_button=Seite löschen
-wiki.delete_page_notice_1=Das Löschen der Wiki-Seite '%s' kann nicht Rückgängig gemacht werden. Fortfahren?
+wiki.delete_page_notice_1=Das Löschen der Wiki-Seite „%s“ kann nicht rückgängig gemacht werden. Fortfahren?
wiki.page_already_exists=Eine Wiki-Seite mit dem gleichen Namen existiert bereits.
-wiki.reserved_page=Der Wiki-Seitenname "%s" ist reserviert.
+wiki.reserved_page=Der Wiki-Seitenname „%s“ ist reserviert.
wiki.pages=Seiten
wiki.last_updated=Zuletzt aktualisiert %s
@@ -911,7 +911,7 @@ activity.published_release_label=Veröffentlicht
search=Suchen
search.search_repo=Repository durchsuchen
-search.results=Suchergebnisse für "%s" in %s
+search.results=Suchergebnisse für „%s“ in %s
settings=Einstellungen
settings.desc=In den Einstellungen kannst du die Einstellungen des Repository anpassen
@@ -925,28 +925,28 @@ settings.hooks=Webhooks
settings.githooks=Git-Hooks
settings.basic_settings=Grundeinstellungen
settings.mirror_settings=Mirror Einstellungen
-settings.sync_mirror=Jetzt Synchronisieren
+settings.sync_mirror=Jetzt synchronisieren
settings.mirror_sync_in_progress=Mirror-Synchronisierung wird zurzeit ausgeführt. Komm in ein paar Minuten zurück.
settings.site=Webseite
settings.update_settings=Einstellungen speichern
settings.advanced_settings=Erweiterte Einstellungen
-settings.wiki_desc=Repository Wiki aktivieren
+settings.wiki_desc=Repository-Wiki aktivieren
settings.use_internal_wiki=Eingebautes Wiki verwenden
settings.use_external_wiki=Externes Wiki verwenden
settings.external_wiki_url=Externe Wiki URL
settings.external_wiki_url_error=Die externe Wiki-URL ist ungültig.
-settings.external_wiki_url_desc=Besucher werden auf die externe Wiki-URL weitergeleitet wenn sie auf das Wiki-Tab klicken.
-settings.issues_desc=Repository Issue-Tracker aktivieren
+settings.external_wiki_url_desc=Besucher werden auf die externe Wiki-URL weitergeleitet, wenn sie auf das Wiki-Tab klicken.
+settings.issues_desc=Repository-Issue-Tracker aktivieren
settings.use_internal_issue_tracker=Integrierten Issue-Tracker verwenden
settings.use_external_issue_tracker=Externen Issue-Tracker verwenden
settings.external_tracker_url=URL eines externen Issue Trackers
settings.external_tracker_url_error=Die URL des externen Issue-Trackers ist ungültig.
-settings.external_tracker_url_desc=Besucher werden auf die externe Issue-Tracker-URL weitergeleitet wenn sie auf das Issues-Tab klicken.
+settings.external_tracker_url_desc=Besucher werden auf die externe Issue-Tracker-URL weitergeleitet, wenn sie auf das Issues-Tab klicken.
settings.tracker_url_format=URL-Format des externen Issue-Systems
settings.tracker_issue_style=Namenskonvention des externen Issue-Trackers
settings.tracker_issue_style.numeric=Numerisch
settings.tracker_issue_style.alphanumeric=Alphanumerisch
-settings.tracker_url_format_desc=Du kannst die Platzhalter {user}
, {repo}
, {index}
für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden.
+settings.tracker_url_format_desc=Du kannst die Platzhalter {user}
, {repo}
, {index}
für den Benutzernamen, den Namen des Repositorys und die Issue-Nummer verwenden.
settings.enable_timetracker=Zeiterfassung aktivieren
settings.allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
settings.pulls_desc=Repository-Pull-Requests aktivieren
@@ -964,22 +964,22 @@ settings.convert_notices_1=Dieser Vorgang wandelt das Mirror-Repository in ein n
settings.convert_confirm=Repository umwandeln
settings.convert_succeed=Das Mirror-Repository wurde erfolgreich in ein normales Repository umgewandelt.
settings.transfer=Besitz übertragen
-settings.transfer_desc=Übertrage dieses Repository auf einen anderen Benutzer oder eine Organisation in der Du Admin-Rechte hast.
-settings.transfer_notices_1=- Du wirst keinen Zugriff mehr haben, wenn der neue Besitzer ein individueller Benutzer ist.
-settings.transfer_notices_2=- Du wirst weiterhin Zugriff haben, wenn der neue Besitzer eine Organisation ist und du einer der Besitzer bist.
+settings.transfer_desc=Übertrage dieses Repository auf einen anderen Benutzer oder eine Organisation, in der du Admin-Rechte hast.
+settings.transfer_notices_1=– Du wirst keinen Zugriff mehr haben, wenn der neue Besitzer ein individueller Benutzer ist.
+settings.transfer_notices_2=– Du wirst weiterhin Zugriff haben, wenn der neue Besitzer eine Organisation ist und du einer der Besitzer bist.
settings.transfer_form_title=Gib den Repository-Namen zur Bestätigung ein:
settings.wiki_delete=Wiki-Daten löschen
settings.wiki_delete_desc=Das Löschen von Wiki-Daten kann nicht rückgängig gemacht werden. Bitte sei vorsichtig.
-settings.wiki_delete_notices_1=- Dies löscht und deaktiviert das Wiki für %s.
+settings.wiki_delete_notices_1=– Dies löscht und deaktiviert das Wiki für %s.
settings.confirm_wiki_delete=Wiki-Daten löschen
-settings.wiki_deletion_success=Repository Wiki-Daten wurden gelöscht.
+settings.wiki_deletion_success=Repository-Wiki-Daten wurden gelöscht.
settings.delete=Dieses Repository löschen
settings.delete_desc=Wenn dieses Repository gelöscht wurde, gibt es keinen Weg zurück. Bitte sei vorsichtig.
settings.delete_notices_1=- Diese Operation kann NICHT rückgängig gemacht werden.
-settings.delete_notices_2=- Die Operation wird das %s-Repository dauerhaft löschen, inklusive der Dateien, Issues, Kommentare und Zugriffseinstellungen.
-settings.delete_notices_fork_1=- Nach dem Löschen werden alle Forks unabhängig.
+settings.delete_notices_2=– Die Operation wird das %s-Repository dauerhaft löschen, inklusive der Dateien, Issues, Kommentare und Zugriffseinstellungen.
+settings.delete_notices_fork_1=– Forks dieses Repositorys werden nach dem Löschen unabhängig.
settings.deletion_success=Das Repository wurde gelöscht.
-settings.update_settings_success=Repository Einstellungen wurden aktualisiert.
+settings.update_settings_success=Repository-Einstellungen wurden aktualisiert.
settings.transfer_owner=Neuer Besitzer
settings.make_transfer=Transfer durchführen
settings.transfer_succeed=Das Repository wurde transferiert.
@@ -994,7 +994,7 @@ settings.search_user_placeholder=Benutzer suchen…
settings.org_not_allowed_to_be_collaborator=Organisationen können nicht als Mitarbeiter hinzugefügt werden.
settings.user_is_org_member=Der Benutzer ist ein Organisationsmitglied und kann nicht als Mitarbeiter hinzugefügt werden.
settings.add_webhook=Webhook hinzufügen
-settings.hooks_desc=Webhooks senden bei bestimmten Gitea-Events automatisch HTTP POST-Requets an einen Server. Lies mehr in unserer Anleitung zu Webhooks (Englisch).
+settings.hooks_desc=Webhooks senden bei bestimmten Gitea-Events automatisch „HTTP POST“-Anfragen an einen Server. Lies mehr in unserer Anleitung zu Webhooks (auf Englisch).
settings.webhook_deletion=Webhook löschen
settings.webhook_deletion_desc=Das Entfernen eines Webhooks löscht seine Einstellungen und Zustellungsverlauf. Fortfahren?
settings.webhook_deletion_success=Webhook wurde entfernt.
@@ -1066,18 +1066,18 @@ settings.title=Titel
settings.deploy_key_content=Inhalt
settings.key_been_used=Ein Deploy-Key mit identischem Inhalt wird bereits verwendet.
settings.key_name_used=Ein Deploy-Key mit diesem Namen existiert bereits.
-settings.add_key_success=Der Deploy-Key '%s' wurde erfolgreich hinzugefügt.
+settings.add_key_success=Der Deploy-Key „%s“ wurde erfolgreich hinzugefügt.
settings.deploy_key_deletion=Deploy-Key löschen
settings.deploy_key_deletion_desc=Nach dem Löschen wird dieser Deploy-Key keinen Zugriff mehr auf dieses Repository haben. Fortfahren?
settings.deploy_key_deletion_success=Der Deploy-Key wurde entfernt.
settings.branches=Branches
-settings.protected_branch=Branch-Protection
+settings.protected_branch=Branch-Schutz
settings.protected_branch_can_push=Push erlauben?
settings.protected_branch_can_push_yes=Du kannst pushen
settings.protected_branch_can_push_no=Du kannst nicht pushen
-settings.branch_protection=Branch-Schutz" für Branch '%s'
+settings.branch_protection=Branch-Schutz für Branch „%s“
settings.protect_this_branch=Brach-Schutz aktivieren
-settings.protect_this_branch_desc=Verhindere Löschen und deaktiviere Git force push auf diese Branch.
+settings.protect_this_branch_desc=Verhindere Löschen und deaktiviere das sog. „force pushing” von Git auf diesen Branch.
settings.protect_whitelist_committers=Push-Whitelist aktivieren
settings.protect_whitelist_committers_desc=Erlaube Nutzern oder Teams auf der Whitelist Push-Beschränkungen zu umgehen.
settings.protect_whitelist_users=Nutzer, die pushen dürfen:
@@ -1085,17 +1085,17 @@ settings.protect_whitelist_search_users=Benutzer suchen…
settings.protect_whitelist_teams=Teams, die pushen dürfen:
settings.protect_whitelist_search_teams=Suche nach Teams…
settings.protect_merge_whitelist_committers=Merge-Whitelist aktivieren
-settings.protect_merge_whitelist_committers_desc=Erlaube Nutzern oder Teams auf der Whitelist Pull-Requests in diese Branch zu mergen.
+settings.protect_merge_whitelist_committers_desc=Erlaube Nutzern oder Teams auf der Whitelist Pull-Requests in diesen Branch zu mergen.
settings.protect_merge_whitelist_users=Nutzer, die mergen dürfen:
settings.protect_merge_whitelist_teams=Teams, die mergen dürfen:
settings.add_protected_branch=Schutz aktivieren
settings.delete_protected_branch=Schutz deaktivieren
-settings.update_protect_branch_success=Branch-protection für die Branch '%s' wurde geändert.
-settings.remove_protected_branch_success=Branch-protection für die Branch '%s' wurde deaktiviert.
-settings.protected_branch_deletion=Brach-Schutz deaktivieren
-settings.protected_branch_deletion_desc=Wenn du die Branch-Protection deaktivierst, können alle Nutzer mit Schreibrechten auf die Branch pushen. Fortfahren?
-settings.default_branch_desc=Wähle eine Standardbranch für Pull-Requests und Code-Commits:
-settings.choose_branch=Wähle eine Branch…
+settings.update_protect_branch_success=Branch-Schutz für den Branch „%s“ wurde geändert.
+settings.remove_protected_branch_success=Branch-Schutz für den Branch „%s“ wurde deaktiviert.
+settings.protected_branch_deletion=Branch-Schutz deaktivieren
+settings.protected_branch_deletion_desc=Wenn du den Branch-Schutz deaktivierst, können alle Nutzer mit Schreibrechten auf den Branch pushen. Fortfahren?
+settings.default_branch_desc=Wähle einen Standardbranch für Pull-Requests und Code-Commits:
+settings.choose_branch=Wähle einen Branch …
settings.no_protected_branch=Es gibt keine geschützten Branches.
diff.browse_source=Quellcode durchsuchen
@@ -1131,7 +1131,7 @@ release.write=Schreiben
release.preview=Vorschau
release.loading=Laden…
release.prerelease_desc=Als Pre-Release kennzeichnen
-release.prerelease_helper=Dieses Release als "ungeeignet für den produktiven Einsatz" markieren.
+release.prerelease_helper=Dieses Release als „ungeeignet für den produktiven Einsatz“ markieren.
release.cancel=Abbrechen
release.publish=Release veröffentlichen
release.save_draft=Entwurf speichern
@@ -1146,27 +1146,29 @@ release.downloads=Downloads
branch.name=Branchname
branch.search=Branches durchsuchen
-branch.already_exists=Eine Branch mit dem Namen '%s' existiert bereits.
+branch.already_exists=Ein Branch mit dem Namen „%s“ existiert bereits.
branch.delete_head=Löschen
-branch.delete=Branch '%s' löschen
+branch.delete=Branch „%s“ löschen
branch.delete_html=Branch löschen
-branch.delete_desc=Das Löschen einer Branch ist permanent. Es KANN NICHT Rückgängig gemacht werden. Fortfahren?
-branch.deletion_success=Branch '%s' wurde gelöscht.
-branch.deletion_failed=Branch '%s' konnte nicht gelöscht werden.
-branch.delete_branch_has_new_commits=Die Branch '%s' kann nicht gelöscht weden, da seit dem letzten Merge neue Commits hinzugefügt wurden.
+branch.delete_desc=Das Löschen eines Branches ist permanent. Es KANN NICHT rückgängig gemacht werden. Fortfahren?
+branch.deletion_success=Branch „%s“ wurde gelöscht.
+branch.deletion_failed=Branch „%s“ konnte nicht gelöscht werden.
+branch.delete_branch_has_new_commits=Der Branch „%s“ kann nicht gelöscht weden, da seit dem letzten Merge neue Commits hinzugefügt wurden.
branch.create_branch=Erstelle Branch %s
branch.create_from=von '%s'
-branch.create_success=Branch '%s' wurde erstellt.
+branch.create_success=Branch „%s“ wurde erstellt.
branch.branch_already_exists=Branch '%s' existiert bereits in diesem Repository.
-branch.branch_name_conflict=Der Branch-Name '%s' steht in Konflikt mit der bestehendem Branch '%s'.
-branch.tag_collision=Branch '%s' kann nicht erstellt werden, da in diesem Repository bereits ein Tag mit dem selben Namen existiert.
+branch.branch_name_conflict=Der Branch-Name „%s“ steht in Konflikt mit dem bestehenden Branch „%s“.
+branch.tag_collision=Branch „%s“ kann nicht erstellt werden, da in diesem Repository bereits ein Tag mit dem selben Namen existiert.
branch.deleted_by=Von %s gelöscht
-branch.restore_success=Branch '%s' wurde wiederhergestellt.
-branch.restore_failed=Wiederherstellung der Branch '%s' fehlgeschlagen.
-branch.protected_deletion_failed=Branch '%s' ist geschützt und kann nicht gelöscht werden.
+branch.restore_success=Branch „%s“ wurde wiederhergestellt.
+branch.restore_failed=Wiederherstellung des Branches „%s“ fehlgeschlagen.
+branch.protected_deletion_failed=Branch „%s“ ist geschützt und kann nicht gelöscht werden.
topic.manage_topics=Themen verwalten
topic.done=Fertig
+topic.count_prompt=Du kannst nicht mehr als 25 Themen auswählen
+topic.format_prompt=Themen müssen mit einem Buchstaben oder einer Zahl beginnen. Sie können Bindestriche (-) enthalten und dürfen nicht länger als 35 Zeichen sein
[org]
org_name_holder=Name der Organisation
@@ -1188,9 +1190,9 @@ team_desc_helper=Beschreibe den Zweck oder die Rolle des Teams.
team_permission_desc=Berechtigungen
team_unit_desc=Zugriff auf Repositorybereiche erlauben
-form.name_reserved=Der Organisationsname '%s' ist reserviert.
-form.name_pattern_not_allowed=Das Muster '%s' ist in Organisationsnamen nicht erlaubt.
-form.create_org_not_allowed=Du bist nicht berechtigt eine Organisation zu erstellen.
+form.name_reserved=Der Organisationsname „%s“ ist reserviert.
+form.name_pattern_not_allowed=Das Muster „%s“ ist in Organisationsnamen nicht erlaubt.
+form.create_org_not_allowed=Du bist nicht berechtigt, eine Organisation zu erstellen.
settings=Einstellungen
settings.options=Organisation
@@ -1229,7 +1231,7 @@ teams.read_access_helper=Mitglieder können Teamrepositories ansehen und klonen.
teams.write_access=Schreibzugriff
teams.write_access_helper=Mitglieder können Teamrepositories ansehen und auf sie pushen.
teams.admin_access=Administratorzugang
-teams.admin_access_helper=Mitglieder können auf Team Repositories "pushen", von ihnen "pullen" und Mitarbeiter hinzufügen.
+teams.admin_access_helper=Mitglieder können auf Team-Repositorys pushen, von ihnen pullen und Mitarbeiter hinzufügen.
teams.no_desc=Dieses Team hat keine Beschreibung
teams.settings=Einstellungen
teams.owners_permission_desc=Besitzer haben vollen Zugriff auf alle Repositories und Admin-Rechte für diese Organisation.
@@ -1238,7 +1240,7 @@ teams.update_settings=Einstellungen aktualisieren
teams.delete_team=Team löschen
teams.add_team_member=Teammitglied hinzufügen
teams.delete_team_title=Team löschen
-teams.delete_team_desc=Das Löschen eines Teams wiederruft den Repository-Zugriff für seine Mitglieder. Fortfahren?
+teams.delete_team_desc=Das Löschen eines Teams widerruft den Repository-Zugriff für seine Mitglieder. Fortfahren?
teams.delete_team_success=Das Team wurde gelöscht.
teams.read_permission_desc=Dieses Team hat Lesezugriff: Mitglieder können Team-Repositories einsehen und klonen.
teams.write_permission_desc=Dieses Team hat Schreibzugriff: Mitglieder können Team-Repositories einsehen und darauf pushen.
@@ -1277,12 +1279,12 @@ dashboard.delete_repo_archives=Alle Repository-Archive löschen
dashboard.delete_repo_archives_success=Alle Repository-Archive wurden gelöscht.
dashboard.delete_missing_repos=Alle Repository-Datensätze mit verlorenen gegangenen Git-Dateien löschen
dashboard.delete_missing_repos_success=Alle Repository-Datensätze mit verlorenen Git-Dateien wurden gelöscht.
-dashboard.git_gc_repos=Garbage Collection auf Repositories ausführen
-dashboard.git_gc_repos_success=Alle Repositories haben Garbage Collection beendet.
-dashboard.resync_all_sshkeys='.ssh/authorized_keys'-Datei mit Gitea SSH-Keys neu schreiben. (Wenn Du den eingebauten SSH Server nutzt, musst du das nicht ausführen.)
+dashboard.git_gc_repos=Garbage-Collection auf Repositories ausführen
+dashboard.git_gc_repos_success=Alle Repositories haben Garbage-Collection beendet.
+dashboard.resync_all_sshkeys=„.ssh/authorized_keys“-Datei mit Gitea-SSH-Keys neu schreiben. (Wenn Du den eingebauten SSH-Server nutzt, musst du das nicht ausführen.)
dashboard.resync_all_sshkeys_success=Alle von Gitea verwalteten öffentlichen Schlüssel wurden neu geschrieben.
-dashboard.resync_all_hooks=Synchronisiere pre-receive, update und post-receive Hooks für alle Repositories.
-dashboard.resync_all_hooks_success=Alle pre-receive, update und post-receive Repository-Hooks wurden synchronisiert.
+dashboard.resync_all_hooks=Synchronisiere „pre-receive“-, „update“- und „post-receive“-Hooks für alle Repositorys erneut.
+dashboard.resync_all_hooks_success=Alle „pre-receive“-, „update“- und „post-receive“-Repository-Hooks wurden erneut synchronisiert.
dashboard.reinit_missing_repos=Alle Git-Repositories mit Einträgen neu einlesen
dashboard.reinit_missing_repos_success=Alle verlorenen Git-Repositories mit existierenden Einträgen wurden erfolgreich aktualisiert.
dashboard.sync_external_users=Externe Benutzerdaten synchronisieren
@@ -1305,11 +1307,11 @@ dashboard.heap_memory_released=Freigegebener Heap-Memory
dashboard.heap_objects=Heap-Objekte
dashboard.bootstrap_stack_usage=Bootstrap-Stack-Auslastung
dashboard.stack_memory_obtained=Erhaltener Stack-Memory
-dashboard.mspan_structures_usage=MSpan-Structures Auslastung
-dashboard.mspan_structures_obtained=MSpan-Structures erhalten
-dashboard.mcache_structures_usage=MCache-Structures Auslastung
+dashboard.mspan_structures_usage=MSpan-Structures-Auslastung
+dashboard.mspan_structures_obtained=Erhaltene MSpan-Structures
+dashboard.mcache_structures_usage=MCache-Structures-Auslastung
dashboard.mcache_structures_obtained=Erhaltene MCache-Structures
-dashboard.profiling_bucket_hash_table_obtained=Analysesatz Hashtabellen erhalten
+dashboard.profiling_bucket_hash_table_obtained=Erhaltene Analysesatz-Hashtabellen
dashboard.gc_metadata_obtained=Erhaltene GC-Metadata
dashboard.other_system_allocation_obtained=Andere erhaltene System-Allokationen
dashboard.next_gc_recycle=Nächster GC-Zyklus
@@ -1342,7 +1344,7 @@ users.max_repo_creation_desc=(Gib -1 ein, um das globale Standardlimit zu verwen
users.is_activated=Account ist aktiviert
users.prohibit_login=Anmelden deaktivieren
users.is_admin=Ist Administrator
-users.allow_git_hook=Darf "Git Hooks" erstellen
+users.allow_git_hook=Darf „Git Hooks“ erstellen
users.allow_import_local=Darf lokale Repositories importieren
users.allow_create_organization=Darf Organisationen erstellen
users.update_profile=Benutzerkonto aktualisieren
@@ -1384,31 +1386,31 @@ auths.bind_dn=DN binden
auths.bind_password=Passwort binden
auths.bind_password_helper=Achtung: Das Passwort wird im Klartext gespeichert. Benutze wenn möglich einen Account mit nur Lesezugriff.
auths.user_base=Basis für Benutzersuche
-auths.user_dn=Benutzer DN
-auths.attribute_username=Benutzername Attribut
+auths.user_dn=Benutzer-DN
+auths.attribute_username=Benutzernamens-Attribut
auths.attribute_username_placeholder=Leerlassen, um den in Gitea eingegebenen Benutzernamen zu verwenden.
auths.attribute_name=Vornamensattribut
auths.attribute_surname=Nachnamensattribut
-auths.attribute_mail=E-Mail Attribut
-auths.attribute_ssh_public_key=Öffentliches SSH-Schlüssel Attribut
+auths.attribute_mail=E-Mail-Attribut
+auths.attribute_ssh_public_key=Öffentlicher-SSH-Schlüssel-Attribut
auths.attributes_in_bind=Hole Attribute im Bind-Kontext
auths.use_paged_search=Seitensuche verwenden
auths.search_page_size=Seitengröße
auths.filter=Benutzerfilter
-auths.admin_filter=Admin Filter
-auths.ms_ad_sa=MS AD Suchattribute
+auths.admin_filter=Admin-Filter
+auths.ms_ad_sa=MS-AD-Suchattribute
auths.smtp_auth=SMTP-Authentifizierungstyp
auths.smtphost=SMTP-Host
auths.smtpport=SMTP-Port
auths.allowed_domains=Erlaubte Domains
-auths.allowed_domains_helper=Leerlassen, um alle Domains zuzulassen. Trenne mehrere Domänen mit einem Komma (',').
+auths.allowed_domains_helper=Leerlassen, um alle Domains zuzulassen. Trenne mehrere Domänen mit einem Komma („,“).
auths.enable_tls=TLS-Verschlüsselung aktivieren
-auths.skip_tls_verify=TLS Verifikation überspringen
-auths.pam_service_name=PAM Dienstname
-auths.oauth2_provider=OAuth2 Anbieter
+auths.skip_tls_verify=TLS-Verifikation überspringen
+auths.pam_service_name=PAM-Dienstname
+auths.oauth2_provider=OAuth2-Anbieter
auths.oauth2_clientID=Client-ID (Schlüssel)
auths.oauth2_clientSecret=Client-Secret
-auths.openIdConnectAutoDiscoveryURL=OpenID Connect Auto Discovery URL
+auths.openIdConnectAutoDiscoveryURL=OpenID-Connect-Auto-Discovery-URL
auths.oauth2_use_custom_url=Benutzerdefinierte URLs anstelle von Standard-URLs verwenden
auths.oauth2_tokenURL=Token-URL
auths.oauth2_authURL=Authorisierungs-URL
@@ -1416,48 +1418,48 @@ auths.oauth2_profileURL=Profil-URL
auths.oauth2_emailURL=E-Mail-URL
auths.enable_auto_register=Automatische Registrierung aktivieren
auths.tips=Tipps
-auths.tips.oauth2.general=OAuth2 Authentifizierung
-auths.tips.oauth2.general.tip=Beim Registrieren einer neuen OAuth2 Authentifizierung sollte die Callback/Weiterleitungs-URL /user/oauth2//callback sein.
-auths.tip.oauth2_provider=OAuth2 Anbieter
-auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter https://bitbucket.org/account/user//oauth-consumers/new und füge die Berechtigung "Account"-"Read" hinzu.
+auths.tips.oauth2.general=OAuth2-Authentifizierung
+auths.tips.oauth2.general.tip=Beim Registrieren einer neuen OAuth2-Authentifizierung sollte die Callback-/Weiterleitungs-URL „/user/oauth2//callback“ sein.
+auths.tip.oauth2_provider=OAuth2-Anbieter
+auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter https://bitbucket.org/account/user//oauth-consumers/new und füge die Berechtigung „Account“ – „Read“ hinzu.
auths.tip.dropbox=Erstelle eine neue App auf https://www.dropbox.com/developers/apps.
-auths.tip.facebook=Erstelle eine neue Anwendung auf https://developers.facebook.com/apps und füge das Produkt "Facebook Login" hinzu.
-auths.tip.github=Erstelle unter https://github.com/settings/applications/new eine neue OAuth Anwendung.
+auths.tip.facebook=Erstelle eine neue Anwendung auf https://developers.facebook.com/apps und füge das Produkt „Facebook Login“ hinzu.
+auths.tip.github=Erstelle unter https://github.com/settings/applications/new eine neue OAuth-Anwendung.
auths.tip.gitlab=Erstelle unter https://gitlab.com/profile/applications eine neue Anwendung.
-auths.tip.google_plus=Du erhältst die OAuth2 Client Zugangsdaten in der Google API Console unter https://console.developers.google.com/
+auths.tip.google_plus=Du erhältst die OAuth2-Client-Zugangsdaten in der Google-API-Konsole unter https://console.developers.google.com/
auths.tip.openid_connect=Benutze die OpenID Connect Discovery URL (/.well-known/openid-configuration) als Endpunkt.
-auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option “Allow this application to be used to Sign in with Twitter” aktiviert ist
+auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option „Allow this application to be used to Sign in with Twitter“ aktiviert ist
auths.edit=Authentifikationsquelle bearbeiten
auths.activated=Diese Authentifikationsquelle ist aktiviert
-auths.new_success=Die Authentifizierung "%s" wurde hinzugefügt.
+auths.new_success=Die Authentifizierung „%s“ wurde hinzugefügt.
auths.update_success=Diese Authentifizierungsquelle wurde aktualisiert.
auths.update=Authentifizierungsquelle aktualisieren
auths.delete=Authentifikationsquelle löschen
auths.delete_auth_title=Authentifizierungsquelle löschen
auths.delete_auth_desc=Das Löschen einer Authentifizierungsquelle verhindert, dass Benutzer sich darüber anmelden können. Fortfahren?
auths.still_in_used=Diese Authentifizierungsquelle wird noch verwendet. Bearbeite oder lösche zuerst alle Benutzer, die diese Authentifizierungsquelle benutzen.
-auths.deletion_success=Die Authentifizierungsquelle '%s' wurde gelöscht.
-auths.login_source_exist=Die Authentifizierungsquelle '%s' existiert bereits.
+auths.deletion_success=Die Authentifizierungsquelle „%s“ wurde gelöscht.
+auths.login_source_exist=Die Authentifizierungsquelle „%s“ existiert bereits.
config.server_config=Serverkonfiguration
config.app_name=Seitentitel
-config.app_ver=Gitea Version
-config.app_url=Gitea Basis-URL
+config.app_ver=Gitea-Version
+config.app_url=Gitea-Basis-URL
config.custom_conf=Konfigurations-Datei-Pfad
-config.domain=SSH Server-Domain
+config.domain=SSH-Server-Domain
config.offline_mode=Lokaler Modus
config.disable_router_log=Router-Log deaktivieren
config.run_user=Ausführen als
config.run_mode=Laufzeit-Modus
-config.git_version=Git Version
-config.repo_root_path=Repository-Verzeichnis
+config.git_version=Git-Version
+config.repo_root_path=Repository-Wurzelpfad
config.lfs_root_path=LFS-Wurzelpfad
config.static_file_root_path=Verzeichnis für statische Dateien
config.log_file_root_path=Logdateipfad
config.script_type=Skript-Typ
config.reverse_auth_user=Nutzer bei Reverse-Authentifizierung
-config.ssh_config=SSH Konfiguration
+config.ssh_config=SSH-Konfiguration
config.ssh_enabled=Aktiviert
config.ssh_start_builtin_server=Eingebauten Server verwenden
config.ssh_domain=Server-Domain
@@ -1465,9 +1467,9 @@ config.ssh_port=Port
config.ssh_listen_port=Listen-Port
config.ssh_root_path=Wurzelverzeichnis
config.ssh_key_test_path=Schlüssel-Test-Pfad
-config.ssh_keygen_path=Keygen ('ssh-keygen') Pfad
+config.ssh_keygen_path=Keygen-Pfad („ssh-keygen“)
config.ssh_minimum_key_size_check=Prüfung der Mindestschlüssellänge
-config.ssh_minimum_key_sizes=Minimale Schlüssellängen
+config.ssh_minimum_key_sizes=Mindestschlüssellängen
config.db_config=Datenbankkonfiguration
config.db_type=Typ
@@ -1481,17 +1483,17 @@ config.service_config=Service-Konfiguration
config.register_email_confirm=E-Mail-Bestätigung benötigt zum Registrieren
config.disable_register=Selbstegistrierung deaktivieren
config.allow_only_external_registration=Registrierung nur über externe Services aktiveren
-config.enable_openid_signup=OpenID Selbstregistrierung aktivieren
-config.enable_openid_signin=OpenID Anmeldung aktivieren
+config.enable_openid_signup=OpenID-Selbstregistrierung aktivieren
+config.enable_openid_signin=OpenID-Anmeldung aktivieren
config.show_registration_button=Schaltfläche zum Registrieren anzeigen
config.require_sign_in_view=Seiten nur für angemeldete Benutzer zugänglich
config.mail_notify=E-Mail-Benachrichtigungen aktivieren
config.disable_key_size_check=Prüfung der Mindestschlüssellänge deaktiveren
config.enable_captcha=CAPTCHA aktivieren
-config.active_code_lives=Aktivierungscode Lebensdauer
+config.active_code_lives=Aktivierungscode-Lebensdauer
config.reset_password_code_lives=Ablaufdatum des Passworts zurücksetzen
config.default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
-config.default_allow_create_organization=Erstellen von Organisationen standarmäßig erlauben
+config.default_allow_create_organization=Erstellen von Organisationen standardmäßig erlauben
config.enable_timetracking=Zeiterfassung aktivieren
config.default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
config.default_allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
@@ -1500,11 +1502,11 @@ config.no_reply_address=Versteckte E-Mail-Domain
config.webhook_config=Webhook-Konfiguration
config.queue_length=Warteschlangenlänge
config.deliver_timeout=Zeitlimit für Zustellung
-config.skip_tls_verify=TLS Verifikation überspringen
+config.skip_tls_verify=TLS-Verifikation überspringen
-config.mailer_config=SMTP Mailer Konfiguration
+config.mailer_config=SMTP-Mailer-Konfiguration
config.mailer_enabled=Aktiviert
-config.mailer_disable_helo=HELO Deaktivieren
+config.mailer_disable_helo=HELO deaktivieren
config.mailer_name=Name
config.mailer_host=Host
config.mailer_user=Benutzer
@@ -1512,8 +1514,8 @@ config.mailer_use_sendmail=Sendmail benutzen
config.mailer_sendmail_path=Sendmail-Pfad
config.mailer_sendmail_args=Zusätzliche Argumente für Sendmail
config.send_test_mail=Test-E-Mail senden
-config.test_mail_failed=Das Senden der Test-E-Mail an '%s' ist fehlgeschlagen: %v
-config.test_mail_sent=Eine Test-E-Mail wurde an '%s' gesendet.
+config.test_mail_failed=Das Senden der Test-E-Mail an „%s“ ist fehlgeschlagen: %v
+config.test_mail_sent=Eine Test-E-Mail wurde an „%s“ gesendet.
config.oauth_config=OAuth-Konfiguration
config.oauth_enabled=Aktiviert
@@ -1533,16 +1535,16 @@ config.session_life_time=Session-Lebensdauer
config.https_only=Nur HTTPS
config.cookie_life_time=Cookie-Lebensdauer
-config.picture_config=Avatar-Konfiguration
+config.picture_config=Bild-und-Profilbild-Konfiguration
config.picture_service=Bilderservice
config.disable_gravatar=Gravatar deaktivieren
config.enable_federated_avatar=Föderierte Profilbilder einschalten
-config.git_config=Git Konfiguration
-config.git_disable_diff_highlight=Diff Syntaxhervorhebung ausschalten
-config.git_max_diff_lines=Max Diff Zeilen (in einer Datei)
-config.git_max_diff_line_characters=Max Diff Zeichen (in einer Zeile)
-config.git_max_diff_files=Max Diff Dateien (Anzeige)
+config.git_config=Git-Konfiguration
+config.git_disable_diff_highlight=Diff-Syntaxhervorhebung ausschalten
+config.git_max_diff_lines=Max. Diff-Zeilen (in einer Datei)
+config.git_max_diff_line_characters=Max. Diff-Zeichen (in einer Zeile)
+config.git_max_diff_files=Max. Diff-Dateien (Angezeigte)
config.git_gc_args=GC-Argumente
config.git_migrate_timeout=Zeitlimit für Migration
config.git_mirror_timeout=Zeitlimit für Mirror-Aktualisierung
@@ -1638,12 +1640,12 @@ mark_all_as_read=Alle als gelesen markieren
[gpg]
error.extract_sign=Die Signatur konnte nicht extrahiert werden
error.generate_hash=Es konnte kein Hash vom Commit generiert werden
-error.no_committer_account=Es ist kein Benutzerkonto mit dieser Commiter-Email verbunden
+error.no_committer_account=Es ist kein Benutzerkonto mit der E-Mail-Adresse des Committers verbunden
error.no_gpg_keys_found=Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
error.not_signed_commit=Kein signierter Commit
error.failed_retrieval_gpg_keys=Fehler beim Abrufen eines Keys des Commiter-Kontos
[units]
-error.no_unit_allowed_repo=Du hast keine Berechtigung auf einen Bereich dieses Repositories zuzugreifen.
-error.unit_not_allowed=Du hast keine Berechtigung auf diesen Repository-Bereich zuzugreifen.
+error.no_unit_allowed_repo=Du hast keine Berechtigung, um auf irgendeinen Bereich dieses Repositories zuzugreifen.
+error.unit_not_allowed=Du hast keine Berechtigung, um auf diesen Repository-Bereich zuzugreifen.
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index e510e9954..21ae775e4 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -213,7 +213,7 @@ send_reset_mail = Click here to resend your password reset email
reset_password = Reset Your Password
invalid_code = Your confirmation code is invalid or has expired.
reset_password_helper = Click here to reset your password
-password_too_short = Password length cannot be less then %d.
+password_too_short = Password length cannot be less than %d characters.
non_local_account = Non-local users can not update their password through the Gitea web interface.
verify = Verify
scratch_code = Scratch code
@@ -1167,6 +1167,8 @@ branch.protected_deletion_failed = Branch '%s' is protected. It cannot be delete
topic.manage_topics = Manage Topics
topic.done = Done
+topic.count_prompt = You can't select more than 25 topics
+topic.format_prompt = Topics must start with a letter or number, can include hyphens(-) and must be no more than 35 characters long
[org]
org_name_holder = Organization Name
diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini
index 5f05cce65..cb9c47a2b 100644
--- a/options/locale/locale_es-ES.ini
+++ b/options/locale/locale_es-ES.ini
@@ -96,7 +96,6 @@ email_not_associate=Esta dirección de correo electrónico no esta asociada a ni
send_reset_mail=Haz clic aquí para reenviar tu email de restauración de contraseña
reset_password=Restablecer su contraseña
reset_password_helper=Haga Clic aquí para restablecer su contraseña
-password_too_short=La longitud de la contraseña no puede ser menor a %d.
verify=Verificar
twofa_scratch_used=Ya has utilizado el código. Has sido redirigido a la página de configuración de dos factores poder remover la inscripción del dispositivo o generar un nuevo código.
twofa_scratch_token_incorrect=El código cero es incorrecto.
diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini
index aefe26919..0d49ff4b3 100644
--- a/options/locale/locale_fi-FI.ini
+++ b/options/locale/locale_fi-FI.ini
@@ -82,7 +82,6 @@ has_unconfirmed_mail=Hei %s, sinulla on varmistamaton sähköposti osoite (%s
resend_mail=Klikkaa tästä uudelleenlähettääksesi aktivointi sähköpostisi
reset_password=Nollaa salasanasi
reset_password_helper=Klikkaa tästä nollataksesi salasanasi
-password_too_short=Salasanan pituus ei voi olla vähemmän kuin %d merkkiä.
verify=Vahvista
[mail]
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index 91961719e..50e90b96f 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -97,7 +97,6 @@ email_not_associate=L'adresse e-mail n'est associée à aucun compte.
send_reset_mail=Cliquez ici pour renvoyer le mail de réinitialisation de votre mot de passe
reset_password=Réinitialiser le mot de passe
reset_password_helper=Cliquez ici pour réinitialiser votre mot de passe
-password_too_short=Le mot de passe doit contenir %d caractères minimum.
verify=Vérifier
scratch_code=Code de secours
use_scratch_code=Utiliser un code de secours
diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini
index b52f8f840..7693a4312 100644
--- a/options/locale/locale_hu-HU.ini
+++ b/options/locale/locale_hu-HU.ini
@@ -101,7 +101,6 @@ email_not_associate=Az email cím nincsen hozzárendelve egyetlen fiókhoz sem.
send_reset_mail=Kattints ide hogy újraküldd a jelszó visszaállító emailt
reset_password=Jelszó visszaállítása
reset_password_helper=Kattintson ide, hogy visszaállítsa a jelszavát
-password_too_short=A jelszó nem lehet rövidebb, mint %d karakter.
verify=Ellenőrzés
scratch_code=Kaparós kód
use_scratch_code=Kaparós kód használata
diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini
index b6999654f..56f14d771 100644
--- a/options/locale/locale_id-ID.ini
+++ b/options/locale/locale_id-ID.ini
@@ -97,7 +97,6 @@ email_not_associate=Alamat surel tidak terhubung dengan akun apapun.
send_reset_mail=Klik di sini untuk mengirim ulang surel pengaturan ulang kata sandi
reset_password=Atur Ulang Kata Sandi Anda
reset_password_helper=Klik di sini untuk mengatur ulang kata sandi anda
-password_too_short=Panjang kata sandi tidak boleh kurang dari %d.
verify=Verifikasi
scratch_code=Kode coretan
use_scratch_code=Gunakan kode coretan
diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini
index 9ea365639..e3b752851 100644
--- a/options/locale/locale_it-IT.ini
+++ b/options/locale/locale_it-IT.ini
@@ -97,7 +97,6 @@ email_not_associate=L'indirizzo email non è associato ad alcuna conta.
send_reset_mail=Clicca qui per inviare nuovamente la tua email di reimpostazione della password
reset_password=Reimposta la tua Password
reset_password_helper=Clicca qui per reimpostare la password
-password_too_short=La lunghezza della password non può essere meno %d caratteri.
verify=Verifica
scratch_code=Codice Gratta e Vinci
use_scratch_code=Utilizza un codice di zero
diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini
index 3c422034e..ea32ad3c3 100644
--- a/options/locale/locale_ja-JP.ini
+++ b/options/locale/locale_ja-JP.ini
@@ -101,7 +101,6 @@ email_not_associate=このEメールアドレスは、どのアカウントに
send_reset_mail=パスワードリセットメールを再送するにはここをクリックしてください
reset_password=パスワードリセット
reset_password_helper=パスワードをリセットするにはここをクリック
-password_too_short=%d文字未満のパスワードは設定できません。
verify=確認
scratch_code=スクラッチコード
use_scratch_code=スクラッチコードを使う
diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini
index cd4528ffb..6497467f4 100644
--- a/options/locale/locale_ko-KR.ini
+++ b/options/locale/locale_ko-KR.ini
@@ -97,7 +97,6 @@ email_not_associate=이 이메일 주소로 등록된 계정이 없습니다.
send_reset_mail=여기를 눌러 비밀번호 초기화 메일을 재전송
reset_password=비밀번호 초기화
reset_password_helper=이곳을 눌러 비밀번호를 재설정
-password_too_short=비밀번호의 길이는 %d글자 미만일 수 없습니다.
verify=확인
scratch_code=스크래치 코드
use_scratch_code=스크래치 코드 사용
diff --git a/options/locale/locale_lt-LT.ini b/options/locale/locale_lt-LT.ini
index 8a9f067ab..e12afe377 100644
--- a/options/locale/locale_lt-LT.ini
+++ b/options/locale/locale_lt-LT.ini
@@ -75,7 +75,6 @@ active_your_account=Aktyvinkite savo paskyrą
resend_mail=Spauskite čia norėdami persiųsti aktyvacijos laišką
reset_password=Atstatyti slaptažodį
reset_password_helper=Paspauskite čia norėdami pakeisti savo slaptažodį
-password_too_short=Slaptažodis negali būti trumpesnis nei %d simbolių.
verify=Patikrinti
[mail]
diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini
index 656910dc8..1b0129ba1 100644
--- a/options/locale/locale_lv-LV.ini
+++ b/options/locale/locale_lv-LV.ini
@@ -54,13 +54,14 @@ password=Parole
db_name=Datu bāzes nosaukums
path=Ceļš
-repo_path=Repozitoriju glabāšanas vieta
-log_root_path=Žurnalizēšanas direktorija
+repo_path=Repozitoriju glabāšanas ceļš
+log_root_path=Žurnalizēšanas ceļš
optional_title=Neobligātie iestatījumi
smtp_host=SMTP resursdators
federated_avatar_lookup_popup=Iespējot apvienoto profila bilžu meklētāju, lai izmantotu atvērtā koda apvienoto servisu balstītu uz libravatar.
openid_signin=Iespējot OpenID autorizāciju
+openid_signin_popup=Iespējot lietotāju autorizāciju ar OpenID.
enable_captcha_popup=Lietotājam reģistrējoties, pieprasīt ievadīt drošības kodu.
admin_password=Parole
confirm_password=Apstipriniet paroli
@@ -101,7 +102,6 @@ email_not_associate=Šī e-pasta adrese nav saistīta ar nevienu kontu.
send_reset_mail=Spiediet šeit, lai nosūtītu paroles maiņas vēstuli uz Jūsu e-pastu
reset_password=Atjaunot savu paroli
reset_password_helper=Nospiediet šeit, lai atjaunotu paroli
-password_too_short=Paroles garums nedrīkst būt mazāks par %d.
verify=Pārbaudīt
scratch_code=Vienreizējais kods
use_scratch_code=Izmantot vienreizējo kodu
diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini
index 6b96b91de..64db50357 100644
--- a/options/locale/locale_nl-NL.ini
+++ b/options/locale/locale_nl-NL.ini
@@ -101,7 +101,6 @@ email_not_associate=Dit emailadres is niet gekoppeld aan een account.
send_reset_mail=Klik hier om de wachtwoord reset mail (nogmaals) te versturen
reset_password=Reset uw wachtwoord
reset_password_helper=Klik hier om uw wachtwoord opnieuw in te stellen.
-password_too_short=De lengte van uw wachtwoord moet minimaal %d karakters zijn.
verify=Verifiëren
scratch_code=Eenmalige code
use_scratch_code=Gebruik een eenmalige code
diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini
index 954a37f5f..3dcb05082 100644
--- a/options/locale/locale_pl-PL.ini
+++ b/options/locale/locale_pl-PL.ini
@@ -97,7 +97,6 @@ email_not_associate=Adres e-mail nie jest powiązany z żadnym kontem.
send_reset_mail=Kliknij tutaj, aby ponownie wysłać e-mail resetowania hasła
reset_password=Resetowanie hasła
reset_password_helper=Kliknij tutaj, aby zresetować hasło
-password_too_short=Długość hasła nie może być mniejsza niż %d znaków.
verify=Potwierdź
scratch_code=Kod jednorazowy
use_scratch_code=Użyj kodu jednorazowego
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index 17b59f7b1..f2ec96dd0 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -213,7 +213,7 @@ send_reset_mail=Clique aqui para re-enviar seu e-mail de redefinição de senha
reset_password=Redefinir sua senha
invalid_code=Seu código de confirmação é inválido ou expirou.
reset_password_helper=Clique aqui para redefinir sua senha
-password_too_short=O comprimento da senha não pode ser menor que %d.
+password_too_short=A senha deve ter %d ou mais caracteres.
non_local_account=Usuários não-locais não podem atualizar sua senha através da interface web do Gitea.
verify=Verificar
scratch_code=Código de backup
@@ -1167,6 +1167,8 @@ branch.protected_deletion_failed=A branch '%s' está protegida. Ela não pode se
topic.manage_topics=Gerenciar Tópicos
topic.done=Feito
+topic.count_prompt=Você não pode selecionar mais de 25 tópicos
+topic.format_prompt=Tópicos devem começar com uma letra ou um número, podem incluir hífens (-) e não devem ter mais de 35 caracteres
[org]
org_name_holder=Nome da organização
diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini
index a8cf3098b..9df7e4e16 100644
--- a/options/locale/locale_ru-RU.ini
+++ b/options/locale/locale_ru-RU.ini
@@ -213,7 +213,7 @@ send_reset_mail=Нажмите сюда, чтобы отправить пись
reset_password=Сброс пароля
invalid_code=Этот код подтверждения недействителен или истек.
reset_password_helper=Нажмите здесь, чтобы сбросить свой пароль
-password_too_short=Длина пароля не менее %d символов.
+password_too_short=Длина пароля не может быть меньше, чем %d символов.
non_local_account=Нелокальные аккаунты не могут изменить пароль через Gitea.
verify=Проверить
scratch_code=Одноразовый пароль
@@ -490,7 +490,7 @@ delete_account_desc=Вы уверены, что хотите навсегда у
[repo]
owner=Владелец
repo_name=Имя репозитория
-repo_name_helper=Лучшие названия репозиториев состоят их коротких, легко запоминаемых и уникальных ключевых слов.
+repo_name_helper=Лучшие названия репозиториев состоят из коротких, легко запоминаемых и уникальных ключевых слов.
visibility=Видимость
visiblity_helper=Сделать репозиторий приватным
visiblity_helper_forced=Администратор сайта настроил параметр видимости новых репозиториев. Репозиторий приватный по умолчанию.
@@ -1167,6 +1167,8 @@ branch.protected_deletion_failed=Ветка '%s' защищена. Её нель
topic.manage_topics=Редактировать тематические метки
topic.done=Сохранить
+topic.count_prompt=Вы не можете выбрать более 25 тем
+topic.format_prompt=Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов
[org]
org_name_holder=Название организации
diff --git a/options/locale/locale_sr-SP.ini b/options/locale/locale_sr-SP.ini
index 3acc22c3a..e20c9ba91 100644
--- a/options/locale/locale_sr-SP.ini
+++ b/options/locale/locale_sr-SP.ini
@@ -79,7 +79,6 @@ has_unconfirmed_mail=Здраво, %s! Имате непотврђену адр
resend_mail=Кликните овде да поново пошаљете писмо
reset_password=Ресет лозинке
reset_password_helper=Кликните овде да ресетујете вашу лозинку
-password_too_short=Лозинка неможе бити краћа од %d карактера.
[mail]
activate_account=Молимо вас активирајте ваш налог
diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini
index e6bb938a5..ca3d703f1 100644
--- a/options/locale/locale_sv-SE.ini
+++ b/options/locale/locale_sv-SE.ini
@@ -97,7 +97,6 @@ email_not_associate=Denna e-postadress är inte knutet till något konto.
send_reset_mail=Klicka här för att skicka e-post med lösenordsåterställning igen
reset_password=Återställ ditt lösenord
reset_password_helper=Klicka här för att återställa ditt lösenord
-password_too_short=Lösenordet får ej vara kortare än %d tecken.
verify=Verifiera
scratch_code=Skrapkod
use_scratch_code=Använd en skrapkod
diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini
index f3ed0f727..17f4fe02b 100644
--- a/options/locale/locale_tr-TR.ini
+++ b/options/locale/locale_tr-TR.ini
@@ -97,7 +97,6 @@ email_not_associate=Bu e-posta adresi hiçbir hesap ile ilişkilendirilmemiştir
send_reset_mail=Parola sıfırlama e-postasını (yeniden) göndermek için buraya tıklayın
reset_password=Parolanızı Sıfırlayın
reset_password_helper=Parolanızı sıfırlamak için buraya tıklayın
-password_too_short=Parola uzunluğu %d karakterden az olamaz.
verify=Doğrula
scratch_code=Çizgi kodu
use_scratch_code=Bir çizgi kodu kullanınız
diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini
index 4f4fda0de..14d6335d8 100644
--- a/options/locale/locale_uk-UA.ini
+++ b/options/locale/locale_uk-UA.ini
@@ -1,4 +1,4 @@
-app_desc=Зручний сервіс, власного Git хостінгу
+app_desc=Зручний сервіс, власного Git хостингу
home=Головна
dashboard=Панель управління
@@ -38,7 +38,10 @@ u2f_use_twofa=Використовуйте дво-факторний код з
u2f_error=Неможливо прочитати ваш ключ безпеки!
u2f_unsupported_browser=Ваш браузер не підтримує U2F ключі. Будь ласка, спробуйте інший браузер.
u2f_error_1=Сталася невідома помилка. Спробуйте ще раз.
+u2f_error_2=Переконайтеся, що ви використовуєте зашифроване з'єднання (https://) та відвідуєте правильну URL-адресу.
u2f_error_3=Сервер не може обробити, ваш запит.
+u2f_error_4=Представлений ключ не дає право на цей запит. Якщо спробуєте зареєструвати його, переконайтеся, що ключ ще не зареєстровано.
+u2f_error_5=Таймаут досягнуто до того, як ваш ключ можна буде прочитати. Перезавантажте, щоб повторити спробу.
u2f_reload=Оновити
repository=Репозиторій
@@ -67,12 +70,12 @@ activities=Дії
pull_requests=Запити на злиття
issues=Проблеми
-cancel=Відміна
+cancel=Відмінити
[install]
install=Встановлення
title=Початкова конфігурація
-docker_helper=Якщо ви запускаєте Gitea всередині Docker, будь ласка уважно прочитайте документацію перед тим, як що-небудь змінити на цій сторінці.
+docker_helper=Якщо ви запускаєте Gitea всередині Docker, будь ласка уважно прочитайте документацію перед тим, як щось змінити на цій сторінці.
requite_db_desc=Gitea потребує MySQL, PostgreSQL, MSSQL, SQLite3 або TiDB.
db_title=Налаштування бази даних
db_type=Тип бази даних
@@ -104,6 +107,7 @@ ssh_port_helper=Номер порту, який використовує SSH с
http_port=Gitea HTTP порт
http_port_helper=Номер порту, який буде прослуховуватися Giteas веб-сервером.
app_url=Базова URL-адреса Gitea
+app_url_helper=Базова адреса для HTTP(S) клонування через URL та повідомлень електронної пошти.
log_root_path=Шлях до лог файлу
log_root_path_helper=Файли журналу будуть записані в цей каталог.
@@ -111,6 +115,7 @@ optional_title=Додаткові налаштування
email_title=Налаштування Email
smtp_host=SMTP хост
smtp_from=Відправляти Email від імені
+smtp_from_helper=Електронна пошта для використання в Gіtea. Введіть звичайну електронну адресу або використовуйте формат: "Ім'я" .
mailer_user=SMTP Ім'я кристувача
mailer_password=SMTP Пароль
register_confirm=Потрібно підтвердити електронну пошту для реєстрації
@@ -124,9 +129,11 @@ federated_avatar_lookup=Увімкнути федеративні аватари
federated_avatar_lookup_popup=Увімкнути зовнішний Аватар за допомогою Libravatar.
disable_registration=Вимкнути самостійну реєстрацію
disable_registration_popup=Вимкнути самостійну реєстрацію користувачів, тільки адміністратор може створювати нові облікові записи.
+allow_only_external_registration_popup=Включити реєстрацію тільки через зовнішні сервіси.
openid_signin=Увімкнути реєстрацію за допомогою OpenID
openid_signin_popup=Увімкнути вхід за допомогою OpenID.
openid_signup=Увімкнути самостійну реєстрацію за допомогою OpenID
+openid_signup_popup=Увімкнути самореєстрацію користувачів на основі OpenID.
enable_captcha=Увімкнути CAPTCHA
enable_captcha_popup=Вимагати перевірку CAPTCHA при самостійній реєстрації користувача.
require_sign_in_view=Вимагати авторизації для перегляду сторінок
@@ -139,7 +146,9 @@ confirm_password=Підтвердження пароля
admin_email=Адреса електронної пошти
install_btn_confirm=Встановлення Gitea
test_git_failed=Не в змозі перевірити 'git' команду: %v
+sqlite3_not_available=Ця версія Gitea не підтримує SQLite3. Будь ласка, завантажте офіційну бінарну версію з %s (не версію gobuild).
invalid_db_setting=Налаштування бази даних є некоректними: %v
+invalid_repo_path=Помилковий шлях до кореня репозиторію: %v
save_config_failed=Не в змозі зберегти конфігурацію: %v
invalid_admin_setting=Неприпустимі налаштування облікового запису адміністратора: %v
install_success=Ласкаво просимо! Дякуємо вам за вибір Gitea. Розважайтеся, і будьте обережні!
@@ -151,6 +160,7 @@ default_allow_create_organization_popup=Дозволити новим облік
default_enable_timetracking=Увімкнути відстеження часу за замовчуванням
default_enable_timetracking_popup=Включити відстеження часу для нових репозиторіїв за замовчуванням.
no_reply_address=Прихований поштовий домен
+no_reply_address_helper=Доменне ім'я для користувачів із прихованою електронною адресою. Наприклад, ім'я користувача 'joe' буде входити в Git як 'joe@noreply.example.org', якщо для прихованого домену електронної пошти встановлено 'noreply.example.org'.
[home]
uname_holder=Ім'я користувача або Ел. пошта
@@ -175,11 +185,13 @@ code=Код
repo_no_results=Відповідних репозиторіїв не знайдено.
user_no_results=Відповідних користувачів не знайдено.
org_no_results=Відповідних організацій не знайдено.
+code_no_results=Відповідний пошуковому запитанню код не знайдено.
code_search_results=Результати пошуку '%s'
[auth]
create_new_account=Реєстрація облікового запису
register_helper_msg=Вже зареєстровані? Увійдіть зараз!
+social_register_helper_msg=Вже є аккаунт? Зв'яжіть його зараз!
disable_register_prompt=Вибачте, можливість реєстрації відключена. Будь ласка, зв'яжіться з адміністратором сайту.
disable_register_mail=Підтвердження реєстрації електронною поштою вимкнено.
remember_me=Запам'ятати мене
@@ -199,19 +211,22 @@ send_reset_mail=Натисніть сюди, щоб відправити лис
reset_password=Скинути пароль
invalid_code=Цей код підтвердження недійсний або закінчився.
reset_password_helper=Натисніть тут для скидання пароля
-password_too_short=Довжина пароля не може бути меншою за %d.
+password_too_short=Довжина пароля не може бути меншою за %d символів.
non_local_account=Нелокальні акаунти не можуть змінити пароль через Gitea.
verify=Підтвердити
scratch_code=Одноразовий пароль
use_scratch_code=Використовувати одноразовий пароль
-twofa_scratch_used=Ви використовували одноразовий пароль. Ви були перенаправлені на сторінку налаштувань для генерації нового коду або відключення двуфакторной аутентифікації.
+twofa_scratch_used=Ви використовували одноразовий пароль. Ви були перенаправлені на сторінку налаштувань для генерації нового коду або відключення двуфакторної автентифікації.
twofa_passcode_incorrect=Ваш пароль є невірним. Якщо ви втратили пристрій, використовуйте ваш одноразовий пароль.
twofa_scratch_token_incorrect=Невірний одноразовий пароль.
login_userpass=Увійти
login_openid=OpenID
openid_connect_submit=Під’єднатися
openid_connect_title=Підключитися до існуючого облікового запису
+openid_connect_desc=Вибраний OpenID URI невідомий. Пов'яжіть його з новим обліковим записом тут.
openid_register_title=Створити новий обліковий запис
+openid_register_desc=Вибраний OpenID URI невідомий. Пов'яжіть йогоз новим обліковим записом тут.
+openid_signin_desc=Введіть свій ідентифікатор OpenID. Наприклад: https://anne.me, bob.openid.org.cn або gnusocial.net/carry.
disable_forgot_password_mail=На жаль скидання пароля відключене. Будь ласка, зв'яжіться з адміністратором сайту.
[mail]
@@ -247,6 +262,8 @@ TreeName=Шлях до файлу
Content=Зміст
require_error=` не може бути пустим.`
+alpha_dash_error=` повинен містити тільки літерно-цифрові символи, дефіс ('-') та підкреслення ('_'). `
+alpha_dash_dot_error=` повинен містити тільки літерно-цифрові символи, дефіс ('-') , підкреслення ('_') та точки ('.'). `
git_ref_name_error=` повинен бути правильним посилальним ім'ям Git.`
size_error=` повинен бути розмір %s.`
min_size_error=` повинен бути принаймні %s символів.`
@@ -262,32 +279,41 @@ username_been_taken=Ім'я користувача вже зайнято.
repo_name_been_taken=Ім'я репозіторію вже використовується.
org_name_been_taken=Назва організації вже зайнято.
team_name_been_taken=Назва команди вже зайнято.
+team_no_units_error=Дозволити доступ до принаймні одного розділу репозитарію.
email_been_used=Ця електронна адреса вже використовується.
openid_been_used=OpenID адреса '%s' вже використовується.
username_password_incorrect=Неправильне ім'я користувача або пароль.
enterred_invalid_repo_name=Невірно введено ім'я репозиторію.
+enterred_invalid_owner_name=Ім'я нового власника не є дійсним.
+enterred_invalid_password=Введений вами пароль некоректний.
user_not_exist=Даний користувач не існує.
+last_org_owner=Ви не можете вилучити останнього користувача з команди 'власники'. У кожній команді має бути хоча б один власник.
cannot_add_org_to_team=Організацію неможливо додати як учасника команди.
invalid_ssh_key=Неможливо перевірити ваш SSH ключ: %s
invalid_gpg_key=Неможливо перевірити ваш GPG ключ: %s
+unable_verify_ssh_key=Не вдається підтвердити ключ SSH; подвійно перевірте його на наявність похибки.
auth_failed=Помилка автентифікації: %v
+still_own_repo=Ваш обліковий запис володіє одним або декількома репозиторіями; видаліть або перенесіть їх в першу чергу.
+still_has_org=Ваш обліковий запис є учасником однієї чи декількох організацій; вийдіть з них в першу чергу.
+org_still_own_repo=Ця організація як і раніше володіє одним або декількома репозиторіями; спочатку видаліть або перенесіть їх.
target_branch_not_exist=Цільової гілки не існує.
[user]
change_avatar=Змінити свій аватар…
-join_on=Приєднався
+join_on=Приєднався(-лась)
repositories=Репозиторії
activity=Публічна активність
-followers=Підписники
+followers=Читачі
starred=Обрані Репозиторії
-following=Слідкувати
+following=Читає
follow=Підписатися
unfollow=Відписатися
form.name_reserved=Ім'я користувача "%s" зарезервовано.
+form.name_pattern_not_allowed=Шаблон '%s' не дозволено в імені користувача.
[settings]
profile=Профіль
@@ -309,6 +335,7 @@ u2f=Ключі безпеки
public_profile=Загальнодоступний профіль
profile_desc=Ваша адреса електронної пошти використовуватиметься для сповіщення та інших операцій.
+password_username_disabled=Нелокальним користувачам заборонено змінювати ім'я користувача. Щоб отримати докладнішу інформацію, зв'яжіться з адміністратором сайту.
full_name=Повне ім'я
website=Веб-сайт
location=Місцезнаходження
@@ -316,7 +343,7 @@ update_profile=Оновити профіль
update_profile_success=Профіль успішно оновлено.
change_username=Ваше Ім'я кристувача було змінено.
continue=Продовжити
-cancel=Відміна
+cancel=Відмінити
language=Мова
lookup_avatar_by_mail=Знайти Аватар за адресою електронної пошти
@@ -338,32 +365,47 @@ password_change_disabled=Нелокальні акаунти не можуть
emails=Адреса електронної пошти
manage_emails=Керування адресами ел. пошти
+manage_openid=Керування OpenID
email_desc=Ваша основна адреса електронної пошти використовуватиметься для сповіщення та інших операцій.
primary=Основний
primary_email=Зробити основним
delete_email=Видалити
email_deletion=Видалити адресу електронної пошти
+email_deletion_success=Адресу електронної пошти було видалено.
+openid_deletion=Видалити адресу OpenID
+openid_deletion_success=Адреса OpenID була видалена.
add_new_email=Додати нову адресу електронної пошти
+add_new_openid=Додати новий OpenID URI
add_email=Додати адресу електронної пошти
+add_openid=Додати OpenID URI
add_email_confirmation_sent=Електронний лист із підтвердженням було відправлено на '%s', будь ласка, перевірте вашу поштову скриньку протягом наступних %s, щоб підтвердити адресу.
+add_email_success=Додано нову адресу електронної пошти.
+add_openid_success=Нова адреса OpenID була додана.
keep_email_private=Приховати адресу електронної пошти
keep_email_private_popup=Вашу адресу електронної пошти буде приховано від інших користувачів.
manage_ssh_keys=Керувати SSH ключами
manage_gpg_keys=Керувати GPG ключами
add_key=Додати ключ
+ssh_desc=Ці відкриті SSH-ключі пов'язані з вашим обліковим записом. Відповідні приватні ключі дозволяють отримати повний доступ до ваших репозиторіїв.
+gpg_desc=Ці публічні ключі GPG пов'язані з вашим обліковим записом. Тримайте свої приватні ключі в безпеці, оскільки вони дозволяють здійснювати перевірку комітів.
ssh_helper=Потрібна допомога? Дивіться гід на GitHub з генерації ключів SSH або виправлення типових неполадок SSH.
gpg_helper= Потрібна допомога? Перегляньте посібник GitHub про GPG .
add_new_key=Додати SSH ключ
add_new_gpg_key=Додати GPG ключ
+ssh_key_been_used=Цей ключ SSH вже додано до вашого облікового запису.
+ssh_key_name_used=Ключ SSH з таким самим ім'ям вже додано до вашого облікового запису.
+gpg_key_id_used=Публічний ключ GPG з таким самим ідентифікатором вже існує.
subkeys=Підключі
key_id=ID ключа
key_name=Ім'я ключа
key_content=Зміст
add_key_success=SSH ключ '%s' додано.
+add_gpg_key_success=GPG ключ '%s' додано.
delete_key=Видалити
ssh_key_deletion=Видалити SSH ключ
gpg_key_deletion=Видалити GPG ключ
+ssh_key_deletion_desc=Видалення ключа SSH скасовує доступ до вашого облікового запису. Продовжити?
gpg_key_deletion_desc=Видалення GPG ключа скасовує перевірку підписаних ним комітів. Продовжити?
ssh_key_deletion_success=SSH було видалено.
gpg_key_deletion_success=GPG було видалено.
@@ -392,19 +434,33 @@ generate_token=Згенерувати токен
delete_token=Видалити
access_token_deletion=Видалити токен доступу
+twofa_desc=Двофакторна автентифікація підвищує безпеку вашого облікового запису.
+twofa_is_enrolled=Ваш обліковий запис на даний час використовує двофакторну автентифікацію.
+twofa_not_enrolled=Ваш обліковий запис наразі не використовує двофакторну автентифікаціїю.
twofa_disable=Вимкнути двофакторну автентифікацію
+twofa_scratch_token_regenerate=Перестворити токен одноразового пароля
+twofa_enroll=Увімкнути двофакторну автентифікацію
+twofa_disable_note=При необхідності можна відключити двофакторну автентифікацію.
+regenerate_scratch_token_desc=Якщо ви втратили свій токен одноразового пароля або вже використовували його для входу, ви можете скинути його тут.
+twofa_disabled=Двофакторна автентифікація вимкнена.
+scan_this_image=Проскануйте це зображення вашим додатком для двуфакторної автентифікації:
or_enter_secret=Або введіть секрет: %s
+passcode_invalid=Некоректний пароль. Спробуй ще раз.
+u2f_desc=Ключами безпеки є апаратні пристрої, що містять криптографічні ключі. Вони можуть використовуватися для двофакторної автентифікації. Ключ безпеки повинен підтримувати стандарт FIDO U2F.
u2f_register_key=Додати ключ безпеки
u2f_nickname=Псевдонім
u2f_delete_key=Видалити ключ безпеки
manage_account_links=Керування обліковими записами
+manage_account_links_desc=Ці зовнішні акаунти прив'язані до вашого аккаунту Gitea.
remove_account_link=Видалити облікові записи
orgs_none=Ви не є учасником будь-якої організації.
+repos_none=У вас немає власних репозиторіїв
delete_account=Видалити ваш обліковий запис
+delete_prompt=Ця операція остаточно видалить обліковий запис користувача. Це НЕ МОЖЛИВО відмінити.
confirm_delete_account=Підтвердження видалення
delete_account_title=Видалити цей обліковий запис
@@ -413,6 +469,7 @@ owner=Власник
repo_name=Назва репозиторію
visibility=Видимість
visiblity_helper=Зробити репозиторій приватним
+visiblity_fork_helper=(Зміна цього вплине на всі форки.)
clone_helper=Потрібна допомога у клонуванні? Відвідайте Допомогу.
fork_repo=Форкнути репозиторій
fork_from=Форк з
@@ -424,6 +481,7 @@ license=Ліцензія
license_helper=Виберіть ліцензійний файл.
readme=README
readme_helper=Виберіть шаблон README.
+auto_init=Ініціалізувати репозиторій (Додає .gitignore, LICENSE та README)
create_repo=Створити репозиторій
default_branch=Головна гілка
mirror_prune=Очистити
@@ -490,6 +548,7 @@ file_history=Історія
file_view_raw=Перегляд Raw
file_permalink=Постійне посилання
file_too_large=Цей файл завеликий щоб бути показаним.
+video_not_supported_in_browser=Ваш браузер не підтримує тег 'video' HTML5.
stored_lfs=Збережено з Git LFS
commit_graph=Графік комітів
@@ -497,6 +556,7 @@ editor.new_file=Новий файл
editor.upload_file=Завантажити файл
editor.edit_file=Редагування файлу
editor.preview_changes=Попередній перегляд змін
+editor.cannot_edit_non_text_files=Бінарні файли не можливо редагувати у веб-інтерфейсі.
editor.edit_this_file=Редагувати файл
editor.must_be_on_a_branch=Ви повинні бути у гілці щоб зробити, або запропонувати зміни до цього файлу.
editor.fork_before_edit=Необхідно зробити форк цього репозиторій, щоб внести або запропонувати зміни в цей файл.
@@ -515,7 +575,7 @@ editor.commit_message_desc=Додати необов'язковий розшир
editor.commit_directly_to_this_branch=Зробіть коміт прямо в гілку %s.
editor.create_new_branch=Створити нову гілку для цього коміту та відкрити запит на злиття.
editor.new_branch_name_desc=Ім'я нової гілки…
-editor.cancel=Відміна
+editor.cancel=Відмінити
editor.filename_cannot_be_empty=Ім'я файлу не може бути порожнім.
editor.branch_already_exists=Гілка '%s' вже присутня в репозиторії.
editor.directory_is_a_file=Ім'я каталогу "%s" уже використовується як ім'я файлу в цьому репозиторії.
@@ -536,8 +596,10 @@ commits.date=Дата
commits.older=Давніше
commits.newer=Новіше
commits.signed_by=Підписано
+commits.gpg_key_id=Ідентифікатор GPG ключа
ext_issues=Зов. Проблеми
+ext_issues.desc=Посилання на зовнішню систему відстеження проблем.
issues.new=Нова проблема
issues.new.labels=Мітки
@@ -559,6 +621,7 @@ issues.new_label_desc_placeholder=Опис
issues.create_label=Створити мітку
issues.label_templates.title=Завантажити визначений набір міток
issues.label_templates.helper=Оберіть набір міток
+issues.label_templates.use=Використовувати набір міток
issues.label_templates.fail_to_load_file=Не вдалося завантажити файл шаблона мітки '%s': %v
issues.add_label_at=додав(ла) мітку %s
%s
issues.add_milestone_at=`додав(ла) до %s етапу %s`
@@ -566,6 +629,7 @@ issues.deleted_milestone=`(видалено)`
issues.add_assignee_at=`був призначений %s %s`
issues.remove_assignee_at=`видалили із призначених %s`
issues.change_title_at=`змінив(ла) заголовок з %s на %s %s`
+issues.delete_branch_at=`видалена гілка %s %s`
issues.open_tab=%d відкрито
issues.close_tab=%d закрито
issues.filter_label=Мітка
@@ -586,7 +650,10 @@ issues.filter_sort.recentupdate=Нещодавно оновлено
issues.filter_sort.leastupdate=Найдавніше оновлені
issues.filter_sort.mostcomment=Найбільш коментовані
issues.filter_sort.leastcomment=Найменш коментовані
+issues.filter_sort.moststars=Найбільш обраних
+issues.filter_sort.feweststars=Найменш обраних
issues.filter_sort.mostforks=Найбільше форків
+issues.filter_sort.fewestforks=Найменше форків
issues.action_open=Відкрити
issues.action_close=Закрити
issues.action_label=Мітка
@@ -617,7 +684,7 @@ issues.collaborator=Співавтор
issues.owner=Власник
issues.sign_in_require_desc=Підпишіться щоб приєднатися до обговорення.
issues.edit=Редагувати
-issues.cancel=Відміна
+issues.cancel=Відмінити
issues.save=Зберегти
issues.label_title=Назва мітки
issues.label_description=Опис мітки
@@ -644,17 +711,21 @@ issues.start_tracking=Почати відстеження часу
issues.start_tracking_history=`почав працювати %s`
issues.tracking_already_started=`Ви вже почали відстежувати час для цієї проблеми!`
issues.stop_tracking=Стоп
+issues.stop_tracking_history=`перестав(-ла) працювати %s`
issues.add_time=Вручну додати час
issues.add_time_short=Додати час
-issues.add_time_cancel=Відміна
+issues.add_time_cancel=Відмінити
+issues.add_time_history=`додав(-ла) витрачений час %s`
issues.add_time_hours=Години
issues.add_time_minutes=Хвилини
issues.add_time_sum_to_small=Час не введено.
-issues.cancel_tracking=Відміна
+issues.cancel_tracking=Відмінити
issues.cancel_tracking_history=`скасував відстеження часу %s`
issues.time_spent_total=Загальний витрачений час
issues.time_spent_from_all_authors=`Загальний витрачений час: %s`
issues.due_date=Дата завершення
+issues.invalid_due_date_format=Дата закінчення має бути в форматі 'ррр-мм-дд'.
+issues.error_modifying_due_date=Не вдалося змінити дату завершення.
issues.due_date_form=рррр-мм-дд
issues.due_date_form_add=Додати дату завершення
issues.due_date_form_update=Оновити дату завершення
@@ -701,13 +772,16 @@ milestones.desc=Опис
milestones.due_date=Дата завершення (опціонально)
milestones.clear=Очистити
milestones.edit=Редагувати етап
-milestones.cancel=Відміна
+milestones.cancel=Відмінити
milestones.modify=Оновити етап
milestones.deletion=Видалити етап
+milestones.filter_sort.closest_due_date=Найближче за датою
+milestones.filter_sort.furthest_due_date=Далі за датою
milestones.filter_sort.most_issues=Найбільш проблем
milestones.filter_sort.least_issues=Найменш проблем
ext_wiki=Зов. Вікі
+ext_wiki.desc=Посилання на зовнішню вікі.
wiki=Вікі
wiki.welcome=Ласкаво просимо до Вікі.
@@ -757,6 +831,7 @@ activity.closed_issue_label=Закрито
activity.new_issues_count_1=Нова Проблема
activity.new_issues_count_n=%d Проблем
activity.new_issue_label=Відкриті
+activity.title.unresolved_conv_1=%d Незавершене обговорення
activity.unresolved_conv_label=Відкрити
activity.title.releases_1=%d Реліз
activity.title.releases_n=%d Релізів
@@ -922,7 +997,7 @@ release.preview=Переглянути
release.loading=Завантаження…
release.prerelease_desc=Позначити як пре-реліз
release.prerelease_helper=Позначте цей випуск непридатним для ПРОД використання.
-release.cancel=Відміна
+release.cancel=Відмінити
release.publish=Опублікувати реліз
release.save_draft=Зберегти чернетку
release.edit_release=Оновити реліз
@@ -951,6 +1026,7 @@ topic.done=Готово
[org]
org_name_holder=Назва організації
org_full_name_holder=Повна назва організації
+org_name_helper=Назва організації має бути простою та зрозумілою.
create_org=Створити організацію
repo_updated=Оновлено
people=Учасники
@@ -963,6 +1039,7 @@ org_desc=Опис
team_name=Назва команди
team_desc=Опис
team_name_helper=Назва команди має бути простою та зрозумілою.
+team_desc_helper=Опишіть мету або роль команди.
team_permission_desc=Права доступу
team_unit_desc=Дозволити доступ до розділів репозиторію
@@ -975,6 +1052,8 @@ settings.website=Веб-сайт
settings.location=Розташування
settings.update_settings=Оновити налаштування
settings.update_setting_success=Налаштування організації оновлені.
+settings.change_orgname_prompt=Ця зміна змінить посилання на організацію.
+settings.update_avatar_success=Аватар організації оновлений.
settings.delete=Видалити організацію
settings.delete_account=Видалити цю організацію
settings.confirm_delete_account=Підтвердіть видалення
@@ -1040,9 +1119,11 @@ dashboard.delete_inactivate_accounts_success=Усі неактивні облі
dashboard.delete_repo_archives=Видалити всі архіви репозиторіїв
dashboard.git_gc_repos_success=Всі репозиторії завершили збирання сміття.
dashboard.server_uptime=Uptime серверу
+dashboard.current_goroutine=Поточна кількість Goroutines
dashboard.current_memory_usage=Поточне використання пам'яті
dashboard.total_memory_allocated=Виділено пам'яті загалом
dashboard.memory_obtained=Отримано пам'яті
+dashboard.pointer_lookup_times=Пошуків вказівника
dashboard.memory_allocate_times=Виділення пам'яті
dashboard.current_heap_usage=Поточне використання динамічної пам'яті
dashboard.heap_memory_obtained=Отримано динамічної пам'яті
@@ -1050,6 +1131,7 @@ dashboard.heap_memory_idle=Не використовується динаміч
dashboard.heap_memory_in_use=Використовується динамічною пам'яттю
dashboard.heap_memory_released=Звільнено динамічної пам'яті
dashboard.heap_objects=Об'єктів динамічної пам'яті
+dashboard.bootstrap_stack_usage=Використання стеку Bootstrap
dashboard.stack_memory_obtained=Зайнято пам'яті стеком
dashboard.mspan_structures_usage=Використання структур MSpan
dashboard.mspan_structures_obtained=Отримано структур MSpan
@@ -1073,7 +1155,9 @@ users.admin=Адміністратор
users.repos=Репозиторії
users.created=Створено
users.last_login=Останній вхід
+users.never_login=Ніколи не входив
users.send_register_notify=Надіслати повідомлення про реєстрацію користувача
+users.new_success=Обліковий запис '%s' створений.
users.edit=Редагувати
users.auth_source=Джерело автентифікації
users.local=Локальні
@@ -1107,7 +1191,7 @@ repos.forks=Форки
repos.issues=Проблеми
repos.size=Розмір
-auths.auth_manage_panel=Керування джерелом аутентифікації
+auths.auth_manage_panel=Керування джерелом автентифікації
auths.new=Додати джерело автентифікації
auths.name=Ім'я
auths.type=Тип
@@ -1124,6 +1208,7 @@ auths.bind_dn=Прив'язати DN
auths.bind_password=Прив'язати пароль
auths.user_base=База пошуку користувачів
auths.user_dn=DN користувача
+auths.attribute_username=Атрибут імені користувача
auths.search_page_size=Розмір сторінки
auths.filter=Користувацький фільтр
auths.admin_filter=Фільтр адміністратора
@@ -1143,8 +1228,8 @@ auths.oauth2_profileURL=URL профілю
auths.oauth2_emailURL=URL електронної пошти
auths.enable_auto_register=Увімкнути автоматичну реєстрацію
auths.tips=Поради
-auths.tips.oauth2.general=OAuth2 аутентифікація
-auths.tips.oauth2.general.tip=При додаванні нового OAuth2 провайдера, URL адреса переадресації по завершенні аутентифікації повинена виглядати так:/user/oauth2//callback
+auths.tips.oauth2.general=OAuth2 автентифікація
+auths.tips.oauth2.general.tip=При додаванні нового OAuth2 провайдера, URL адреса переадресації по завершенні автентифікації повинена виглядати так:/user/oauth2//callback
auths.tip.oauth2_provider=Постачальник OAuth2
auths.tip.dropbox=Додайте новий додаток на https://www.dropbox.com/developers/apps
auths.tip.facebook=Створіть новий додаток на https://developers.facebook.com/apps і додайте модуль "Facebook Login
@@ -1208,6 +1293,7 @@ config.default_keep_email_private=Приховати адресу електро
config.default_allow_create_organization=Дозволити створення організацій за замовчуванням
config.enable_timetracking=Увімкнути відстеження часу
config.default_enable_timetracking=Увімкнути відстеження часу за замовчуванням
+config.no_reply_address=Прихований домен електронної пошти
config.webhook_config=Конфігурація web-хуків
config.queue_length=Довжина черги
@@ -1267,12 +1353,14 @@ monitor.name=Ім'я
monitor.schedule=Розклад
monitor.next=Наступного разу
monitor.previous=Попереднього разу
+monitor.execute_times=Кількість виконань
monitor.process=Запущені процеси
monitor.desc=Опис
monitor.start=Час початку
monitor.execute_time=Час виконання
notices.system_notice_list=Сповіщення системи
+notices.view_detail_header=Переглянути деталі повідомлення
notices.actions=Дії
notices.select_all=Вибрати все
notices.deselect_all=Скасувати виділення
@@ -1327,6 +1415,7 @@ raw_minutes=хвилини
[dropzone]
default_message=Перетягніть файли або натисніть тут, щоб завантажити.
+invalid_input_type=Ви не можете завантажувати файли цього типу.
file_too_big=Розмір файлу ({{filesize}} MB), що більше ніж максимальний розмір: ({{maxFilesize}} MB).
remove_file=Видалити файл
diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini
index 8b23e404c..4e59ed08e 100644
--- a/options/locale/locale_zh-CN.ini
+++ b/options/locale/locale_zh-CN.ini
@@ -213,7 +213,7 @@ send_reset_mail=单击此处(重新)发送您的密码重置邮件
reset_password=重置密码
invalid_code=此确认密钥无效或已过期。
reset_password_helper=单击此处重置密码
-password_too_short=密码长度不能少于 %d 位!
+password_too_short=密码长度不能少于 %d 位。
non_local_account=非本地帐户不能通过 Gitea 的 web 界面更改密码。
verify=验证
scratch_code=验证口令
diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini
index a64367d39..d8b8e210c 100644
--- a/options/locale/locale_zh-HK.ini
+++ b/options/locale/locale_zh-HK.ini
@@ -94,7 +94,6 @@ email_not_associate=此電子郵件地址未與任何帳戶連結
send_reset_mail=點選此處重發您的密碼重製郵件
reset_password=重置密碼
reset_password_helper=單擊此處重置密碼
-password_too_short=密碼長度不能少於 %d 位!
verify=驗證
scratch_code=備用碼
use_scratch_code=使用備用碼
diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini
index fa716b27d..8a6914af2 100644
--- a/options/locale/locale_zh-TW.ini
+++ b/options/locale/locale_zh-TW.ini
@@ -97,7 +97,6 @@ email_not_associate=此電子郵件地址未與任何帳戶連結
send_reset_mail=點選此處重發您的密碼重製郵件
reset_password=重置密碼
reset_password_helper=單擊此處重置密碼
-password_too_short=密碼長度不能少於 %d 位!
verify=驗證
scratch_code=備用碼
use_scratch_code=使用備用碼
diff --git a/public/css/index.css b/public/css/index.css
index 607ab3f6a..2ee3e8314 100644
--- a/public/css/index.css
+++ b/public/css/index.css
@@ -1 +1 @@
-.tribute-container{box-shadow:0 1px 3px 1px #c7c7c7}.tribute-container ul{background:#fff}.tribute-container li{padding:8px 12px;border-bottom:1px solid #dcdcdc}.tribute-container li img{display:inline-block;vertical-align:middle;width:28px;height:28px;margin-right:5px}.tribute-container li span.fullname{font-weight:400;font-size:.8rem;margin-left:3px}.tribute-container li.highlight,.tribute-container li:hover{background:#2185D0;color:#fff}.emoji{width:1.5em;height:1.5em;display:inline-block;background-size:contain}body{font-family:Lato,"Segoe UI","Microsoft YaHei",Arial,Helvetica,sans-serif!important;background-color:#fff;overflow-y:scroll;-webkit-font-smoothing:antialiased}img{border-radius:3px}.rounded{border-radius:.28571429rem!important}code,pre{font:12px Consolas,"Liberation Mono",Menlo,Courier,monospace}code.raw,pre.raw{padding:7px 12px;margin:10px 0;background-color:#f8f8f8;border:1px solid #ddd;border-radius:3px;font-size:13px;line-height:1.5;overflow:auto}code.wrap,pre.wrap{white-space:pre-wrap;-ms-word-break:break-all;word-break:break-all;overflow-wrap:break-word;word-wrap:break-word}.dont-break-out{overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.full.height{padding:0;margin:0 0 -40px 0;min-height:100%}.following.bar{z-index:900;left:0;width:100%;margin:0}.following.bar.light{background-color:#fff;border-bottom:1px solid #DDD;box-shadow:0 2px 3px rgba(0,0,0,.04)}.following.bar .column .menu{margin-top:0}.following.bar .top.menu a.item.brand{padding-left:0}.following.bar .brand .ui.mini.image{width:30px}.following.bar .top.menu .dropdown.item.active,.following.bar .top.menu .dropdown.item:hover,.following.bar .top.menu a.item:hover{background-color:transparent}.following.bar .top.menu a.item:hover{color:rgba(0,0,0,.45)}.following.bar .top.menu .menu{z-index:900}.following.bar .octicon{margin-right:.75em}.following.bar .octicon.fitted{margin-right:0}.following.bar .searchbox{background-color:#f4f4f4!important}.following.bar .searchbox:focus{background-color:#e9e9e9!important}.following.bar .text .octicon{width:16px;text-align:center}@media only screen and (max-width:767px){.following.bar #navbar:not(.shown)>:not(:first-child){display:none}}.right.stackable.menu{margin-left:auto;display:flex;display:-ms-flexbox;-ms-flex-align:inherit;align-items:inherit;-ms-flex-direction:inherit;flex-direction:inherit}.ui.left{float:left}.ui.right{float:right}.ui.button,.ui.menu .item{-moz-user-select:auto;-ms-user-select:auto;-webkit-user-select:auto;user-select:auto}.ui.container.fluid.padded{padding:0 10px 0 10px}.ui.form .ui.button{font-weight:400}.ui.floating.label{z-index:10}.ui.menu,.ui.segment,.ui.vertical.menu{box-shadow:none}.ui .menu:not(.vertical) .item>.button.compact{padding:.58928571em 1.125em}.ui .menu:not(.vertical) .item>.button.small{font-size:.92857143rem}.ui.dropdown .menu>.item>.floating.label{z-index:11}.ui.dropdown .menu .menu>.item>.floating.label{z-index:21}.ui .text.red{color:#d95c5c!important}.ui .text.red a{color:#d95c5c!important}.ui .text.red a:hover{color:#E67777!important}.ui .text.blue{color:#428bca!important}.ui .text.blue a{color:#15c!important}.ui .text.blue a:hover{color:#428bca!important}.ui .text.black{color:#444}.ui .text.black:hover{color:#000}.ui .text.grey{color:#767676!important}.ui .text.grey a{color:#444!important}.ui .text.grey a:hover{color:#000!important}.ui .text.light.grey{color:#888!important}.ui .text.green{color:#6cc644!important}.ui .text.purple{color:#6e5494!important}.ui .text.yellow{color:#FBBD08!important}.ui .text.gold{color:#a1882b!important}.ui .text.left{text-align:left!important}.ui .text.right{text-align:right!important}.ui .text.small{font-size:.75em}.ui .text.normal{font-weight:400}.ui .text.bold{font-weight:700}.ui .text.italic{font-style:italic}.ui .text.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}.ui .text.thin{font-weight:400}.ui .text.middle{vertical-align:middle}.ui .message{text-align:center}.ui .header>i+.content{padding-left:.75rem;vertical-align:middle}.ui .warning.header{background-color:#F9EDBE!important;border-color:#F0C36D}.ui .warning.segment{border-color:#F0C36D}.ui .info.segment{border:1px solid #c5d5dd}.ui .info.segment.top{background-color:#e6f1f6!important}.ui .info.segment.top h3,.ui .info.segment.top h4{margin-top:0}.ui .info.segment.top h3:last-child{margin-top:4px}.ui .info.segment.top>:last-child{margin-bottom:0}.ui .normal.header{font-weight:400}.ui .avatar.image{border-radius:3px}.ui .form .fake{display:none!important}.ui .form .sub.field{margin-left:25px}.ui .sha.label{font-family:Consolas,Menlo,Monaco,"Lucida Console",monospace;font-size:13px;padding:6px 10px 4px 10px;font-weight:400;margin:0 6px}.ui.status.buttons .octicon{margin-right:4px}.ui.inline.delete-button{padding:8px 15px;font-weight:400}.ui .background.red{background-color:#d95c5c!important}.ui .background.blue{background-color:#428bca!important}.ui .background.black{background-color:#444}.ui .background.grey{background-color:#767676!important}.ui .background.light.grey{background-color:#888!important}.ui .background.green{background-color:#6cc644!important}.ui .background.purple{background-color:#6e5494!important}.ui .background.yellow{background-color:#FBBD08!important}.ui .background.gold{background-color:#a1882b!important}.ui .branch-tag-choice{line-height:20px}.overflow.menu .items{max-height:300px;overflow-y:auto}.overflow.menu .items .item{position:relative;cursor:pointer;display:block;border:none;height:auto;border-top:none;line-height:1em;color:rgba(0,0,0,.8);padding:.71428571em 1.14285714em!important;font-size:1rem;text-transform:none;font-weight:400;box-shadow:none;-webkit-touch-callout:none}.overflow.menu .items .item.active{font-weight:700}.overflow.menu .items .item:hover{background:rgba(0,0,0,.05);color:rgba(0,0,0,.8);z-index:13}.scrolling.menu .item.selected{font-weight:700!important}footer{height:40px;background-color:#fff;border-top:1px solid #d6d6d6;clear:both;width:100%;color:#888}footer .container{padding-top:10px}footer .container .fa{width:16px;text-align:center;color:#428bca}footer .container .links>*{border-left:1px solid #d6d6d6;padding-left:8px;margin-left:5px}footer .container .links>:first-child{border-left:none}footer .ui.language .menu{max-height:500px;overflow-y:auto;margin-bottom:7px}.hide{display:none}.center{text-align:center}.img-1{width:2px!important;height:2px!important}.img-2{width:4px!important;height:4px!important}.img-3{width:6px!important;height:6px!important}.img-4{width:8px!important;height:8px!important}.img-5{width:10px!important;height:10px!important}.img-6{width:12px!important;height:12px!important}.img-7{width:14px!important;height:14px!important}.img-8{width:16px!important;height:16px!important}.img-9{width:18px!important;height:18px!important}.img-10{width:20px!important;height:20px!important}.img-11{width:22px!important;height:22px!important}.img-12{width:24px!important;height:24px!important}.img-13{width:26px!important;height:26px!important}.img-14{width:28px!important;height:28px!important}.img-15{width:30px!important;height:30px!important}.img-16{width:32px!important;height:32px!important}@media only screen and (min-width:768px){.mobile-only,.ui.button.mobile-only{display:none}.sr-mobile-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}}@media only screen and (max-width:767px){.not-mobile{display:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}@media only screen and (max-width:991px) and (min-width:768px){.ui.container{width:95%}}.hljs{background:inherit!important;padding:0!important}.ui.menu.new-menu{justify-content:center!important;padding-top:15px!important;margin-top:-15px!important;margin-bottom:15px!important;background-color:#FAFAFA!important;border-width:1px!important}@media only screen and (max-width:1200px){.ui.menu.new-menu{overflow-x:auto!important;justify-content:left!important;padding-bottom:5px}.ui.menu.new-menu::-webkit-scrollbar{height:8px;display:none}.ui.menu.new-menu:hover::-webkit-scrollbar{display:block}.ui.menu.new-menu::-webkit-scrollbar-track{background:rgba(0,0,0,.01)}.ui.menu.new-menu::-webkit-scrollbar-thumb{background:rgba(0,0,0,.2)}.ui.menu.new-menu:after{position:absolute;margin-top:-15px;display:block;background-image:linear-gradient(to right,rgba(255,255,255,0),#fff 100%);content:' ';right:0;height:53px;z-index:1000;width:60px;clear:none;visibility:visible}.ui.menu.new-menu a.item:last-child{padding-right:30px!important}}[v-cloak]{display:none!important}.repos-search{padding-bottom:0!important}.repos-filter{margin-top:0!important;border-bottom-width:0!important;margin-bottom:2px!important}.markdown:not(code){overflow:hidden;font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif;font-size:16px;line-height:1.6!important;word-wrap:break-word}.markdown:not(code).file-view{padding:2em 2em 2em!important}.markdown:not(code)>:first-child{margin-top:0!important}.markdown:not(code)>:last-child{margin-bottom:0!important}.markdown:not(code) a:not([href]){color:inherit;text-decoration:none}.markdown:not(code) .absent{color:#c00}.markdown:not(code) .anchor{position:absolute;top:0;left:0;display:block;padding-right:6px;padding-left:30px;margin-left:-30px}.markdown:not(code) .anchor:focus{outline:0}.markdown:not(code) h1,.markdown:not(code) h2,.markdown:not(code) h3,.markdown:not(code) h4,.markdown:not(code) h5,.markdown:not(code) h6{position:relative;margin-top:1em;margin-bottom:16px;font-weight:700;line-height:1.4}.markdown:not(code) h1:first-of-type,.markdown:not(code) h2:first-of-type,.markdown:not(code) h3:first-of-type,.markdown:not(code) h4:first-of-type,.markdown:not(code) h5:first-of-type,.markdown:not(code) h6:first-of-type{margin-top:0!important}.markdown:not(code) h1 .octicon-link,.markdown:not(code) h2 .octicon-link,.markdown:not(code) h3 .octicon-link,.markdown:not(code) h4 .octicon-link,.markdown:not(code) h5 .octicon-link,.markdown:not(code) h6 .octicon-link{display:none;color:#000;vertical-align:middle}.markdown:not(code) h1:hover .anchor,.markdown:not(code) h2:hover .anchor,.markdown:not(code) h3:hover .anchor,.markdown:not(code) h4:hover .anchor,.markdown:not(code) h5:hover .anchor,.markdown:not(code) h6:hover .anchor{padding-left:8px;margin-left:-30px;text-decoration:none}.markdown:not(code) h1:hover .anchor .octicon-link,.markdown:not(code) h2:hover .anchor .octicon-link,.markdown:not(code) h3:hover .anchor .octicon-link,.markdown:not(code) h4:hover .anchor .octicon-link,.markdown:not(code) h5:hover .anchor .octicon-link,.markdown:not(code) h6:hover .anchor .octicon-link{display:inline-block}.markdown:not(code) h1 code,.markdown:not(code) h1 tt,.markdown:not(code) h2 code,.markdown:not(code) h2 tt,.markdown:not(code) h3 code,.markdown:not(code) h3 tt,.markdown:not(code) h4 code,.markdown:not(code) h4 tt,.markdown:not(code) h5 code,.markdown:not(code) h5 tt,.markdown:not(code) h6 code,.markdown:not(code) h6 tt{font-size:inherit}.markdown:not(code) h1{padding-bottom:.3em;font-size:2.25em;line-height:1.2;border-bottom:1px solid #eee}.markdown:not(code) h1 .anchor{line-height:1}.markdown:not(code) h2{padding-bottom:.3em;font-size:1.75em;line-height:1.225;border-bottom:1px solid #eee}.markdown:not(code) h2 .anchor{line-height:1}.markdown:not(code) h3{font-size:1.5em;line-height:1.43}.markdown:not(code) h3 .anchor{line-height:1.2}.markdown:not(code) h4{font-size:1.25em}.markdown:not(code) h4 .anchor{line-height:1.2}.markdown:not(code) h5{font-size:1em}.markdown:not(code) h5 .anchor{line-height:1.1}.markdown:not(code) h6{font-size:1em;color:#777}.markdown:not(code) h6 .anchor{line-height:1.1}.markdown:not(code) blockquote,.markdown:not(code) dl,.markdown:not(code) ol,.markdown:not(code) p,.markdown:not(code) pre,.markdown:not(code) table,.markdown:not(code) ul{margin-top:0;margin-bottom:16px}.markdown:not(code) blockquote{margin-left:0}.markdown:not(code) hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none}.markdown:not(code) ol,.markdown:not(code) ul{padding-left:2em}.markdown:not(code) ol.no-list,.markdown:not(code) ul.no-list{padding:0;list-style-type:none}.markdown:not(code) ol ol,.markdown:not(code) ol ul,.markdown:not(code) ul ol,.markdown:not(code) ul ul{margin-top:0;margin-bottom:0}.markdown:not(code) ol ol,.markdown:not(code) ul ol{list-style-type:lower-roman}.markdown:not(code) li>p{margin-top:0}.markdown:not(code) dl{padding:0}.markdown:not(code) dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}.markdown:not(code) dl dd{padding:0 16px;margin-bottom:16px}.markdown:not(code) blockquote{padding:0 15px;color:#777;border-left:4px solid #ddd}.markdown:not(code) blockquote>:first-child{margin-top:0}.markdown:not(code) blockquote>:last-child{margin-bottom:0}.markdown:not(code) table{width:auto;overflow:auto;word-break:normal;word-break:keep-all}.markdown:not(code) table th{font-weight:700}.markdown:not(code) table td,.markdown:not(code) table th{padding:6px 13px!important;border:1px solid #ddd!important}.markdown:not(code) table tr{background-color:#fff;border-top:1px solid #ccc}.markdown:not(code) table tr:nth-child(2n){background-color:#f8f8f8}.markdown:not(code) img{max-width:100%;box-sizing:border-box}.markdown:not(code) .emoji{max-width:none}.markdown:not(code) span.frame{display:block;overflow:hidden}.markdown:not(code) span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #ddd}.markdown:not(code) span.frame span img{display:block;float:left}.markdown:not(code) span.frame span span{display:block;padding:5px 0 0;clear:both;color:#333}.markdown:not(code) span.align-center{display:block;overflow:hidden;clear:both}.markdown:not(code) span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown:not(code) span.align-center span img{margin:0 auto;text-align:center}.markdown:not(code) span.align-right{display:block;overflow:hidden;clear:both}.markdown:not(code) span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown:not(code) span.align-right span img{margin:0;text-align:right}.markdown:not(code) span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown:not(code) span.float-left span{margin:13px 0 0}.markdown:not(code) span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown:not(code) span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown:not(code) code,.markdown:not(code) tt{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px}.markdown:not(code) code:after,.markdown:not(code) code:before,.markdown:not(code) tt:after,.markdown:not(code) tt:before{letter-spacing:-.2em;content:"\00a0"}.markdown:not(code) code br,.markdown:not(code) tt br{display:none}.markdown:not(code) del code{text-decoration:inherit}.markdown:not(code) pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown:not(code) .highlight{margin-bottom:16px}.markdown:not(code) .highlight pre,.markdown:not(code) pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border-radius:3px}.markdown:not(code) .highlight pre{margin-bottom:0;word-break:normal}.markdown:not(code) pre{word-wrap:normal}.markdown:not(code) pre code,.markdown:not(code) pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown:not(code) pre code:after,.markdown:not(code) pre code:before,.markdown:not(code) pre tt:after,.markdown:not(code) pre tt:before{content:normal}.markdown:not(code) kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:solid 1px #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.markdown:not(code) input[type=checkbox]{vertical-align:middle!important}.markdown:not(code) .csv-data td,.markdown:not(code) .csv-data th{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown:not(code) .csv-data .blob-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown:not(code) .csv-data tr{border-top:0}.markdown:not(code) .csv-data th{font-weight:700;background:#f8f8f8;border-top:0}.markdown:not(code) .ui.list .list,.markdown:not(code) ol.ui.list ol,.markdown:not(code) ul.ui.list ul{padding-left:2em}.home{padding-bottom:80px}.home .logo{max-width:220px}.home .hero h1,.home .hero h2{font-family:'PT Sans Narrow',sans-serif,'Microsoft YaHei'}@media only screen and (max-width:767px){.home .hero h1{font-size:3.5em}.home .hero h2{font-size:2em}}@media only screen and (min-width:768px){.home .hero h1{font-size:5.5em}.home .hero h2{font-size:3em}}.home .hero .octicon{color:#5aa509;font-size:40px;width:50px}.home .hero.header{font-size:20px}.home p.large{font-size:16px}.home .stackable{padding-top:30px}.home a{color:#5aa509}.signup{padding-top:15px;padding-bottom:80px}.install{padding-top:45px;padding-bottom:80px}.install form label{text-align:right;width:320px!important}.install form input{width:35%!important}.install form .field{text-align:left}.install form .field .help{margin-left:335px!important}.install form .field.optional .title{margin-left:38%}.install .ui .checkbox{margin-left:40%!important}.install .ui .checkbox label{width:auto!important}.form .help{color:#999;padding-top:.6em;padding-bottom:.6em;display:inline-block}.ui.attached.header{background:#f0f0f0}.ui.attached.header .right{margin-top:-5px}.ui.attached.header .right .button{padding:8px 10px;font-weight:400}#create-page-form form{margin:auto}#create-page-form form .ui.message{text-align:center}@media only screen and (min-width:768px){#create-page-form form{width:800px!important}#create-page-form form .header{padding-left:280px!important}#create-page-form form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}#create-page-form form .help{margin-left:265px!important}#create-page-form form .optional .title{margin-left:250px!important}#create-page-form form input,#create-page-form form textarea{width:50%!important}}@media only screen and (max-width:767px){#create-page-form form .optional .title{margin-left:15px}#create-page-form form .inline.field>label{display:block}}.signin .oauth2 div{display:inline-block}.signin .oauth2 div p{margin:10px 5px 0 0;float:left}.signin .oauth2 a{margin-right:3px}.signin .oauth2 a:last-child{margin-right:0}.signin .oauth2 img{width:32px;height:32px}.signin .oauth2 img.openidConnect{width:auto}.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{margin:auto}.user.activate form .ui.message,.user.forgot.password form .ui.message,.user.reset.password form .ui.message,.user.signin form .ui.message,.user.signup form .ui.message{text-align:center}@media only screen and (min-width:768px){.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{width:800px!important}.user.activate form .header,.user.forgot.password form .header,.user.reset.password form .header,.user.signin form .header,.user.signup form .header{padding-left:280px!important}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.user.activate form .help,.user.forgot.password form .help,.user.reset.password form .help,.user.signin form .help,.user.signup form .help{margin-left:265px!important}.user.activate form .optional .title,.user.forgot.password form .optional .title,.user.reset.password form .optional .title,.user.signin form .optional .title,.user.signup form .optional .title{margin-left:250px!important}.user.activate form input,.user.activate form textarea,.user.forgot.password form input,.user.forgot.password form textarea,.user.reset.password form input,.user.reset.password form textarea,.user.signin form input,.user.signin form textarea,.user.signup form input,.user.signup form textarea{width:50%!important}}@media only screen and (max-width:767px){.user.activate form .optional .title,.user.forgot.password form .optional .title,.user.reset.password form .optional .title,.user.signin form .optional .title,.user.signup form .optional .title{margin-left:15px}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{display:block}}.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{width:700px!important}.user.activate form .header,.user.forgot.password form .header,.user.reset.password form .header,.user.signin form .header,.user.signup form .header{padding-left:0!important;text-align:center}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{width:200px!important}.repository.new.fork form,.repository.new.migrate form,.repository.new.repo form{margin:auto}.repository.new.fork form .ui.message,.repository.new.migrate form .ui.message,.repository.new.repo form .ui.message{text-align:center}@media only screen and (min-width:768px){.repository.new.fork form,.repository.new.migrate form,.repository.new.repo form{width:800px!important}.repository.new.fork form .header,.repository.new.migrate form .header,.repository.new.repo form .header{padding-left:280px!important}.repository.new.fork form .inline.field>label,.repository.new.migrate form .inline.field>label,.repository.new.repo form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.repository.new.fork form .help,.repository.new.migrate form .help,.repository.new.repo form .help{margin-left:265px!important}.repository.new.fork form .optional .title,.repository.new.migrate form .optional .title,.repository.new.repo form .optional .title{margin-left:250px!important}.repository.new.fork form input,.repository.new.fork form textarea,.repository.new.migrate form input,.repository.new.migrate form textarea,.repository.new.repo form input,.repository.new.repo form textarea{width:50%!important}}@media only screen and (max-width:767px){.repository.new.fork form .optional .title,.repository.new.migrate form .optional .title,.repository.new.repo form .optional .title{margin-left:15px}.repository.new.fork form .inline.field>label,.repository.new.migrate form .inline.field>label,.repository.new.repo form .inline.field>label{display:block}}.repository.new.fork form .dropdown .dropdown.icon,.repository.new.migrate form .dropdown .dropdown.icon,.repository.new.repo form .dropdown .dropdown.icon{margin-top:-7px!important}.repository.new.fork form .dropdown .text,.repository.new.migrate form .dropdown .text,.repository.new.repo form .dropdown .text{margin-right:0!important}.repository.new.fork form .dropdown .text i,.repository.new.migrate form .dropdown .text i,.repository.new.repo form .dropdown .text i{margin-right:0!important}.repository.new.fork form .header,.repository.new.migrate form .header,.repository.new.repo form .header{padding-left:0!important;text-align:center}.repository.new.repo .ui.form .selection.dropdown:not(.owner){width:50%!important}@media only screen and (min-width:768px){.repository.new.repo .ui.form #auto-init{margin-left:265px!important}}.new.webhook form .help{margin-left:25px}.new.webhook .events.fields .column{padding-left:40px}.githook textarea{font-family:monospace}.repository{padding-top:15px;padding-bottom:80px}.repository .header-grid{padding-top:5px;padding-bottom:5px}.repository .header-grid .ui.compact.menu{margin-left:1rem}.repository .header-grid .ui.header{margin-top:0}.repository .header-grid .mega-octicon{width:30px;font-size:30px}.repository .header-grid .ui.huge.breadcrumb{font-weight:400;font-size:1.7rem}.repository .header-grid .fork-flag{margin-left:38px;margin-top:3px;display:block;font-size:12px;white-space:nowrap}.repository .header-grid .octicon.octicon-repo-forked{margin-top:-1px;font-size:15px}.repository .header-grid .button{margin-top:2px;margin-bottom:2px}.repository .tabs .navbar{justify-content:initial}.repository .navbar{display:flex;justify-content:space-between}.repository .navbar .ui.label{margin-top:-2px;margin-left:7px;padding:3px 5px}.repository .owner.dropdown{min-width:40%!important}.repository #file-buttons{margin-left:auto!important;font-weight:400}.repository #file-buttons .ui.button{padding:8px 10px;font-weight:400}.repository .metas .menu{max-height:300px;overflow-x:auto}.repository .metas .ui.list .hide{display:none!important}.repository .metas .ui.list .item{padding:0}.repository .metas .ui.list .label.color{padding:0 8px;margin-right:5px}.repository .metas .ui.list a{margin:2px 0}.repository .metas .ui.list a .text{color:#444}.repository .metas .ui.list a .text:hover{color:#000}.repository .header-wrapper{background-color:#FAFAFA;margin-top:-15px;padding-top:15px}.repository .header-wrapper .ui.tabs.divider{border-bottom:none}.repository .header-wrapper .ui.tabular .octicon{margin-right:5px}.repository .filter.menu .label.color{border-radius:3px;margin-left:15px;padding:0 8px}.repository .filter.menu .octicon{float:left;margin:5px -7px 0 -5px;width:16px}.repository .filter.menu .text{margin-left:.9em}.repository .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.repository .filter.menu .dropdown.item{margin:1px;padding-right:0}.repository .select-label .item{max-width:250px;overflow:hidden;text-overflow:ellipsis}.repository .select-label .desc{padding-left:16px}.repository .ui.tabs.container{margin-top:14px;margin-bottom:0}.repository .ui.tabs.container .ui.menu{border-bottom:none}.repository .ui.tabs.divider{margin-top:0;margin-bottom:20px}.repository #clone-panel{width:350px}.repository #clone-panel input{border-radius:0;padding:5px 10px}.repository #clone-panel .clone.button{font-size:13px;padding:0 5px}.repository #clone-panel .clone.button:first-child{border-radius:.28571429rem 0 0 .28571429rem}.repository #clone-panel .icon.button{padding:0 10px}.repository #clone-panel .dropdown .menu{right:0!important;left:auto!important}.repository.file.list .repo-description{display:flex;justify-content:space-between;align-items:center}.repository.file.list #repo-desc{font-size:1.2em}.repository.file.list .choose.reference .header .icon{font-size:1.4em}.repository.file.list .repo-path .divider,.repository.file.list .repo-path .section{display:inline}.repository.file.list #file-buttons{font-weight:400}.repository.file.list #file-buttons .ui.button{padding:8px 10px;font-weight:400}.repository.file.list #repo-files-table thead th{padding-top:8px;padding-bottom:5px;font-weight:400}.repository.file.list #repo-files-table thead th:first-child{display:block;position:relative;width:325%}.repository.file.list #repo-files-table thead .ui.avatar{margin-bottom:5px}.repository.file.list #repo-files-table tbody .octicon{margin-left:3px;margin-right:5px;color:#777}.repository.file.list #repo-files-table tbody .octicon.octicon-mail-reply{margin-right:10px}.repository.file.list #repo-files-table tbody .octicon.octicon-file-directory,.repository.file.list #repo-files-table tbody .octicon.octicon-file-submodule,.repository.file.list #repo-files-table tbody .octicon.octicon-file-symlink-directory{color:#1e70bf}.repository.file.list #repo-files-table td{padding-top:8px;padding-bottom:8px}.repository.file.list #repo-files-table td.message .isSigned{cursor:default}.repository.file.list #repo-files-table tr:hover{background-color:#ffE}.repository.file.list #repo-files-table .jumpable-path{color:#888}.repository.file.list .non-diff-file-content .header .icon{font-size:1em}.repository.file.list .non-diff-file-content .header .file-actions{margin-top:0;margin-bottom:-5px;padding-left:20px}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon{display:inline-block;padding:5px;margin-left:5px;line-height:1;color:#767676;vertical-align:middle;background:0 0;border:0;outline:0}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon:hover{color:#4078c0}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon-danger:hover{color:#bd2c00}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon.disabled{color:#bbb;cursor:default}.repository.file.list .non-diff-file-content .header .file-actions #delete-file-form{display:inline-block}.repository.file.list .non-diff-file-content .view-raw{padding:5px}.repository.file.list .non-diff-file-content .view-raw *{max-width:100%}.repository.file.list .non-diff-file-content .view-raw img{padding:5px 5px 0 5px}.repository.file.list .non-diff-file-content .plain-text{padding:1em 2em 1em 2em}.repository.file.list .non-diff-file-content .code-view *{font-size:12px;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;line-height:20px}.repository.file.list .non-diff-file-content .code-view table{width:100%}.repository.file.list .non-diff-file-content .code-view .lines-num{vertical-align:top;text-align:right;color:#999;background:#f5f5f5;width:1%;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}.repository.file.list .non-diff-file-content .code-view .lines-num span{line-height:20px;padding:0 10px;cursor:pointer;display:block}.repository.file.list .non-diff-file-content .code-view .lines-code,.repository.file.list .non-diff-file-content .code-view .lines-num{padding:0}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs,.repository.file.list .non-diff-file-content .code-view .lines-code ol,.repository.file.list .non-diff-file-content .code-view .lines-code pre,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs,.repository.file.list .non-diff-file-content .code-view .lines-num ol,.repository.file.list .non-diff-file-content .code-view .lines-num pre{background-color:#fff;margin:0;padding:0!important}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li,.repository.file.list .non-diff-file-content .code-view .lines-code ol li,.repository.file.list .non-diff-file-content .code-view .lines-code pre li,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li,.repository.file.list .non-diff-file-content .code-view .lines-num ol li,.repository.file.list .non-diff-file-content .code-view .lines-num pre li{display:block;width:100%}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li.active,.repository.file.list .non-diff-file-content .code-view .lines-code ol li.active,.repository.file.list .non-diff-file-content .code-view .lines-code pre li.active,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li.active,.repository.file.list .non-diff-file-content .code-view .lines-num ol li.active,.repository.file.list .non-diff-file-content .code-view .lines-num pre li.active{background:#ffd}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li:before,.repository.file.list .non-diff-file-content .code-view .lines-code ol li:before,.repository.file.list .non-diff-file-content .code-view .lines-code pre li:before,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li:before,.repository.file.list .non-diff-file-content .code-view .lines-num ol li:before,.repository.file.list .non-diff-file-content .code-view .lines-num pre li:before{content:' '}.repository.file.list .non-diff-file-content .code-view .active{background:#ffd}.repository.file.list .sidebar{padding-left:0}.repository.file.list .sidebar .octicon{width:16px}.repository.file.editor .treepath{width:100%}.repository.file.editor .treepath input{vertical-align:middle;box-shadow:rgba(0,0,0,.0745098) 0 1px 2px inset;width:inherit;padding:7px 8px;margin-right:5px}.repository.file.editor .tabular.menu .octicon{margin-right:5px}.repository.file.editor .commit-form-wrapper{padding-left:64px}.repository.file.editor .commit-form-wrapper .commit-avatar{float:left;margin-left:-64px;width:3em;height:auto}.repository.file.editor .commit-form-wrapper .commit-form{position:relative;padding:15px;margin-bottom:10px;border:1px solid #ddd;border-radius:3px}.repository.file.editor .commit-form-wrapper .commit-form:after,.repository.file.editor .commit-form-wrapper .commit-form:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.file.editor .commit-form-wrapper .commit-form:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.file.editor .commit-form-wrapper .commit-form:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.file.editor .commit-form-wrapper .commit-form:after{border-right-color:#fff}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .branch-name{display:inline-block;padding:3px 6px;font:12px Consolas,"Liberation Mono",Menlo,Courier,monospace;color:rgba(0,0,0,.65);background-color:rgba(209,227,237,.45);border-radius:3px}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input{position:relative;margin-left:25px}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input input{width:240px!important;padding-left:26px!important}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .octicon-git-branch{position:absolute;top:9px;left:10px;color:#b0c4ce}.repository.options #interval{width:100px!important;min-width:100px}.repository.options .danger .item{padding:20px 15px}.repository.options .danger .ui.divider{margin:0}.repository.new.issue .comment.form .comment .avatar{width:3em}.repository.new.issue .comment.form .content{margin-left:4em}.repository.new.issue .comment.form .content:after,.repository.new.issue .comment.form .content:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.new.issue .comment.form .content:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.new.issue .comment.form .content:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.new.issue .comment.form .content:after{border-right-color:#fff}.repository.new.issue .comment.form .content .markdown{font-size:14px}.repository.new.issue .comment.form .metas{min-width:220px}.repository.new.issue .comment.form .metas .filter.menu{max-height:300px;overflow-x:auto}.repository.view.issue .title{padding-bottom:0!important}.repository.view.issue .title h1{font-weight:300;font-size:2.3rem;margin-bottom:5px}.repository.view.issue .title h1 .ui.input{font-size:.5em;vertical-align:top;width:50%;min-width:600px}.repository.view.issue .title h1 .ui.input input{font-size:1.5em;padding:6px 10px}.repository.view.issue .title .index{font-weight:300;color:#aaa;letter-spacing:-1px}.repository.view.issue .title .label{margin-right:10px}.repository.view.issue .title .edit-zone{margin-top:10px}.repository.view.issue .pull-desc code{color:#0166E6}.repository.view.issue .pull.tabular.menu{margin-bottom:10px}.repository.view.issue .pull.tabular.menu .octicon{margin-right:5px}.repository.view.issue .pull.tab.segment{border:none;padding:0;padding-top:10px;box-shadow:none;background-color:inherit}.repository.view.issue .pull .merge.box .avatar{margin-left:10px;margin-top:10px}.repository.view.issue .comment-list:before{display:block;content:"";position:absolute;margin-top:12px;margin-bottom:14px;top:0;bottom:0;left:96px;width:2px;background-color:#f3f3f3;z-index:-1}.repository.view.issue .comment-list .comment .avatar{width:3em}.repository.view.issue .comment-list .comment .tag{color:#767676;margin-top:3px;padding:2px 5px;font-size:12px;border:1px solid rgba(0,0,0,.1);border-radius:3px}.repository.view.issue .comment-list .comment .actions .item{float:left}.repository.view.issue .comment-list .comment .actions .item.tag{margin-right:5px}.repository.view.issue .comment-list .comment .actions .item.action{margin-top:6px;margin-left:10px}.repository.view.issue .comment-list .comment .content{margin-left:4em}.repository.view.issue .comment-list .comment .content>.header{font-weight:400;padding:auto 15px;position:relative;color:#767676;background-color:#f7f7f7;border-bottom:1px solid #eee;border-top-left-radius:3px;border-top-right-radius:3px}.repository.view.issue .comment-list .comment .content>.header:after,.repository.view.issue .comment-list .comment .content>.header:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.view.issue .comment-list .comment .content>.header:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.view.issue .comment-list .comment .content>.header:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.view.issue .comment-list .comment .content>.header .text{max-width:78%;padding-top:10px;padding-bottom:10px}.repository.view.issue .comment-list .comment .content .markdown{font-size:14px}.repository.view.issue .comment-list .comment .content .no-content{color:#767676;font-style:italic}.repository.view.issue .comment-list .comment .content>.bottom.segment{background:#f3f4f5}.repository.view.issue .comment-list .comment .content>.bottom.segment .ui.images::after{clear:both;content:' ';display:block}.repository.view.issue .comment-list .comment .content>.bottom.segment a{display:block;float:left;margin:5px;padding:5px;height:150px;border:solid 1px #eee;border-radius:3px;max-width:150px;background-color:#fff}.repository.view.issue .comment-list .comment .content>.bottom.segment a:before{content:' ';display:inline-block;height:100%;vertical-align:middle}.repository.view.issue .comment-list .comment .content>.bottom.segment .ui.image{max-height:100%;width:auto;margin:0;vertical-align:middle}.repository.view.issue .comment-list .comment .content>.bottom.segment span.ui.image{font-size:128px;color:#000}.repository.view.issue .comment-list .comment .content>.bottom.segment span.ui.image:hover{color:#000}.repository.view.issue .comment-list .comment .ui.form .field:first-child{clear:none}.repository.view.issue .comment-list .comment .ui.form .tab.segment{border:none;padding:0;padding-top:10px}.repository.view.issue .comment-list .comment .ui.form textarea{height:200px;font-family:Consolas,monospace}.repository.view.issue .comment-list .comment .edit.buttons{margin-top:10px}.repository.view.issue .comment-list .event{position:relative;margin:15px 0 15px 79px;padding-left:25px}.repository.view.issue .comment-list .event .octicon{width:30px;float:left;text-align:center}.repository.view.issue .comment-list .event .octicon.octicon-circle-slash{margin-top:5px;margin-left:-34.5px;font-size:20px;color:#bd2c00}.repository.view.issue .comment-list .event .octicon.octicon-primitive-dot{margin-left:-28.5px;margin-right:-1px;font-size:30px;color:#6cc644}.repository.view.issue .comment-list .event .octicon.octicon-bookmark{margin-top:3px;margin-left:-31px;margin-right:-1px;font-size:25px}.repository.view.issue .comment-list .event .detail{font-size:.9rem;margin-top:5px;margin-left:35px}.repository.view.issue .comment-list .event .detail .octicon.octicon-git-commit{margin-top:2px}.repository.view.issue .ui.segment.metas{margin-top:-3px}.repository.view.issue .ui.participants img{margin-top:5px;margin-right:5px}.repository .comment.form .ui.comments{margin-top:-12px;max-width:100%}.repository .comment.form .content .field:first-child{clear:none}.repository .comment.form .content .form:after,.repository .comment.form .content .form:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository .comment.form .content .form:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository .comment.form .content .form:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository .comment.form .content .form:after{border-right-color:#fff}.repository .comment.form .content .tab.segment{border:none;padding:0;padding-top:10px}.repository .comment.form .content textarea{height:200px;font-family:Consolas,monospace}.repository .label.list{list-style:none;padding-top:15px}.repository .label.list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .label.list .item a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .label.list .item a:hover{color:#000}.repository .label.list .item a.open-issues{margin-right:30px}.repository .label.list .item .ui.label{font-size:1em}.repository .milestone.list{list-style:none;padding-top:15px}.repository .milestone.list>.item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .milestone.list>.item>a{padding-top:5px;padding-right:10px;color:#000}.repository .milestone.list>.item>a:hover{color:#4078c0}.repository .milestone.list>.item .ui.progress{width:40%;padding:0;border:0;margin:0}.repository .milestone.list>.item .ui.progress .bar{height:20px}.repository .milestone.list>.item .meta{color:#999;padding-top:5px}.repository .milestone.list>.item .meta .issue-stats .octicon{padding-left:5px}.repository .milestone.list>.item .meta .overdue{color:red}.repository .milestone.list>.item .operate{margin-top:-15px}.repository .milestone.list>.item .operate>a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .milestone.list>.item .operate>a:hover{color:#000}.repository .milestone.list>.item .content{padding-top:10px}.repository.new.milestone textarea{height:200px}.repository.new.milestone #deadline{width:150px}.repository.compare.pull .choose.branch .octicon{padding-right:10px}.repository.compare.pull .comment.form .content:after,.repository.compare.pull .comment.form .content:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.compare.pull .comment.form .content:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.compare.pull .comment.form .content:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.compare.pull .comment.form .content:after{border-right-color:#fff}.repository .filter.dropdown .menu{margin-top:1px!important}.repository.commits .header .search input{font-weight:400;padding:5px 10px}.repository #commits-table thead th:first-of-type{padding-left:15px}.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.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}.repository #commits-table td.sha .sha.label.isSigned.isVerified,.repository #repo-files-table .sha.label.isSigned.isVerified{border:1px solid #21BA45;background:#21BA4518}.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon,.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon{border-left:1px solid #21BA4580}.repository .diff-detail-box{margin:15px 0;line-height:30px}.repository .diff-detail-box ol{clear:both;padding-left:0;margin-top:5px;margin-bottom:28px}.repository .diff-detail-box ol li{list-style:none;padding-bottom:4px;margin-bottom:4px;border-bottom:1px dashed #DDD;padding-left:6px}.repository .diff-detail-box span.status{display:inline-block;width:12px;height:12px;margin-right:8px;vertical-align:middle}.repository .diff-detail-box span.status.modify{background-color:#f0db88}.repository .diff-detail-box span.status.add{background-color:#b4e2b4}.repository .diff-detail-box span.status.del{background-color:#e9aeae}.repository .diff-detail-box span.status.rename{background-color:#dad8ff}.repository .diff-detail-box .ui.right{margin-bottom:15px}.repository .diff-box .header{display:flex;align-items:center}.repository .diff-box .header .count{margin-right:12px;font-size:13px;flex:0 0 auto}.repository .diff-box .header .count .bar{background-color:#bd2c00;height:12px;width:40px;display:inline-block;margin:2px 4px 0 4px;vertical-align:text-top}.repository .diff-box .header .count .bar .add{background-color:#55a532;height:12px}.repository .diff-box .header .file{flex:1;color:#888;word-break:break-all}.repository .diff-box .header .button{margin:-5px 0 -5px 12px;padding:8px 10px;flex:0 0 auto}.repository .diff-file-box .header{background-color:#f7f7f7}.repository .diff-file-box .file-body.file-code .lines-num{text-align:right;color:#A7A7A7;background:#fafafa;width:1%;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;vertical-align:top}.repository .diff-file-box .file-body.file-code .lines-num span.fold{display:block;text-align:center}.repository .diff-file-box .file-body.file-code .lines-num-old{border-right:1px solid #DDD}.repository .diff-file-box .code-diff{font-size:12px}.repository .diff-file-box .code-diff td{padding:0;padding-left:10px;border-top:none}.repository .diff-file-box .code-diff pre{margin:0}.repository .diff-file-box .code-diff .lines-num{border-color:#d4d4d5;border-right-width:1px;border-right-style:solid;padding:0 5px}.repository .diff-file-box .code-diff tbody tr td.halfwidth{width:49%}.repository .diff-file-box .code-diff tbody tr td.tag-code,.repository .diff-file-box .code-diff tbody tr.tag-code td{background-color:#F0F0F0!important;border-color:#D2CECE!important;padding-top:8px;padding-bottom:8px}.repository .diff-file-box .code-diff tbody tr .removed-code{background-color:#f99}.repository .diff-file-box .code-diff tbody tr .added-code{background-color:#9f9}.repository .diff-file-box .code-diff-unified tbody tr.del-code td{background-color:#ffe0e0!important;border-color:#f1c0c0!important}.repository .diff-file-box .code-diff-unified tbody tr.add-code td{background-color:#d6fcd6!important;border-color:#c1e9c1!important}.repository .diff-file-box .code-diff-split table,.repository .diff-file-box .code-diff-split tbody{width:100%}.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4){background-color:#fafafa}.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2){background-color:#ffe0e0!important;border-color:#f1c0c0!important}.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4){background-color:#d6fcd6!important;border-color:#c1e9c1!important}.repository .diff-file-box .code-diff-split tbody tr td:nth-child(3){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 .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}.repository.quickstart .guide .item{padding:1em}.repository.quickstart .guide .item small{font-weight:400}.repository.quickstart .guide .clone.button:first-child{border-radius:.28571429rem 0 0 .28571429rem}.repository.quickstart .guide .ui.action.small.input{width:100%}.repository.quickstart .guide #repo-clone-url{border-radius:0;padding:5px 10px;font-size:1.2em}.repository.release #release-list{border-top:1px solid #DDD;margin-top:20px;padding-top:15px}.repository.release #release-list>li{list-style:none}.repository.release #release-list>li .detail,.repository.release #release-list>li .meta{padding-top:30px;padding-bottom:40px}.repository.release #release-list>li .meta{text-align:right;position:relative}.repository.release #release-list>li .meta .tag:not(.icon){display:block;margin-top:15px}.repository.release #release-list>li .meta .commit{display:block;margin-top:10px}.repository.release #release-list>li .detail{border-left:1px solid #DDD}.repository.release #release-list>li .detail .author img{margin-bottom:-3px}.repository.release #release-list>li .detail .download{margin-top:20px}.repository.release #release-list>li .detail .download>a .octicon{margin-left:5px;margin-right:5px}.repository.release #release-list>li .detail .download .list{padding-left:0;border-top:1px solid #eee}.repository.release #release-list>li .detail .download .list li{list-style:none;display:block;padding-top:8px;padding-bottom:8px;border-bottom:1px solid #eee}.repository.release #release-list>li .detail .dot{width:9px;height:9px;background-color:#ccc;z-index:999;position:absolute;display:block;left:-5px;top:40px;border-radius:6px;border:1px solid #FFF}.repository.new.release .target{min-width:500px}.repository.new.release .target #tag-name{margin-top:-4px}.repository.new.release .target .at{margin-left:-5px;margin-right:5px}.repository.new.release .target .dropdown.icon{margin:0;padding-top:3px}.repository.new.release .target .selection.dropdown{padding-top:10px;padding-bottom:10px}.repository.new.release .prerelease.field{margin-bottom:0}.repository.forks .list{margin-top:0}.repository.forks .list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #DDD}.repository.forks .list .item .ui.avatar{float:left;margin-right:5px}.repository.forks .list .item .link{padding-top:5px}.repository.wiki.start .ui.segment{padding-top:70px;padding-bottom:100px}.repository.wiki.start .ui.segment .mega-octicon{font-size:48px}.repository.wiki.new .CodeMirror .CodeMirror-code{font-family:Consolas,monospace}.repository.wiki.new .CodeMirror .CodeMirror-code .cm-comment{background:inherit}.repository.wiki.new .editor-preview{background-color:#fff}.repository.wiki.view .choose.page{margin-top:-5px}.repository.wiki.view .ui.sub.header{text-transform:none}.repository.wiki.view>.markdown{padding:15px 30px}.repository.wiki.view>.markdown h1:first-of-type,.repository.wiki.view>.markdown h2:first-of-type,.repository.wiki.view>.markdown h3:first-of-type,.repository.wiki.view>.markdown h4:first-of-type,.repository.wiki.view>.markdown h5:first-of-type,.repository.wiki.view>.markdown h6:first-of-type{margin-top:0}@media only screen and (max-width:767px){.repository.wiki .dividing.header .stackable.grid .button{margin-top:2px;margin-bottom:2px}}.repository.settings.collaboration .collaborator.list{padding:0}.repository.settings.collaboration .collaborator.list>.item{margin:0;line-height:2em}.repository.settings.collaboration .collaborator.list>.item:not(:last-child){border-bottom:1px solid #DDD}.repository.settings.collaboration #repo-collab-form #search-user-box .results{left:7px}.repository.settings.collaboration #repo-collab-form .ui.button{margin-left:5px;margin-top:-3px}.repository.settings.branches .protected-branches .selection.dropdown{width:300px}.repository.settings.branches .protected-branches .item{border:1px solid #eaeaea;padding:10px 15px}.repository.settings.branches .protected-branches .item:not(:last-child){border-bottom:0}.repository.settings.branches .branch-protection .help{margin-left:26px;padding-top:0}.repository.settings.branches .branch-protection .fields{margin-left:20px;display:block}.repository.settings.branches .branch-protection .whitelist{margin-left:26px}.repository.settings.branches .branch-protection .whitelist .dropdown img{display:inline-block}.repository.settings.webhook .events .column{padding-bottom:0}.repository.settings.webhook .events .help{font-size:13px;margin-left:26px;padding-top:0}.repository .ui.attached.isSigned.isVerified:not(.positive){border-left:1px solid #A3C293;border-right:1px solid #A3C293}.repository .ui.attached.isSigned.isVerified.top:not(.positive){border-top:1px solid #A3C293}.repository .ui.attached.isSigned.isVerified:not(.positive):last-child{border-bottom:1px solid #A3C293}.repository .ui.segment.sub-menu{padding:7px;line-height:0}.repository .ui.segment.sub-menu .list{width:100%;display:flex}.repository .ui.segment.sub-menu .list .item{width:100%;border-radius:3px}.repository .ui.segment.sub-menu .list .item a{color:#000}.repository .ui.segment.sub-menu .list .item a:hover{color:#666}.repository .ui.segment.sub-menu .list .item.active{background:rgba(0,0,0,.05)}.repository .segment.reactions.dropdown .menu,.repository .select-reaction.dropdown .menu{right:0!important;left:auto!important}.repository .segment.reactions.dropdown .menu>.header,.repository .select-reaction.dropdown .menu>.header{margin:.75rem 0 .5rem}.repository .segment.reactions.dropdown .menu>.item,.repository .select-reaction.dropdown .menu>.item{float:left;padding:.5rem .5rem!important}.repository .segment.reactions.dropdown .menu>.item img.emoji,.repository .select-reaction.dropdown .menu>.item img.emoji{margin-right:0}.repository .segment.reactions{padding:.3em 1em}.repository .segment.reactions .ui.label{padding:.4em}.repository .segment.reactions .ui.label.disabled{cursor:default}.repository .segment.reactions .ui.label>img{height:1.5em!important}.repository .segment.reactions .select-reaction{float:none}.repository .segment.reactions .select-reaction:not(.active) a{display:none}.repository .segment.reactions:hover .select-reaction a{display:block}.user-cards .list{padding:0}.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}.user-cards .list .item .meta{margin-top:5px}#search-repo-box .results .result .image,#search-user-box .results .result .image{float:left;margin-right:8px;width:2em;height:2em}#search-repo-box .results .result .content,#search-user-box .results .result .content{margin:6px 0}#issue-actions{display:none}.issue.list{list-style:none;padding-top:15px}.issue.list>.item{padding-top:15px;padding-bottom:10px;border-bottom:1px dashed #AAA}.issue.list>.item .title{color:#444;font-size:15px;font-weight:700;margin:0 6px}.issue.list>.item .title:hover{color:#000}.issue.list>.item .comment{padding-right:10px;color:#666}.issue.list>.item .desc{padding-top:5px;color:#999}.issue.list>.item .desc .checklist{padding-left:5px}.issue.list>.item .desc .checklist .progress-bar{margin-left:2px;width:80px;height:6px;display:inline-block;background-color:#eee;overflow:hidden;border-radius:3px;vertical-align:2px!important}.issue.list>.item .desc .checklist .progress-bar .progress{background-color:#ccc;display:block;height:100%}.issue.list>.item .desc a.milestone{padding-left:5px;color:#999!important}.issue.list>.item .desc a.milestone:hover{color:#000!important}.issue.list>.item .desc .assignee{margin-top:-5px;margin-right:5px}.issue.list>.item .desc .overdue{color:red}.page.buttons{padding-top:15px}.ui.form .dropzone{width:100%;margin-bottom:10px;border:2px dashed #0087F7;box-shadow:none!important}.ui.form .dropzone .dz-error-message{top:140px}.settings .content{margin-top:2px}.settings .content .segment,.settings .content>.header{box-shadow:0 1px 2px 0 rgba(34,36,38,.15)}.settings .list>.item .green{color:#21BA45!important}.settings .list>.item:not(:first-child){border-top:1px solid #eaeaea;padding:1rem;margin:15px -1rem -1rem -1rem}.settings .list>.item>.mega-octicon{display:table-cell}.settings .list>.item>.mega-octicon+.content{display:table-cell;padding:0 0 0 .5em;vertical-align:top}.settings .list>.item .info{margin-top:10px}.settings .list>.item .info .tab.segment{border:none;padding:10px 0 0}.settings .list.key .meta{padding-top:5px;color:#666}.settings .list.email>.item:not(:first-child){min-height:60px}.settings .list.collaborator>.item{padding:0}.ui.vertical.menu .header.item{font-size:1.1em;background:#f0f0f0}.edit-label.modal .form .column,.new-label.segment .form .column{padding-right:0}.edit-label.modal .form .buttons,.new-label.segment .form .buttons{margin-left:auto;padding-top:15px}.edit-label.modal .form .color.picker.column,.new-label.segment .form .color.picker.column{width:auto}.edit-label.modal .form .color.picker.column .color-picker,.new-label.segment .form .color.picker.column .color-picker{height:35px;width:auto;padding-left:30px}.edit-label.modal .form .minicolors-swatch.minicolors-sprite,.new-label.segment .form .minicolors-swatch.minicolors-sprite{top:10px;left:10px;width:15px;height:15px}.edit-label.modal .form .precolors,.new-label.segment .form .precolors{padding-left:0;padding-right:0;margin:3px 10px auto 10px;width:120px}.edit-label.modal .form .precolors .color,.new-label.segment .form .precolors .color{float:left;width:15px;height:15px}#avatar-arrow:after,#avatar-arrow:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}#avatar-arrow:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}#avatar-arrow:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}#delete-repo-modal .ui.message,#transfer-repo-modal .ui.message{width:100%!important}.tab-size-1{tab-size:1!important;-moz-tab-size:1!important}.tab-size-2{tab-size:2!important;-moz-tab-size:2!important}.tab-size-3{tab-size:3!important;-moz-tab-size:3!important}.tab-size-4{tab-size:4!important;-moz-tab-size:4!important}.tab-size-5{tab-size:5!important;-moz-tab-size:5!important}.tab-size-6{tab-size:6!important;-moz-tab-size:6!important}.tab-size-7{tab-size:7!important;-moz-tab-size:7!important}.tab-size-8{tab-size:8!important;-moz-tab-size:8!important}.tab-size-9{tab-size:9!important;-moz-tab-size:9!important}.tab-size-10{tab-size:10!important;-moz-tab-size:10!important}.tab-size-11{tab-size:11!important;-moz-tab-size:11!important}.tab-size-12{tab-size:12!important;-moz-tab-size:12!important}.tab-size-13{tab-size:13!important;-moz-tab-size:13!important}.tab-size-14{tab-size:14!important;-moz-tab-size:14!important}.tab-size-15{tab-size:15!important;-moz-tab-size:15!important}.tab-size-16{tab-size:16!important;-moz-tab-size:16!important}.stats-table{display:table;width:100%}.stats-table .table-cell{display:table-cell}.stats-table .table-cell.tiny{height:.5em}tbody.commit-list{vertical-align:baseline}.commit-body{white-space:pre-wrap}@media only screen and (max-width:767px){.ui.stackable.menu.mobile--margin-between-items>.item{margin-top:5px;margin-bottom:5px}.ui.stackable.menu.mobile--no-negative-margins{margin-left:0;margin-right:0}}#topic_edit{margin-top:5px;display:none}#repo-topic{margin-top:5px}.CodeMirror{font:14px Consolas,"Liberation Mono",Menlo,Courier,monospace}.CodeMirror.cm-s-default{border-radius:3px;padding:0!important}.CodeMirror .cm-comment{background:inherit!important}.repository.file.editor .tab[data-tab=write]{padding:0!important}.repository.file.editor .tab[data-tab=write] .editor-toolbar{border:none!important}.repository.file.editor .tab[data-tab=write] .CodeMirror{border-left:none;border-right:none;border-bottom:none}.organization{padding-top:15px;padding-bottom:80px}.organization .head .ui.header .text{vertical-align:middle;font-size:1.6rem;margin-left:15px}.organization .head .ui.header .ui.right{margin-top:5px}.organization.new.org form{margin:auto}.organization.new.org form .ui.message{text-align:center}@media only screen and (min-width:768px){.organization.new.org form{width:800px!important}.organization.new.org form .header{padding-left:280px!important}.organization.new.org form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.organization.new.org form .help{margin-left:265px!important}.organization.new.org form .optional .title{margin-left:250px!important}.organization.new.org form input,.organization.new.org form textarea{width:50%!important}}@media only screen and (max-width:767px){.organization.new.org form .optional .title{margin-left:15px}.organization.new.org form .inline.field>label{display:block}}.organization.new.org form .header{padding-left:0!important;text-align:center}.organization.options input{min-width:300px}.organization.profile #org-avatar{width:100px;height:100px;margin-right:15px}.organization.profile #org-info .ui.header{font-size:36px;margin-bottom:0}.organization.profile #org-info .desc{font-size:16px;margin-bottom:10px}.organization.profile #org-info .meta .item{display:inline-block;margin-right:10px}.organization.profile #org-info .meta .item .icon{margin-right:5px}.organization.profile .ui.top.header .ui.right{margin-top:0}.organization.profile .teams .item{padding:10px 15px}.organization.profile .members .ui.avatar,.organization.teams .members .ui.avatar{width:48px;height:48px;margin-right:5px}.organization.invite #invite-box{margin:auto;margin-top:50px;width:500px!important}.organization.invite #invite-box #search-user-box input{margin-left:0;width:300px}.organization.invite #invite-box .ui.button{margin-left:5px;margin-top:-3px}.organization.members .list .item{margin-left:0;margin-right:0;border-bottom:1px solid #eee}.organization.members .list .item .ui.avatar{width:48px;height:48px}.organization.members .list .item .meta{line-height:24px}.organization.teams .detail .item{padding:10px 15px}.organization.teams .detail .item:not(:last-child){border-bottom:1px solid #eee}.organization.teams .members .item,.organization.teams .repositories .item{padding:10px 20px;line-height:32px}.organization.teams .members .item:not(:last-child),.organization.teams .repositories .item:not(:last-child){border-bottom:1px solid #DDD}.organization.teams .members .item .button,.organization.teams .repositories .item .button{padding:9px 10px}.organization.teams #add-member-form input,.organization.teams #add-repo-form input{margin-left:0}.organization.teams #add-member-form .ui.button,.organization.teams #add-repo-form .ui.button{margin-left:5px;margin-top:-3px}.user:not(.icon){padding-top:15px;padding-bottom:80px}.user.profile .ui.card .username{display:block}.user.profile .ui.card .extra.content{padding:0}.user.profile .ui.card .extra.content ul{margin:0;padding:0}.user.profile .ui.card .extra.content ul li{padding:10px;list-style:none}.user.profile .ui.card .extra.content ul li:not(:last-child){border-bottom:1px solid #eaeaea}.user.profile .ui.card .extra.content ul li .octicon{margin-left:1px;margin-right:5px}.user.profile .ui.card .extra.content ul li.follow .ui.button{width:100%}.user.profile .ui.repository.list{margin-top:25px}.user.followers .header.name{font-size:20px;line-height:24px;vertical-align:middle}.user.followers .follow .ui.button{padding:8px 15px}.user.notification .octicon{float:left;font-size:2em}.user.notification .content{float:left;margin-left:7px}.user.notification table form{display:inline-block}.user.notification table button{padding:3px 3px 3px 5px}.user.notification table tr{cursor:pointer}.user.notification .octicon.green{color:#21ba45}.user.notification .octicon.red{color:#d01919}.user.notification .octicon.purple{color:#a333c8}.user.notification .octicon.blue{color:#2185d0}.user.link-account:not(.icon){padding-top:15px;padding-bottom:5px}.user.settings .iconFloat{float:left}.dashboard{padding-top:15px;padding-bottom:80px}.dashboard.feeds .context.user.menu,.dashboard.issues .context.user.menu{z-index:101;min-width:200px}.dashboard.feeds .context.user.menu .ui.header,.dashboard.issues .context.user.menu .ui.header{font-size:1rem;text-transform:none}.dashboard.feeds .filter.menu .item,.dashboard.issues .filter.menu .item{text-align:left}.dashboard.feeds .filter.menu .item .text,.dashboard.issues .filter.menu .item .text{height:16px;vertical-align:middle}.dashboard.feeds .filter.menu .item .text.truncate,.dashboard.issues .filter.menu .item .text.truncate{width:85%}.dashboard.feeds .filter.menu .item .floating.label,.dashboard.issues .filter.menu .item .floating.label{top:7px;left:90%;width:15%}.dashboard.feeds .filter.menu .jump.item,.dashboard.issues .filter.menu .jump.item{margin:1px;padding-right:0}.dashboard.feeds .filter.menu .menu,.dashboard.issues .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.dashboard.feeds .right.stackable.menu>.item.active,.dashboard.issues .right.stackable.menu>.item.active{color:#d9453d}.dashboard .dashboard-repos{margin:0 1px}.feeds .news>.ui.grid{margin-left:auto;margin-right:auto}.feeds .news .ui.avatar{margin-top:13px}.feeds .news p{line-height:1em}.feeds .news .time-since{font-size:13px}.feeds .news .issue.title{width:80%}.feeds .news .push.news .content ul{font-size:13px;list-style:none;padding-left:10px}.feeds .news .push.news .content ul img{margin-bottom:-2px}.feeds .news .push.news .content ul .text.truncate{width:80%;margin-bottom:-5px}.feeds .news .commit-id{font-family:Consolas,monospace}.feeds .news code{padding:1px;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px;word-break:break-all}.feeds .list .header .ui.label{margin-top:-4px;padding:4px 5px;font-weight:400}.feeds .list .header .plus.icon{margin-top:5px}.feeds .list ul{list-style:none;margin:0;padding-left:0}.feeds .list ul li:not(:last-child){border-bottom:1px solid #EAEAEA}.feeds .list ul li.private{background-color:#fcf8e9}.feeds .list ul li a{padding:6px 1.2em;display:block}.feeds .list ul li a .octicon{color:#888}.feeds .list ul li a .octicon.rear{font-size:15px}.feeds .list ul li a .star-num{font-size:12px}.feeds .list .repo-owner-name-list .item-name{max-width:70%;margin-bottom:-4px}.feeds .list #collaborative-repo-list .owner-and-repo{max-width:80%;margin-bottom:-5px}.feeds .list #collaborative-repo-list .owner-name{max-width:120px;margin-bottom:-5px}.admin{padding-top:15px;padding-bottom:80px}.admin .table.segment{padding:0;font-size:13px}.admin .table.segment:not(.striped){padding-top:5px}.admin .table.segment:not(.striped) thead th:last-child{padding-right:5px!important}.admin .table.segment th{padding-top:5px;padding-bottom:5px}.admin .table.segment:not(.select) td:first-of-type,.admin .table.segment:not(.select) th:first-of-type{padding-left:15px!important}.admin .ui.header,.admin .ui.segment{box-shadow:0 1px 2px 0 rgba(34,36,38,.15)}.admin.user .email{max-width:200px}.admin dl.admin-dl-horizontal{padding:20px;margin:0}.admin dl.admin-dl-horizontal dd{margin-left:275px}.admin dl.admin-dl-horizontal dt{font-weight:bolder;float:left;width:285px;clear:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.admin.config #test-mail-btn{margin-left:5px}.explore{padding-top:15px;padding-bottom:80px}.explore .navbar{justify-content:center;padding-top:15px!important;margin-top:-15px!important;margin-bottom:15px!important;background-color:#FAFAFA!important;border-width:1px!important}.explore .navbar .octicon{width:16px;text-align:center;margin-right:5px}.ui.repository.list .item{padding-bottom:25px}.ui.repository.list .item:not(:first-child){border-top:1px solid #eee;padding-top:25px}.ui.repository.list .item .ui.header{font-size:1.5rem;padding-bottom:10px}.ui.repository.list .item .ui.header .name{word-break:break-all}.ui.repository.list .item .ui.header .metas{color:#888;font-size:14px;font-weight:400}.ui.repository.list .item .ui.header .metas span:not(:last-child){margin-right:5px}.ui.repository.list .item .time{font-size:12px;color:grey}.ui.repository.branches .time{font-size:12px;color:grey}.ui.user.list .item{padding-bottom:25px}.ui.user.list .item:not(:first-child){border-top:1px solid #eee;padding-top:25px}.ui.user.list .item .ui.avatar.image{width:40px;height:40px}.ui.user.list .item .description{margin-top:5px}.ui.user.list .item .description .octicon:not(:first-child){margin-left:5px}.ui.user.list .item .description a{color:#333}.ui.user.list .item .description a:hover{text-decoration:underline}
\ No newline at end of file
+.tribute-container{box-shadow:0 1px 3px 1px #c7c7c7}.tribute-container ul{background:#fff}.tribute-container li{padding:8px 12px;border-bottom:1px solid #dcdcdc}.tribute-container li img{display:inline-block;vertical-align:middle;width:28px;height:28px;margin-right:5px}.tribute-container li span.fullname{font-weight:400;font-size:.8rem;margin-left:3px}.tribute-container li.highlight,.tribute-container li:hover{background:#2185D0;color:#fff}.emoji{width:1.5em;height:1.5em;display:inline-block;background-size:contain}body{font-family:Lato,"Segoe UI","Microsoft YaHei",Arial,Helvetica,sans-serif!important;background-color:#fff;overflow-y:scroll;-webkit-font-smoothing:antialiased}img{border-radius:3px}.rounded{border-radius:.28571429rem!important}code,pre{font:12px Consolas,"Liberation Mono",Menlo,Courier,monospace}code.raw,pre.raw{padding:7px 12px;margin:10px 0;background-color:#f8f8f8;border:1px solid #ddd;border-radius:3px;font-size:13px;line-height:1.5;overflow:auto}code.wrap,pre.wrap{white-space:pre-wrap;-ms-word-break:break-all;word-break:break-all;overflow-wrap:break-word;word-wrap:break-word}.dont-break-out{overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.full.height{padding:0;margin:0 0 -40px 0;min-height:100%}.following.bar{z-index:900;left:0;width:100%;margin:0}.following.bar.light{background-color:#fff;border-bottom:1px solid #DDD;box-shadow:0 2px 3px rgba(0,0,0,.04)}.following.bar .column .menu{margin-top:0}.following.bar .top.menu a.item.brand{padding-left:0}.following.bar .brand .ui.mini.image{width:30px}.following.bar .top.menu .dropdown.item.active,.following.bar .top.menu .dropdown.item:hover,.following.bar .top.menu a.item:hover{background-color:transparent}.following.bar .top.menu a.item:hover{color:rgba(0,0,0,.45)}.following.bar .top.menu .menu{z-index:900}.following.bar .octicon{margin-right:.75em}.following.bar .octicon.fitted{margin-right:0}.following.bar .searchbox{background-color:#f4f4f4!important}.following.bar .searchbox:focus{background-color:#e9e9e9!important}.following.bar .text .octicon{width:16px;text-align:center}@media only screen and (max-width:767px){.following.bar #navbar:not(.shown)>:not(:first-child){display:none}}.right.stackable.menu{margin-left:auto;display:flex;display:-ms-flexbox;-ms-flex-align:inherit;align-items:inherit;-ms-flex-direction:inherit;flex-direction:inherit}.ui.left{float:left}.ui.right{float:right}.ui.button,.ui.menu .item{-moz-user-select:auto;-ms-user-select:auto;-webkit-user-select:auto;user-select:auto}.ui.container.fluid.padded{padding:0 10px 0 10px}.ui.form .ui.button{font-weight:400}.ui.floating.label{z-index:10}.ui.menu,.ui.segment,.ui.vertical.menu{box-shadow:none}.ui .menu:not(.vertical) .item>.button.compact{padding:.58928571em 1.125em}.ui .menu:not(.vertical) .item>.button.small{font-size:.92857143rem}.ui.dropdown .menu>.item>.floating.label{z-index:11}.ui.dropdown .menu .menu>.item>.floating.label{z-index:21}.ui .text.red{color:#d95c5c!important}.ui .text.red a{color:#d95c5c!important}.ui .text.red a:hover{color:#E67777!important}.ui .text.blue{color:#428bca!important}.ui .text.blue a{color:#15c!important}.ui .text.blue a:hover{color:#428bca!important}.ui .text.black{color:#444}.ui .text.black:hover{color:#000}.ui .text.grey{color:#767676!important}.ui .text.grey a{color:#444!important}.ui .text.grey a:hover{color:#000!important}.ui .text.light.grey{color:#888!important}.ui .text.green{color:#6cc644!important}.ui .text.purple{color:#6e5494!important}.ui .text.yellow{color:#FBBD08!important}.ui .text.gold{color:#a1882b!important}.ui .text.left{text-align:left!important}.ui .text.right{text-align:right!important}.ui .text.small{font-size:.75em}.ui .text.normal{font-weight:400}.ui .text.bold{font-weight:700}.ui .text.italic{font-style:italic}.ui .text.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}.ui .text.thin{font-weight:400}.ui .text.middle{vertical-align:middle}.ui .message{text-align:center}.ui .header>i+.content{padding-left:.75rem;vertical-align:middle}.ui .warning.header{background-color:#F9EDBE!important;border-color:#F0C36D}.ui .warning.segment{border-color:#F0C36D}.ui .info.segment{border:1px solid #c5d5dd}.ui .info.segment.top{background-color:#e6f1f6!important}.ui .info.segment.top h3,.ui .info.segment.top h4{margin-top:0}.ui .info.segment.top h3:last-child{margin-top:4px}.ui .info.segment.top>:last-child{margin-bottom:0}.ui .normal.header{font-weight:400}.ui .avatar.image{border-radius:3px}.ui .form .fake{display:none!important}.ui .form .sub.field{margin-left:25px}.ui .sha.label{font-family:Consolas,Menlo,Monaco,"Lucida Console",monospace;font-size:13px;padding:6px 10px 4px 10px;font-weight:400;margin:0 6px}.ui.status.buttons .octicon{margin-right:4px}.ui.inline.delete-button{padding:8px 15px;font-weight:400}.ui .background.red{background-color:#d95c5c!important}.ui .background.blue{background-color:#428bca!important}.ui .background.black{background-color:#444}.ui .background.grey{background-color:#767676!important}.ui .background.light.grey{background-color:#888!important}.ui .background.green{background-color:#6cc644!important}.ui .background.purple{background-color:#6e5494!important}.ui .background.yellow{background-color:#FBBD08!important}.ui .background.gold{background-color:#a1882b!important}.ui .branch-tag-choice{line-height:20px}.overflow.menu .items{max-height:300px;overflow-y:auto}.overflow.menu .items .item{position:relative;cursor:pointer;display:block;border:none;height:auto;border-top:none;line-height:1em;color:rgba(0,0,0,.8);padding:.71428571em 1.14285714em!important;font-size:1rem;text-transform:none;font-weight:400;box-shadow:none;-webkit-touch-callout:none}.overflow.menu .items .item.active{font-weight:700}.overflow.menu .items .item:hover{background:rgba(0,0,0,.05);color:rgba(0,0,0,.8);z-index:13}.scrolling.menu .item.selected{font-weight:700!important}footer{height:40px;background-color:#fff;border-top:1px solid #d6d6d6;clear:both;width:100%;color:#888}footer .container{padding-top:10px}footer .container .fa{width:16px;text-align:center;color:#428bca}footer .container .links>*{border-left:1px solid #d6d6d6;padding-left:8px;margin-left:5px}footer .container .links>:first-child{border-left:none}footer .ui.language .menu{max-height:500px;overflow-y:auto;margin-bottom:7px}.hide{display:none}.center{text-align:center}.img-1{width:2px!important;height:2px!important}.img-2{width:4px!important;height:4px!important}.img-3{width:6px!important;height:6px!important}.img-4{width:8px!important;height:8px!important}.img-5{width:10px!important;height:10px!important}.img-6{width:12px!important;height:12px!important}.img-7{width:14px!important;height:14px!important}.img-8{width:16px!important;height:16px!important}.img-9{width:18px!important;height:18px!important}.img-10{width:20px!important;height:20px!important}.img-11{width:22px!important;height:22px!important}.img-12{width:24px!important;height:24px!important}.img-13{width:26px!important;height:26px!important}.img-14{width:28px!important;height:28px!important}.img-15{width:30px!important;height:30px!important}.img-16{width:32px!important;height:32px!important}@media only screen and (min-width:768px){.mobile-only,.ui.button.mobile-only{display:none}.sr-mobile-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}}@media only screen and (max-width:767px){.not-mobile{display:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}@media only screen and (max-width:991px) and (min-width:768px){.ui.container{width:95%}}.hljs{background:inherit!important;padding:0!important}.ui.menu.new-menu{justify-content:center!important;padding-top:15px!important;margin-top:-15px!important;margin-bottom:15px!important;background-color:#FAFAFA!important;border-width:1px!important}@media only screen and (max-width:1200px){.ui.menu.new-menu{overflow-x:auto!important;justify-content:left!important;padding-bottom:5px}.ui.menu.new-menu::-webkit-scrollbar{height:8px;display:none}.ui.menu.new-menu:hover::-webkit-scrollbar{display:block}.ui.menu.new-menu::-webkit-scrollbar-track{background:rgba(0,0,0,.01)}.ui.menu.new-menu::-webkit-scrollbar-thumb{background:rgba(0,0,0,.2)}.ui.menu.new-menu:after{position:absolute;margin-top:-15px;display:block;background-image:linear-gradient(to right,rgba(255,255,255,0),#fff 100%);content:' ';right:0;height:53px;z-index:1000;width:60px;clear:none;visibility:visible}.ui.menu.new-menu a.item:last-child{padding-right:30px!important}}[v-cloak]{display:none!important}.repos-search{padding-bottom:0!important}.repos-filter{margin-top:0!important;border-bottom-width:0!important;margin-bottom:2px!important}.markdown:not(code){overflow:hidden;font-family:"Helvetica Neue",Helvetica,"Segoe UI",Arial,freesans,sans-serif;font-size:16px;line-height:1.6!important;word-wrap:break-word}.markdown:not(code).ui.segment{padding:3em}.markdown:not(code).file-view{padding:2em 2em 2em!important}.markdown:not(code)>:first-child{margin-top:0!important}.markdown:not(code)>:last-child{margin-bottom:0!important}.markdown:not(code) a:not([href]){color:inherit;text-decoration:none}.markdown:not(code) .absent{color:#c00}.markdown:not(code) .anchor{position:absolute;top:0;left:0;display:block;padding-right:6px;padding-left:30px;margin-left:-30px}.markdown:not(code) .anchor:focus{outline:0}.markdown:not(code) h1,.markdown:not(code) h2,.markdown:not(code) h3,.markdown:not(code) h4,.markdown:not(code) h5,.markdown:not(code) h6{position:relative;margin-top:1em;margin-bottom:16px;font-weight:700;line-height:1.4}.markdown:not(code) h1:first-of-type,.markdown:not(code) h2:first-of-type,.markdown:not(code) h3:first-of-type,.markdown:not(code) h4:first-of-type,.markdown:not(code) h5:first-of-type,.markdown:not(code) h6:first-of-type{margin-top:0!important}.markdown:not(code) h1 .octicon-link,.markdown:not(code) h2 .octicon-link,.markdown:not(code) h3 .octicon-link,.markdown:not(code) h4 .octicon-link,.markdown:not(code) h5 .octicon-link,.markdown:not(code) h6 .octicon-link{display:none;color:#000;vertical-align:middle}.markdown:not(code) h1:hover .anchor,.markdown:not(code) h2:hover .anchor,.markdown:not(code) h3:hover .anchor,.markdown:not(code) h4:hover .anchor,.markdown:not(code) h5:hover .anchor,.markdown:not(code) h6:hover .anchor{padding-left:8px;margin-left:-30px;text-decoration:none}.markdown:not(code) h1:hover .anchor .octicon-link,.markdown:not(code) h2:hover .anchor .octicon-link,.markdown:not(code) h3:hover .anchor .octicon-link,.markdown:not(code) h4:hover .anchor .octicon-link,.markdown:not(code) h5:hover .anchor .octicon-link,.markdown:not(code) h6:hover .anchor .octicon-link{display:inline-block}.markdown:not(code) h1 code,.markdown:not(code) h1 tt,.markdown:not(code) h2 code,.markdown:not(code) h2 tt,.markdown:not(code) h3 code,.markdown:not(code) h3 tt,.markdown:not(code) h4 code,.markdown:not(code) h4 tt,.markdown:not(code) h5 code,.markdown:not(code) h5 tt,.markdown:not(code) h6 code,.markdown:not(code) h6 tt{font-size:inherit}.markdown:not(code) h1{padding-bottom:.3em;font-size:2.25em;line-height:1.2;border-bottom:1px solid #eee}.markdown:not(code) h1 .anchor{line-height:1}.markdown:not(code) h2{padding-bottom:.3em;font-size:1.75em;line-height:1.225;border-bottom:1px solid #eee}.markdown:not(code) h2 .anchor{line-height:1}.markdown:not(code) h3{font-size:1.5em;line-height:1.43}.markdown:not(code) h3 .anchor{line-height:1.2}.markdown:not(code) h4{font-size:1.25em}.markdown:not(code) h4 .anchor{line-height:1.2}.markdown:not(code) h5{font-size:1em}.markdown:not(code) h5 .anchor{line-height:1.1}.markdown:not(code) h6{font-size:1em;color:#777}.markdown:not(code) h6 .anchor{line-height:1.1}.markdown:not(code) blockquote,.markdown:not(code) dl,.markdown:not(code) ol,.markdown:not(code) p,.markdown:not(code) pre,.markdown:not(code) table,.markdown:not(code) ul{margin-top:0;margin-bottom:16px}.markdown:not(code) blockquote{margin-left:0}.markdown:not(code) hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none}.markdown:not(code) ol,.markdown:not(code) ul{padding-left:2em}.markdown:not(code) ol.no-list,.markdown:not(code) ul.no-list{padding:0;list-style-type:none}.markdown:not(code) ol ol,.markdown:not(code) ol ul,.markdown:not(code) ul ol,.markdown:not(code) ul ul{margin-top:0;margin-bottom:0}.markdown:not(code) ol ol,.markdown:not(code) ul ol{list-style-type:lower-roman}.markdown:not(code) li>p{margin-top:0}.markdown:not(code) dl{padding:0}.markdown:not(code) dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:700}.markdown:not(code) dl dd{padding:0 16px;margin-bottom:16px}.markdown:not(code) blockquote{padding:0 15px;color:#777;border-left:4px solid #ddd}.markdown:not(code) blockquote>:first-child{margin-top:0}.markdown:not(code) blockquote>:last-child{margin-bottom:0}.markdown:not(code) table{width:auto;overflow:auto;word-break:normal;word-break:keep-all}.markdown:not(code) table th{font-weight:700}.markdown:not(code) table td,.markdown:not(code) table th{padding:6px 13px!important;border:1px solid #ddd!important}.markdown:not(code) table tr{background-color:#fff;border-top:1px solid #ccc}.markdown:not(code) table tr:nth-child(2n){background-color:#f8f8f8}.markdown:not(code) img{max-width:100%;box-sizing:border-box}.markdown:not(code) .emoji{max-width:none}.markdown:not(code) span.frame{display:block;overflow:hidden}.markdown:not(code) span.frame>span{display:block;float:left;width:auto;padding:7px;margin:13px 0 0;overflow:hidden;border:1px solid #ddd}.markdown:not(code) span.frame span img{display:block;float:left}.markdown:not(code) span.frame span span{display:block;padding:5px 0 0;clear:both;color:#333}.markdown:not(code) span.align-center{display:block;overflow:hidden;clear:both}.markdown:not(code) span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown:not(code) span.align-center span img{margin:0 auto;text-align:center}.markdown:not(code) span.align-right{display:block;overflow:hidden;clear:both}.markdown:not(code) span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown:not(code) span.align-right span img{margin:0;text-align:right}.markdown:not(code) span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown:not(code) span.float-left span{margin:13px 0 0}.markdown:not(code) span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown:not(code) span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown:not(code) code,.markdown:not(code) tt{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px}.markdown:not(code) code:after,.markdown:not(code) code:before,.markdown:not(code) tt:after,.markdown:not(code) tt:before{letter-spacing:-.2em;content:"\00a0"}.markdown:not(code) code br,.markdown:not(code) tt br{display:none}.markdown:not(code) del code{text-decoration:inherit}.markdown:not(code) pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown:not(code) .highlight{margin-bottom:16px}.markdown:not(code) .highlight pre,.markdown:not(code) pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border-radius:3px}.markdown:not(code) .highlight pre{margin-bottom:0;word-break:normal}.markdown:not(code) pre{word-wrap:normal}.markdown:not(code) pre code,.markdown:not(code) pre tt{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown:not(code) pre code:after,.markdown:not(code) pre code:before,.markdown:not(code) pre tt:after,.markdown:not(code) pre tt:before{content:normal}.markdown:not(code) kbd{display:inline-block;padding:3px 5px;font-size:11px;line-height:10px;color:#555;vertical-align:middle;background-color:#fcfcfc;border:solid 1px #ccc;border-bottom-color:#bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb}.markdown:not(code) input[type=checkbox]{vertical-align:middle!important}.markdown:not(code) .csv-data td,.markdown:not(code) .csv-data th{padding:5px;overflow:hidden;font-size:12px;line-height:1;text-align:left;white-space:nowrap}.markdown:not(code) .csv-data .blob-num{padding:10px 8px 9px;text-align:right;background:#fff;border:0}.markdown:not(code) .csv-data tr{border-top:0}.markdown:not(code) .csv-data th{font-weight:700;background:#f8f8f8;border-top:0}.markdown:not(code) .ui.list .list,.markdown:not(code) ol.ui.list ol,.markdown:not(code) ul.ui.list ul{padding-left:2em}.home{padding-bottom:80px}.home .logo{max-width:220px}.home .hero h1,.home .hero h2{font-family:'PT Sans Narrow',sans-serif,'Microsoft YaHei'}@media only screen and (max-width:767px){.home .hero h1{font-size:3.5em}.home .hero h2{font-size:2em}}@media only screen and (min-width:768px){.home .hero h1{font-size:5.5em}.home .hero h2{font-size:3em}}.home .hero .octicon{color:#5aa509;font-size:40px;width:50px}.home .hero.header{font-size:20px}.home p.large{font-size:16px}.home .stackable{padding-top:30px}.home a{color:#5aa509}.signup{padding-top:15px;padding-bottom:80px}.install{padding-top:45px;padding-bottom:80px}.install form label{text-align:right;width:320px!important}.install form input{width:35%!important}.install form .field{text-align:left}.install form .field .help{margin-left:335px!important}.install form .field.optional .title{margin-left:38%}.install .ui .checkbox{margin-left:40%!important}.install .ui .checkbox label{width:auto!important}.form .help{color:#999;padding-top:.6em;padding-bottom:.6em;display:inline-block}.ui.attached.header{background:#f0f0f0}.ui.attached.header .right{margin-top:-5px}.ui.attached.header .right .button{padding:8px 10px;font-weight:400}#create-page-form form{margin:auto}#create-page-form form .ui.message{text-align:center}@media only screen and (min-width:768px){#create-page-form form{width:800px!important}#create-page-form form .header{padding-left:280px!important}#create-page-form form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}#create-page-form form .help{margin-left:265px!important}#create-page-form form .optional .title{margin-left:250px!important}#create-page-form form input,#create-page-form form textarea{width:50%!important}}@media only screen and (max-width:767px){#create-page-form form .optional .title{margin-left:15px}#create-page-form form .inline.field>label{display:block}}.signin .oauth2 div{display:inline-block}.signin .oauth2 div p{margin:10px 5px 0 0;float:left}.signin .oauth2 a{margin-right:3px}.signin .oauth2 a:last-child{margin-right:0}.signin .oauth2 img{width:32px;height:32px}.signin .oauth2 img.openidConnect{width:auto}.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{margin:auto}.user.activate form .ui.message,.user.forgot.password form .ui.message,.user.reset.password form .ui.message,.user.signin form .ui.message,.user.signup form .ui.message{text-align:center}@media only screen and (min-width:768px){.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{width:800px!important}.user.activate form .header,.user.forgot.password form .header,.user.reset.password form .header,.user.signin form .header,.user.signup form .header{padding-left:280px!important}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.user.activate form .help,.user.forgot.password form .help,.user.reset.password form .help,.user.signin form .help,.user.signup form .help{margin-left:265px!important}.user.activate form .optional .title,.user.forgot.password form .optional .title,.user.reset.password form .optional .title,.user.signin form .optional .title,.user.signup form .optional .title{margin-left:250px!important}.user.activate form input,.user.activate form textarea,.user.forgot.password form input,.user.forgot.password form textarea,.user.reset.password form input,.user.reset.password form textarea,.user.signin form input,.user.signin form textarea,.user.signup form input,.user.signup form textarea{width:50%!important}}@media only screen and (max-width:767px){.user.activate form .optional .title,.user.forgot.password form .optional .title,.user.reset.password form .optional .title,.user.signin form .optional .title,.user.signup form .optional .title{margin-left:15px}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{display:block}}.user.activate form,.user.forgot.password form,.user.reset.password form,.user.signin form,.user.signup form{width:700px!important}.user.activate form .header,.user.forgot.password form .header,.user.reset.password form .header,.user.signin form .header,.user.signup form .header{padding-left:0!important;text-align:center}.user.activate form .inline.field>label,.user.forgot.password form .inline.field>label,.user.reset.password form .inline.field>label,.user.signin form .inline.field>label,.user.signup form .inline.field>label{width:200px!important}.repository.new.fork form,.repository.new.migrate form,.repository.new.repo form{margin:auto}.repository.new.fork form .ui.message,.repository.new.migrate form .ui.message,.repository.new.repo form .ui.message{text-align:center}@media only screen and (min-width:768px){.repository.new.fork form,.repository.new.migrate form,.repository.new.repo form{width:800px!important}.repository.new.fork form .header,.repository.new.migrate form .header,.repository.new.repo form .header{padding-left:280px!important}.repository.new.fork form .inline.field>label,.repository.new.migrate form .inline.field>label,.repository.new.repo form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.repository.new.fork form .help,.repository.new.migrate form .help,.repository.new.repo form .help{margin-left:265px!important}.repository.new.fork form .optional .title,.repository.new.migrate form .optional .title,.repository.new.repo form .optional .title{margin-left:250px!important}.repository.new.fork form input,.repository.new.fork form textarea,.repository.new.migrate form input,.repository.new.migrate form textarea,.repository.new.repo form input,.repository.new.repo form textarea{width:50%!important}}@media only screen and (max-width:767px){.repository.new.fork form .optional .title,.repository.new.migrate form .optional .title,.repository.new.repo form .optional .title{margin-left:15px}.repository.new.fork form .inline.field>label,.repository.new.migrate form .inline.field>label,.repository.new.repo form .inline.field>label{display:block}}.repository.new.fork form .dropdown .dropdown.icon,.repository.new.migrate form .dropdown .dropdown.icon,.repository.new.repo form .dropdown .dropdown.icon{margin-top:-7px!important}.repository.new.fork form .dropdown .text,.repository.new.migrate form .dropdown .text,.repository.new.repo form .dropdown .text{margin-right:0!important}.repository.new.fork form .dropdown .text i,.repository.new.migrate form .dropdown .text i,.repository.new.repo form .dropdown .text i{margin-right:0!important}.repository.new.fork form .header,.repository.new.migrate form .header,.repository.new.repo form .header{padding-left:0!important;text-align:center}.repository.new.repo .ui.form .selection.dropdown:not(.owner){width:50%!important}@media only screen and (min-width:768px){.repository.new.repo .ui.form #auto-init{margin-left:265px!important}}.new.webhook form .help{margin-left:25px}.new.webhook .events.fields .column{padding-left:40px}.githook textarea{font-family:monospace}.repository{padding-top:15px;padding-bottom:80px}.repository .header-grid{padding-top:5px;padding-bottom:5px}.repository .header-grid .ui.compact.menu{margin-left:1rem}.repository .header-grid .ui.header{margin-top:0}.repository .header-grid .mega-octicon{width:30px;font-size:30px}.repository .header-grid .ui.huge.breadcrumb{font-weight:400;font-size:1.7rem}.repository .header-grid .fork-flag{margin-left:38px;margin-top:3px;display:block;font-size:12px;white-space:nowrap}.repository .header-grid .octicon.octicon-repo-forked{margin-top:-1px;font-size:15px}.repository .header-grid .button{margin-top:2px;margin-bottom:2px}.repository .tabs .navbar{justify-content:initial}.repository .navbar{display:flex;justify-content:space-between}.repository .navbar .ui.label{margin-top:-2px;margin-left:7px;padding:3px 5px}.repository .owner.dropdown{min-width:40%!important}.repository #file-buttons{margin-left:auto!important;font-weight:400}.repository #file-buttons .ui.button{padding:8px 10px;font-weight:400}.repository .metas .menu{max-height:300px;overflow-x:auto}.repository .metas .ui.list .hide{display:none!important}.repository .metas .ui.list .item{padding:0}.repository .metas .ui.list .label.color{padding:0 8px;margin-right:5px}.repository .metas .ui.list a{margin:2px 0}.repository .metas .ui.list a .text{color:#444}.repository .metas .ui.list a .text:hover{color:#000}.repository .header-wrapper{background-color:#FAFAFA;margin-top:-15px;padding-top:15px}.repository .header-wrapper .ui.tabs.divider{border-bottom:none}.repository .header-wrapper .ui.tabular .octicon{margin-right:5px}.repository .filter.menu .label.color{border-radius:3px;margin-left:15px;padding:0 8px}.repository .filter.menu .octicon{float:left;margin:5px -7px 0 -5px;width:16px}.repository .filter.menu .text{margin-left:.9em}.repository .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.repository .filter.menu .dropdown.item{margin:1px;padding-right:0}.repository .select-label .item{max-width:250px;overflow:hidden;text-overflow:ellipsis}.repository .select-label .desc{padding-left:16px}.repository .ui.tabs.container{margin-top:14px;margin-bottom:0}.repository .ui.tabs.container .ui.menu{border-bottom:none}.repository .ui.tabs.divider{margin-top:0;margin-bottom:20px}.repository #clone-panel{width:350px}.repository #clone-panel input{border-radius:0;padding:5px 10px}.repository #clone-panel .clone.button{font-size:13px;padding:0 5px}.repository #clone-panel .clone.button:first-child{border-radius:.28571429rem 0 0 .28571429rem}.repository #clone-panel .icon.button{padding:0 10px}.repository #clone-panel .dropdown .menu{right:0!important;left:auto!important}.repository.file.list .repo-description{display:flex;justify-content:space-between;align-items:center}.repository.file.list #repo-desc{font-size:1.2em}.repository.file.list .choose.reference .header .icon{font-size:1.4em}.repository.file.list .repo-path .divider,.repository.file.list .repo-path .section{display:inline}.repository.file.list #file-buttons{font-weight:400}.repository.file.list #file-buttons .ui.button{padding:8px 10px;font-weight:400}.repository.file.list #repo-files-table thead th{padding-top:8px;padding-bottom:5px;font-weight:400}.repository.file.list #repo-files-table thead th:first-child{display:block;position:relative;width:325%}.repository.file.list #repo-files-table thead .ui.avatar{margin-bottom:5px}.repository.file.list #repo-files-table tbody .octicon{margin-left:3px;margin-right:5px;color:#777}.repository.file.list #repo-files-table tbody .octicon.octicon-mail-reply{margin-right:10px}.repository.file.list #repo-files-table tbody .octicon.octicon-file-directory,.repository.file.list #repo-files-table tbody .octicon.octicon-file-submodule,.repository.file.list #repo-files-table tbody .octicon.octicon-file-symlink-directory{color:#1e70bf}.repository.file.list #repo-files-table td{padding-top:8px;padding-bottom:8px}.repository.file.list #repo-files-table td.message .isSigned{cursor:default}.repository.file.list #repo-files-table tr:hover{background-color:#ffE}.repository.file.list #repo-files-table .jumpable-path{color:#888}.repository.file.list .non-diff-file-content .header .icon{font-size:1em}.repository.file.list .non-diff-file-content .header .file-actions{margin-top:0;margin-bottom:-5px;padding-left:20px}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon{display:inline-block;padding:5px;margin-left:5px;line-height:1;color:#767676;vertical-align:middle;background:0 0;border:0;outline:0}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon:hover{color:#4078c0}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon-danger:hover{color:#bd2c00}.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon.disabled{color:#bbb;cursor:default}.repository.file.list .non-diff-file-content .header .file-actions #delete-file-form{display:inline-block}.repository.file.list .non-diff-file-content .view-raw{padding:5px}.repository.file.list .non-diff-file-content .view-raw *{max-width:100%}.repository.file.list .non-diff-file-content .view-raw img{padding:5px 5px 0 5px}.repository.file.list .non-diff-file-content .plain-text{padding:1em 2em 1em 2em}.repository.file.list .non-diff-file-content .code-view *{font-size:12px;font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;line-height:20px}.repository.file.list .non-diff-file-content .code-view table{width:100%}.repository.file.list .non-diff-file-content .code-view .lines-num{vertical-align:top;text-align:right;color:#999;background:#f5f5f5;width:1%;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}.repository.file.list .non-diff-file-content .code-view .lines-num span{line-height:20px;padding:0 10px;cursor:pointer;display:block}.repository.file.list .non-diff-file-content .code-view .lines-code,.repository.file.list .non-diff-file-content .code-view .lines-num{padding:0}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs,.repository.file.list .non-diff-file-content .code-view .lines-code ol,.repository.file.list .non-diff-file-content .code-view .lines-code pre,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs,.repository.file.list .non-diff-file-content .code-view .lines-num ol,.repository.file.list .non-diff-file-content .code-view .lines-num pre{background-color:#fff;margin:0;padding:0!important}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li,.repository.file.list .non-diff-file-content .code-view .lines-code ol li,.repository.file.list .non-diff-file-content .code-view .lines-code pre li,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li,.repository.file.list .non-diff-file-content .code-view .lines-num ol li,.repository.file.list .non-diff-file-content .code-view .lines-num pre li{display:block;width:100%}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li.active,.repository.file.list .non-diff-file-content .code-view .lines-code ol li.active,.repository.file.list .non-diff-file-content .code-view .lines-code pre li.active,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li.active,.repository.file.list .non-diff-file-content .code-view .lines-num ol li.active,.repository.file.list .non-diff-file-content .code-view .lines-num pre li.active{background:#ffd}.repository.file.list .non-diff-file-content .code-view .lines-code .hljs li:before,.repository.file.list .non-diff-file-content .code-view .lines-code ol li:before,.repository.file.list .non-diff-file-content .code-view .lines-code pre li:before,.repository.file.list .non-diff-file-content .code-view .lines-num .hljs li:before,.repository.file.list .non-diff-file-content .code-view .lines-num ol li:before,.repository.file.list .non-diff-file-content .code-view .lines-num pre li:before{content:' '}.repository.file.list .non-diff-file-content .code-view .active{background:#ffd}.repository.file.list .sidebar{padding-left:0}.repository.file.list .sidebar .octicon{width:16px}.repository.file.editor .treepath{width:100%}.repository.file.editor .treepath input{vertical-align:middle;box-shadow:rgba(0,0,0,.0745098) 0 1px 2px inset;width:inherit;padding:7px 8px;margin-right:5px}.repository.file.editor .tabular.menu .octicon{margin-right:5px}.repository.file.editor .commit-form-wrapper{padding-left:64px}.repository.file.editor .commit-form-wrapper .commit-avatar{float:left;margin-left:-64px;width:3em;height:auto}.repository.file.editor .commit-form-wrapper .commit-form{position:relative;padding:15px;margin-bottom:10px;border:1px solid #ddd;border-radius:3px}.repository.file.editor .commit-form-wrapper .commit-form:after,.repository.file.editor .commit-form-wrapper .commit-form:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.file.editor .commit-form-wrapper .commit-form:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.file.editor .commit-form-wrapper .commit-form:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.file.editor .commit-form-wrapper .commit-form:after{border-right-color:#fff}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .branch-name{display:inline-block;padding:3px 6px;font:12px Consolas,"Liberation Mono",Menlo,Courier,monospace;color:rgba(0,0,0,.65);background-color:rgba(209,227,237,.45);border-radius:3px}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input{position:relative;margin-left:25px}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input input{width:240px!important;padding-left:26px!important}.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .octicon-git-branch{position:absolute;top:9px;left:10px;color:#b0c4ce}.repository.options #interval{width:100px!important;min-width:100px}.repository.options .danger .item{padding:20px 15px}.repository.options .danger .ui.divider{margin:0}.repository.new.issue .comment.form .comment .avatar{width:3em}.repository.new.issue .comment.form .content{margin-left:4em}.repository.new.issue .comment.form .content:after,.repository.new.issue .comment.form .content:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.new.issue .comment.form .content:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.new.issue .comment.form .content:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.new.issue .comment.form .content:after{border-right-color:#fff}.repository.new.issue .comment.form .content .markdown{font-size:14px}.repository.new.issue .comment.form .metas{min-width:220px}.repository.new.issue .comment.form .metas .filter.menu{max-height:300px;overflow-x:auto}.repository.view.issue .title{padding-bottom:0!important}.repository.view.issue .title h1{font-weight:300;font-size:2.3rem;margin-bottom:5px}.repository.view.issue .title h1 .ui.input{font-size:.5em;vertical-align:top;width:50%;min-width:600px}.repository.view.issue .title h1 .ui.input input{font-size:1.5em;padding:6px 10px}.repository.view.issue .title .index{font-weight:300;color:#aaa;letter-spacing:-1px}.repository.view.issue .title .label{margin-right:10px}.repository.view.issue .title .edit-zone{margin-top:10px}.repository.view.issue .pull-desc code{color:#0166E6}.repository.view.issue .pull.tabular.menu{margin-bottom:10px}.repository.view.issue .pull.tabular.menu .octicon{margin-right:5px}.repository.view.issue .pull.tab.segment{border:none;padding:0;padding-top:10px;box-shadow:none;background-color:inherit}.repository.view.issue .pull .merge.box .avatar{margin-left:10px;margin-top:10px}.repository.view.issue .comment-list:before{display:block;content:"";position:absolute;margin-top:12px;margin-bottom:14px;top:0;bottom:0;left:96px;width:2px;background-color:#f3f3f3;z-index:-1}.repository.view.issue .comment-list .comment .avatar{width:3em}.repository.view.issue .comment-list .comment .tag{color:#767676;margin-top:3px;padding:2px 5px;font-size:12px;border:1px solid rgba(0,0,0,.1);border-radius:3px}.repository.view.issue .comment-list .comment .actions .item{float:left}.repository.view.issue .comment-list .comment .actions .item.tag{margin-right:5px}.repository.view.issue .comment-list .comment .actions .item.action{margin-top:6px;margin-left:10px}.repository.view.issue .comment-list .comment .content{margin-left:4em}.repository.view.issue .comment-list .comment .content>.header{font-weight:400;padding:auto 15px;position:relative;color:#767676;background-color:#f7f7f7;border-bottom:1px solid #eee;border-top-left-radius:3px;border-top-right-radius:3px}.repository.view.issue .comment-list .comment .content>.header:after,.repository.view.issue .comment-list .comment .content>.header:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.view.issue .comment-list .comment .content>.header:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.view.issue .comment-list .comment .content>.header:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.view.issue .comment-list .comment .content>.header .text{max-width:78%;padding-top:10px;padding-bottom:10px}.repository.view.issue .comment-list .comment .content .markdown{font-size:14px}.repository.view.issue .comment-list .comment .content .no-content{color:#767676;font-style:italic}.repository.view.issue .comment-list .comment .content>.bottom.segment{background:#f3f4f5}.repository.view.issue .comment-list .comment .content>.bottom.segment .ui.images::after{clear:both;content:' ';display:block}.repository.view.issue .comment-list .comment .content>.bottom.segment a{display:block;float:left;margin:5px;padding:5px;height:150px;border:solid 1px #eee;border-radius:3px;max-width:150px;background-color:#fff}.repository.view.issue .comment-list .comment .content>.bottom.segment a:before{content:' ';display:inline-block;height:100%;vertical-align:middle}.repository.view.issue .comment-list .comment .content>.bottom.segment .ui.image{max-height:100%;width:auto;margin:0;vertical-align:middle}.repository.view.issue .comment-list .comment .content>.bottom.segment span.ui.image{font-size:128px;color:#000}.repository.view.issue .comment-list .comment .content>.bottom.segment span.ui.image:hover{color:#000}.repository.view.issue .comment-list .comment .ui.form .field:first-child{clear:none}.repository.view.issue .comment-list .comment .ui.form .tab.segment{border:none;padding:0;padding-top:10px}.repository.view.issue .comment-list .comment .ui.form textarea{height:200px;font-family:Consolas,monospace}.repository.view.issue .comment-list .comment .edit.buttons{margin-top:10px}.repository.view.issue .comment-list .event{position:relative;margin:15px 0 15px 79px;padding-left:25px}.repository.view.issue .comment-list .event .octicon{width:30px;float:left;text-align:center}.repository.view.issue .comment-list .event .octicon.octicon-circle-slash{margin-top:5px;margin-left:-34.5px;font-size:20px;color:#bd2c00}.repository.view.issue .comment-list .event .octicon.octicon-primitive-dot{margin-left:-28.5px;margin-right:-1px;font-size:30px;color:#6cc644}.repository.view.issue .comment-list .event .octicon.octicon-bookmark{margin-top:3px;margin-left:-31px;margin-right:-1px;font-size:25px}.repository.view.issue .comment-list .event .detail{font-size:.9rem;margin-top:5px;margin-left:35px}.repository.view.issue .comment-list .event .detail .octicon.octicon-git-commit{margin-top:2px}.repository.view.issue .ui.segment.metas{margin-top:-3px}.repository.view.issue .ui.participants img{margin-top:5px;margin-right:5px}.repository .comment.form .ui.comments{margin-top:-12px;max-width:100%}.repository .comment.form .content .field:first-child{clear:none}.repository .comment.form .content .form:after,.repository .comment.form .content .form:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository .comment.form .content .form:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository .comment.form .content .form:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository .comment.form .content .form:after{border-right-color:#fff}.repository .comment.form .content .tab.segment{border:none;padding:0;padding-top:10px}.repository .comment.form .content textarea{height:200px;font-family:Consolas,monospace}.repository .label.list{list-style:none;padding-top:15px}.repository .label.list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .label.list .item a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .label.list .item a:hover{color:#000}.repository .label.list .item a.open-issues{margin-right:30px}.repository .label.list .item .ui.label{font-size:1em}.repository .milestone.list{list-style:none;padding-top:15px}.repository .milestone.list>.item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .milestone.list>.item>a{padding-top:5px;padding-right:10px;color:#000}.repository .milestone.list>.item>a:hover{color:#4078c0}.repository .milestone.list>.item .ui.progress{width:40%;padding:0;border:0;margin:0}.repository .milestone.list>.item .ui.progress .bar{height:20px}.repository .milestone.list>.item .meta{color:#999;padding-top:5px}.repository .milestone.list>.item .meta .issue-stats .octicon{padding-left:5px}.repository .milestone.list>.item .meta .overdue{color:red}.repository .milestone.list>.item .operate{margin-top:-15px}.repository .milestone.list>.item .operate>a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .milestone.list>.item .operate>a:hover{color:#000}.repository .milestone.list>.item .content{padding-top:10px}.repository.new.milestone textarea{height:200px}.repository.new.milestone #deadline{width:150px}.repository.compare.pull .choose.branch .octicon{padding-right:10px}.repository.compare.pull .comment.form .content:after,.repository.compare.pull .comment.form .content:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}.repository.compare.pull .comment.form .content:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}.repository.compare.pull .comment.form .content:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}.repository.compare.pull .comment.form .content:after{border-right-color:#fff}.repository .filter.dropdown .menu{margin-top:1px!important}.repository.commits .header .search input{font-weight:400;padding:5px 10px}.repository #commits-table thead th:first-of-type{padding-left:15px}.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.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}.repository #commits-table td.sha .sha.label.isSigned.isVerified,.repository #repo-files-table .sha.label.isSigned.isVerified{border:1px solid #21BA45;background:#21BA4518}.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon,.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon{border-left:1px solid #21BA4580}.repository .diff-detail-box{margin:15px 0;line-height:30px}.repository .diff-detail-box ol{clear:both;padding-left:0;margin-top:5px;margin-bottom:28px}.repository .diff-detail-box ol li{list-style:none;padding-bottom:4px;margin-bottom:4px;border-bottom:1px dashed #DDD;padding-left:6px}.repository .diff-detail-box span.status{display:inline-block;width:12px;height:12px;margin-right:8px;vertical-align:middle}.repository .diff-detail-box span.status.modify{background-color:#f0db88}.repository .diff-detail-box span.status.add{background-color:#b4e2b4}.repository .diff-detail-box span.status.del{background-color:#e9aeae}.repository .diff-detail-box span.status.rename{background-color:#dad8ff}.repository .diff-detail-box .ui.right{margin-bottom:15px}.repository .diff-box .header{display:flex;align-items:center}.repository .diff-box .header .count{margin-right:12px;font-size:13px;flex:0 0 auto}.repository .diff-box .header .count .bar{background-color:#bd2c00;height:12px;width:40px;display:inline-block;margin:2px 4px 0 4px;vertical-align:text-top}.repository .diff-box .header .count .bar .add{background-color:#55a532;height:12px}.repository .diff-box .header .file{flex:1;color:#888;word-break:break-all}.repository .diff-box .header .button{margin:-5px 0 -5px 12px;padding:8px 10px;flex:0 0 auto}.repository .diff-file-box .header{background-color:#f7f7f7}.repository .diff-file-box .file-body.file-code .lines-num{text-align:right;color:#A7A7A7;background:#fafafa;width:1%;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;vertical-align:top}.repository .diff-file-box .file-body.file-code .lines-num span.fold{display:block;text-align:center}.repository .diff-file-box .file-body.file-code .lines-num-old{border-right:1px solid #DDD}.repository .diff-file-box .code-diff{font-size:12px}.repository .diff-file-box .code-diff td{padding:0;padding-left:10px;border-top:none}.repository .diff-file-box .code-diff pre{margin:0}.repository .diff-file-box .code-diff .lines-num{border-color:#d4d4d5;border-right-width:1px;border-right-style:solid;padding:0 5px}.repository .diff-file-box .code-diff tbody tr td.halfwidth{width:49%}.repository .diff-file-box .code-diff tbody tr td.tag-code,.repository .diff-file-box .code-diff tbody tr.tag-code td{background-color:#F0F0F0!important;border-color:#D2CECE!important;padding-top:8px;padding-bottom:8px}.repository .diff-file-box .code-diff tbody tr .removed-code{background-color:#f99}.repository .diff-file-box .code-diff tbody tr .added-code{background-color:#9f9}.repository .diff-file-box .code-diff-unified tbody tr.del-code td{background-color:#ffe0e0!important;border-color:#f1c0c0!important}.repository .diff-file-box .code-diff-unified tbody tr.add-code td{background-color:#d6fcd6!important;border-color:#c1e9c1!important}.repository .diff-file-box .code-diff-split table,.repository .diff-file-box .code-diff-split tbody{width:100%}.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4){background-color:#fafafa}.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2){background-color:#ffe0e0!important;border-color:#f1c0c0!important}.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4){background-color:#d6fcd6!important;border-color:#c1e9c1!important}.repository .diff-file-box .code-diff-split tbody tr td:nth-child(3){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 .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}.repository.quickstart .guide .item{padding:1em}.repository.quickstart .guide .item small{font-weight:400}.repository.quickstart .guide .clone.button:first-child{border-radius:.28571429rem 0 0 .28571429rem}.repository.quickstart .guide .ui.action.small.input{width:100%}.repository.quickstart .guide #repo-clone-url{border-radius:0;padding:5px 10px;font-size:1.2em}.repository.release #release-list{border-top:1px solid #DDD;margin-top:20px;padding-top:15px}.repository.release #release-list>li{list-style:none}.repository.release #release-list>li .detail,.repository.release #release-list>li .meta{padding-top:30px;padding-bottom:40px}.repository.release #release-list>li .meta{text-align:right;position:relative}.repository.release #release-list>li .meta .tag:not(.icon){display:block;margin-top:15px}.repository.release #release-list>li .meta .commit{display:block;margin-top:10px}.repository.release #release-list>li .detail{border-left:1px solid #DDD}.repository.release #release-list>li .detail .author img{margin-bottom:-3px}.repository.release #release-list>li .detail .download{margin-top:20px}.repository.release #release-list>li .detail .download>a .octicon{margin-left:5px;margin-right:5px}.repository.release #release-list>li .detail .download .list{padding-left:0;border-top:1px solid #eee}.repository.release #release-list>li .detail .download .list li{list-style:none;display:block;padding-top:8px;padding-bottom:8px;border-bottom:1px solid #eee}.repository.release #release-list>li .detail .dot{width:9px;height:9px;background-color:#ccc;z-index:999;position:absolute;display:block;left:-5px;top:40px;border-radius:6px;border:1px solid #FFF}.repository.new.release .target{min-width:500px}.repository.new.release .target #tag-name{margin-top:-4px}.repository.new.release .target .at{margin-left:-5px;margin-right:5px}.repository.new.release .target .dropdown.icon{margin:0;padding-top:3px}.repository.new.release .target .selection.dropdown{padding-top:10px;padding-bottom:10px}.repository.new.release .prerelease.field{margin-bottom:0}.repository.forks .list{margin-top:0}.repository.forks .list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px solid #DDD}.repository.forks .list .item .ui.avatar{float:left;margin-right:5px}.repository.forks .list .item .link{padding-top:5px}.repository.wiki.start .ui.segment{padding-top:70px;padding-bottom:100px}.repository.wiki.start .ui.segment .mega-octicon{font-size:48px}.repository.wiki.new .CodeMirror .CodeMirror-code{font-family:Consolas,monospace}.repository.wiki.new .CodeMirror .CodeMirror-code .cm-comment{background:inherit}.repository.wiki.new .editor-preview{background-color:#fff}.repository.wiki.view .choose.page{margin-top:-5px}.repository.wiki.view .ui.sub.header{text-transform:none}.repository.wiki.view>.markdown{padding:15px 30px}.repository.wiki.view>.markdown h1:first-of-type,.repository.wiki.view>.markdown h2:first-of-type,.repository.wiki.view>.markdown h3:first-of-type,.repository.wiki.view>.markdown h4:first-of-type,.repository.wiki.view>.markdown h5:first-of-type,.repository.wiki.view>.markdown h6:first-of-type{margin-top:0}@media only screen and (max-width:767px){.repository.wiki .dividing.header .stackable.grid .button{margin-top:2px;margin-bottom:2px}}.repository.settings.collaboration .collaborator.list{padding:0}.repository.settings.collaboration .collaborator.list>.item{margin:0;line-height:2em}.repository.settings.collaboration .collaborator.list>.item:not(:last-child){border-bottom:1px solid #DDD}.repository.settings.collaboration #repo-collab-form #search-user-box .results{left:7px}.repository.settings.collaboration #repo-collab-form .ui.button{margin-left:5px;margin-top:-3px}.repository.settings.branches .protected-branches .selection.dropdown{width:300px}.repository.settings.branches .protected-branches .item{border:1px solid #eaeaea;padding:10px 15px}.repository.settings.branches .protected-branches .item:not(:last-child){border-bottom:0}.repository.settings.branches .branch-protection .help{margin-left:26px;padding-top:0}.repository.settings.branches .branch-protection .fields{margin-left:20px;display:block}.repository.settings.branches .branch-protection .whitelist{margin-left:26px}.repository.settings.branches .branch-protection .whitelist .dropdown img{display:inline-block}.repository.settings.webhook .events .column{padding-bottom:0}.repository.settings.webhook .events .help{font-size:13px;margin-left:26px;padding-top:0}.repository .ui.attached.isSigned.isVerified:not(.positive){border-left:1px solid #A3C293;border-right:1px solid #A3C293}.repository .ui.attached.isSigned.isVerified.top:not(.positive){border-top:1px solid #A3C293}.repository .ui.attached.isSigned.isVerified:not(.positive):last-child{border-bottom:1px solid #A3C293}.repository .ui.segment.sub-menu{padding:7px;line-height:0}.repository .ui.segment.sub-menu .list{width:100%;display:flex}.repository .ui.segment.sub-menu .list .item{width:100%;border-radius:3px}.repository .ui.segment.sub-menu .list .item a{color:#000}.repository .ui.segment.sub-menu .list .item a:hover{color:#666}.repository .ui.segment.sub-menu .list .item.active{background:rgba(0,0,0,.05)}.repository .segment.reactions.dropdown .menu,.repository .select-reaction.dropdown .menu{right:0!important;left:auto!important}.repository .segment.reactions.dropdown .menu>.header,.repository .select-reaction.dropdown .menu>.header{margin:.75rem 0 .5rem}.repository .segment.reactions.dropdown .menu>.item,.repository .select-reaction.dropdown .menu>.item{float:left;padding:.5rem .5rem!important}.repository .segment.reactions.dropdown .menu>.item img.emoji,.repository .select-reaction.dropdown .menu>.item img.emoji{margin-right:0}.repository .segment.reactions{padding:.3em 1em}.repository .segment.reactions .ui.label{padding:.4em}.repository .segment.reactions .ui.label.disabled{cursor:default}.repository .segment.reactions .ui.label>img{height:1.5em!important}.repository .segment.reactions .select-reaction{float:none}.repository .segment.reactions .select-reaction:not(.active) a{display:none}.repository .segment.reactions:hover .select-reaction a{display:block}.user-cards .list{padding:0}.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}.user-cards .list .item .meta{margin-top:5px}#search-repo-box .results .result .image,#search-user-box .results .result .image{float:left;margin-right:8px;width:2em;height:2em}#search-repo-box .results .result .content,#search-user-box .results .result .content{margin:6px 0}#issue-actions{display:none}.issue.list{list-style:none;padding-top:15px}.issue.list>.item{padding-top:15px;padding-bottom:10px;border-bottom:1px dashed #AAA}.issue.list>.item .title{color:#444;font-size:15px;font-weight:700;margin:0 6px}.issue.list>.item .title:hover{color:#000}.issue.list>.item .comment{padding-right:10px;color:#666}.issue.list>.item .desc{padding-top:5px;color:#999}.issue.list>.item .desc .checklist{padding-left:5px}.issue.list>.item .desc .checklist .progress-bar{margin-left:2px;width:80px;height:6px;display:inline-block;background-color:#eee;overflow:hidden;border-radius:3px;vertical-align:2px!important}.issue.list>.item .desc .checklist .progress-bar .progress{background-color:#ccc;display:block;height:100%}.issue.list>.item .desc a.milestone{padding-left:5px;color:#999!important}.issue.list>.item .desc a.milestone:hover{color:#000!important}.issue.list>.item .desc .assignee{margin-top:-5px;margin-right:5px}.issue.list>.item .desc .overdue{color:red}.page.buttons{padding-top:15px}.ui.form .dropzone{width:100%;margin-bottom:10px;border:2px dashed #0087F7;box-shadow:none!important}.ui.form .dropzone .dz-error-message{top:140px}.settings .content{margin-top:2px}.settings .content .segment,.settings .content>.header{box-shadow:0 1px 2px 0 rgba(34,36,38,.15)}.settings .list>.item .green{color:#21BA45!important}.settings .list>.item:not(:first-child){border-top:1px solid #eaeaea;padding:1rem;margin:15px -1rem -1rem -1rem}.settings .list>.item>.mega-octicon{display:table-cell}.settings .list>.item>.mega-octicon+.content{display:table-cell;padding:0 0 0 .5em;vertical-align:top}.settings .list>.item .info{margin-top:10px}.settings .list>.item .info .tab.segment{border:none;padding:10px 0 0}.settings .list.key .meta{padding-top:5px;color:#666}.settings .list.email>.item:not(:first-child){min-height:60px}.settings .list.collaborator>.item{padding:0}.ui.vertical.menu .header.item{font-size:1.1em;background:#f0f0f0}.edit-label.modal .form .column,.new-label.segment .form .column{padding-right:0}.edit-label.modal .form .buttons,.new-label.segment .form .buttons{margin-left:auto;padding-top:15px}.edit-label.modal .form .color.picker.column,.new-label.segment .form .color.picker.column{width:auto}.edit-label.modal .form .color.picker.column .color-picker,.new-label.segment .form .color.picker.column .color-picker{height:35px;width:auto;padding-left:30px}.edit-label.modal .form .minicolors-swatch.minicolors-sprite,.new-label.segment .form .minicolors-swatch.minicolors-sprite{top:10px;left:10px;width:15px;height:15px}.edit-label.modal .form .precolors,.new-label.segment .form .precolors{padding-left:0;padding-right:0;margin:3px 10px auto 10px;width:120px}.edit-label.modal .form .precolors .color,.new-label.segment .form .precolors .color{float:left;width:15px;height:15px}#avatar-arrow:after,#avatar-arrow:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none}#avatar-arrow:before{border-right-color:#D4D4D5;border-width:9px;margin-top:-9px}#avatar-arrow:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}#delete-repo-modal .ui.message,#transfer-repo-modal .ui.message{width:100%!important}.tab-size-1{tab-size:1!important;-moz-tab-size:1!important}.tab-size-2{tab-size:2!important;-moz-tab-size:2!important}.tab-size-3{tab-size:3!important;-moz-tab-size:3!important}.tab-size-4{tab-size:4!important;-moz-tab-size:4!important}.tab-size-5{tab-size:5!important;-moz-tab-size:5!important}.tab-size-6{tab-size:6!important;-moz-tab-size:6!important}.tab-size-7{tab-size:7!important;-moz-tab-size:7!important}.tab-size-8{tab-size:8!important;-moz-tab-size:8!important}.tab-size-9{tab-size:9!important;-moz-tab-size:9!important}.tab-size-10{tab-size:10!important;-moz-tab-size:10!important}.tab-size-11{tab-size:11!important;-moz-tab-size:11!important}.tab-size-12{tab-size:12!important;-moz-tab-size:12!important}.tab-size-13{tab-size:13!important;-moz-tab-size:13!important}.tab-size-14{tab-size:14!important;-moz-tab-size:14!important}.tab-size-15{tab-size:15!important;-moz-tab-size:15!important}.tab-size-16{tab-size:16!important;-moz-tab-size:16!important}.stats-table{display:table;width:100%}.stats-table .table-cell{display:table-cell}.stats-table .table-cell.tiny{height:.5em}tbody.commit-list{vertical-align:baseline}.commit-body{white-space:pre-wrap}@media only screen and (max-width:767px){.ui.stackable.menu.mobile--margin-between-items>.item{margin-top:5px;margin-bottom:5px}.ui.stackable.menu.mobile--no-negative-margins{margin-left:0;margin-right:0}}#topic_edit{margin-top:5px;display:none}#repo-topic{margin-top:5px}.CodeMirror{font:14px Consolas,"Liberation Mono",Menlo,Courier,monospace}.CodeMirror.cm-s-default{border-radius:3px;padding:0!important}.CodeMirror .cm-comment{background:inherit!important}.repository.file.editor .tab[data-tab=write]{padding:0!important}.repository.file.editor .tab[data-tab=write] .editor-toolbar{border:none!important}.repository.file.editor .tab[data-tab=write] .CodeMirror{border-left:none;border-right:none;border-bottom:none}.organization{padding-top:15px;padding-bottom:80px}.organization .head .ui.header .text{vertical-align:middle;font-size:1.6rem;margin-left:15px}.organization .head .ui.header .ui.right{margin-top:5px}.organization.new.org form{margin:auto}.organization.new.org form .ui.message{text-align:center}@media only screen and (min-width:768px){.organization.new.org form{width:800px!important}.organization.new.org form .header{padding-left:280px!important}.organization.new.org form .inline.field>label{text-align:right;width:250px!important;word-wrap:break-word}.organization.new.org form .help{margin-left:265px!important}.organization.new.org form .optional .title{margin-left:250px!important}.organization.new.org form input,.organization.new.org form textarea{width:50%!important}}@media only screen and (max-width:767px){.organization.new.org form .optional .title{margin-left:15px}.organization.new.org form .inline.field>label{display:block}}.organization.new.org form .header{padding-left:0!important;text-align:center}.organization.options input{min-width:300px}.organization.profile #org-avatar{width:100px;height:100px;margin-right:15px}.organization.profile #org-info .ui.header{font-size:36px;margin-bottom:0}.organization.profile #org-info .desc{font-size:16px;margin-bottom:10px}.organization.profile #org-info .meta .item{display:inline-block;margin-right:10px}.organization.profile #org-info .meta .item .icon{margin-right:5px}.organization.profile .ui.top.header .ui.right{margin-top:0}.organization.profile .teams .item{padding:10px 15px}.organization.profile .members .ui.avatar,.organization.teams .members .ui.avatar{width:48px;height:48px;margin-right:5px}.organization.invite #invite-box{margin:auto;margin-top:50px;width:500px!important}.organization.invite #invite-box #search-user-box input{margin-left:0;width:300px}.organization.invite #invite-box .ui.button{margin-left:5px;margin-top:-3px}.organization.members .list .item{margin-left:0;margin-right:0;border-bottom:1px solid #eee}.organization.members .list .item .ui.avatar{width:48px;height:48px}.organization.members .list .item .meta{line-height:24px}.organization.teams .detail .item{padding:10px 15px}.organization.teams .detail .item:not(:last-child){border-bottom:1px solid #eee}.organization.teams .members .item,.organization.teams .repositories .item{padding:10px 20px;line-height:32px}.organization.teams .members .item:not(:last-child),.organization.teams .repositories .item:not(:last-child){border-bottom:1px solid #DDD}.organization.teams .members .item .button,.organization.teams .repositories .item .button{padding:9px 10px}.organization.teams #add-member-form input,.organization.teams #add-repo-form input{margin-left:0}.organization.teams #add-member-form .ui.button,.organization.teams #add-repo-form .ui.button{margin-left:5px;margin-top:-3px}.user:not(.icon){padding-top:15px;padding-bottom:80px}.user.profile .ui.card .username{display:block}.user.profile .ui.card .extra.content{padding:0}.user.profile .ui.card .extra.content ul{margin:0;padding:0}.user.profile .ui.card .extra.content ul li{padding:10px;list-style:none}.user.profile .ui.card .extra.content ul li:not(:last-child){border-bottom:1px solid #eaeaea}.user.profile .ui.card .extra.content ul li .octicon{margin-left:1px;margin-right:5px}.user.profile .ui.card .extra.content ul li.follow .ui.button{width:100%}.user.profile .ui.repository.list{margin-top:25px}.user.followers .header.name{font-size:20px;line-height:24px;vertical-align:middle}.user.followers .follow .ui.button{padding:8px 15px}.user.notification .octicon{float:left;font-size:2em}.user.notification .content{float:left;margin-left:7px}.user.notification table form{display:inline-block}.user.notification table button{padding:3px 3px 3px 5px}.user.notification table tr{cursor:pointer}.user.notification .octicon.green{color:#21ba45}.user.notification .octicon.red{color:#d01919}.user.notification .octicon.purple{color:#a333c8}.user.notification .octicon.blue{color:#2185d0}.user.link-account:not(.icon){padding-top:15px;padding-bottom:5px}.user.settings .iconFloat{float:left}.dashboard{padding-top:15px;padding-bottom:80px}.dashboard.feeds .context.user.menu,.dashboard.issues .context.user.menu{z-index:101;min-width:200px}.dashboard.feeds .context.user.menu .ui.header,.dashboard.issues .context.user.menu .ui.header{font-size:1rem;text-transform:none}.dashboard.feeds .filter.menu .item,.dashboard.issues .filter.menu .item{text-align:left}.dashboard.feeds .filter.menu .item .text,.dashboard.issues .filter.menu .item .text{height:16px;vertical-align:middle}.dashboard.feeds .filter.menu .item .text.truncate,.dashboard.issues .filter.menu .item .text.truncate{width:85%}.dashboard.feeds .filter.menu .item .floating.label,.dashboard.issues .filter.menu .item .floating.label{top:7px;left:90%;width:15%}.dashboard.feeds .filter.menu .jump.item,.dashboard.issues .filter.menu .jump.item{margin:1px;padding-right:0}.dashboard.feeds .filter.menu .menu,.dashboard.issues .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.dashboard.feeds .right.stackable.menu>.item.active,.dashboard.issues .right.stackable.menu>.item.active{color:#d9453d}.dashboard .dashboard-repos{margin:0 1px}.feeds .news>.ui.grid{margin-left:auto;margin-right:auto}.feeds .news .ui.avatar{margin-top:13px}.feeds .news p{line-height:1em}.feeds .news .time-since{font-size:13px}.feeds .news .issue.title{width:80%}.feeds .news .push.news .content ul{font-size:13px;list-style:none;padding-left:10px}.feeds .news .push.news .content ul img{margin-bottom:-2px}.feeds .news .push.news .content ul .text.truncate{width:80%;margin-bottom:-5px}.feeds .news .commit-id{font-family:Consolas,monospace}.feeds .news code{padding:1px;font-size:85%;background-color:rgba(0,0,0,.04);border-radius:3px;word-break:break-all}.feeds .list .header .ui.label{margin-top:-4px;padding:4px 5px;font-weight:400}.feeds .list .header .plus.icon{margin-top:5px}.feeds .list ul{list-style:none;margin:0;padding-left:0}.feeds .list ul li:not(:last-child){border-bottom:1px solid #EAEAEA}.feeds .list ul li.private{background-color:#fcf8e9}.feeds .list ul li a{padding:6px 1.2em;display:block}.feeds .list ul li a .octicon{color:#888}.feeds .list ul li a .octicon.rear{font-size:15px}.feeds .list ul li a .star-num{font-size:12px}.feeds .list .repo-owner-name-list .item-name{max-width:70%;margin-bottom:-4px}.feeds .list #collaborative-repo-list .owner-and-repo{max-width:80%;margin-bottom:-5px}.feeds .list #collaborative-repo-list .owner-name{max-width:120px;margin-bottom:-5px}.admin{padding-top:15px;padding-bottom:80px}.admin .table.segment{padding:0;font-size:13px}.admin .table.segment:not(.striped){padding-top:5px}.admin .table.segment:not(.striped) thead th:last-child{padding-right:5px!important}.admin .table.segment th{padding-top:5px;padding-bottom:5px}.admin .table.segment:not(.select) td:first-of-type,.admin .table.segment:not(.select) th:first-of-type{padding-left:15px!important}.admin .ui.header,.admin .ui.segment{box-shadow:0 1px 2px 0 rgba(34,36,38,.15)}.admin.user .email{max-width:200px}.admin dl.admin-dl-horizontal{padding:20px;margin:0}.admin dl.admin-dl-horizontal dd{margin-left:275px}.admin dl.admin-dl-horizontal dt{font-weight:bolder;float:left;width:285px;clear:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.admin.config #test-mail-btn{margin-left:5px}.explore{padding-top:15px;padding-bottom:80px}.explore .navbar{justify-content:center;padding-top:15px!important;margin-top:-15px!important;margin-bottom:15px!important;background-color:#FAFAFA!important;border-width:1px!important}.explore .navbar .octicon{width:16px;text-align:center;margin-right:5px}.ui.repository.list .item{padding-bottom:25px}.ui.repository.list .item:not(:first-child){border-top:1px solid #eee;padding-top:25px}.ui.repository.list .item .ui.header{font-size:1.5rem;padding-bottom:10px}.ui.repository.list .item .ui.header .name{word-break:break-all}.ui.repository.list .item .ui.header .metas{color:#888;font-size:14px;font-weight:400}.ui.repository.list .item .ui.header .metas span:not(:last-child){margin-right:5px}.ui.repository.list .item .time{font-size:12px;color:grey}.ui.repository.branches .time{font-size:12px;color:grey}.ui.user.list .item{padding-bottom:25px}.ui.user.list .item:not(:first-child){border-top:1px solid #eee;padding-top:25px}.ui.user.list .item .ui.avatar.image{width:40px;height:40px}.ui.user.list .item .description{margin-top:5px}.ui.user.list .item .description .octicon:not(:first-child){margin-left:5px}.ui.user.list .item .description a{color:#333}.ui.user.list .item .description a:hover{text-decoration:underline}
\ No newline at end of file
diff --git a/public/js/index.js b/public/js/index.js
index e98a3fe6d..823dd8766 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -2336,8 +2336,10 @@ function initTopicbar() {
}).done(function() {
editDiv.hide();
viewDiv.show();
+ }).fail(function(xhr) {
+ alert(xhr.responseJSON.message)
})
- })
+ });
$('#topic_edit .dropdown').dropdown({
allowAdditions: true,
diff --git a/public/less/_markdown.less b/public/less/_markdown.less
index 9e2734e42..458016d71 100644
--- a/public/less/_markdown.less
+++ b/public/less/_markdown.less
@@ -5,6 +5,10 @@
line-height: 1.6 !important;
word-wrap: break-word;
+ &.ui.segment {
+ padding: 3em;
+ }
+
&.file-view {
padding: 2em 2em 2em !important;
}
diff --git a/public/swagger.v1.json b/public/swagger.v1.json
index 2c263ef1f..9fd790281 100644
--- a/public/swagger.v1.json
+++ b/public/swagger.v1.json
@@ -321,9 +321,13 @@
"operationId": "renderMarkdownRaw",
"parameters": [
{
- "type": "string",
+ "description": "Request body to render",
"name": "body",
- "in": "body"
+ "in": "body",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -448,6 +452,15 @@
],
"summary": "List an organization's webhooks",
"operationId": "orgListHooks",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"200": {
"$ref": "#/responses/HookList"
@@ -468,6 +481,15 @@
],
"summary": "Create a hook",
"operationId": "orgCreateHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"201": {
"$ref": "#/responses/Hook"
@@ -485,6 +507,22 @@
],
"summary": "Get a hook",
"operationId": "orgGetHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "id of the hook to get",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"200": {
"$ref": "#/responses/Hook"
@@ -500,6 +538,22 @@
],
"summary": "Delete a hook",
"operationId": "orgDeleteHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"204": {
"$ref": "#/responses/empty"
@@ -518,6 +572,22 @@
],
"summary": "Update a hook",
"operationId": "orgEditHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "name of the organization",
+ "name": "org",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "id of the hook to update",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"200": {
"$ref": "#/responses/Hook"
@@ -994,7 +1064,7 @@
}
}
},
- "/repos/{owner}/{repo}/archive/{filepath}": {
+ "/repos/{owner}/{repo}/archive/{archive}": {
"get": {
"produces": [
"application/json"
@@ -1530,6 +1600,47 @@
}
}
},
+ "delete": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "repository"
+ ],
+ "summary": "Delete a hook in a repository",
+ "operationId": "repoDeleteHook",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "id of the hook to delete",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "204": {
+ "$ref": "#/responses/empty"
+ },
+ "404": {
+ "$ref": "#/responses/notFound"
+ }
+ }
+ },
"patch": {
"produces": [
"application/json"
@@ -1554,6 +1665,13 @@
"in": "path",
"required": true
},
+ {
+ "type": "integer",
+ "description": "index of the hook",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
{
"name": "body",
"in": "body",
@@ -1825,6 +1943,100 @@
}
}
},
+ "/repos/{owner}/{repo}/issues/{id}/times": {
+ "get": {
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "List an issue's tracked times",
+ "operationId": "issueTrackedTimes",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "index of the issue",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTimeList"
+ }
+ }
+ },
+ "post": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "issue"
+ ],
+ "summary": "Add a tracked time to a issue",
+ "operationId": "issueAddTime",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "index of the issue to add tracked time to",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "name": "body",
+ "in": "body",
+ "schema": {
+ "$ref": "#/definitions/AddTimeOption"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "$ref": "#/responses/TrackedTime"
+ },
+ "400": {
+ "$ref": "#/responses/error"
+ },
+ "403": {
+ "$ref": "#/responses/error"
+ }
+ }
+ }
+ },
"/repos/{owner}/{repo}/issues/{index}": {
"get": {
"produces": [
@@ -1941,7 +2153,7 @@
{
"type": "integer",
"description": "index of the issue",
- "name": "id",
+ "name": "index",
"in": "path",
"required": true
},
@@ -1988,7 +2200,7 @@
{
"type": "integer",
"description": "index of the issue",
- "name": "id",
+ "name": "index",
"in": "path",
"required": true
},
@@ -1996,7 +2208,7 @@
"name": "body",
"in": "body",
"schema": {
- "$ref": "#/definitions/CreateIssueOption"
+ "$ref": "#/definitions/CreateIssueCommentOption"
}
}
],
@@ -2332,100 +2544,6 @@
}
}
},
- "/repos/{owner}/{repo}/issues/{index}/times": {
- "get": {
- "produces": [
- "application/json"
- ],
- "tags": [
- "issue"
- ],
- "summary": "List an issue's tracked times",
- "operationId": "issueTrackedTimes",
- "parameters": [
- {
- "type": "string",
- "description": "owner of the repo",
- "name": "owner",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "name of the repo",
- "name": "repo",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "description": "index of the issue",
- "name": "repo",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/responses/TrackedTimeList"
- }
- }
- },
- "post": {
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "issue"
- ],
- "summary": "Add a tracked time to a issue",
- "operationId": "issueAddTime",
- "parameters": [
- {
- "type": "string",
- "description": "owner of the repo",
- "name": "owner",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "name of the repo",
- "name": "repo",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "description": "index of the issue to add tracked time to",
- "name": "id",
- "in": "path",
- "required": true
- },
- {
- "name": "body",
- "in": "body",
- "schema": {
- "$ref": "#/definitions/AddTimeOption"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/responses/TrackedTime"
- },
- "400": {
- "$ref": "#/responses/error"
- },
- "403": {
- "$ref": "#/responses/error"
- }
- }
- }
- },
"/repos/{owner}/{repo}/keys": {
"get": {
"produces": [
@@ -2781,7 +2899,7 @@
"issue"
],
"summary": "Get all of a repository's milestones",
- "operationId": "issueGetMilestones",
+ "operationId": "issueGetMilestonesList",
"parameters": [
{
"type": "string",
@@ -2796,13 +2914,6 @@
"name": "repo",
"in": "path",
"required": true
- },
- {
- "type": "integer",
- "description": "id of the milestone to get",
- "name": "id",
- "in": "path",
- "required": true
}
],
"responses": {
@@ -2863,6 +2974,29 @@
],
"summary": "Get a milestone",
"operationId": "issueGetMilestone",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "owner of the repo",
+ "name": "owner",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "name of the repo",
+ "name": "repo",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "integer",
+ "description": "id of the milestone",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"200": {
"$ref": "#/responses/Milestone"
@@ -2893,7 +3027,7 @@
{
"type": "integer",
"description": "id of the milestone to delete",
- "name": "body",
+ "name": "id",
"in": "path",
"required": true
}
@@ -2931,6 +3065,13 @@
"in": "path",
"required": true
},
+ {
+ "type": "integer",
+ "description": "id of the milestone",
+ "name": "id",
+ "in": "path",
+ "required": true
+ },
{
"name": "body",
"in": "body",
@@ -3979,7 +4120,7 @@
}
}
},
- "/repos/{owner}/{repo}/times/{tracker}": {
+ "/repos/{owner}/{repo}/times/{user}": {
"get": {
"produces": [
"application/json"
@@ -4019,49 +4160,6 @@
}
}
},
- "/repos/{user}/{repo}/hooks/{id}": {
- "delete": {
- "produces": [
- "application/json"
- ],
- "tags": [
- "repository"
- ],
- "summary": "Delete a hook in a repository",
- "operationId": "repoDeleteHook",
- "parameters": [
- {
- "type": "string",
- "description": "owner of the repo",
- "name": "owner",
- "in": "path",
- "required": true
- },
- {
- "type": "string",
- "description": "name of the repo",
- "name": "repo",
- "in": "path",
- "required": true
- },
- {
- "type": "integer",
- "description": "id of the hook to delete",
- "name": "id",
- "in": "path",
- "required": true
- }
- ],
- "responses": {
- "204": {
- "$ref": "#/responses/empty"
- },
- "404": {
- "$ref": "#/responses/notFound"
- }
- }
- }
- },
"/repositories/{id}": {
"get": {
"produces": [
@@ -4238,7 +4336,7 @@
"organization"
],
"summary": "Remove a team member",
- "operationId": "orgAddTeamMember",
+ "operationId": "orgRemoveTeamMember",
"parameters": [
{
"type": "integer",
@@ -4297,7 +4395,7 @@
"organization"
],
"summary": "Add a repository to a team",
- "operationId": "orgAddTeamMember",
+ "operationId": "orgAddTeamRepository",
"parameters": [
{
"type": "integer",
@@ -4336,7 +4434,7 @@
"organization"
],
"summary": "Remove a repository from a team",
- "operationId": "orgAddTeamMember",
+ "operationId": "orgRemoveTeamRepository",
"parameters": [
{
"type": "integer",
@@ -4379,10 +4477,10 @@
"operationId": "topicSearch",
"parameters": [
{
- "type": "integer",
- "description": "id of the repo to get",
- "name": "keyword",
- "in": "path",
+ "type": "string",
+ "description": "keywords to search",
+ "name": "q",
+ "in": "query",
"required": true
}
],
@@ -4509,7 +4607,7 @@
}
}
},
- "/user/following/{followee}": {
+ "/user/following/{username}": {
"get": {
"tags": [
"user"
@@ -4520,7 +4618,7 @@
{
"type": "string",
"description": "username of followed user",
- "name": "followee",
+ "name": "username",
"in": "path",
"required": true
}
@@ -4533,9 +4631,7 @@
"$ref": "#/responses/notFound"
}
}
- }
- },
- "/user/following/{username}": {
+ },
"put": {
"tags": [
"user"
@@ -5301,6 +5397,15 @@
],
"summary": "List the authenticated user's access tokens",
"operationId": "userGetTokens",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
+ }
+ ],
"responses": {
"200": {
"$ref": "#/responses/AccessTokenList"
@@ -5323,8 +5428,10 @@
{
"type": "string",
"x-go-name": "Name",
- "name": "name",
- "in": "query"
+ "description": "username of user",
+ "name": "username",
+ "in": "path",
+ "required": true
}
],
"responses": {
@@ -7612,9 +7719,6 @@
"description": "SearchResults",
"schema": {
"$ref": "#/definitions/SearchResults"
- },
- "headers": {
- "body": {}
}
},
"ServerVersion": {
@@ -7721,40 +7825,6 @@
"description": "parameterBodies",
"schema": {
"$ref": "#/definitions/EditAttachmentOptions"
- },
- "headers": {
- "AddCollaboratorOption": {},
- "AddTimeOption": {},
- "CreateEmailOption": {},
- "CreateForkOption": {},
- "CreateHookOption": {},
- "CreateIssueCommentOption": {},
- "CreateIssueOption": {},
- "CreateKeyOption": {},
- "CreateLabelOption": {},
- "CreateMilestoneOption": {},
- "CreateOrgOption": {},
- "CreatePullRequestOption": {},
- "CreateReleaseOption": {},
- "CreateRepoOption": {},
- "CreateStatusOption": {},
- "CreateTeamOption": {},
- "CreateUserOption": {},
- "DeleteEmailOption": {},
- "EditAttachmentOptions": {},
- "EditHookOption": {},
- "EditIssueCommentOption": {},
- "EditIssueOption": {},
- "EditLabelOption": {},
- "EditMilestoneOption": {},
- "EditOrgOption": {},
- "EditPullRequestOption": {},
- "EditReleaseOption": {},
- "EditTeamOption": {},
- "EditUserOption": {},
- "IssueLabelsOption": {},
- "MarkdownOption": {},
- "MigrateRepoForm": {}
}
},
"redirect": {
@@ -7794,24 +7864,16 @@
},
"security": [
{
- "BasicAuth": [
- "[]"
- ]
+ "BasicAuth": []
},
{
- "Token": [
- "[]"
- ]
+ "Token": []
},
{
- "AccessToken": [
- "[]"
- ]
+ "AccessToken": []
},
{
- "AuthorizationHeaderToken": [
- "[]"
- ]
+ "AuthorizationHeaderToken": []
}
]
}
\ No newline at end of file
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index eec55cac6..5007a0d56 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -20,10 +20,10 @@
// - text/html
//
// Security:
-// - BasicAuth: []
-// - Token: []
-// - AccessToken: []
-// - AuthorizationHeaderToken: []
+// - BasicAuth :
+// - Token :
+// - AccessToken :
+// - AuthorizationHeaderToken :
//
// SecurityDefinitions:
// BasicAuth:
diff --git a/routers/api/v1/misc/markdown.go b/routers/api/v1/misc/markdown.go
index fd7d1489b..633dff98e 100644
--- a/routers/api/v1/misc/markdown.go
+++ b/routers/api/v1/misc/markdown.go
@@ -62,9 +62,12 @@ func MarkdownRaw(ctx *context.APIContext) {
// ---
// summary: Render raw markdown as HTML
// parameters:
- // - name: body
- // in: body
- // type: string
+ // - name: body
+ // in: body
+ // description: Request body to render
+ // required: true
+ // schema:
+ // type: string
// consumes:
// - text/plain
// produces:
diff --git a/routers/api/v1/org/hook.go b/routers/api/v1/org/hook.go
index 0a77d795e..83d2a5e5b 100644
--- a/routers/api/v1/org/hook.go
+++ b/routers/api/v1/org/hook.go
@@ -20,6 +20,12 @@ func ListHooks(ctx *context.APIContext) {
// summary: List an organization's webhooks
// produces:
// - application/json
+ // parameters:
+ // - name: org
+ // in: path
+ // description: name of the organization
+ // type: string
+ // required: true
// responses:
// "200":
// "$ref": "#/responses/HookList"
@@ -43,6 +49,17 @@ func GetHook(ctx *context.APIContext) {
// summary: Get a hook
// produces:
// - application/json
+ // parameters:
+ // - name: org
+ // in: path
+ // description: name of the organization
+ // type: string
+ // required: true
+ // - name: id
+ // in: path
+ // description: id of the hook to get
+ // type: integer
+ // required: true
// responses:
// "200":
// "$ref": "#/responses/Hook"
@@ -64,9 +81,17 @@ func CreateHook(ctx *context.APIContext, form api.CreateHookOption) {
// - application/json
// produces:
// - application/json
+ // parameters:
+ // - name: org
+ // in: path
+ // description: name of the organization
+ // type: string
+ // required: true
// responses:
// "201":
// "$ref": "#/responses/Hook"
+
+ //TODO in body params
if !utils.CheckCreateHookOption(ctx, &form) {
return
}
@@ -82,9 +107,22 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) {
// - application/json
// produces:
// - application/json
+ // parameters:
+ // - name: org
+ // in: path
+ // description: name of the organization
+ // type: string
+ // required: true
+ // - name: id
+ // in: path
+ // description: id of the hook to update
+ // type: integer
+ // required: true
// responses:
// "200":
// "$ref": "#/responses/Hook"
+
+ //TODO in body params
hookID := ctx.ParamsInt64(":id")
utils.EditOrgHook(ctx, &form, hookID)
}
@@ -96,6 +134,17 @@ func DeleteHook(ctx *context.APIContext) {
// summary: Delete a hook
// produces:
// - application/json
+ // parameters:
+ // - name: org
+ // in: path
+ // description: name of the organization
+ // type: string
+ // required: true
+ // - name: id
+ // in: path
+ // description: id of the hook to delete
+ // type: integer
+ // required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go
index 408d8921d..b8dd026bf 100644
--- a/routers/api/v1/org/team.go
+++ b/routers/api/v1/org/team.go
@@ -227,7 +227,7 @@ func AddTeamMember(ctx *context.APIContext) {
// RemoveTeamMember api for remove one member from a team
func RemoveTeamMember(ctx *context.APIContext) {
- // swagger:operation DELETE /teams/{id}/members/{username} organization orgAddTeamMember
+ // swagger:operation DELETE /teams/{id}/members/{username} organization orgRemoveTeamMember
// ---
// summary: Remove a team member
// produces:
@@ -306,7 +306,7 @@ func getRepositoryByParams(ctx *context.APIContext) *models.Repository {
// AddTeamRepository api for adding a repository to a team
func AddTeamRepository(ctx *context.APIContext) {
- // swagger:operation PUT /teams/{id}/repos/{org}/{repo} organization orgAddTeamMember
+ // swagger:operation PUT /teams/{id}/repos/{org}/{repo} organization orgAddTeamRepository
// ---
// summary: Add a repository to a team
// produces:
@@ -350,7 +350,7 @@ func AddTeamRepository(ctx *context.APIContext) {
// RemoveTeamRepository api for removing a repository from a team
func RemoveTeamRepository(ctx *context.APIContext) {
- // swagger:operation DELETE /teams/{id}/repos/{org}/{repo} organization orgAddTeamMember
+ // swagger:operation DELETE /teams/{id}/repos/{org}/{repo} organization orgRemoveTeamRepository
// ---
// summary: Remove a repository from a team
// description: This does not delete the repository, it only removes the
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index a3c8309ac..610247bc2 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -64,7 +64,7 @@ func GetRawFile(ctx *context.APIContext) {
// GetArchive get archive of a repository
func GetArchive(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/archive/{filepath} repository repoGetArchive
+ // swagger:operation GET /repos/{owner}/{repo}/archive/{archive} repository repoGetArchive
// ---
// summary: Get an archive of a repository
// produces:
diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go
index e412a7f1f..1f121dfc3 100644
--- a/routers/api/v1/repo/hook.go
+++ b/routers/api/v1/repo/hook.go
@@ -189,6 +189,11 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) {
// description: name of the repo
// type: string
// required: true
+ // - name: id
+ // in: path
+ // description: index of the hook
+ // type: integer
+ // required: true
// - name: body
// in: body
// schema:
@@ -202,7 +207,7 @@ func EditHook(ctx *context.APIContext, form api.EditHookOption) {
// DeleteHook delete a hook of a repository
func DeleteHook(ctx *context.APIContext) {
- // swagger:operation DELETE /repos/{user}/{repo}/hooks/{id} repository repoDeleteHook
+ // swagger:operation DELETE /repos/{owner}/{repo}/hooks/{id} repository repoDeleteHook
// ---
// summary: Delete a hook in a repository
// produces:
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index 211d8045a..7be39166d 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -1,4 +1,5 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
+// Copyright 2018 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
@@ -165,7 +166,7 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
// "$ref": "#/responses/Issue"
var deadlineUnix util.TimeStamp
- if form.Deadline != nil {
+ if form.Deadline != nil && ctx.Repo.IsWriter() {
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
}
@@ -178,15 +179,22 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
DeadlineUnix: deadlineUnix,
}
- // Get all assignee IDs
- assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees)
- if err != nil {
- if models.IsErrUserNotExist(err) {
- ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
- } else {
- ctx.Error(500, "AddAssigneeByName", err)
+ var assigneeIDs = make([]int64, 0)
+ var err error
+ if ctx.Repo.IsWriter() {
+ issue.MilestoneID = form.Milestone
+ assigneeIDs, err = models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees)
+ if err != nil {
+ if models.IsErrUserNotExist(err) {
+ ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
+ } else {
+ ctx.Error(500, "AddAssigneeByName", err)
+ }
+ return
}
- return
+ } else {
+ // setting labels is not allowed if user is not a writer
+ form.Labels = make([]int64, 0)
}
if err := models.NewIssue(ctx.Repo.Repository, issue, form.Labels, assigneeIDs, nil); err != nil {
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index 2865ea916..af952a070 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -31,7 +31,7 @@ func ListIssueComments(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
- // - name: id
+ // - name: index
// in: path
// description: index of the issue
// type: integer
@@ -139,7 +139,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
// description: name of the repo
// type: string
// required: true
- // - name: id
+ // - name: index
// in: path
// description: index of the issue
// type: integer
@@ -147,7 +147,7 @@ func CreateIssueComment(ctx *context.APIContext, form api.CreateIssueCommentOpti
// - name: body
// in: body
// schema:
- // "$ref": "#/definitions/CreateIssueOption"
+ // "$ref": "#/definitions/CreateIssueCommentOption"
// responses:
// "201":
// "$ref": "#/responses/Comment"
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index 1111d672a..9be9fee91 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -21,7 +21,7 @@ func trackedTimesToAPIFormat(trackedTimes []*models.TrackedTime) []*api.TrackedT
// ListTrackedTimes list all the tracked times of an issue
func ListTrackedTimes(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/issues/{index}/times issue issueTrackedTimes
+ // swagger:operation GET /repos/{owner}/{repo}/issues/{id}/times issue issueTrackedTimes
// ---
// summary: List an issue's tracked times
// produces:
@@ -37,7 +37,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
- // - name: repo
+ // - name: id
// in: path
// description: index of the issue
// type: integer
@@ -70,7 +70,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
// AddTime adds time manual to the given issue
func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
- // swagger:operation Post /repos/{owner}/{repo}/issues/{index}/times issue issueAddTime
+ // swagger:operation Post /repos/{owner}/{repo}/issues/{id}/times issue issueAddTime
// ---
// summary: Add a tracked time to a issue
// consumes:
@@ -132,7 +132,7 @@ func AddTime(ctx *context.APIContext, form api.AddTimeOption) {
// ListTrackedTimesByUser lists all tracked times of the user
func ListTrackedTimesByUser(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/times/{tracker} user userTrackedTimes
+ // swagger:operation GET /repos/{owner}/{repo}/times/{user} user userTrackedTimes
// ---
// summary: List a user's tracked times in a repo
// produces:
diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go
index 3953b0c3c..a138cb7a6 100644
--- a/routers/api/v1/repo/milestone.go
+++ b/routers/api/v1/repo/milestone.go
@@ -16,30 +16,7 @@ import (
// ListMilestones list all the milestones for a repository
func ListMilestones(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/milestones/{id} issue issueGetMilestone
- // ---
- // summary: Get a milestone
- // produces:
- // - application/json
- // responses:
- // "200":
- // "$ref": "#/responses/Milestone"
- milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID)
- if err != nil {
- ctx.Error(500, "GetMilestonesByRepoID", err)
- return
- }
-
- apiMilestones := make([]*api.Milestone, len(milestones))
- for i := range milestones {
- apiMilestones[i] = milestones[i].APIFormat()
- }
- ctx.JSON(200, &apiMilestones)
-}
-
-// GetMilestone get a milestone for a repository
-func GetMilestone(ctx *context.APIContext) {
- // swagger:operation GET /repos/{owner}/{repo}/milestones issue issueGetMilestones
+ // swagger:operation GET /repos/{owner}/{repo}/milestones issue issueGetMilestonesList
// ---
// summary: Get all of a repository's milestones
// produces:
@@ -55,6 +32,29 @@ func GetMilestone(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
+ // responses:
+ // "200":
+ // "$ref": "#/responses/MilestoneList"
+ milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID)
+ if err != nil {
+ ctx.Error(500, "GetMilestonesByRepoID", err)
+ return
+ }
+
+ apiMilestones := make([]*api.Milestone, len(milestones))
+ for i := range milestones {
+ apiMilestones[i] = milestones[i].APIFormat()
+ }
+ ctx.JSON(200, &apiMilestones)
+}
+
+// GetMilestone get a milestone for a repository
+func GetMilestone(ctx *context.APIContext) {
+ // swagger:operation GET /repos/{owner}/{repo}/milestones/{id} issue issueGetMilestone
+ // ---
+ // summary: Get a milestone
+ // produces:
+ // - application/json
// parameters:
// - name: owner
// in: path
@@ -68,12 +68,12 @@ func GetMilestone(ctx *context.APIContext) {
// required: true
// - name: id
// in: path
- // description: id of the milestone to get
+ // description: id of the milestone
// type: integer
// required: true
// responses:
// "200":
- // "$ref": "#/responses/MilestoneList"
+ // "$ref": "#/responses/Milestone"
milestone, err := models.GetMilestoneByRepoID(ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
if err != nil {
if models.IsErrMilestoneNotExist(err) {
@@ -152,6 +152,11 @@ func EditMilestone(ctx *context.APIContext, form api.EditMilestoneOption) {
// description: name of the repo
// type: string
// required: true
+ // - name: id
+ // in: path
+ // description: id of the milestone
+ // type: integer
+ // required: true
// - name: body
// in: body
// schema:
@@ -202,7 +207,7 @@ func DeleteMilestone(ctx *context.APIContext) {
// description: name of the repo
// type: string
// required: true
- // - name: body
+ // - name: id
// in: path
// description: id of the milestone to delete
// type: integer
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 9f64dda61..ccfe0440c 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -508,13 +508,13 @@ func TopicSearch(ctx *context.Context) {
// ---
// summary: search topics via keyword
// produces:
- // - application/json
+ // - application/json
// parameters:
- // - name: keyword
- // in: path
- // description: id of the repo to get
- // type: integer
- // required: true
+ // - name: q
+ // in: query
+ // description: keywords to search
+ // required: true
+ // type: string
// responses:
// "200":
// "$ref": "#/responses/Repository"
diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go
index 8d9363fe9..4f2461f46 100644
--- a/routers/api/v1/swagger/options.go
+++ b/routers/api/v1/swagger/options.go
@@ -15,55 +15,87 @@ import (
// parameterBodies
// swagger:response parameterBodies
type swaggerParameterBodies struct {
+ // in:body
AddCollaboratorOption api.AddCollaboratorOption
+ // in:body
CreateEmailOption api.CreateEmailOption
+ // in:body
DeleteEmailOption api.DeleteEmailOption
+ // in:body
CreateHookOption api.CreateHookOption
- EditHookOption api.EditHookOption
+ // in:body
+ EditHookOption api.EditHookOption
+ // in:body
CreateIssueOption api.CreateIssueOption
- EditIssueOption api.EditIssueOption
+ // in:body
+ EditIssueOption api.EditIssueOption
+ // in:body
CreateIssueCommentOption api.CreateIssueCommentOption
- EditIssueCommentOption api.EditIssueCommentOption
+ // in:body
+ EditIssueCommentOption api.EditIssueCommentOption
+ // in:body
IssueLabelsOption api.IssueLabelsOption
+ // in:body
CreateKeyOption api.CreateKeyOption
+ // in:body
CreateLabelOption api.CreateLabelOption
- EditLabelOption api.EditLabelOption
+ // in:body
+ EditLabelOption api.EditLabelOption
+ // in:body
MarkdownOption api.MarkdownOption
+ // in:body
CreateMilestoneOption api.CreateMilestoneOption
- EditMilestoneOption api.EditMilestoneOption
+ // in:body
+ EditMilestoneOption api.EditMilestoneOption
+ // in:body
CreateOrgOption api.CreateOrgOption
- EditOrgOption api.EditOrgOption
+ // in:body
+ EditOrgOption api.EditOrgOption
+ // in:body
CreatePullRequestOption api.CreatePullRequestOption
- EditPullRequestOption api.EditPullRequestOption
+ // in:body
+ EditPullRequestOption api.EditPullRequestOption
+ // in:body
CreateReleaseOption api.CreateReleaseOption
- EditReleaseOption api.EditReleaseOption
+ // in:body
+ EditReleaseOption api.EditReleaseOption
+ // in:body
CreateRepoOption api.CreateRepoOption
+ // in:body
CreateForkOption api.CreateForkOption
+ // in:body
CreateStatusOption api.CreateStatusOption
+ // in:body
CreateTeamOption api.CreateTeamOption
- EditTeamOption api.EditTeamOption
+ // in:body
+ EditTeamOption api.EditTeamOption
+ // in:body
AddTimeOption api.AddTimeOption
+ // in:body
CreateUserOption api.CreateUserOption
- EditUserOption api.EditUserOption
+ // in:body
+ EditUserOption api.EditUserOption
+ // in:body
MigrateRepoForm auth.MigrateRepoForm
+ // in:body
EditAttachmentOptions api.EditAttachmentOptions
}
diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go
index 97837dfc2..9decc8f58 100644
--- a/routers/api/v1/swagger/repo.go
+++ b/routers/api/v1/swagger/repo.go
@@ -102,6 +102,7 @@ type swaggerResponseWatchInfo struct {
// SearchResults
// swagger:response SearchResults
type swaggerResponseSearchResults struct {
+ // in:body
Body api.SearchResults `json:"body"`
}
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index e1f75de68..fc4118649 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -18,6 +18,12 @@ func ListAccessTokens(ctx *context.APIContext) {
// summary: List the authenticated user's access tokens
// produces:
// - application/json
+ // parameters:
+ // - name: username
+ // in: path
+ // description: username of user
+ // type: string
+ // required: true
// responses:
// "200":
// "$ref": "#/responses/AccessTokenList"
@@ -46,6 +52,12 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption
// - application/json
// produces:
// - application/json
+ // parameters:
+ // - name: username
+ // in: path
+ // description: username of user
+ // type: string
+ // required: true
// responses:
// "200":
// "$ref": "#/responses/AccessToken"
diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go
index 49d13cc38..284b7323c 100644
--- a/routers/api/v1/user/follower.go
+++ b/routers/api/v1/user/follower.go
@@ -119,11 +119,11 @@ func checkUserFollowing(ctx *context.APIContext, u *models.User, followID int64)
// CheckMyFollowing whether the given user is followed by the authenticated user
func CheckMyFollowing(ctx *context.APIContext) {
- // swagger:operation GET /user/following/{followee} user userCurrentCheckFollowing
+ // swagger:operation GET /user/following/{username} user userCurrentCheckFollowing
// ---
// summary: Check whether a user is followed by the authenticated user
// parameters:
- // - name: followee
+ // - name: username
// in: path
// description: username of followed user
// type: string
diff --git a/routers/home.go b/routers/home.go
index 5bb353c7e..0aa907658 100644
--- a/routers/home.go
+++ b/routers/home.go
@@ -42,6 +42,10 @@ func Home(ctx *context.Context) {
user.Dashboard(ctx)
}
return
+ // Check non-logged users landing page.
+ } else if setting.LandingPageURL != setting.LandingPageHome {
+ ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
+ return
}
// Check auto-login.
diff --git a/routers/org/teams.go b/routers/org/teams.go
index d894c8661..87bfb8596 100644
--- a/routers/org/teams.go
+++ b/routers/org/teams.go
@@ -182,7 +182,14 @@ func NewTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
Authorize: models.ParseAccessMode(form.Permission),
}
if t.Authorize < models.AccessModeAdmin {
- t.UnitTypes = form.Units
+ var units = make([]*models.TeamUnit, 0, len(form.Units))
+ for _, tp := range form.Units {
+ units = append(units, &models.TeamUnit{
+ OrgID: ctx.Org.Organization.ID,
+ Type: tp,
+ })
+ }
+ t.Units = units
}
ctx.Data["Team"] = t
@@ -264,9 +271,17 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) {
}
t.Description = form.Description
if t.Authorize < models.AccessModeAdmin {
- t.UnitTypes = form.Units
+ var units = make([]models.TeamUnit, 0, len(form.Units))
+ for _, tp := range form.Units {
+ units = append(units, models.TeamUnit{
+ OrgID: t.OrgID,
+ TeamID: t.ID,
+ Type: tp,
+ })
+ }
+ models.UpdateTeamUnits(t, units)
} else {
- t.UnitTypes = nil
+ models.UpdateTeamUnits(t, nil)
}
if ctx.HasError() {
diff --git a/routers/repo/topic.go b/routers/repo/topic.go
index 2a43d53ff..63fcf793f 100644
--- a/routers/repo/topic.go
+++ b/routers/repo/topic.go
@@ -12,8 +12,8 @@ import (
"code.gitea.io/gitea/modules/log"
)
-// TopicPost response for creating repository
-func TopicPost(ctx *context.Context) {
+// TopicsPost response for creating repository
+func TopicsPost(ctx *context.Context) {
if ctx.User == nil {
ctx.JSON(403, map[string]interface{}{
"message": "Only owners could change the topics.",
@@ -27,6 +27,37 @@ func TopicPost(ctx *context.Context) {
topics = strings.Split(topicsStr, ",")
}
+ invalidTopics := make([]string, 0)
+ i := 0
+ for _, topic := range topics {
+ topic = strings.TrimSpace(strings.ToLower(topic))
+ // ignore empty string
+ if len(topic) > 0 {
+ topics[i] = topic
+ i++
+ }
+ if !models.ValidateTopic(topic) {
+ invalidTopics = append(invalidTopics, topic)
+ }
+ }
+ topics = topics[:i]
+
+ if len(topics) > 25 {
+ ctx.JSON(422, map[string]interface{}{
+ "invalidTopics": topics[:0],
+ "message": ctx.Tr("repo.topic.count_prompt"),
+ })
+ return
+ }
+
+ if len(invalidTopics) > 0 {
+ ctx.JSON(422, map[string]interface{}{
+ "invalidTopics": invalidTopics,
+ "message": ctx.Tr("repo.topic.format_prompt"),
+ })
+ return
+ }
+
err := models.SaveTopics(ctx.Repo.Repository.ID, topics...)
if err != nil {
log.Error(2, "SaveTopics failed: %v", err)
diff --git a/routers/repo/view.go b/routers/repo/view.go
index d2efe3009..4f1deeae4 100644
--- a/routers/repo/view.go
+++ b/routers/repo/view.go
@@ -105,7 +105,9 @@ func renderDirectory(ctx *context.Context, treeLink string) {
ctx.Data["FileContent"] = string(markup.Render(readmeFile.Name(), buf, treeLink, ctx.Repo.Repository.ComposeMetas()))
} else {
ctx.Data["IsRenderedHTML"] = true
- ctx.Data["FileContent"] = string(bytes.Replace(buf, []byte("\n"), []byte(`
`), -1))
+ ctx.Data["FileContent"] = strings.Replace(
+ gotemplate.HTMLEscapeString(string(buf)), "\n", `
`, -1,
+ )
}
}
}
@@ -208,7 +210,9 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
ctx.Data["FileContent"] = string(markup.Render(blob.Name(), buf, path.Dir(treeLink), ctx.Repo.Repository.ComposeMetas()))
} else if readmeExist {
ctx.Data["IsRenderedHTML"] = true
- ctx.Data["FileContent"] = string(bytes.Replace(buf, []byte("\n"), []byte(`
`), -1))
+ ctx.Data["FileContent"] = strings.Replace(
+ gotemplate.HTMLEscapeString(string(buf)), "\n", `
`, -1,
+ )
} else {
// Building code view blocks with line number on server side.
var fileContent string
diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go
index 63450ed88..53c1afe66 100644
--- a/routers/repo/webhook.go
+++ b/routers/repo/webhook.go
@@ -210,7 +210,7 @@ func GogsHooksNewPost(ctx *context.Context, form auth.NewGogshookForm) {
Secret: form.Secret,
HookEvent: ParseHookEvent(form.WebhookForm),
IsActive: form.Active,
- HookTaskType: models.GITEA,
+ HookTaskType: models.GOGS,
OrgID: orCtx.OrgID,
}
if err := w.UpdateEvent(); err != nil {
diff --git a/routers/routes/routes.go b/routers/routes/routes.go
index 15b91f159..1eefbf1b6 100644
--- a/routers/routes/routes.go
+++ b/routers/routes/routes.go
@@ -486,7 +486,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/:id", repo.WebHooksEdit)
m.Post("/:id/test", repo.TestWebhook)
m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
- m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost)
+ m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost)
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)
@@ -626,7 +626,7 @@ func RegisterRoutes(m *macaron.Macaron) {
}, context.RepoAssignment(), context.UnitTypes(), context.LoadRepoUnits(), context.CheckUnit(models.UnitTypeReleases))
m.Group("/:username/:reponame", func() {
- m.Post("/topics", repo.TopicPost)
+ m.Post("/topics", repo.TopicsPost)
}, context.RepoAssignment(), reqRepoAdmin)
m.Group("/:username/:reponame", func() {
diff --git a/routers/user/auth.go b/routers/user/auth.go
index 9a59f52db..317b4af3b 100644
--- a/routers/user/auth.go
+++ b/routers/user/auth.go
@@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
"github.com/go-macaron/captcha"
"github.com/markbates/goth"
@@ -474,7 +475,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
return setting.AppSubURL + "/"
}
- if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
+ if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) {
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
if obeyRedirect {
ctx.RedirectToFirst(redirectTo)
diff --git a/routers/user/home.go b/routers/user/home.go
index 693b04b02..1a79da191 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -203,7 +203,11 @@ func Issues(ctx *context.Context) {
return
}
} else {
- userRepoIDs, err = ctxUser.GetAccessRepoIDs()
+ unitType := models.UnitTypeIssues
+ if isPullList {
+ unitType = models.UnitTypePullRequests
+ }
+ userRepoIDs, err = ctxUser.GetAccessRepoIDs(unitType)
if err != nil {
ctx.ServerError("ctxUser.GetAccessRepoIDs", err)
return
diff --git a/routers/user/home_test.go b/routers/user/home_test.go
index a9b146b76..8a3d9b9f5 100644
--- a/routers/user/home_test.go
+++ b/routers/user/home_test.go
@@ -26,8 +26,8 @@ func TestIssues(t *testing.T) {
Issues(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
- assert.EqualValues(t, map[int64]int64{1: 1, 2: 1}, ctx.Data["Counts"])
+ assert.EqualValues(t, map[int64]int64{1: 1}, ctx.Data["Counts"])
assert.EqualValues(t, true, ctx.Data["IsShowClosed"])
assert.Len(t, ctx.Data["Issues"], 1)
- assert.Len(t, ctx.Data["Repos"], 2)
+ assert.Len(t, ctx.Data["Repos"], 1)
}
diff --git a/routers/user/setting/account.go b/routers/user/setting/account.go
index 966d96aed..bcf602c5e 100644
--- a/routers/user/setting/account.go
+++ b/routers/user/setting/account.go
@@ -24,12 +24,7 @@ func Account(ctx *context.Context) {
ctx.Data["PageIsSettingsAccount"] = true
ctx.Data["Email"] = ctx.User.Email
- emails, err := models.GetEmailAddresses(ctx.User.ID)
- if err != nil {
- ctx.ServerError("GetEmailAddresses", err)
- return
- }
- ctx.Data["Emails"] = emails
+ loadAccountData(ctx)
ctx.HTML(200, tplSettingsAccount)
}
@@ -40,6 +35,8 @@ func AccountPost(ctx *context.Context, form auth.ChangePasswordForm) {
ctx.Data["PageIsSettingsAccount"] = true
if ctx.HasError() {
+ loadAccountData(ctx)
+
ctx.HTML(200, tplSettingsAccount)
return
}
@@ -85,15 +82,9 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) {
return
}
- // Add Email address.
- emails, err := models.GetEmailAddresses(ctx.User.ID)
- if err != nil {
- ctx.ServerError("GetEmailAddresses", err)
- return
- }
- ctx.Data["Emails"] = emails
-
if ctx.HasError() {
+ loadAccountData(ctx)
+
ctx.HTML(200, tplSettingsAccount)
return
}
@@ -105,6 +96,8 @@ func EmailPost(ctx *context.Context, form auth.AddEmailForm) {
}
if err := models.AddEmailAddress(email); err != nil {
if models.IsErrEmailAlreadyUsed(err) {
+ loadAccountData(ctx)
+
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form)
return
}
@@ -149,6 +142,8 @@ func DeleteAccount(ctx *context.Context) {
if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
if models.IsErrUserNotExist(err) {
+ loadAccountData(ctx)
+
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsAccount, nil)
} else {
ctx.ServerError("UserSignIn", err)
@@ -172,3 +167,12 @@ func DeleteAccount(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/")
}
}
+
+func loadAccountData(ctx *context.Context) {
+ emails, err := models.GetEmailAddresses(ctx.User.ID)
+ if err != nil {
+ ctx.ServerError("GetEmailAddresses", err)
+ return
+ }
+ ctx.Data["Emails"] = emails
+}
diff --git a/routers/user/setting/applications.go b/routers/user/setting/applications.go
index f292b65d7..ac7252469 100644
--- a/routers/user/setting/applications.go
+++ b/routers/user/setting/applications.go
@@ -22,12 +22,7 @@ func Applications(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsApplications"] = true
- tokens, err := models.ListAccessTokens(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListAccessTokens", err)
- return
- }
- ctx.Data["Tokens"] = tokens
+ loadApplicationsData(ctx)
ctx.HTML(200, tplSettingsApplications)
}
@@ -38,12 +33,8 @@ func ApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
ctx.Data["PageIsSettingsApplications"] = true
if ctx.HasError() {
- tokens, err := models.ListAccessTokens(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListAccessTokens", err)
- return
- }
- ctx.Data["Tokens"] = tokens
+ loadApplicationsData(ctx)
+
ctx.HTML(200, tplSettingsApplications)
return
}
@@ -75,3 +66,12 @@ func DeleteApplication(ctx *context.Context) {
"redirect": setting.AppSubURL + "/user/settings/applications",
})
}
+
+func loadApplicationsData(ctx *context.Context) {
+ tokens, err := models.ListAccessTokens(ctx.User.ID)
+ if err != nil {
+ ctx.ServerError("ListAccessTokens", err)
+ return
+ }
+ ctx.Data["Tokens"] = tokens
+}
diff --git a/routers/user/setting/keys.go b/routers/user/setting/keys.go
index ef986ef8c..c62b117a7 100644
--- a/routers/user/setting/keys.go
+++ b/routers/user/setting/keys.go
@@ -23,19 +23,7 @@ func Keys(ctx *context.Context) {
ctx.Data["PageIsSettingsKeys"] = true
ctx.Data["DisableSSH"] = setting.SSH.Disabled
- keys, err := models.ListPublicKeys(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListPublicKeys", err)
- return
- }
- ctx.Data["Keys"] = keys
-
- gpgkeys, err := models.ListGPGKeys(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListGPGKeys", err)
- return
- }
- ctx.Data["GPGKeys"] = gpgkeys
+ loadKeysData(ctx)
ctx.HTML(200, tplSettingsKeys)
}
@@ -45,21 +33,9 @@ func KeysPost(ctx *context.Context, form auth.AddKeyForm) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsKeys"] = true
- keys, err := models.ListPublicKeys(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListPublicKeys", err)
- return
- }
- ctx.Data["Keys"] = keys
-
- gpgkeys, err := models.ListGPGKeys(ctx.User.ID)
- if err != nil {
- ctx.ServerError("ListGPGKeys", err)
- return
- }
- ctx.Data["GPGKeys"] = gpgkeys
-
if ctx.HasError() {
+ loadKeysData(ctx)
+
ctx.HTML(200, tplSettingsKeys)
return
}
@@ -73,9 +49,13 @@ func KeysPost(ctx *context.Context, form auth.AddKeyForm) {
ctx.Flash.Error(ctx.Tr("form.invalid_gpg_key", err.Error()))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case models.IsErrGPGKeyIDAlreadyUsed(err):
+ loadKeysData(ctx)
+
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.gpg_key_id_used"), tplSettingsKeys, &form)
case models.IsErrGPGNoEmailFound(err):
+ loadKeysData(ctx)
+
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.gpg_no_key_email_found"), tplSettingsKeys, &form)
default:
@@ -103,9 +83,13 @@ func KeysPost(ctx *context.Context, form auth.AddKeyForm) {
ctx.Data["HasSSHError"] = true
switch {
case models.IsErrKeyAlreadyExist(err):
+ loadKeysData(ctx)
+
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsKeys, &form)
case models.IsErrKeyNameAlreadyUsed(err):
+ loadKeysData(ctx)
+
ctx.Data["Err_Title"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsKeys, &form)
default:
@@ -147,3 +131,19 @@ func DeleteKey(ctx *context.Context) {
"redirect": setting.AppSubURL + "/user/settings/keys",
})
}
+
+func loadKeysData(ctx *context.Context) {
+ keys, err := models.ListPublicKeys(ctx.User.ID)
+ if err != nil {
+ ctx.ServerError("ListPublicKeys", err)
+ return
+ }
+ ctx.Data["Keys"] = keys
+
+ gpgkeys, err := models.ListGPGKeys(ctx.User.ID)
+ if err != nil {
+ ctx.ServerError("ListGPGKeys", err)
+ return
+ }
+ ctx.Data["GPGKeys"] = gpgkeys
+}
diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go
index cf222d002..22511ab89 100644
--- a/routers/user/setting/profile.go
+++ b/routers/user/setting/profile.go
@@ -32,6 +32,7 @@ const (
func Profile(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsProfile"] = true
+
ctx.HTML(200, tplSettingsProfile)
}
diff --git a/routers/user/setting/security.go b/routers/user/setting/security.go
index 860730303..862e4413c 100644
--- a/routers/user/setting/security.go
+++ b/routers/user/setting/security.go
@@ -22,6 +22,30 @@ func Security(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsSecurity"] = true
+ if ctx.Query("openid.return_to") != "" {
+ settingsOpenIDVerify(ctx)
+ return
+ }
+
+ loadSecurityData(ctx)
+
+ ctx.HTML(200, tplSettingsSecurity)
+}
+
+// DeleteAccountLink delete a single account link
+func DeleteAccountLink(ctx *context.Context) {
+ if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
+ ctx.Flash.Error("RemoveAccountLink: " + err.Error())
+ } else {
+ ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
+ }
+
+ ctx.JSON(200, map[string]interface{}{
+ "redirect": setting.AppSubURL + "/user/settings/security",
+ })
+}
+
+func loadSecurityData(ctx *context.Context) {
enrolled := true
_, err := models.GetTwoFactorByUID(ctx.User.ID)
if err != nil {
@@ -71,30 +95,10 @@ func Security(ctx *context.Context) {
}
ctx.Data["AccountLinks"] = sources
- if ctx.Query("openid.return_to") != "" {
- settingsOpenIDVerify(ctx)
- return
- }
-
openid, err := models.GetUserOpenIDs(ctx.User.ID)
if err != nil {
ctx.ServerError("GetUserOpenIDs", err)
return
}
ctx.Data["OpenIDs"] = openid
-
- ctx.HTML(200, tplSettingsSecurity)
-}
-
-// DeleteAccountLink delete a single account link
-func DeleteAccountLink(ctx *context.Context) {
- if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
- ctx.Flash.Error("RemoveAccountLink: " + err.Error())
- } else {
- ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
- }
-
- ctx.JSON(200, map[string]interface{}{
- "redirect": setting.AppSubURL + "/user/settings/security",
- })
}
diff --git a/routers/user/setting/security_openid.go b/routers/user/setting/security_openid.go
index c98dc2cda..6813765f6 100644
--- a/routers/user/setting/security_openid.go
+++ b/routers/user/setting/security_openid.go
@@ -19,12 +19,8 @@ func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
ctx.Data["PageIsSettingsSecurity"] = true
if ctx.HasError() {
- openid, err := models.GetUserOpenIDs(ctx.User.ID)
- if err != nil {
- ctx.ServerError("GetUserOpenIDs", err)
- return
- }
- ctx.Data["OpenIDs"] = openid
+ loadSecurityData(ctx)
+
ctx.HTML(200, tplSettingsSecurity)
return
}
@@ -37,6 +33,8 @@ func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
id, err := openid.Normalize(form.Openid)
if err != nil {
+ loadSecurityData(ctx)
+
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
return
}
@@ -53,6 +51,8 @@ func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
// Check that the OpenID is not already used
for _, obj := range oids {
if obj.URI == id {
+ loadSecurityData(ctx)
+
ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &form)
return
}
@@ -61,6 +61,8 @@ func OpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
redirectTo := setting.AppURL + "user/settings/security"
url, err := openid.RedirectURL(id, redirectTo, setting.AppURL)
if err != nil {
+ loadSecurityData(ctx)
+
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
return
}
@@ -73,13 +75,6 @@ func settingsOpenIDVerify(ctx *context.Context) {
fullURL := setting.AppURL + ctx.Req.Request.URL.String()[1:]
log.Trace("Full URL: " + fullURL)
- oids, err := models.GetUserOpenIDs(ctx.User.ID)
- if err != nil {
- ctx.ServerError("GetUserOpenIDs", err)
- return
- }
- ctx.Data["OpenIDs"] = oids
-
id, err := openid.Verify(fullURL)
if err != nil {
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &auth.AddOpenIDForm{
diff --git a/templates/admin/monitor.tmpl b/templates/admin/monitor.tmpl
index ceca29146..6cc927d68 100644
--- a/templates/admin/monitor.tmpl
+++ b/templates/admin/monitor.tmpl
@@ -49,8 +49,8 @@
{{.PID}} |
{{.Description}} |
- {{.Start.FormatLong}} |
- {{TimeSinceUnix .Start $.Lang}} |
+ {{DateFmtLong .Start}} |
+ {{TimeSince .Start $.Lang}} |
{{end}}
diff --git a/templates/org/team/new.tmpl b/templates/org/team/new.tmpl
index ec1a3dd72..12cdd697c 100644
--- a/templates/org/team/new.tmpl
+++ b/templates/org/team/new.tmpl
@@ -57,7 +57,7 @@
{{range $t, $unit := $.Units}}
{{if .CanBeForked}}