Compare commits

...

122 Commits

Author SHA1 Message Date
Unknwon
f54bcba339 Update locales 2017-03-13 23:41:22 -04:00
Unknwon
f0209ac2f6 api: handle new events for hook 2017-03-13 14:32:16 -04:00
Unknwon
e1dcd11051 repo/settings: improve Git hook editor 2017-03-13 06:00:37 -04:00
Unknwon
24734a33e7 release: improve attachment handle 2017-03-13 05:26:17 -04:00
Unknwon
1df54ea0cd release: able to add attchments to release (#1614)
Added new config section '[release.attachment]’.
2017-03-13 04:32:20 -04:00
Unknwon
e6df2259ab explore: panic if search without login (#3088) 2017-03-13 02:41:04 -04:00
Unknwon
96ae0129ef models/repo: minor code style and comment fix (#4273) 2017-03-13 00:53:50 -04:00
Rob Richards
aaadc61ee8 models/repo: allow SearchRepos to return private but accessible repositories (#4273)
* models/repo.go SearchRepositoryByName()
Updated function to return public and private repositories that the logged in user has been given rights to view
issue #3088

* models/repo.go SearchRepositoryName
changed repository table alias to 'repo'
removed debug line

* models/repo.go SearchRepositoryByName
modified UserID search query to use the "access" table instead of team_repo, team_user etc

* models/repo.go SearchRepositoryByName
1) uppercased SQL keywords
2) removed alias for ACCESS table
2017-03-13 00:37:12 -04:00
Danny Althoff
44a6b63316 cmd/hook: fixed typo (#4280) 2017-03-12 13:43:05 -04:00
Unknwon
5f058c3f07 issue_mail: fix issue poster not receive email if not watching (#2929) 2017-03-12 13:42:19 -04:00
Unknwon
b116dc506b migrations/v16: use continue not return for bad records 2017-03-12 03:34:19 -04:00
Unknwon
bf58f26305 migrations/v16: make SQLite3 work 2017-03-12 03:30:53 -04:00
Unknwon
601f174ea0 migrations/v16: only Warn if repository happens to have bad data 2017-03-12 03:08:25 -04:00
Unknwon
a34c21cde3 migrations/v16: sync table 2017-03-12 03:05:41 -04:00
Unknwon
bb19bb601e repo: able to view size (#1158) 2017-03-12 01:59:48 -05:00
Unknwon
05dbd3f7d7 refactoring: experimental with models/errors package 2017-03-12 00:47:34 -05:00
Unknwon
dee76e4189 models/webhook: add skip check for Release event 2017-03-11 18:44:50 -05:00
Unknwon
b615d670b3 webhook: add Release event (#2387) 2017-03-11 18:41:32 -05:00
Girish Sonawane
b9bb4a62d6 api: make CORS work by handling preflight OPTIONS request (#4264)
* make CORS work by handling preflight OPTIONS request

* Update api.go
2017-03-11 03:01:59 -05:00
Unknwon
61e2bff757 repo: commits, branches and releases should highlight files tab 2017-03-11 02:13:42 -05:00
Unknwon
9713016637 repo/branches: hide buttons for regular users 2017-03-11 01:52:37 -05:00
Unknwon
5c7cb1594b repo/branches: overview and all (#2310) 2017-03-11 01:43:45 -05:00
Unknwon
3eb57370a6 api/repo: fix cannot reponse branch with slashes (#4198) 2017-03-10 23:37:25 -05:00
Unknwon
ac8b1e595f markdown: support Smartypants (#4162)
Added new config section '[smartypants]', and disabled by default.
2017-03-10 23:30:40 -05:00
Unknwon
31c55213ff css/repository: fix undesired style for label template select list 2017-03-10 19:15:28 -05:00
Unknwon
23da90e25d issue_mail: send notifications to participants in comments (#2929) 2017-03-10 18:47:02 -05:00
Unknwon
60ee79363d templates: use owner's avatar as image of repository 2017-03-10 17:00:10 -05:00
Unknwon
8fa6d0d302 repo/pull: handle head repository of merged pull requests deleted 2017-03-10 16:58:41 -05:00
Unknwon
a534f9f9b6 templates/repo: change some buttons to use 'basic' style 2017-03-10 15:36:55 -05:00
Unknwon
aa99e805c8 repo/release: 404 when edit draft (4262) 2017-03-10 15:27:55 -05:00
Unknwon
0049c80cd9 less/repository: minor fix for #git-stats 2017-03-10 15:23:01 -05:00
Unknwon
ebc0943713 templates/repo: only show Git stats in repository home page (#3518)
Move 'Commits' and 'Releases' tabs down to body.

This patch also reduces page load time for pages that do not need
to use commits count anywhere. Get commits count can hurt
performance badly for huge repositories that has tens of thousands
commits like Linux Kernel.
2017-03-10 15:13:48 -05:00
Unknwon
451aef7a1c release: improve page load performance
Previously, we load all releases of a repository which could hurt
performance when the repository has a lot of releases.

Now we're able to only load releases in current page view we need
to show by matching with 'tag_name'.
2017-03-10 14:12:46 -05:00
Unknwon
22882d7c04 models/user: explicitly select for organization type 2017-03-10 12:31:50 -05:00
Unknwon
c3cde864f8 models/pull: treat all errors as conflict (#4265)
If there is a misdetection, log shows everything.
2017-03-09 13:36:40 -05:00
Unknwon
f860ddbbb7 models/pull: better error message detection (#4265)
Stop using English phrases in case of Git localization.
2017-03-09 13:04:41 -05:00
Unknwon
89cc6aa430 webhook: add issue comment event 2017-03-09 04:11:23 -05:00
Unknwon
c93731339f webhook: support Issues event (#2319)
Also addresses #3485.
2017-03-09 00:03:29 -05:00
Unknwon
bab448681d models/user: handle case when user doesn't belong to any organization (#4258) 2017-03-08 22:21:31 -05:00
Unknwon
de2d3e3fd8 ssh_key: create parent directory of 'authorized_keys' file 2017-03-08 22:08:31 -05:00
Unknwon
295d251232 mirror: update repository updated_unix after sync (#2807) 2017-03-08 17:47:44 -05:00
Unknwon
83f6b8e847 Protected branches: allow whitelist bypass require pull request check (#4207) 2017-03-08 16:43:36 -05:00
Unknwon
e38fef0009 Update README 2017-03-08 10:17:53 -05:00
Unknwon
6c3424dc3f repo/setting: fix admin cannot transfer organizational repository 2017-03-07 18:51:24 -05:00
Unknwon
d1f0bc48ce repo/setting: fix admin cannot delete organizational repository wiki 2017-03-07 15:51:53 -05:00
Unknwon
bb005f3f9a models/user: better directory handling when change username
Previously, if the user base directory somehow doesn't exist, the
application throws 500 for failure of rename.

Now it detects if the application should rename or just create a
new directory.
2017-03-07 14:12:19 -05:00
Unknwon
e6dbfd918c security: fix vulnerability in changing username
Reported by João Arnaut.
2017-03-07 14:07:20 -05:00
Unknwon
c2f0711db0 Update locale 2017-03-06 23:37:46 -05:00
Unknwon
92153fd898 git_hook: add new env var 'GOGS_AUTH_USER_EMAIL' (#4252) 2017-03-06 23:28:03 -05:00
Unknwon
a9d2480c7f templates/user/profile: fix link to avatar settings (#4251) 2017-03-06 23:23:37 -05:00
Unknwon
fd70d503e0 public: minor fixes on build tool config 2017-03-06 17:59:36 -05:00
Unknwon
8b73c8076f modules/markdown: fix wrong raw link to internal images 2017-03-05 16:54:00 -05:00
Unknwon
971a96a962 Revert "public: update Semantic UI from 2.2.7 -> 2.2.9"
This reverts commit eaab01fa49.
2017-03-05 16:35:35 -05:00
Unknwon
e9838a83ce routers/repo/http: only prompt HTTP Basic Authentication when intended
Sometimes user could simply request wrong URL, but if that wrong URL
has nothing related Git HTTP operations, HTTP Basic Authentication
should not prompted. Instead, clean 404 page should be presented.

The patch also supports Git HTTP operations without '.git' suffix
to the repository name, which addresses #4226 and #4189.
2017-03-04 21:26:32 -05:00
Fastidious
837fc9847d conf/gitignore: use correct OS name (#4240)
This is no more OSX, but macOS. Long live macOS!
2017-03-04 20:17:25 -05:00
Unknwon
7e883f891a scripts: update gogs.service (#4223)
According to https://goo.gl/ea8k9K, it hurts nothing to use
nonexistent services but gains convenient for default settings.
2017-03-04 11:40:37 -05:00
Félix MIKAELIAN
e19a69442d Update README.md (#4238) 2017-03-04 11:19:14 -05:00
Unknwon
ebd95dd082 models/org: reduce to 2 SQL executions for GetOrgIDsByUserID
This also addresses #4231. It is now ignoring nonexistent
organizations returned from 'org_user' table.
This was a bug caused in older version that didn't cleanup
'org_user' table when delete an organization.
2017-03-03 18:26:51 -05:00
Unknwon
f7b7d008b6 setting: fix Webhook.SkipTLSVerify didn't load (#4228) 2017-03-02 22:08:39 -05:00
Unknwon
b39454ca16 scripts: update gogs.service (#4223)
Add 'After=mariadb.service’.

[CI SKIP]
2017-03-02 12:21:31 -05:00
Bo-Yi Wu
00943a025f locale: update TRANSLATORS (#4224) 2017-03-02 11:37:14 -05:00
Unknwon
600f748cb0 vendor: update golang.org/x/crypto/ssh
Related to #4160
2017-03-01 21:33:58 -05:00
Unknwon
038b107c3d Update locale
Also fixes #4213
2017-03-01 12:31:04 -05:00
Unknwon
c6e08d76fd admin/config: minor CSS fix 2017-02-28 23:25:03 -05:00
Unknwon
6daac151b8 miniwinsvc: fix import path 2017-02-28 23:01:51 -05:00
Unknwon
e08161a302 hook: fix can’t be executed while run as service on Windows (#4207) 2017-02-28 22:58:52 -05:00
atzoum
341eafcf04 adapt Dockerfile.aarch64 (#4210) 2017-02-28 16:16:23 -05:00
Unknwon
dd649eb4cc admin: fix template error
Also a try to display key-value pairs in table.
2017-02-28 12:42:16 -05:00
Unknwon
d43f5f17fd webhook: fix push panic to organizational repository (#4206) 2017-02-28 10:28:48 -05:00
Corentin BRETON
193cc3ba9a locale: update TRANSLATORS (#4204) 2017-02-28 07:06:12 -05:00
Unknwon
fd667ca1d8 Merge branch 'master' of github.com:gogits/gogs into develop 2017-02-28 06:22:28 -05:00
Unknwon
9d40b8a83c Bump version 2017-02-28 05:45:50 -05:00
Unknwon
b0169ba064 Merge branch 'master' of github.com:gogits/gogs into develop 2017-02-28 05:34:51 -05:00
Unknwon
9ace35ee8b repo_branch: fix inapproriate logic 2017-02-28 05:33:30 -05:00
Unknwon
ca2cfaf71e cmd: able to backup and restore
Not very robust, must execute under correct workdir.

Addresses #2072, #3708, #648
2017-02-27 22:48:19 -05:00
Unknwon
b06f299748 webhook: add fork event 2017-02-27 22:48:18 -05:00
Unknwon
beea014343 template: add more icons for news feed 2017-02-27 22:47:33 -05:00
Unknwon
70072e2842 dashboard: add delete branch and tag news feeds 2017-02-27 22:47:33 -05:00
Unknwon
f0086e66ae webhook: able to detect delete branch or tag (#2315) 2017-02-27 22:47:21 -05:00
Unknwon
7fe13e72d8 cmd: refactoring command name 2017-02-27 22:47:12 -05:00
Unknwon
87f0ce793d repo: able to perform initial commit on behave of actual user 2017-02-27 22:47:12 -05:00
Unknwon
25cf755f30 editor: fix compile error 2017-02-27 22:46:42 -05:00
Unknwon
c7a8051a71 mailer: make text/html as default format
Change config option from '[mailer] ENABLE_HTML_ALTERNATIVE' to '[mailer] USE_PLAIN_TEXT'
2017-02-27 22:46:42 -05:00
Unknwon
a47553b7aa admin/config: remove duplicated config info 2017-02-27 22:46:32 -05:00
Unknwon
d7954014a4 markdown: fix links for image nested inside a link (#2636) 2017-02-27 22:46:32 -05:00
Unknwon
429345b9df editor: fix cannot create branch with slashes (#3568) 2017-02-27 22:46:32 -05:00
Unknwon
eaab01fa49 public: update Semantic UI from 2.2.7 -> 2.2.9 2017-02-27 22:45:35 -05:00
Unknwon
4f9c5981a9 refactoring: modules/auth/*_form.go -> modules/form 2017-02-27 22:45:35 -05:00
Unknwon
b3757e424f Prepare release 2017-02-27 18:38:16 -05:00
Unknwon
2381fe72cb base/tool: downgrade error to warning 2017-02-26 20:44:53 -05:00
Unknwon
e28bc7023f modes/org: code format for PR #4194 2017-02-26 15:29:16 -05:00
dlob
aff8fb28bd models/org: use XORM chain operations instead of raw SQL (#4194)
This also solved MSSQL pagination query syntax problem reported in #4176.
2017-02-26 15:19:34 -05:00
Unknwon
6a543c8066 Update README 2017-02-25 21:21:12 -05:00
Unknwon
4d90527a6e repo: does not allow fork to original owner (#4182)
But can still fork to organizations.
2017-02-25 03:52:54 -05:00
Unknwon
c64b842df9 templates: able to inject content to head and footer (#1286) 2017-02-24 18:26:41 -05:00
Unknwon
27c4252548 dashboard: fix commits CSS 2017-02-24 14:55:07 -05:00
Unknwon
10b93efc4a repo: able to add organization member as repository collaborator 2017-02-24 13:56:02 -05:00
Unknwon
0696d430c9 protect_branch: only list teams have write access
List teams without write access to the repository cause confusion
to make users think members of team could push to the branch.
2017-02-24 13:19:42 -05:00
Unknwon
68b231bd89 template: use DisplayName of users when possible (#4187) 2017-02-24 12:43:49 -05:00
Unknwon
6ec859f2b0 webhook: send secret with SHA256 HMAC hex digest (#3692) 2017-02-24 12:23:19 -05:00
Unknwon
452551fa23 webhook: highlight delivery response on click
This decreases page load time for webhook edit page.
2017-02-24 12:22:22 -05:00
Kyle Filz
ec05c64ead docker: update Dockerfile for Raspberry Pi (#4185) 2017-02-24 00:37:21 -05:00
Unknwon
cd15a17970 models/repo: delete protect branch options when delete repository 2017-02-23 18:42:03 -05:00
Unknwon
6072e9a52c repo: add protect branch whitelist (#4177)
Add options to add users and teams to whitelist of a protected
branch. This is only available for organizational repositories.
2017-02-23 18:25:12 -05:00
Unknwon
b78e03934d models/access: hasAccess only need userID not user object 2017-02-23 16:15:25 -05:00
Cyril Rohr
3c0d162961 packager: update files (#4181)
* Fix packaging

* Fix macaron vendor sha

Revision 8be5635c28f40a85ce8e8f65c6118b4ee4e548e9 does not exist

* Add build dependency for centos
2017-02-23 15:33:58 -05:00
Unknwon
48cf9edcf5 templates/repo/diff: fix tag-code doesn't display in split view 2017-02-23 13:24:59 -05:00
Unknwon
0c8c1ee96f pull: fix split view on pull request page (#3695) 2017-02-23 13:12:28 -05:00
Unknwon
7d80c5a722 mirror: does not allow create releases 2017-02-23 13:09:26 -05:00
Unknwon
5ec21d56ef editor: fix cannot redirect to correct pull request URL
Was only possible to correctly redirect to pull request page within
same repository. And didn't take care of case when upstream has
disabled pull request.

Also add a new method 'PullRequestURL' to unify the code.
2017-02-23 13:05:29 -05:00
Unknwon
266c8f5a85 release: fix unable to edit release of a fork repository 2017-02-23 11:35:33 -05:00
Unknwon
162504e90c repo/setting: fix admin cannot delete organizational repository 2017-02-22 23:16:23 -05:00
Unknwon
5ea0592f61 webhook: fix organizational webhook last delivery status cannot be updated 2017-02-22 22:55:28 -05:00
Unknwon
054e97d614 csrf: able to set custom cookie name
Add new config option '[session] CSRF_COOKIE_NAME'.
2017-02-22 21:46:43 -05:00
Unknwon
28983c94ff comment: only show title of commit message from a commit ref (#3206) 2017-02-22 08:25:26 -05:00
Unknwon
0cfa489cf0 models/git_diff: add bound check 2017-02-22 06:59:45 -05:00
Anders H
e0af5c280d locale: update TRANSLATORS (#4170) 2017-02-22 06:17:08 -05:00
Unknwon
d21dc0da78 migrate: fix unexpected removal of repository when wiki is detected 2017-02-21 22:00:45 -05:00
Unknwon
60aca9ea18 webhook: also only enable certain types (#3356)
Add new config option '[webhook] TYPES’.
2017-02-21 20:21:25 -05:00
Argentumbolo
6a8ad0b357 locale: changes relates to Ukrainian language (#4168)
- Add Ukrainian translation into templates/home.tmpl
    - Fix Ukrainian language name in conf/app.ini
          because on Ukrainian 'language' is female.
    - Add me as translator into conf/locale/TRANSLATORS
2017-02-21 17:57:27 -05:00
Unknwon
bd970b8b27 webhook: only trigger specific webhook for test delivery (#3030) 2017-02-21 15:44:35 -05:00
Unknwon
0f3155660e webhook: minor improvements on Discord 2017-02-21 13:58:00 -05:00
201 changed files with 6205 additions and 2743 deletions

View File

@@ -13,6 +13,7 @@ The issue will be closed without any reasons if it does not satisfy any of follo
- Database (use `[x]`):
- [ ] PostgreSQL
- [ ] MySQL
- [ ] MSSQL
- [ ] SQLite
- Can you reproduce the bug at https://try.gogs.io:
- [ ] Yes (provide example URL)

View File

@@ -20,7 +20,7 @@ github.com/go-xorm/xorm = commit:19f6dfc
github.com/gogits/chardet = commit:2404f77
github.com/gogits/cron = commit:2fc07a4
github.com/gogits/git-module = commit:1b9552b
github.com/gogits/go-gogs-client = commit:98046bb
github.com/gogits/go-gogs-client = commit:264a3d5
github.com/gogits/go-libravatar = commit:cd1abbd
github.com/issue9/identicon = commit:d36b545
github.com/jaytaylor/html2text = commit:d16d412

View File

@@ -19,6 +19,8 @@ targets:
centos-6: &el
build_dependencies:
- pam-devel
# required for go buildpack
- perl-Digest-SHA
dependencies:
- pam
- git
@@ -26,7 +28,7 @@ targets:
<<: *el
before:
- mv packager/Procfile .
- mv packager/.godir .
after:
- mv bin/main gogs
- mv bin/gogs gogs
after_install: ./packager/hooks/postinst
buildpack: https://github.com/heroku/heroku-buildpack-go.git#v62

View File

@@ -1,5 +1,4 @@
FROM aarch64/alpine:3.5
MAINTAINER atzoum@gmail.com
# Install system utils & Gogs runtime dependencies
ADD https://github.com/tianon/gosu/releases/download/1.9/gosu-arm64 /usr/sbin/gosu
@@ -8,9 +7,12 @@ RUN chmod +x /usr/sbin/gosu \
ENV GOGS_CUSTOM /data/gogs
COPY . /app/gogs/
WORKDIR /app/gogs/
RUN ./docker/build.sh
COPY . /app/gogs/build
WORKDIR /app/gogs/build
RUN ./docker/build-go.sh \
&& ./docker/build.sh \
&& ./docker/finalize.sh
# Configure LibC Name Service
COPY docker/nsswitch.conf /etc/nsswitch.conf
@@ -18,5 +20,5 @@ COPY docker/nsswitch.conf /etc/nsswitch.conf
# Configure Docker Container
VOLUME ["/data"]
EXPOSE 22 3000
ENTRYPOINT ["docker/start.sh"]
ENTRYPOINT ["/app/gogs/docker/start.sh"]
CMD ["/bin/s6-svscan", "/app/gogs/docker/s6/"]

View File

@@ -1,19 +1,18 @@
FROM hypriot/rpi-alpine-scratch:v3.2
MAINTAINER jp@roemer.im, raxetul@gmail.com
FROM armhf/alpine:3.5
# Install system utils & Gogs runtime dependencies
ADD https://github.com/tianon/gosu/releases/download/1.9/gosu-armhf /usr/sbin/gosu
RUN chmod +x /usr/sbin/gosu \
&& echo "http://dl-4.alpinelinux.org/alpine/v3.3/main/" | tee /etc/apk/repositories \
&& echo "http://dl-4.alpinelinux.org/alpine/v3.3/community/" | tee -a /etc/apk/repositories \
&& apk -U --no-progress upgrade && rm -f /var/cache/apk/APKINDEX.* \
&& apk --no-cache --no-progress add ca-certificates bash git linux-pam s6 curl openssh socat tzdata
ENV GOGS_CUSTOM /data/gogs
COPY . /app/gogs/
WORKDIR /app/gogs/
RUN ./docker/build.sh
COPY . /app/gogs/build
WORKDIR /app/gogs/build
RUN ./docker/build-go.sh \
&& ./docker/build.sh \
&& ./docker/finalize.sh
# Configure LibC Name Service
COPY docker/nsswitch.conf /etc/nsswitch.conf
@@ -21,5 +20,5 @@ COPY docker/nsswitch.conf /etc/nsswitch.conf
# Configure Docker Container
VOLUME ["/data"]
EXPOSE 22 3000
ENTRYPOINT ["docker/start.sh"]
ENTRYPOINT ["/app/gogs/docker/start.sh"]
CMD ["/bin/s6-svscan", "/app/gogs/docker/s6/"]

View File

@@ -3,7 +3,7 @@ Gogs [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](http
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
##### Current tip version: [`.VERSION`](templates/.VERSION) (see [Releases](https://github.com/gogits/gogs/releases) for binary versions ~~or submit a task on [alpha stage automated binary building system](https://build.gogs.io/)~~)
##### Current tip version: [`.VERSION`](templates/.VERSION) (see [Releases](https://github.com/gogits/gogs/releases) for binary versions)
| Web | UI | Preview |
|:-------------:|:-------:|:-------:|
@@ -16,7 +16,7 @@ Gogs [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](http
1. **YOU MUST READ [Contributing Code](https://github.com/gogits/gogs/wiki/Contributing-Code) BEFORE STARTING TO WORK ON A PULL REQUEST**.
2. Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
3. The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
4. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks!
4. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**, and the name you want to be credited as. Thanks!
5. If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki).
6. If your team/company is using Gogs and would like to put your logo on [our website](https://gogs.io), contact us by any means.
@@ -98,7 +98,6 @@ There are 5 ways to install Gogs:
- [OpenShift](https://github.com/tkisme/gogs-openshift)
- [Cloudron](https://cloudron.io/appstore.html#io.gogs.cloudronapp)
- [Scaleway](https://www.scaleway.com/imagehub/gogs/)
- [Portal](https://portaldemo.xyz/cloud/)
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
- [YunoHost](https://github.com/YunoHost-Apps/gogs_ynh)
@@ -122,8 +121,6 @@ There are 5 ways to install Gogs:
## Acknowledgments
- Router and middleware mechanism of [Macaron](https://github.com/go-macaron/macaron).
- System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog).
- Thanks [Egon Elbre](https://twitter.com/egonelbre) for designing logo.
- Thanks [Crowdin](https://crowdin.com/project/gogs) for providing open source translation plan.
- Thanks [DigitalOcean](https://www.digitalocean.com) for hosting home and demo sites.
@@ -131,8 +128,7 @@ There are 5 ways to install Gogs:
## Contributors
- Ex-team members [@lunny](https://github.com/lunny), [@fuxiaohei](https://github.com/fuxiaohei) and [@slene](https://github.com/slene).
- See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors.
- See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for top 100 contributors.
- See [TRANSLATORS](conf/locale/TRANSLATORS) for public list of translators.
## License

View File

@@ -67,7 +67,6 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- [OpenShift](https://github.com/tkisme/gogs-openshift)
- [Cloudron](https://cloudron.io/appstore.html#io.gogs.cloudronapp)
- [Scaleway](https://www.scaleway.com/imagehub/gogs/)
- [Portal](https://portaldemo.xyz/cloud/)
- [Sandstorm](https://github.com/cem/gogs-sandstorm)
- [sloppy.io](https://github.com/sloppyio/quickstarters/tree/master/gogs)
- [YunoHost](https://github.com/mbugeia/gogs_ynh)
@@ -91,8 +90,6 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
## 特别鸣谢
- 基于 [Macaron](https://github.com/go-macaron/macaron) 的路由与中间件机制。
- 基于 [GoBlog](https://github.com/fuxiaohei/goblog) 修改的系统监视状态。
- 感谢 [Egon Elbre](https://twitter.com/egonelbre) 设计的 Logo。
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
- 感谢 [DigitalOcean](https://www.digitalocean.com) 提供主站和体验站点的服务器赞助。
@@ -100,8 +97,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
## 贡献成员
- 前团队成员 [@lunny](https://github.com/lunny)、[@fuxiaohei](https://github.com/fuxiaohei) 和 [@slene](https://github.com/slene)
- 您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取完整的贡献者列表。
- 您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取 TOP 100 的贡献者列表
- 您可以通过查看 [TRANSLATORS](conf/locale/TRANSLATORS) 文件获取公开的翻译人员列表。
## 授权许可

View File

@@ -14,7 +14,7 @@ import (
)
var (
CmdAdmin = cli.Command{
Admin = cli.Command{
Name: "admin",
Usage: "Preform admin operations on command line",
Description: `Allow using internal logic of Gogs without hacking into the source code

135
cmd/backup.go Normal file
View File

@@ -0,0 +1,135 @@
// Copyright 2017 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.
package cmd
import (
"fmt"
"io/ioutil"
"os"
"path"
"time"
"github.com/Unknwon/cae/zip"
"github.com/Unknwon/com"
"github.com/urfave/cli"
log "gopkg.in/clog.v1"
"gopkg.in/ini.v1"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/setting"
)
var Backup = cli.Command{
Name: "backup",
Usage: "Backup files and database",
Description: `Backup dumps and compresses all related files and database into zip file,
which can be used for migrating Gogs to another server. The output format is meant to be
portable among all supported database engines.`,
Action: runBackup,
Flags: []cli.Flag{
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
boolFlag("verbose, v", "Show process details"),
stringFlag("tempdir, t", os.TempDir(), "Temporary directory path"),
stringFlag("target", "./", "Target directory path to save backup archive"),
boolFlag("database-only", "Only dump database"),
boolFlag("exclude-repos", "Exclude repositories"),
},
}
const _ARCHIVE_ROOT_DIR = "gogs-backup"
func runBackup(c *cli.Context) error {
zip.Verbose = c.Bool("verbose")
if c.IsSet("config") {
setting.CustomConf = c.String("config")
}
setting.NewContext()
models.LoadConfigs()
models.SetEngine()
tmpDir := c.String("tempdir")
if !com.IsExist(tmpDir) {
log.Fatal(0, "'--tempdir' does not exist: %s", tmpDir)
}
rootDir, err := ioutil.TempDir(tmpDir, "gogs-backup-")
if err != nil {
log.Fatal(0, "Fail to create backup root directory '%s': %v", rootDir, err)
}
log.Info("Backup root directory: %s", rootDir)
// Metadata
metaFile := path.Join(rootDir, "metadata.ini")
metadata := ini.Empty()
metadata.Section("").Key("VERSION").SetValue("1")
metadata.Section("").Key("DATE_TIME").SetValue(time.Now().String())
metadata.Section("").Key("GOGS_VERSION").SetValue(setting.AppVer)
if err = metadata.SaveTo(metaFile); err != nil {
log.Fatal(0, "Fail to save metadata '%s': %v", metaFile, err)
}
archiveName := path.Join(c.String("target"), fmt.Sprintf("gogs-backup-%d.zip", time.Now().Unix()))
log.Info("Packing backup files to: %s", archiveName)
z, err := zip.Create(archiveName)
if err != nil {
log.Fatal(0, "Fail to create backup archive '%s': %v", archiveName, err)
}
if err = z.AddFile(_ARCHIVE_ROOT_DIR+"/metadata.ini", metaFile); err != nil {
log.Fatal(0, "Fail to include 'metadata.ini': %v", err)
}
// Database
dbDir := path.Join(rootDir, "db")
if err = models.DumpDatabase(dbDir); err != nil {
log.Fatal(0, "Fail to dump database: %v", err)
}
if err = z.AddDir(_ARCHIVE_ROOT_DIR+"/db", dbDir); err != nil {
log.Fatal(0, "Fail to include 'db': %v", err)
}
// Custom files
if !c.Bool("database-only") {
if err = z.AddDir(_ARCHIVE_ROOT_DIR+"/custom", setting.CustomPath); err != nil {
log.Fatal(0, "Fail to include 'custom': %v", err)
}
}
// Data files
if !c.Bool("database-only") {
for _, dir := range []string{"attachments", "avatars"} {
dirPath := path.Join(setting.AppDataPath, dir)
if !com.IsDir(dirPath) {
continue
}
if err = z.AddDir(path.Join(_ARCHIVE_ROOT_DIR+"/data", dir), dirPath); err != nil {
log.Fatal(0, "Fail to include 'data': %v", err)
}
}
}
// Repositories
if !c.Bool("exclude-repos") && !c.Bool("database-only") {
reposDump := path.Join(rootDir, "repositories.zip")
log.Info("Dumping repositories in '%s'", setting.RepoRootPath)
if err = zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
log.Fatal(0, "Fail to dump repositories: %v", err)
}
log.Info("Repositories dumped to: %s", reposDump)
if err = z.AddFile(_ARCHIVE_ROOT_DIR+"/repositories.zip", reposDump); err != nil {
log.Fatal(0, "Fail to include 'repositories.zip': %v", err)
}
}
if err = z.Close(); err != nil {
log.Fatal(0, "Fail to save backup archive '%s': %v", archiveName, err)
}
os.RemoveAll(rootDir)
log.Info("Backup succeed! Archive is located at: %s", archiveName)
log.Shutdown()
return nil
}

View File

@@ -25,10 +25,10 @@ import (
"github.com/urfave/cli"
)
var CmdCert = cli.Command{
var Cert = cli.Command{
Name: "cert",
Usage: "Generate self-signed certificate",
Description: `Generate a self-signed X.509 certificate for a TLS server.
Description: `Generate a self-signed X.509 certificate for a TLS server.
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
Action: runCert,
Flags: []cli.Flag{

View File

@@ -13,7 +13,7 @@ import (
"github.com/urfave/cli"
)
var CmdCert = cli.Command{
var Cert = cli.Command{
Name: "cert",
Usage: "Generate self-signed certificate",
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,

View File

@@ -1,122 +0,0 @@
// Copyright 2014 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.
package cmd
import (
"fmt"
"log"
"os"
"path"
"time"
"io/ioutil"
"github.com/Unknwon/cae/zip"
"github.com/Unknwon/com"
"github.com/urfave/cli"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/setting"
)
var CmdDump = cli.Command{
Name: "dump",
Usage: "Dump Gogs files and database",
Description: `Dump compresses all related files and database into zip file.
It can be used for backup and capture Gogs server image to send to maintainer`,
Action: runDump,
Flags: []cli.Flag{
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
boolFlag("verbose, v", "Show process details"),
stringFlag("tempdir, t", os.TempDir(), "Temporary dir path"),
},
}
func runDump(ctx *cli.Context) error {
if ctx.IsSet("config") {
setting.CustomConf = ctx.String("config")
}
setting.NewContext()
models.LoadConfigs()
models.SetEngine()
tmpDir := ctx.String("tempdir")
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
log.Fatalf("Path does not exist: %s", tmpDir)
}
TmpWorkDir, err := ioutil.TempDir(tmpDir, "gogs-dump-")
if err != nil {
log.Fatalf("Fail to create tmp work directory: %v", err)
}
log.Printf("Creating tmp work dir: %s", TmpWorkDir)
reposDump := path.Join(TmpWorkDir, "gogs-repo.zip")
dbDump := path.Join(TmpWorkDir, "gogs-db.sql")
log.Printf("Dumping local repositories...%s", setting.RepoRootPath)
zip.Verbose = ctx.Bool("verbose")
if err := zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
log.Fatalf("Fail to dump local repositories: %v", err)
}
log.Printf("Dumping database...")
if err := models.DumpDatabase(dbDump); err != nil {
log.Fatalf("Fail to dump database: %v", err)
}
fileName := fmt.Sprintf("gogs-dump-%d.zip", time.Now().Unix())
log.Printf("Packing dump files...")
z, err := zip.Create(fileName)
if err != nil {
os.Remove(fileName)
log.Fatalf("Fail to create %s: %v", fileName, err)
}
if err := z.AddFile("gogs-repo.zip", reposDump); err != nil {
log.Fatalf("Fail to include gogs-repo.zip: %v", err)
}
if err := z.AddFile("gogs-db.sql", dbDump); err != nil {
log.Fatalf("Fail to include gogs-db.sql: %v", err)
}
customDir, err := os.Stat(setting.CustomPath)
if err == nil && customDir.IsDir() {
if err := z.AddDir("custom", setting.CustomPath); err != nil {
log.Fatalf("Fail to include custom: %v", err)
}
} else {
log.Printf("Custom dir %s doesn't exist, skipped", setting.CustomPath)
}
if err := z.AddDir("log", setting.LogRootPath); err != nil {
log.Fatalf("Fail to include log: %v", err)
}
for _, dir := range []string{"attachments", "avatars"} {
dirPath := path.Join(setting.AppDataPath, dir)
if !com.IsDir(dirPath) {
continue
}
if err := z.AddDir(path.Join("data", dir), dirPath); err != nil {
log.Fatalf("Fail to include '%s': %v", dirPath, err)
}
}
// FIXME: SSH key file.
if err = z.Close(); err != nil {
os.Remove(fileName)
log.Fatalf("Fail to save %s: %v", fileName, err)
}
if err := os.Chmod(fileName, 0600); err != nil {
log.Printf("Can't change file access permissions mask to 0600: %v", err)
}
log.Printf("Removing tmp work dir: %s", TmpWorkDir)
os.RemoveAll(TmpWorkDir)
log.Printf("Finish dumping in file %s", fileName)
return nil
}

View File

@@ -27,7 +27,7 @@ import (
)
var (
CmdHook = cli.Command{
Hook = cli.Command{
Name: "hook",
Usage: "Delegate commands to corresponding Git hooks",
Description: "All sub-commands should only be called by Git",
@@ -100,8 +100,21 @@ func runHookPreReceive(c *cli.Context) error {
continue
}
// Whitelist users can bypass require pull request check
bypassRequirePullRequest := false
// Check if user is in whitelist when enabled
userID := com.StrTo(os.Getenv(http.ENV_AUTH_USER_ID)).MustInt64()
if protectBranch.EnableWhitelist {
if !models.IsUserInProtectBranchWhitelist(repoID, userID, branchName) {
fail(fmt.Sprintf("Branch '%s' is protected and you are not in the push whitelist", branchName), "")
}
bypassRequirePullRequest = true
}
// Check if branch allows direct push
if protectBranch.RequirePullRequest {
if !bypassRequirePullRequest && protectBranch.RequirePullRequest {
fail(fmt.Sprintf("Branch '%s' is protected and commits must be merged through pull request", branchName), "")
}
@@ -111,7 +124,8 @@ func runHookPreReceive(c *cli.Context) error {
}
// Check force push
output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).Run()
output, err := git.NewCommand("rev-list", oldCommitID, "^"+newCommitID).
RunInDir(models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME)))
if err != nil {
fail("Internal error", "Fail to detect force push: %v", err)
} else if len(output) > 0 {
@@ -125,6 +139,7 @@ func runHookPreReceive(c *cli.Context) error {
}
hookCmd := exec.Command(customHooksPath)
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr
@@ -153,6 +168,7 @@ func runHookUpdate(c *cli.Context) error {
}
hookCmd := exec.Command(customHooksPath, args...)
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = os.Stdin
hookCmd.Stderr = os.Stderr
@@ -225,6 +241,7 @@ func runHookPostReceive(c *cli.Context) error {
}
hookCmd := exec.Command(customHooksPath)
hookCmd.Dir = models.RepoPath(os.Getenv(http.ENV_REPO_OWNER_NAME), os.Getenv(http.ENV_REPO_NAME))
hookCmd.Stdout = os.Stdout
hookCmd.Stdin = buf
hookCmd.Stderr = os.Stderr

View File

@@ -19,7 +19,7 @@ import (
)
var (
CmdImport = cli.Command{
Import = cli.Command{
Name: "import",
Usage: "Import portable data as local Gogs data",
Description: `Allow user import data from other Gogs installations to local instance

129
cmd/restore.go Normal file
View File

@@ -0,0 +1,129 @@
// Copyright 2017 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.
package cmd
import (
"os"
"path"
"github.com/Unknwon/cae/zip"
"github.com/Unknwon/com"
"github.com/mcuadros/go-version"
"github.com/urfave/cli"
log "gopkg.in/clog.v1"
"gopkg.in/ini.v1"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/setting"
)
var Restore = cli.Command{
Name: "restore",
Usage: "Restore files and database from backup",
Description: `Restore imports all related files and database from a backup archive.
The backup version must lower or equal to current Gogs version. You can also import
backup from other database engines, which is useful for database migrating.
If corresponding files or database tables are not presented in the archive, they will
be skipped and remian unchanged.`,
Action: runRestore,
Flags: []cli.Flag{
stringFlag("config, c", "custom/conf/app.ini", "Custom configuration file path"),
boolFlag("verbose, v", "Show process details"),
stringFlag("tempdir, t", os.TempDir(), "Temporary directory path"),
stringFlag("from", "", "Path to backup archive"),
boolFlag("database-only", "Only import database"),
boolFlag("exclude-repos", "Exclude repositories"),
},
}
func runRestore(c *cli.Context) error {
zip.Verbose = c.Bool("verbose")
tmpDir := c.String("tempdir")
if !com.IsExist(tmpDir) {
log.Fatal(0, "'--tempdir' does not exist: %s", tmpDir)
}
log.Info("Restore backup from: %s", c.String("from"))
if err := zip.ExtractTo(c.String("from"), tmpDir); err != nil {
log.Fatal(0, "Fail to extract backup archive: %v", err)
}
archivePath := path.Join(tmpDir, _ARCHIVE_ROOT_DIR)
// Check backup version
metaFile := path.Join(archivePath, "metadata.ini")
if !com.IsExist(metaFile) {
log.Fatal(0, "File 'metadata.ini' is missing")
}
metadata, err := ini.Load(metaFile)
if err != nil {
log.Fatal(0, "Fail to load metadata '%s': %v", metaFile, err)
}
backupVersion := metadata.Section("").Key("GOGS_VERSION").MustString("999.0")
if version.Compare(setting.AppVer, backupVersion, "<") {
log.Fatal(0, "Current Gogs version is lower than backup version: %s < %s", setting.AppVer, backupVersion)
}
// If config file is not present in backup, user must set this file via flag.
// Otherwise, it's optional to set config file flag.
configFile := path.Join(archivePath, "custom/conf/app.ini")
if c.IsSet("config") {
setting.CustomConf = c.String("config")
} else if !com.IsExist(configFile) {
log.Fatal(0, "'--config' is not specified and custom config file is not found in backup")
} else {
setting.CustomConf = configFile
}
setting.NewContext()
models.LoadConfigs()
models.SetEngine()
// Database
dbDir := path.Join(archivePath, "db")
if err = models.ImportDatabase(dbDir); err != nil {
log.Fatal(0, "Fail to import database: %v", err)
}
// Custom files
if !c.Bool("database-only") {
if com.IsExist(setting.CustomPath) {
if err = os.Rename(setting.CustomPath, setting.CustomPath+".bak"); err != nil {
log.Fatal(0, "Fail to backup current 'custom': %v", err)
}
}
if err = os.Rename(path.Join(archivePath, "custom"), setting.CustomPath); err != nil {
log.Fatal(0, "Fail to import 'custom': %v", err)
}
}
// Data files
if !c.Bool("database-only") {
for _, dir := range []string{"attachments", "avatars"} {
dirPath := path.Join(setting.AppDataPath, dir)
if com.IsExist(dirPath) {
if err = os.Rename(dirPath, dirPath+".bak"); err != nil {
log.Fatal(0, "Fail to backup current 'data': %v", err)
}
}
if err = os.Rename(path.Join(archivePath, "data", dir), dirPath); err != nil {
log.Fatal(0, "Fail to import 'data': %v", err)
}
}
}
// Repositories
reposPath := path.Join(archivePath, "repositories.zip")
if !c.Bool("exclude-repos") && !c.Bool("database-only") && com.IsExist(reposPath) {
if err := zip.ExtractTo(reposPath, path.Dir(setting.RepoRootPath)); err != nil {
log.Fatal(0, "Fail to extract 'repositories.zip': %v", err)
}
}
os.RemoveAll(path.Join(tmpDir, _ARCHIVE_ROOT_DIR))
log.Info("Restore succeed!")
log.Shutdown()
return nil
}

View File

@@ -199,7 +199,7 @@ func runServ(c *cli.Context) error {
fail("Internal error", "Fail to get user by key ID '%d': %v", key.ID, err)
}
mode, err := models.AccessLevel(user, repo)
mode, err := models.AccessLevel(user.ID, repo)
if err != nil {
fail("Internal error", "Fail to check access: %v", err)
}

View File

@@ -15,6 +15,7 @@ import (
"path"
"strings"
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"github.com/go-macaron/cache"
"github.com/go-macaron/captcha"
@@ -34,9 +35,9 @@ import (
"github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/context"
"github.com/gogits/gogs/modules/form"
"github.com/gogits/gogs/modules/mailer"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template"
@@ -49,9 +50,9 @@ import (
"github.com/gogits/gogs/routers/user"
)
var CmdWeb = cli.Command{
var Web = cli.Command{
Name: "web",
Usage: "Start Gogs web server",
Usage: "Start web server",
Description: `Gogs web server is the only thing you need to run,
and it takes care of all the other things for you`,
Action: runWeb,
@@ -219,35 +220,35 @@ func runWeb(ctx *cli.Context) error {
m.Get("/organizations", routers.ExploreOrganizations)
}, ignSignIn)
m.Combo("/install", routers.InstallInit).Get(routers.Install).
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
Post(bindIgnErr(form.Install{}), routers.InstallPost)
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
// ***** START: User *****
m.Group("/user", func() {
m.Get("/login", user.SignIn)
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
m.Post("/login", bindIgnErr(form.SignIn{}), user.SignInPost)
m.Get("/sign_up", user.SignUp)
m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
m.Post("/sign_up", bindIgnErr(form.Register{}), user.SignUpPost)
m.Get("/reset_password", user.ResetPasswd)
m.Post("/reset_password", user.ResetPasswdPost)
}, reqSignOut)
m.Group("/user/settings", func() {
m.Get("", user.Settings)
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
m.Post("", bindIgnErr(form.UpdateProfile{}), user.SettingsPost)
m.Combo("/avatar").Get(user.SettingsAvatar).
Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
Post(binding.MultipartForm(form.Avatar{}), user.SettingsAvatarPost)
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
m.Combo("/email").Get(user.SettingsEmails).
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
Post(bindIgnErr(form.AddEmail{}), user.SettingsEmailPost)
m.Post("/email/delete", user.DeleteEmail)
m.Get("/password", user.SettingsPassword)
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
m.Post("/password", bindIgnErr(form.ChangePassword{}), user.SettingsPasswordPost)
m.Combo("/ssh").Get(user.SettingsSSHKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
Post(bindIgnErr(form.AddSSHKey{}), user.SettingsSSHKeysPost)
m.Post("/ssh/delete", user.DeleteSSHKey)
m.Combo("/applications").Get(user.SettingsApplications).
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
Post(bindIgnErr(form.NewAccessToken{}), user.SettingsApplicationsPost)
m.Post("/applications/delete", user.SettingsDeleteApplication)
m.Group("/organizations", func() {
@@ -261,7 +262,7 @@ func runWeb(ctx *cli.Context) error {
})
m.Group("/user", func() {
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
// r.Get("/feeds", binding.Bind(form.Feeds{}), user.Feeds)
m.Any("/activate", user.Activate)
m.Any("/activate_email", user.ActivateEmail)
m.Get("/email2user", user.Email2User)
@@ -282,8 +283,8 @@ func runWeb(ctx *cli.Context) error {
m.Group("/users", func() {
m.Get("", admin.Users)
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(form.AdminCrateUser{}), admin.NewUserPost)
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(form.AdminEditUser{}), admin.EditUserPost)
m.Post("/:userid/delete", admin.DeleteUser)
})
@@ -298,9 +299,9 @@ func runWeb(ctx *cli.Context) error {
m.Group("/auths", func() {
m.Get("", admin.Authentications)
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(form.Authentication{}), admin.NewAuthSourcePost)
m.Combo("/:authid").Get(admin.EditAuthSource).
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
Post(bindIgnErr(form.Authentication{}), admin.EditAuthSourcePost)
m.Post("/:authid/delete", admin.DeleteAuthSource)
})
@@ -323,11 +324,10 @@ func runWeb(ctx *cli.Context) error {
m.Get("/attachments/:uuid", func(ctx *context.Context) {
attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid"))
if err != nil {
if models.IsErrAttachmentNotExist(err) {
ctx.Error(404)
} else {
ctx.Handle(500, "GetAttachmentByUUID", err)
}
ctx.NotFoundOrServerError("GetAttachmentByUUID", models.IsErrAttachmentNotExist, err)
return
} else if !com.IsFile(attach.LocalPath()) {
ctx.NotFound()
return
}
@@ -339,15 +339,15 @@ func runWeb(ctx *cli.Context) error {
defer fr.Close()
ctx.Header().Set("Cache-Control", "public,max-age=86400")
fmt.Println("attach.Name:", attach.Name)
ctx.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
// Fix #312. Attachments with , in their name are not handled correctly by Google Chrome.
// We must put the name in " manually.
if err = repo.ServeData(ctx, "\""+attach.Name+"\"", fr); err != nil {
if err = repo.ServeData(ctx, attach.Name, fr); err != nil {
ctx.Handle(500, "ServeData", err)
return
}
})
m.Post("/issues/attachments", repo.UploadIssueAttachment)
m.Post("/releases/attachments", repo.UploadReleaseAttachment)
}, ignSignIn)
m.Group("/:username", func() {
@@ -365,7 +365,7 @@ func runWeb(ctx *cli.Context) error {
m.Group("/org", func() {
m.Group("", func() {
m.Get("/create", org.Create)
m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
m.Post("/create", bindIgnErr(form.CreateOrg{}), org.CreatePost)
}, func(ctx *context.Context) {
if !ctx.User.CanCreateOrganization() {
ctx.NotFound()
@@ -390,28 +390,28 @@ func runWeb(ctx *cli.Context) error {
m.Group("/:org", func() {
m.Get("/teams/new", org.NewTeam)
m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
m.Post("/teams/new", bindIgnErr(form.CreateTeam{}), org.NewTeamPost)
m.Get("/teams/:team/edit", org.EditTeam)
m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
m.Post("/teams/:team/edit", bindIgnErr(form.CreateTeam{}), org.EditTeamPost)
m.Post("/teams/:team/delete", org.DeleteTeam)
m.Group("/settings", func() {
m.Combo("").Get(org.Settings).
Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), org.SettingsAvatar)
Post(bindIgnErr(form.UpdateOrgSetting{}), org.SettingsPost)
m.Post("/avatar", binding.MultipartForm(form.Avatar{}), org.SettingsAvatar)
m.Post("/avatar/delete", org.SettingsDeleteAvatar)
m.Group("/hooks", func() {
m.Get("", org.Webhooks)
m.Post("/delete", org.DeleteWebhook)
m.Get("/:type/new", repo.WebhooksNew)
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
m.Get("/:id", repo.WebHooksEdit)
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
})
m.Route("/delete", "GET,POST", org.SettingsDelete)
@@ -425,17 +425,17 @@ func runWeb(ctx *cli.Context) error {
// ***** START: Repository *****
m.Group("/repo", func() {
m.Get("/create", repo.Create)
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
m.Post("/create", bindIgnErr(form.CreateRepo{}), repo.CreatePost)
m.Get("/migrate", repo.Migrate)
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
m.Post("/migrate", bindIgnErr(form.MigrateRepo{}), repo.MigratePost)
m.Combo("/fork/:repoid").Get(repo.Fork).
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
Post(bindIgnErr(form.CreateRepo{}), repo.ForkPost)
}, reqSignIn)
m.Group("/:username/:reponame", func() {
m.Group("/settings", func() {
m.Combo("").Get(repo.Settings).
Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)
m.Group("/collaboration", func() {
m.Combo("").Get(repo.SettingsCollaboration).Post(repo.SettingsCollaborationPost)
m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
@@ -445,7 +445,7 @@ func runWeb(ctx *cli.Context) error {
m.Get("", repo.SettingsBranches)
m.Post("/default_branch", repo.UpdateDefaultBranch)
m.Combo("/*").Get(repo.SettingsProtectedBranch).
Post(bindIgnErr(auth.ProtectBranchForm{}), repo.SettingsProtectedBranchPost)
Post(bindIgnErr(form.ProtectBranch{}), repo.SettingsProtectedBranchPost)
}, func(ctx *context.Context) {
if ctx.Repo.Repository.IsMirror {
ctx.NotFound()
@@ -457,14 +457,14 @@ func runWeb(ctx *cli.Context) error {
m.Get("", repo.Webhooks)
m.Post("/delete", repo.DeleteWebhook)
m.Get("/:type/new", repo.WebhooksNew)
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
m.Get("/:id", repo.WebHooksEdit)
m.Post("/:id/test", repo.TestWebhook)
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
m.Group("/git", func() {
m.Get("", repo.SettingsGitHooks)
@@ -475,7 +475,7 @@ func runWeb(ctx *cli.Context) error {
m.Group("/keys", func() {
m.Combo("").Get(repo.SettingsDeployKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.SettingsDeployKeysPost)
Post(bindIgnErr(form.AddSSHKey{}), repo.SettingsDeployKeysPost)
m.Post("/delete", repo.DeleteDeployKey)
})
@@ -490,7 +490,7 @@ func runWeb(ctx *cli.Context) error {
// So they can apply their own enable/disable logic on routers.
m.Group("/issues", func() {
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost)
m.Group("/:index", func() {
m.Post("/label", repo.UpdateIssueLabel)
@@ -501,7 +501,7 @@ func runWeb(ctx *cli.Context) error {
m.Group("/:index", func() {
m.Post("/title", repo.UpdateIssueTitle)
m.Post("/content", repo.UpdateIssueContent)
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
m.Combo("/comments").Post(bindIgnErr(form.CreateComment{}), repo.NewComment)
})
})
m.Group("/comments/:id", func() {
@@ -509,42 +509,28 @@ func runWeb(ctx *cli.Context) error {
m.Post("/delete", repo.DeleteComment)
})
m.Group("/labels", func() {
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel)
m.Post("/delete", repo.DeleteLabel)
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
m.Post("/initialize", bindIgnErr(form.InitializeLabels{}), repo.InitializeLabels)
}, reqRepoWriter, context.RepoRef())
m.Group("/milestones", func() {
m.Combo("/new").Get(repo.NewMilestone).
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
Post(bindIgnErr(form.CreateMilestone{}), repo.NewMilestonePost)
m.Get("/:id/edit", repo.EditMilestone)
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
m.Post("/:id/edit", bindIgnErr(form.CreateMilestone{}), repo.EditMilestonePost)
m.Get("/:id/:action", repo.ChangeMilestonStatus)
m.Post("/delete", repo.DeleteMilestone)
}, reqRepoWriter, context.RepoRef())
m.Group("/releases", func() {
m.Get("/new", repo.NewRelease)
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
m.Post("/new", bindIgnErr(form.NewRelease{}), repo.NewReleasePost)
m.Post("/delete", repo.DeleteRelease)
}, reqRepoWriter, context.RepoRef())
m.Group("/releases", func() {
m.Get("/edit/*", repo.EditRelease)
m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
m.Post("/edit/*", bindIgnErr(form.EditRelease{}), repo.EditReleasePost)
}, reqRepoWriter, func(ctx *context.Context) {
var err error
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
if err != nil {
ctx.Handle(500, "GetBranchCommit", err)
return
}
ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
if err != nil {
ctx.Handle(500, "CommitsCount", err)
return
}
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
ctx.Data["PageIsViewCode"] = true
})
// FIXME: Should use ctx.Repo.PullRequest to unify template, currently we have inconsistent URL
@@ -552,22 +538,22 @@ func runWeb(ctx *cli.Context) error {
// e.g. /org1/test-repo/compare/master...org1:develop
// which should be /org1/test-repo/compare/master...develop
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
Post(bindIgnErr(form.NewIssue{}), repo.CompareAndPullRequestPost)
m.Group("", func() {
m.Combo("/_edit/*").Get(repo.EditFile).
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.EditFilePost)
Post(bindIgnErr(form.EditRepoFile{}), repo.EditFilePost)
m.Combo("/_new/*").Get(repo.NewFile).
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.NewFilePost)
m.Post("/_preview/*", bindIgnErr(auth.EditPreviewDiffForm{}), repo.DiffPreviewPost)
Post(bindIgnErr(form.EditRepoFile{}), repo.NewFilePost)
m.Post("/_preview/*", bindIgnErr(form.EditPreviewDiff{}), repo.DiffPreviewPost)
m.Combo("/_delete/*").Get(repo.DeleteFile).
Post(bindIgnErr(auth.DeleteRepoFileForm{}), repo.DeleteFilePost)
Post(bindIgnErr(form.DeleteRepoFile{}), repo.DeleteFilePost)
m.Group("", func() {
m.Combo("/_upload/*").Get(repo.UploadFile).
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
Post(bindIgnErr(form.UploadRepoFile{}), repo.UploadFilePost)
m.Post("/upload-file", repo.UploadFileToServer)
m.Post("/upload-remove", bindIgnErr(auth.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
m.Post("/upload-remove", bindIgnErr(form.RemoveUploadFile{}), repo.RemoveUploadFileFromServer)
}, func(ctx *context.Context) {
if !setting.Repository.Upload.Enabled {
ctx.NotFound()
@@ -591,8 +577,13 @@ func runWeb(ctx *cli.Context) error {
m.Get("/milestones", repo.Milestones)
}, context.RepoRef())
// m.Get("/branches", repo.Branches)
m.Post("/branches/delete/*", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
m.Group("/branches", func() {
m.Get("", repo.Branches)
m.Get("/all", repo.AllBranches)
m.Post("/delete/*", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
}, func(ctx *context.Context) {
ctx.Data["PageIsViewCode"] = true
})
m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki)
@@ -600,9 +591,9 @@ func runWeb(ctx *cli.Context) error {
m.Group("", func() {
m.Combo("/_new").Get(repo.NewWiki).
Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost)
Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost)
m.Combo("/:page/_edit").Get(repo.EditWiki).
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
Post(bindIgnErr(form.NewWiki{}), repo.EditWikiPost)
m.Post("/:page/delete", repo.DeleteWikiPagePost)
}, reqSignIn, reqRepoWriter)
}, repo.MustEnableWiki, context.RepoRef())
@@ -632,18 +623,19 @@ func runWeb(ctx *cli.Context) error {
}, ignSignIn, context.RepoAssignment(), context.RepoRef())
m.Group("/:username", func() {
m.Group("", func() {
m.Get("/:reponame", repo.Home)
}, ignSignIn, context.RepoAssignment(true), context.RepoRef())
m.Get("/:reponame", ignSignIn, context.RepoAssignment(true), context.RepoRef(), repo.Home)
m.Group("/:reponame", func() {
m.Head("/tasks/trigger", repo.TriggerTask)
})
// Use the regexp to match the repository name validation
// Use the regexp to match the repository name
// Duplicated routes to enable different ways of accessing same set of URLs,
// e.g. with or without ".git" suffix.
m.Group("/:reponame([\\d\\w-_\\.]+\\.git$)", func() {
m.Get("", ignSignIn, context.RepoAssignment(true), context.RepoRef(), repo.Home)
m.Route("/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
})
m.Route("/:reponame/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
})
// ***** END: Repository *****

View File

@@ -114,6 +114,19 @@ FILE_MAX_SIZE = 3
; Maximum number of files per upload
MAX_FILES = 5
; Attachment settings for releases
[release.attachment]
; Whether attachments are enabled. Defaults to `true`
ENABLED = true
; Path for attachments. Defaults to `data/attachments`
PATH = data/attachments
; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = */*
; Max size of each file. Defaults to 32MB
MAX_SIZE = 32
; Max number of files per upload. Defaults to 10
MAX_FILES = 10
[markdown]
; Enable hard line break extension
ENABLE_HARD_LINE_BREAK = false
@@ -124,6 +137,13 @@ CUSTOM_URL_SCHEMES =
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
[smartypants]
ENABLED = false
FRACTIONS = true
DASHES = true
LATEX_DASHES = true
ANGLED_QUOTES = true
[http]
; Value for Access-Control-Allow-Origin header, default is not to present
ACCESS_CONTROL_ALLOW_ORIGIN =
@@ -181,6 +201,8 @@ ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
ENABLE_CAPTCHA = true
[webhook]
; Types are enabled for users to use, can be "gogs", "slack", "discord"
TYPES = gogs, slack, discord
; Hook task queue length, increase if webhook shooting starts hanging
QUEUE_LENGTH = 1000
; Deliver timeout in seconds
@@ -216,8 +238,8 @@ FROM =
; Mailer user name and password
USER =
PASSWD =
; Use text/html as alternative format of content
ENABLE_HTML_ALTERNATIVE = false
; Use text/plain as format of content
USE_PLAIN_TEXT = false
[cache]
; Either "memory", "redis", or "memcache", default is "memory"
@@ -248,6 +270,8 @@ ENABLE_SET_COOKIE = true
GC_INTERVAL_TIME = 86400
; Session life time, default is 86400
SESSION_LIFE_TIME = 86400
; Cookie name for CSRF
CSRF_COOKIE_NAME = _csrf
[picture]
; Path to store user uploaded avatars
@@ -262,6 +286,7 @@ DISABLE_GRAVATAR = false
; This value will be forced to be false in offline mode or Gravatar is disbaled.
ENABLE_FEDERATED_AVATAR = true
; Attachment settings for issues
[attachment]
; Whether attachments are enabled. Defaults to `true`
ENABLE = true
@@ -269,9 +294,9 @@ ENABLE = true
PATH = data/attachments
; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = image/jpeg|image/png
; Max size of each file. Defaults to 32MB
; Max size of each file. Defaults to 4MB
MAX_SIZE = 4
; Max number of files per upload. Defaults to 10
; Max number of files per upload. Defaults to 5
MAX_FILES = 5
[time]
@@ -407,7 +432,7 @@ REPO_PAGING_NUM = 15
[i18n]
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR,gl-ES,uk-UA
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어,Galego,Український
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어,Galego,Українська
; Used for datetimepicker
[i18n.datelang]

View File

@@ -1,24 +1,25 @@
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View File

@@ -9,6 +9,7 @@ Aleksey Tarakin <hukendo AT yandex DOT ru>
Alexander Steinhöfer <kontakt AT lx-s DOT de>
Alexandre Espinosa Menor <aemenor DOT gmail DOT com>
Alexandre Magno <alexandre DOT mbm AT gmail DOT com>
Anders B. Hansen <anders AT birkoe DOT com>
András Schenkerik <moviesharkteam AT gmail DOT com>
Andrey Nering <andrey AT nering DOT com DOT br>
Andrey Paskal <apaskal AT gmail DOT com>
@@ -17,12 +18,15 @@ Antoine GIRARD <sapk AT sapk DOT fr>
Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com>
Aurelien Darragon <aurelien DOT darragon AT gmail DOT com>
Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
Bo-Yi Wu <appleboy DOT tw AT gmail DOT com>
Breton Corentin <contact AT neodarz DOT net>
Camille Baronnet <gogs AT camillebaronnet DOT fr>
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
Cysioland
Damaris Padieu <damizx AT hotmail DOT fr>
Daniel Speichert <daniel AT speichert DOT pl>
David Yzaguirre <dvdyzag AT gmail DOT com>
Denys Khomenko
Dmitriy Nogay <me AT catwhocode DOT ga>
Enrico Testori hypertesto AT gmail DOT com
Ezequiel Gonzalez Rial <gonrial AT gmail DOT com>

View File

@@ -201,6 +201,7 @@ Content=Съдържание
require_error=` не може да бъде празен.`
alpha_dash_error=` трябва да e валидна буква, число или тире(-_).`
alpha_dash_dot_error=` трябва да e валидна буква, число, тире(-_) или точка.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` трябва да е с размер %s.`
min_size_error=` трябва да съдържа поне %s знака.`
max_size_error=` трябва да съдържа най-много %s знака.`
@@ -426,6 +427,7 @@ pulls=Заявки за сливане
labels=Етикети
milestones=Етапи
commits=Ревизии
git_branches=Branches
releases=Версии
file_raw=Директен файл
file_history=История
@@ -434,6 +436,13 @@ file_permalink=Постоянна връзка
file_too_large=Този файл е твърде голям за да се визуализира
video_not_supported_in_browser=Вашият браузър не поддържа HTML5 видео тагове.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Нов файл
editor.upload_file=Качи файл
editor.edit_file=Редактирай файл
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Уеб-куки
settings.githooks=Git куки
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Символен
settings.tracker_url_format_desc=Можете да използвате текстови маркери <code>{user} {repo} {index}</code> за потребителско име, име на хранилище и индекс на задача съответно.
settings.pulls_desc=Включва заявки за сливане за да може да се приемат външни доработки
settings.danger_zone=Опасна зона
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Новият притежател вече има хранилище със същото име. Изберете друго име.
settings.convert=Промени към редовно хранилище
settings.convert_desc=Можете да промените това огледало към редовно хранилище. Конверсията не може да се отмени.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Този потребител няма да
settings.remove_collaborator_success=Сътрудникът е премахнат.
settings.search_user_placeholder=Име на потребител...
settings.org_not_allowed_to_be_collaborator=Невъзможно добавяне на организация като сътрудник.
settings.user_is_org_member=Потребителят вече участва в организацията и не може да бъде добавен като сътрудник.
settings.add_webhook=Добави уеб-кука
settings.hooks_desc=Уеб-куките много приличат на обикновен HTTP POST тригер. Когато нещо се случи в Gogs, ние ще изпратим уведомление до сървъра, който посочите. Научете повече в <a target="_blank" href="%s">Ръководство за уеб-куки</a>.
settings.webhook_deletion=Изтрий уеб-кука
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs ще изпрати <code>POST</code> заявк
settings.payload_url=URL адрес на изпращане
settings.content_type=Тип на съдържанието
settings.secret=Тайна
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Потребителско име
settings.slack_icon_url=URL адрес на икона
settings.slack_color=Цвят
@@ -750,10 +764,20 @@ settings.event_send_everything=При <strong>всички</strong> събити
settings.event_choose=Нека избера от какво имам нужда.
settings.event_create=Създаване
settings.event_create_desc=Създаване на клон или маркер
settings.event_pull_request=Заявка за сливане
settings.event_pull_request_desc=Заявка за сливане е отворена, затворена, отворена повторно, редактирана, възложена, отменена, при модифициран етикет, при премахнат етикет или е синхронизирана.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Предаване
settings.event_push_desc=Git предаване към хранилището
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Заявка за сливане
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Активна
settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени.
settings.add_hook_success=Новата уеб-кука е добавена успешно.
@@ -798,7 +822,6 @@ release.releases=Версии
release.new_release=Нова версия
release.draft=Чернови
release.prerelease=Предварителни
release.stable=Стабилни
release.edit=редактиране
release.ahead=<strong>%d</strong> ревизии на %s след тази версия
release.source_code=Изходен код
@@ -1014,6 +1037,7 @@ repos.private=Частно
repos.watches=Наблюдавания
repos.stars=Харесвания
repos.issues=Задачи
repos.size=Size
auths.auth_manage_panel=Управление на удостоверявания
auths.new=Добави нов начин на удостоверяване
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Време за отказ при сливане
config.git_gc_timeout=Време за отказ при GC
config.log_config=Конфигурация на журнал
config.log_mode=Режим на журнал
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron задачи
monitor.name=Име
@@ -1200,19 +1225,23 @@ notices.delete_success=Системните съобщения са изтрит
[action]
create_repo=създаде хранилище <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=предаде към <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
compare_commits=Сравнение между тези %d ревизии
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
create_issue=`отвори задача <a href="%s/issues/%s">%s#%[2]s"</a>`
close_issue=`затвори <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`повторно отвори <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`затвори заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`повторно отвори заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
merge_pull_request=`обедини заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a>
compare_commits=Сравнение между тези %d ревизии
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=преди

View File

@@ -201,6 +201,7 @@ Content=Obsah
require_error=` nemůže být prázdný.`
alpha_dash_error=` musí být pouze písmena, číslice či znaky - a _ .`
alpha_dash_dot_error=` musí být pouze písmena, číslice, tečka či znaky - a _ .`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` musí být minimálně velikosti %s.`
min_size_error=` musí obsahovat nejméně %s znaků.`
max_size_error=` musí obsahovat maximálně %s znaků.`
@@ -426,6 +427,7 @@ pulls=Požadavky na natažení
labels=Štítky
milestones=Mezníky
commits=Revize
git_branches=Branches
releases=Vydání
file_raw=Surový
file_history=Historie
@@ -434,6 +436,13 @@ file_permalink=Trvalý odkaz
file_too_large=Tento soubor je příliš velký pro zobrazení
video_not_supported_in_browser=Váš prohlížeč nepodporuje tag pro HTML5 video.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nový soubor
editor.upload_file=Nahrát soubor
editor.edit_file=Upravit soubor
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webové háčky
settings.githooks=Háčky Gitu
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumerický
settings.tracker_url_format_desc=Můžete použít zástupné výrazy <code>{user} {repo} {index}</code> pro uživatelské jméno, název repositáře a index úkolu.
settings.pulls_desc=Povolit požadavky na stažení, aby veřejné příspěvky mohly být akceptovány
settings.danger_zone=Nebezpečná zóna
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Nový vlastník již repositář se stejným názvem má. Vyberte, prosíme, jiné jméno.
settings.convert=Převést na běžný repositář
settings.convert_desc=Můžete převést toto zrcadlo na běžný repositář. Tato změna nemůže být vrácena.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Tento uživatel po tom, co bude smazán, ji
settings.remove_collaborator_success=Spolupracovník byl smazán.
settings.search_user_placeholder=Hledat uživatele...
settings.org_not_allowed_to_be_collaborator=Není dovoleno přidat organizaci jako spolupracovníka.
settings.user_is_org_member=Uživatel je již členem organizace, tudíž nemůže být přidán jako spolupracovník.
settings.add_webhook=Přidat webový háček
settings.hooks_desc=Webové háčky jsou podobné základním spouštím HTTP POST událostí. Kdykoliv se něco stane v Gogs, bude postaráno o oznámení specifikovanému cílovému serveru. Více se o daném dozvíte v <a target="_blank" href="%s">příručce webových háčků</a>.
settings.webhook_deletion=Smazat webový háček
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs zašle požadavek typu <code>POST</code> na zadan
settings.payload_url=URL obsahu
settings.content_type=Typ obsahu
settings.secret=Tajný klíč
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Uživatelské jméno
settings.slack_icon_url=URL ikony uživatele
settings.slack_color=Barva
@@ -750,10 +764,20 @@ settings.event_send_everything=Potřebuji <strong>vše</strong>.
settings.event_choose=Nech mne vybrat, co potřebuji.
settings.event_create=Vytvořit
settings.event_create_desc=Větev nebo značka byla vytvořena
settings.event_pull_request=Požadavek na stažení
settings.event_pull_request_desc=Pull request byl otevřen, uzavřen, znovu-otevřen, upraven, přiřazen, zrušeno přiřazení, popis upraven, smazán nebo synchronizován.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Nahrát
settings.event_push_desc=Nahrání pomocí Gitu do repositáře
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Požadavek na stažení
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktivní
settings.active_helper=Podrobnosti vztahující se k události, která spustila háček, budou doručeny taktéž.
settings.add_hook_success=Nový webový háček byl přidán.
@@ -798,7 +822,6 @@ release.releases=Vydání
release.new_release=Nové vydání
release.draft=Koncept
release.prerelease=Předběžná verze
release.stable=Stabilní
release.edit=upravit
release.ahead=<strong>%d</strong> revizí do větve %s od tohoto vydání
release.source_code=Zdrojový kód
@@ -1014,6 +1037,7 @@ repos.private=Soukromý
repos.watches=Sledovače
repos.stars=Oblíbení
repos.issues=Úkoly
repos.size=Size
auths.auth_manage_panel=Panel správy způsobů ověřování
auths.new=Přidat nový zdroj
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Časový limit operace stažení
config.git_gc_timeout=Časový limit operace GC
config.log_config=Nastavení logů
config.log_mode=Způsob logování
config.log_mode=Mode
config.log_options=Options
monitor.cron=Naplánované úlohy
monitor.name=Název
@@ -1200,19 +1225,23 @@ notices.delete_success=Systémová upozornění byla úspěšně smazána.
[action]
create_repo=vytvořil repositář <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=přejmenoval repositář z <code>%[1]s</code> na <a href="%[2]s">%[3]s</a>
commit_repo=odeslal do <a href="%[1]s/src/%[2]s">%[3]s</a> v <a href="%[1]s">%[4]s</a>
compare_commits=Zobrazit porovnání pro tyto %d revize
transfer_repo=předal repositář <code>%s</code> uživateli/organizaci <a href="%s">%s</a>
create_issue=`vytvořil úkol <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`uzavřel úkol <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`znovuotevřel úkol <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`přidal komentář k úkolu <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`vytvořil požadavek na stažení <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`zavřel požadavek na stažení <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`znovuotevřel požadavek na stažení <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`přidal komentář k úkolu <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`sloučil požadavek na stažení <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=předal repositář <code>%s</code> uživateli/organizaci <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=nahrál značku <a href="%s/src/%s">%[2]s</a> do <a href="%[1]s">%[3]s</a>
compare_commits=Zobrazit porovnání pro tyto %d revize
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=před

View File

@@ -48,7 +48,7 @@ cancel=Abbrechen
install=Installation
title=Installationsschritte für den ersten Start
docker_helper=Wenn Gogs innerhalb von Docker läuft, lesen Sie sich bitte den <a target="_blank" href="%s">Leitfaden</a> genau durch, bevor Sie irgendwas auf dieser Seite ändern!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs benötigt MySQL, PostgreSQL, SQLite3, MSSQL oder TiDB.
db_title=Datenbankeinstellungen
db_type=Datenbanktyp
host=Host
@@ -58,8 +58,8 @@ db_name=Datenbankname
db_helper=Bitte verwenden Sie in MySQL die InnoDB-Engine mit dem Zeichensatz utf8_general_ci.
ssl_mode=SSL-Modus
path=Pfad
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=Der Dateipfad zur SQLite3-Datenbank. <br>Bitte verwenden Sie einen absoluten Pfad, wenn Gogs als Service gestartet wird.
err_empty_db_path=SQLite3 Datenbankpfad darf nicht leer sein.
no_admin_and_disable_registration=Sie können die Registrierung nicht deaktivieren, ohne ein Administratorkonto zu erstellen.
err_empty_admin_password=Das Administrator-Passwort darf nicht leer sein.
@@ -74,8 +74,8 @@ domain=Domain
domain_helper=Dies hat Auswirkung auf die SSH Klon-URLs.
ssh_port=SSH Port
ssh_port_helper=Der Port Ihres SSH-Servers. Leer lassen um SSH zu deaktivieren.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
use_builtin_ssh_server=Eingebauten SSH-Server verwenden
use_builtin_ssh_server_popup=Starte eingebauten SSH-Server für git-Aufgaben, um es vom System-SSH-Dämon zu trennen.
http_port=HTTP Port
http_port_helper=Auf dieser Port Nummer wird Gogs erreichbar sein.
app_url=Anwendungs-URL
@@ -117,7 +117,7 @@ sqlite3_not_available=Ihre Gogs-Version unterstützt SQLite3 nicht. Bitte laden
invalid_db_setting=Datenbankeinstellungen sind nicht korrekt: %v
invalid_repo_path=Repository Verzeichnis ist ungültig: %v
run_user_not_match=Der ausführende Benutzer ist nicht der aktuelle Benutzer: %s -> %s
invalid_smtp_from=SMPT ist nicht gültig im Feld: %v
invalid_smtp_from=SMTP Absender Feld ist nicht gültig: %v
save_config_failed=Fehler beim Speichern der Konfiguration: %v
invalid_admin_setting=Admin-Konto Einstellungen sind ungültig: %v
install_success=Herzlich Willkommen! Wir sind froh, dass Sie sich für Gogs entschieden haben. Wir wünschen viel Vergnügen damit.
@@ -201,6 +201,7 @@ Content=Inhalt
require_error=` darf nicht leer sein.`
alpha_dash_error=` kann ausschließlich alphanumerische Zeichen und "-_" enthalten.`
alpha_dash_dot_error=` kann ausschließlich alphanumerische Zeichen und ".-_" enthalten.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` muss die Größe %s haben.`
min_size_error=` muss mindestens %s Zeichen enthalten.`
max_size_error=` darf höchstens %s Zeichen enthalten.`
@@ -426,6 +427,7 @@ pulls=Pull-Requests
labels=Label
milestones=Meilensteine
commits=Commits
git_branches=Branches
releases=Releases
file_raw=Originalformat
file_history=Verlauf
@@ -434,6 +436,13 @@ file_permalink=Permalink
file_too_large=Diese Datei ist zu groß zum Anzeigen
video_not_supported_in_browser=Ihr Browser unterstützt HTML5 Video-Tags nicht.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Neue Datei
editor.upload_file=Datei hochladen
editor.edit_file=Datei bearbeiten
@@ -462,7 +471,7 @@ 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='%s' im übergeordneten Verzeichnis ist eine Datei und kein Verzeichnis.
editor.file_is_a_symlink=Die Datei '%s' ist ein Symlink die nicht im Webeditor verändert werden kann.
editor.file_is_a_symlink=Die Datei '%s' ist ein Symlink, der im Webeditor nicht bearbeitet werden kann.
editor.filename_is_a_directory=Die Datei '%s' existiert bereits als Verzeichnis in diesem Repository.
editor.file_editing_no_longer_exists=Die Datei '%s', welche Sie bearbeiten, existiert in diesem Repository nicht mehr.
editor.file_changed_while_editing=Seit dem Start der Bearbeitung hat sich die Datei geändert. <a target="_blank" href="%s">Hier klicken</a> um die Änderungen zu sehen, oder nochmals <strong>Commit drücken</strong> um die Änderungen zu überschreiben.
@@ -473,7 +482,7 @@ editor.add_subdir=Unterverzeichnis erstellen...
editor.unable_to_upload_files=Fehler beim Hochladen der Dateien zu '%s'. Fehler: %v
editor.upload_files_to_dir=Dateien hochladen nach '%s'
commits.commit_history=Commit History
commits.commit_history=Commit Verlauf
commits.commits=Commits
commits.search=Commits durchsuchen
commits.find=Finden
@@ -641,22 +650,26 @@ settings.collaboration.write=Schreibrechte
settings.collaboration.read=Leserechte
settings.collaboration.undefined=Nicht definiert
settings.branches=Branches
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.default_branch=Standard-Branch
settings.default_branch_desc=Der Standard-Branch gilt als Basis für Commits, Pull-Requests und Online-Bearbeitung.
settings.update=Aktualisieren
settings.update_default_branch_success=Standard-Branch dieses Repositories wurde erfolgreich aktualisiert!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
settings.choose_a_branch=Choose a branch...
settings.branch_protection=Branch Protection
settings.branch_protection_desc=Please choose protect options for branch <b>%s</b>.
settings.protect_this_branch=Protect this branch
settings.protect_this_branch_desc=Disable force pushes and prevent from deletion.
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.protected_branches_desc=Schützt Branches vor forcierten Pushes und versehentlichem Löschen. Comitter können freigeschaltet werden.
settings.choose_a_branch=Wählen Sie einen Branch...
settings.branch_protection=Branch-Schutz
settings.branch_protection_desc=Bitte wählen Sie Schutzoptionen für den Branch <b>%s</b>.
settings.protect_this_branch=Diesen Branch schützen
settings.protect_this_branch_desc=Verhindere forcierte Pushes sowie Löschungen.
settings.protect_require_pull_request=Verlange Pull-Request an Stelle von direkten Pushes
settings.protect_require_pull_request_desc=Aktivieren Sie diese Option, um direktes Pushen in diesen Branch zu verhindern. Commits müssen in einen anderen, ungeschützten Branch gepusht werden und dann per Pull-Request in diesen Branch überführt werden.
settings.protect_whitelist_committers=Hinzufügen von Benutzern oder Teams zur Whitelist, die in diesen Branch pushen dürfen
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Benutzer, die in diesen Branch pushen können
settings.protect_whitelist_search_users=Benutzer suchen
settings.protect_whitelist_teams=Teams, deren Mitglieder in diesen Branch pushen können
settings.protect_whitelist_search_teams=Teams suchen
settings.update_protect_branch_success=Schutzoptionen für diesen Branch wurden erfolgreich aktualisiert!
settings.hooks=Webhooks
settings.githooks=Git-Hooks
settings.basic_settings=Grundeinstellungen
@@ -675,7 +688,7 @@ settings.external_wiki_url_desc=Besucher werden auf diese URL umgeleitet, wenn s
settings.issues_desc=Issue-Tracker einschalten
settings.use_internal_issue_tracker=Eingebauten Issue-Tracker verwenden
settings.use_external_issue_tracker=Externes Issue-System verwenden
settings.external_tracker_url=Externe Issue-Tracker URL
settings.external_tracker_url=URL eines externen Issue Trackers
settings.external_tracker_url_desc=Besucher werden auf diese URL umgeleitet, wenn sie auf den Tab klicken.
settings.tracker_url_format=URL-Format des externen Issue-Systems
settings.tracker_issue_style=Namenskonvention des externen Issue-Trackers:
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumerisch
settings.tracker_url_format_desc=Sie können die Platzhalter <code>{user} {repo} {index}</code> für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden.
settings.pulls_desc=Pull-Requests aktivieren, um öffentliche Mitwirkung zu ermöglichen
settings.danger_zone=Gefahrenzone
settings.cannot_fork_to_same_owner=Besitzer kann das Repository nicht forken.
settings.new_owner_has_same_repo=Der neue Eigentümer hat bereits ein Repository mit dem gleichen Namen. Bitte wählen Sie einen anderen Namen.
settings.convert=In ein normales Repository umwandeln
settings.convert_desc=Dieser Mirror kann in ein normales Repository umgewandelt werden. Dies kann nicht rückgängig gemacht werden.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Nach dem Löschen wird dieser Benutzer keine
settings.remove_collaborator_success=Mitarbeiter wurde entfernt.
settings.search_user_placeholder=Benutzer suchen...
settings.org_not_allowed_to_be_collaborator=Eine Organisation kann nicht als Mitarbeiter hinzugefügt werden.
settings.user_is_org_member=Benutzer ist ein Organisationsmitglied und kann nicht als Mitarbeiter hinzugefügt werden.
settings.add_webhook=Webhook hinzufügen
settings.hooks_desc=Webhooks erlauben es Ihnen, externe Dienste zu informieren, wenn etwas Bestimmtes in Ihrem Repository passiert. Gogs sendet dann einen POST-Request an alle angegebenen URLs. Erfahren Sie mehr in unserem <a target="_blank" href="%s">Webhooks Guide</a>.
settings.webhook_deletion=Webhook entfernen
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs sendet einen <code>POST</code>-Request an die unt
settings.payload_url=Payload URL
settings.content_type=Inhaltstyp
settings.secret=Secret
settings.secret_desc=Das Secret wird im <code>X-Gogs-Signature</code> Header als hexadezimalem SHA256 HMAC Stempel der Nutzlast.
settings.slack_username=Benutzername
settings.slack_icon_url=Icon URL
settings.slack_color=Farbe
@@ -750,10 +764,20 @@ settings.event_send_everything=Ich brauche <strong>alles</strong>.
settings.event_choose=Lass mich auswählen, was ich brauche.
settings.event_create=Erstellen
settings.event_create_desc=Branch/Tag erstellt
settings.event_pull_request=Pull-Request
settings.event_pull_request_desc=Pull-Request geöffnet, geschlossen, wieder geöffnet, bearbeitet, zugewiesen, nicht zugewiesen, Label aktualisiert, Label gelöscht oder synchronisiert.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push auf ein Repository
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull-Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktiv
settings.active_helper=Details über das auslösende Ereignis des Webhooks werden ebenfalls mit gesendet
settings.add_hook_success=Webhook hinzugefügt
@@ -763,12 +787,12 @@ settings.delete_webhook=Webhook löschen
settings.recent_deliveries=Letzte Zustellungen
settings.hook_type=Hook Typ
settings.add_slack_hook_desc=Fügen Sie <a href="%s">Slack</a>-Integration zu Ihrem Repository hinzu.
settings.add_discord_hook_desc=Add <a href="%s">Discord</a> integration to your repository.
settings.add_discord_hook_desc=Fügen Sie <a href="%s">Discord</a>-Integration zu Ihrem Repository hinzu.
settings.slack_token=Token
settings.slack_domain=Domain
settings.slack_channel=Kanal
settings.deploy_keys=Deploy-Schlüssel
settings.deploy_keys_helper=<b>Common Gotcha!</b> If you're looking for adding personal public keys, please add them in your <a href="%s%s">account settings</a>.
settings.deploy_keys_helper=<b>Häufiger Fehler!</b> Wenn Sie öffentliche Schlüssel hinzufügen wollen, gehen Sie zu Ihren <a href="%s%s"> Kontoeinstellungen</a>.
settings.add_deploy_key=Deploy-Schlüssel hinzufügen
settings.deploy_key_desc=Deploy-Schlüssel haben nur lesenden Zugriff. Sie sind nicht identisch mit dem SSH-Schlüssel des persönlichen Kontos.
settings.no_deploy_keys=Sie haben noch keine Deploy-Schlüssel hinzugefügt.
@@ -798,7 +822,6 @@ release.releases=Releases
release.new_release=Neues Release
release.draft=Entwurf
release.prerelease=Pre-Release
release.stable=Stabil
release.edit=bearbeiten
release.ahead=<strong>%d</strong> Commits zu %s seit diesem Release
release.source_code=Quelltext
@@ -847,7 +870,7 @@ team_permission_desc=Welche Berechtigungsstufe soll das Team haben?
form.name_reserved=Organisationsname '%s' ist bereits vergeben.
form.name_pattern_not_allowed=Organisationsnamen der Form '%s' sind nicht erlaubt.
form.team_name_reserved=Team name '%s' is reserved.
form.team_name_reserved=Der Teamname '%s' ist reserviert.
settings=Einstellungen
settings.options=Optionen
@@ -938,8 +961,8 @@ dashboard.git_gc_repos=Garbage Collection auf Repositories ausführen
dashboard.git_gc_repos_success=Garbage Collection wurde auf allen Repositories erfolgreich ausgeführt.
dashboard.resync_all_sshkeys=Datei '.ssh/authorized_keys' neu anlegen (Achtung: Schlüssel, die nicht zu Gogs gehören gehen verloren)
dashboard.resync_all_sshkeys_success=Alle öffentlichen Keys wurden erfolgreich neu geschrieben.
dashboard.resync_all_hooks=Resync pre-receive, update and post-receive hooks of all repositories
dashboard.resync_all_hooks_success=All repositories' pre-receive, update and post-receive hooks have been resynced successfully.
dashboard.resync_all_hooks=Synchronisiere pre-receive, update und post-receive Hooks für alle Repositorien
dashboard.resync_all_hooks_success=Pre-receive, update und post-receive Hooks aller Repositorien wurden erfolgreich synchronisiert.
dashboard.reinit_missing_repos=Alle Repository-Datensätze mit verloren gegangenen Git-Dateien neu initialisieren
dashboard.reinit_missing_repos_success=Alle Repository-Datensätze, die Git-Dateien verloren haben wurden erfolgreich neu initialisiert.
@@ -1014,6 +1037,7 @@ repos.private=Privat
repos.watches=Beobachtungen
repos.stars=Favoriten
repos.issues=Issues
repos.size=Size
auths.auth_manage_panel=Authentifizierung
auths.new=Neue Quelle hinzufügen
@@ -1089,15 +1113,15 @@ config.ssh_keygen_path=Keygen ('ssh-keygen') Pfad
config.ssh_minimum_key_size_check=Prüfung der Mindestschlüssellänge
config.ssh_minimum_key_sizes=Minimale Schlüssellängen
config.repo_config=Repository Configuration
config.repo_config=Repository-Konfiguration
config.repo_root_path=Repository-Verzeichnis
config.script_type=Skript-Typ
config.repo_force_private=Force Private
config.max_creation_limit=Max Creation Limit
config.preferred_licenses=Preferred Licenses
config.disable_http_git=Disable HTTP Git
config.enable_local_path_migration=Enable Local Path Migration
config.commits_fetch_concurrency=Commits Fetch Concurrency
config.repo_force_private=Erzwinge privat
config.max_creation_limit=Maximal erstellbare Anzahl
config.preferred_licenses=Bevorzugte Lizenzen
config.disable_http_git=Deaktiviere HTTP-Git
config.enable_local_path_migration=Erlaube Migration von lokalem Pfad
config.commits_fetch_concurrency=Anzahl gleichzeitiger Commit-/Fetch-Prozesse
config.db_config=Datenbankkonfiguration
config.db_type=Typ
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Zeitlimit für Pull
config.git_gc_timeout=Zeitlimit für GC
config.log_config=Konfiguration des Loggings
config.log_mode=Log-Modus
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron-Tasks
monitor.name=Name
@@ -1200,19 +1225,23 @@ notices.delete_success=Systemmitteilungen wurden erfolgreich gelöscht.
[action]
create_repo=hat das Repository <a href="%s">%s</a> erstellt
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=hat das Repository von <code>%[1]s</code> zu <a href="%[2]s">%[3]s</a> umbenannt
commit_repo=hat auf <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> gepusht
compare_commits=Zeige Vergleich für diese %d Commits
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
create_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> geöffnet`
close_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> geschlossen`
reopen_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> wieder geöffnet`
comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
create_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> erstellt`
close_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> geschlossen`
reopen_pull_request=`hat den Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> wieder geöffnet`
comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
merge_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> zuammengeführt`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=hat Tag <a href="%s/src/%s">%[2]s</a> auf <a href="%[1]s">%[3]s</a> gepusht
compare_commits=Zeige Vergleich für diese %d Commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=vor

View File

@@ -201,6 +201,7 @@ Content = Content
require_error = ` cannot be empty.`
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot characters.`
alpha_dash_dot_slash_error = ` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error = ` must be size %s.`
min_size_error = ` must contain at least %s characters.`
max_size_error = ` must contain at most %s characters.`
@@ -426,6 +427,7 @@ pulls = Pull Requests
labels = Labels
milestones = Milestones
commits = Commits
git_branches = Branches
releases = Releases
file_raw = Raw
file_history = History
@@ -434,6 +436,13 @@ file_permalink = Permalink
file_too_large = This file is too large to be shown
video_not_supported_in_browser = Your browser doesn't support HTML5 video tag.
branches.overview = Overview
branches.active_branches = Active Branches
branches.stale_branches = Stale Branches
branches.all = All Branches
branches.updated_by = Updated %[1]s by %[2]s
branches.change_default_branch = Change Default Branch
editor.new_file = New file
editor.upload_file = Upload file
editor.edit_file = Edit file
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc = Disable force pushes and prevent from deleti
settings.protect_require_pull_request = Require pull request instead direct pushing
settings.protect_require_pull_request_desc = Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers = Whitelist who can push to this branch
settings.protect_whitelist_committers_desc = Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc = Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users = Users who can push to this branch
settings.protect_whitelist_search_users = Search users
settings.protect_whitelist_teams = Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams = Search teams
settings.update_protect_branch_success = Protect options for this branch has been updated successfully!
settings.hooks = Webhooks
settings.githooks = Git Hooks
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric = Alphanumeric
settings.tracker_url_format_desc = You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
settings.pulls_desc = Enable pull requests to accept public contributions
settings.danger_zone = Danger Zone
settings.cannot_fork_to_same_owner = You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo = The new owner already has a repository with same name. Please choose another name.
settings.convert = Convert To Regular Repository
settings.convert_desc = You can convert this mirror to a regular repository. This cannot be reversed.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc = This user will no longer have collaboratio
settings.remove_collaborator_success = Collaborator has been removed.
settings.search_user_placeholder = Search user...
settings.org_not_allowed_to_be_collaborator = Organization is not allowed to be added as a collaborator.
settings.user_is_org_member = User is organization member who cannot be added as a collaborator.
settings.add_webhook = Add Webhook
settings.hooks_desc = Webhooks are much like basic HTTP POST event triggers. Whenever something occurs in Gogs, we will handle the notification to the target host you specify. Learn more in this <a target="_blank" href="%s">Webhooks Guide</a>.
settings.webhook_deletion = Delete Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc = Gogs will send a <code>POST</code> request to the UR
settings.payload_url = Payload URL
settings.content_type = Content Type
settings.secret = Secret
settings.secret_desc = Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username = Username
settings.slack_icon_url = Icon URL
settings.slack_color = Color
@@ -749,11 +763,21 @@ settings.event_push_only = Just the <code>push</code> event.
settings.event_send_everything = I need <strong>everything</strong>.
settings.event_choose = Let me choose what I need.
settings.event_create = Create
settings.event_create_desc = Branch, or tag created
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_create_desc = Branch or tag created
settings.event_delete = Delete
settings.event_delete_desc = Branch or tag deleted
settings.event_fork = Fork
settings.event_fork_desc = Repository forked
settings.event_push = Push
settings.event_push_desc = Git push to a repository
settings.event_issues = Issues
settings.event_issues_desc = Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment = Issue Comment
settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release = Release
settings.event_release_desc = Release published in a repository.
settings.active = Active
settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
settings.add_hook_success = New webhook has been added.
@@ -798,7 +822,6 @@ release.releases = Releases
release.new_release = New Release
release.draft = Draft
release.prerelease = Pre-Release
release.stable = Stable
release.edit = edit
release.ahead = <strong>%d</strong> commits to %s since this release
release.source_code = Source Code
@@ -1014,6 +1037,7 @@ repos.private = Private
repos.watches = Watches
repos.stars = Stars
repos.issues = Issues
repos.size = Size
auths.auth_manage_panel = Authentication Manage Panel
auths.new = Add New Source
@@ -1171,7 +1195,8 @@ config.git_pull_timeout = Pull Operation Timeout
config.git_gc_timeout = GC Operation Timeout
config.log_config = Log Configuration
config.log_mode = Log Mode
config.log_mode = Mode
config.log_options = Options
monitor.cron = Cron Tasks
monitor.name = Name
@@ -1200,19 +1225,23 @@ notices.delete_success = System notices have been deleted successfully.
[action]
create_repo = created repository <a href="%s">%s</a>
fork_repo = forked a repository to <a href="%s">%s</a>
rename_repo = renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
commit_repo = pushed to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
compare_commits = View comparison for these %d commits
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
create_issue = `opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue = `closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue = `reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request = `created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request = `closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request = `reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
create_branch = created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch = deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_commits = View comparison for these %d commits
delete_tag = deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago = ago

View File

@@ -201,6 +201,7 @@ Content=Contenido
require_error=` no puede estar vacío.`
alpha_dash_error=` los caracteres deben ser Alfanumericos o dash(-_).`
alpha_dash_dot_error=` debe ser un caracter alfanumérivo válido, un guión alto o bajo (-_) o un signo de puntuación.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` debe ser de tamaño %s.`
min_size_error=` debe contener al menos %s caracteres.`
max_size_error=` debe contener como máximo %s caracteres.`
@@ -426,6 +427,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Milestones
commits=Commits
git_branches=Branches
releases=Releases
file_raw=Raw
file_history=Histórico
@@ -434,6 +436,13 @@ file_permalink=Permalink
file_too_large=Este archivo es demasiado grande para ser mostrado
video_not_supported_in_browser=Su navegador no soporta el tag video de HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nuevo archivo
editor.upload_file=Subir archivo
editor.edit_file=Editar archivo
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Desactivar force pushes y evite la eliminació
settings.protect_require_pull_request=Requiere una solicitud pull, en lugar de un push directo
settings.protect_require_pull_request_desc=Active esta opción para deshabilitar un push directo a esta rama. Los commits tienen que ser empujados a otra rama no protegida y fusionados a esta rama a través de la solicitud pull.
settings.protect_whitelist_committers=Lista blanca de quienes pueden empujar a esta rama
settings.protect_whitelist_committers_desc=Añadir personas o equipos a la lista blanca de empuje directo a esta rama.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git Hooks
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumérico
settings.tracker_url_format_desc=Puedes usar las plantillas <code>{user} {repo} {index}</code> para el nombre de usuario, nombre del repositorio e índice de la incidencia.
settings.pulls_desc=Habilitar Pull Requests para aceptar contribuciones públicas
settings.danger_zone=Zona de Peligro
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=El nuevo propietario tiene un repositorio con el mismo nombre.
settings.convert=Convertir en un repositorio normal
settings.convert_desc=Puedes convertir este repositorio en un repositorio normal. Este cambio no se puede deshacer.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Este usuario no podrá colaborar en este rep
settings.remove_collaborator_success=El colaborador ha sido eliminado.
settings.search_user_placeholder=Buscar usuario...
settings.org_not_allowed_to_be_collaborator=Las organizaciones no tiene permitido ser añadidas como colaboradores.
settings.user_is_org_member=El usuario es miembro de la organización, no puede ser añadido como colaborador.
settings.add_webhook=Añadir Webhook
settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificaciones cuando sucedan ciertos eventos en Gogs. Cuando sucedan los eventos especificados, enviaremos una petición POST a cada una de las URLs indicadas. Para obtener más información, consulta nuestra <a target="_blank" href="%s">Guía de Webhooks</a>.
settings.webhook_deletion=Eliminar Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Enviaremos una petición <code>POST</code> a la siguie
settings.payload_url=URL de Payload
settings.content_type=Tipo de contenido
settings.secret=Secreto
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Nombre de usuario
settings.slack_icon_url=URL de icono
settings.slack_color=Color
@@ -750,10 +764,20 @@ settings.event_send_everything=Necesito <strong>todo</strong>.
settings.event_choose=Déjeme elegir lo que necesito.
settings.event_create=Crear
settings.event_create_desc=Rama o etiqueta creada
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request, abierta, cerrada, reabierta, editada, asignada, desasignada, con etiqueta actualizada, con etiqueta eliminada, o sincronizada.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push a un repositorio
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Activo
settings.active_helper=Enviaremos detalles del evento cuando este hook se dispare.
settings.add_hook_success=Se ha añadido un nuevo webhook.
@@ -798,7 +822,6 @@ release.releases=Releases
release.new_release=Nueva Release
release.draft=Borrador
release.prerelease=Pre-Release
release.stable=Estable
release.edit=editar
release.ahead=<strong>%d</strong> commits en %s desde esta release
release.source_code=Código Fuente
@@ -1014,6 +1037,7 @@ repos.private=Privado
repos.watches=Vigilantes
repos.stars=Estrellas
repos.issues=Incidencias
repos.size=Size
auths.auth_manage_panel=Panel de administración de autenticación
auths.new=Añadir nuevo origen
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Tiempo de espera de operación de pull
config.git_gc_timeout=Tiempo de espera de operación de GC
config.log_config=Configuración del Log
config.log_mode=Modo del Log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tareas de Cron
monitor.name=Nombre
@@ -1200,19 +1225,23 @@ notices.delete_success=Las notificaciones del sistema han sido eliminadas satisf
[action]
create_repo=creó el repositorio <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
commit_repo=hizo push a <a href="%[1]s/src/%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparación de estos %d commits
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
create_issue=`incidencia abierta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`cerró la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reabrió la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`cerró el pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabrió el pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparación de estos %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=hace

View File

@@ -201,6 +201,7 @@ Content=Sisältö
require_error=` ei voi olla tyhjä.`
alpha_dash_error=` täytyy olla kirjaimia tai numeroita tai väliviiva(-_) merkkejä.`
alpha_dash_dot_error=` täytyy olla kirjaimia tai numeroita tai väliviiva(-_) tai piste merkkejä.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` täytyy olla kokoa %s.`
min_size_error=` täytyy sisältää vähintään %s merkkiä.`
max_size_error=` täytyy sisältää enintään %s merkkiä.`
@@ -426,6 +427,7 @@ pulls=Pull-pyynnöt
labels=Tunnisteet
milestones=Merkkipaalut
commits=Commitit
git_branches=Branches
releases=Julkaisut
file_raw=Raaka
file_history=Historia
@@ -434,6 +436,13 @@ file_permalink=Pysyvä linkki
file_too_large=Tämä tiedosto on liian suuri näytettäväksi
video_not_supported_in_browser=Selaimesi ei tue HTML5 video-tagia.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Uusi tiedosto
editor.upload_file=Liitä tiedosto
editor.edit_file=Muokkaa tiedostoa
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Kiellä pakoteut push-operaatiot ja estä pois
settings.protect_require_pull_request=Vaadi pull-pyyntö suoran push-operaation sijaan
settings.protect_require_pull_request_desc=Estä suorat push-operaatiot tähän haaraan. Commitit täytyy pushata ei-suojattuun haaraan ja yhdistää tähän haaraan pull-pyynnön kautta.
settings.protect_whitelist_committers=Lista sallituista, jotka voivat pushata tähän haaraan
settings.protect_whitelist_committers_desc=Lisää ihmisiä tai tiimejä sallittujen listaan, jotka voivat pushata suoraan tähän haaraan.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webkoukut
settings.githooks=Git koukut
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Aakkosnumeerinen
settings.tracker_url_format_desc=Voit käyttää paikkamerkkiä <code>{user} {repo} {index}</code> käyttäjänimelle, reponimelle ja vikanumerolle.
settings.pulls_desc=Ota käyttöön pull-pyynnöt salliaksesi julkiset koodilahjoitukset
settings.danger_zone=Vaaravyöhyke
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Uudella omistajalla on jo samanniminen repo. Ole hyvä ja valitse toinen nimi.
settings.convert=Muunna tavalliseksi repoksi
settings.convert_desc=Voit muuntaa tämän peilin tavalliseksi repoksi. Tätä ei voi peruuttaa.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Tällä käyttäjällä ei tule enää olema
settings.remove_collaborator_success=Yhteistyökumppani on poistettu.
settings.search_user_placeholder=Etsi käyttäjä...
settings.org_not_allowed_to_be_collaborator=Yhteistyökumppaniksi ei voi lisätä organisaatiota.
settings.user_is_org_member=Käyttäjä on organisaation jäsen, jota ei voi lisätä yhteistyökumppaniksi.
settings.add_webhook=Lisää webkoukku
settings.hooks_desc=Webkoukut muistuttavat paljon perus HTTP POST tapahtuma laukaisimia. Aina kun jotain tapahtuu Gogsissa, käsittelemme ilmoituksen määrittäämääsi kohteeseen. Lisätietoja <a target="_blank" href="%s">webkoukku oppaassa</a>.
settings.webhook_deletion=Poista webkoukku
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs lähettää <code>POST</code> requestin määritt
settings.payload_url=Payload URL
settings.content_type=Sisältötyyppi
settings.secret=Salaus
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Käyttäjätunnus
settings.slack_icon_url=Kuvakkeen URL
settings.slack_color=Väri
@@ -750,10 +764,20 @@ settings.event_send_everything=Tarvitsen <strong>kaiken</strong>.
settings.event_choose=Haluan valita, mitä tarvitsen.
settings.event_create=Luo
settings.event_create_desc=Branch, tai tagi luotu
settings.event_pull_request=Pull-pyyntö
settings.event_pull_request_desc=Pull-pyyntö avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, tarra päivitetty, tarra poistettu tai synkronoitu.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push repoon
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull-pyyntö
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktiivinen
settings.active_helper=Yksityiskohdat koskien tapahtumaa joka laukaisi koukun toimitetaan myös.
settings.add_hook_success=Uusi webkoukku on lisätty.
@@ -798,7 +822,6 @@ release.releases=Julkaisut
release.new_release=Uusi julkaisu
release.draft=Työversio
release.prerelease=Esiversio
release.stable=Vakaa
release.edit=muokkaa
release.ahead=<strong>%d</strong> committia kohteeseen %s version jälkeen
release.source_code=Lähdekoodi
@@ -1014,6 +1037,7 @@ repos.private=Yksityinen
repos.watches=Tarkkailijat
repos.stars=Äänet
repos.issues=Ongelmat
repos.size=Size
auths.auth_manage_panel=Todennus hallintapaneeli
auths.new=Lisää uusi lähde
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull-operaatio aikakatkaistiin
config.git_gc_timeout=Roskienkeruu aikakatkaistiin
config.log_config=Loki asetukset
config.log_mode=Loki tila
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron tehtävät
monitor.name=Nimi
@@ -1200,19 +1225,23 @@ notices.delete_success=Järjestelmän ilmoitukset on poistettu onnistuneesti.
[action]
create_repo=luotu repo <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a>
commit_repo=pushattu kohteeseen <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a>
compare_commits=Näytä vertailu näille %d commiteille
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
create_issue=`avasi ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`sulki ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`avasi uudelleen ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`kommentoi ongelmaa <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`luotu pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`sulki pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`avasi uudelleen pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`kommentoi ongelmaa <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`yhdistetty pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pushattu tagi <a href="%s/src/%s">%[2]s</a> kohteeseen <a href="%[1]s">%[3]s</a>
compare_commits=Näytä vertailu näille %d commiteille
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=sitten

View File

@@ -201,6 +201,7 @@ Content=Contenu
require_error=` ne peut pas être vide.`
alpha_dash_error=` doivent être des caractères alpha, numériques ou tirets (-_) valides.`
alpha_dash_dot_error=` doivent être des caractères alpha, numériques, tirets (-_) valides ou des points.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` doit être à la taille de %s.`
min_size_error=` %s caractères minimum `
max_size_error=` %s caractères maximum `
@@ -399,7 +400,7 @@ migrate.failed=Echec de migration: %v
mirror_from=miroir de
forked_from=forké depuis
copy_link=Copier
copy_link_success=Copié!
copy_link_success=Copié !
copy_link_error=Appuyez sur ⌘-C ou Ctrl-C pour copier
copied=Copié
unwatch=Ne plus suivre
@@ -423,9 +424,10 @@ branches=Branches
tags=Tags
issues=Tickets
pulls=Pull Requests
labels=Etiquettes
labels=Étiquettes
milestones=Jalons
commits=Commits
git_branches=Branches
releases=Publications
file_raw=Raw
file_history=Historique
@@ -434,6 +436,13 @@ file_permalink=Lien permanent
file_too_large=Ce fichier est trop gros pour être afficher
video_not_supported_in_browser=Votre navigateur ne supporte pas la balise video HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nouveau fichier
editor.upload_file=Téléverser un fichier
editor.edit_file=Modifier fichier
@@ -473,7 +482,7 @@ editor.add_subdir=Ajouter un sous-répertoire...
editor.unable_to_upload_files=Échec lors de l'envoie du fichier '%s' avec lerreur : %v
editor.upload_files_to_dir=Transférer les fichiers vers '%s'
commits.commit_history=Commit History
commits.commit_history=Historique des commits
commits.commits=Commits
commits.search=Rechercher des commits
commits.find=Trouver
@@ -484,7 +493,7 @@ commits.older=Précédemment
commits.newer=Récemment
issues.new=Nouveau ticket
issues.new.labels=Etiquettes
issues.new.labels=Étiquettes
issues.new.no_label=Pas d'étiquette
issues.new.clear_labels=Effacer les étiquettes
issues.new.milestone=Jalon
@@ -655,8 +664,12 @@ settings.protect_this_branch_desc=Interdire les push forcés et empêcher la sup
settings.protect_require_pull_request=Exiger une requête de fusion plutôt qu'un push immédiat
settings.protect_require_pull_request_desc=Activez cette option pour empêcher la publication immédiate vers cette branche. Les commits devront être publiés vers une autre branche (non protégée) et fusionnée dans cette branche avec une requête de fusion.
settings.protect_whitelist_committers=Liste blanche de personnes pouvant publier sur cette branche
settings.protect_whitelist_committers_desc=Ajouter des personnes ou des équipes à la liste blanche de publication directe vers cette branche.
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Utilisateurs qui peuvent pousser sur cette branche
settings.protect_whitelist_search_users=Rechercher des utilisateurs
settings.protect_whitelist_teams=Les équipes pour lesquelles les membres peuvent pousser sur cette branche
settings.protect_whitelist_search_teams=Rechercher des équipes
settings.update_protect_branch_success=Les options de protection de cette branches ont été mises à jour avec succès.
settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Paramètres de base
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumérique
settings.tracker_url_format_desc=Vous pouvez utiliser l'espace réservé <code>{user} {repo} {index}</code> pour le nom d'utilisateur, le nom du dépôt et le numéro de bug.
settings.pulls_desc=Activer les pull requests pour accepter les contributions publiques
settings.danger_zone=Zone de danger
settings.cannot_fork_to_same_owner=Vous ne pouvez par créer un fork d'un dépot à son propriétaire actuel.
settings.new_owner_has_same_repo=Le nouveau propriétaire a déjà un dépôt nommé ainsi.
settings.convert=Convertir en dépôt ordinaire
settings.convert_desc=Vous pouvez convertir ce miroir en dépôt ordinaire. Cela ne peut pas être inversée.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Cet utilisateur n'aura plus accès pour coll
settings.remove_collaborator_success=Collaborateur supprimé.
settings.search_user_placeholder=Rechercher un utilisateur...
settings.org_not_allowed_to_be_collaborator=Une organisation n'est pas autorisée à être ajoutée en tant que collaborateur.
settings.user_is_org_member=Cet utilisateur ne peut pas être ajouté en tant que collaborateur car il fait partie d'une organisation.
settings.add_webhook=Ajouter un Webhook
settings.hooks_desc=Les Webhooks sont des déclencheurs de POST HTTP . Lorsque qu'un événement se produit dans Gogs, une notification sera envoyée vers l'hôte cible préalablement spécifié. Apprenez-en davantage dans le <a target="_blank" href="%s">Guide des Webhooks</a>.
settings.webhook_deletion=Supprimer le Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Une requête <code>POST</code> sera transmise vers l'U
settings.payload_url=URL des Données Utiles
settings.content_type=Type de contenu
settings.secret=Confidentiel
settings.secret_desc=Le secret sera envoyé comme digest de payload SHA256 HMAC hex avec l'entête <code>X-Gogs-Signature</code>.
settings.slack_username=Nom d'utilisateur
settings.slack_icon_url=URL de l'icône
settings.slack_color=Couleur
@@ -750,10 +764,20 @@ settings.event_send_everything=J'ai besoin de <strong>tout</strong>.
settings.event_choose=Permettez-moi de choisir ce dont j'ai besoin.
settings.event_create=Créer
settings.event_create_desc=Branche, ou Tag créé
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request ouvert, fermé, rouvert, édité, attribuée, non attribuées, étiquette mise à jour, étiquette désactivée ou synchronisé.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push vers un dépôt
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Actif
settings.active_helper=Les détails seront délivrés lorsque ce Hook sera déclenché.
settings.add_hook_success=Nouveau Webhook ajouté.
@@ -781,7 +805,7 @@ settings.deploy_key_deletion=Supprimer la Clé de Déploiement
settings.deploy_key_deletion_desc=Supprimer cette clé de déploiement effacera tous les accès relatifs pour ce référentiel. Voulez-vous continuer ?
settings.deploy_key_deletion_success=La clé de déploiement a été supprimée avec succès !
diff.browse_source=Parcourir la Source
diff.browse_source=Parcourir la source
diff.parent=Parent
diff.commit=commit
diff.data_not_available=Données Diff indisponibles.
@@ -798,7 +822,6 @@ release.releases=Versions
release.new_release=Nouvelle version
release.draft=Brouillon
release.prerelease=Pré-publication
release.stable=Stable
release.edit=Éditer
release.ahead=<strong>%d</strong> commits jusqu'à %s depuis cette publication
release.source_code=Code source
@@ -1014,6 +1037,7 @@ repos.private=Privé
repos.watches=Suivi par
repos.stars=Votes
repos.issues=Tickets
repos.size=Size
auths.auth_manage_panel=Panel d'administration des authentifications
auths.new=Ajouter une nouvelle source d'authentification
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Délai imparti pour l'opération "Pull"
config.git_gc_timeout=Délai imparti pour l'opération "GC"
config.log_config=Configuration du Journal
config.log_mode=Mode du journal
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tâches Cron
monitor.name=Nom
@@ -1200,19 +1225,23 @@ notices.delete_success=Notifications système supprimées avec succès.
[action]
create_repo=a créé le dépôt <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=a rebaptisé le dépôt de <code>%[1]s</code> vers <a href="%[2]s">%[3]s</a>
commit_repo=a commité dans <a href="%[1]s/src/%[2]s">%[3]s</a> sur <a href="%[1]s">%[4]s</a>
compare_commits=Comparer ces %d commits
transfer_repo=a transféré le dépôt <code>%s</code> à <a href="%s">%s</a>
create_issue=`a ouvert un problème <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`tickets clos <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`tickets ré-ouverts <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`pull request créée le <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`pull request fermé <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`pull request ré-ouverte <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`pull request fusionné le <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=a transféré le dépôt <code>%s</code> à <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=a soumis le tag <a href="%s/src/%s">%[2]s</a> sur <a href="%[1]s">%[3]s</a>
compare_commits=Comparer ces %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=il y a

View File

@@ -201,6 +201,7 @@ Content=Contido
require_error=` non pode estar baleiro.`
alpha_dash_error=` os caracteres deben ser alfanuméricos ou dash(-_).`
alpha_dash_dot_error=` debe ser un carácter alfanumérivo válido, un guión alto ou baixo (-_) ou un signo de puntuación.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` debe ser de tamaño %s.`
min_size_error=` debe conter polo menos %s caracteres.`
max_size_error=` debe conter como máximo %s caracteres.`
@@ -426,6 +427,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Fitos
commits=Achegas
git_branches=Branches
releases=Lanzamentos
file_raw=Raw
file_history=Histórico
@@ -434,6 +436,13 @@ file_permalink=Permalink
file_too_large=Este arquivo é demasiado grande para ser mostrado
video_not_supported_in_browser=O teu navegador non soporte a etiqueta video de HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Novo arquivo
editor.upload_file=Subir arquivo
editor.edit_file=Editar arquivo
@@ -531,7 +540,7 @@ issues.next=Páxina seguinte
issues.open_title=Aberta
issues.closed_title=Cerrada
issues.num_comments=%d comentarios
issues.commented_at='comentado <a href="#%s"> %s'</a>
issues.commented_at=`comentado <a href="#%s"> %s'</a>`
issues.delete_comment_confirm=Seguro que desexas eliminar este comentario?
issues.no_content=Aínda non existe contido.
issues.close_issue=Cerrar
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git Hooks
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumérico
settings.tracker_url_format_desc=Podes usar os modelos <code>{user} {repo} {index}</code> para o nome de usuario, nome do repositorio e índice da incidencia.
settings.pulls_desc=Habilitar Pull Requests para aceptar contribucións públicas
settings.danger_zone=Zona de perigo
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=O novo propietario ten un repositorio co mesmo nome.
settings.convert=Converter nun repositorio normal
settings.convert_desc=Podes converter este repositorio nun repositorio normal. Este cambio non se pode desfacer.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Este usuario non poderá colaborar neste rep
settings.remove_collaborator_success=O colaborador foi eliminado.
settings.search_user_placeholder=Buscar usuario...
settings.org_not_allowed_to_be_collaborator=As organizacións non teñen permitido ser engadidas como colaboradores.
settings.user_is_org_member=O usuario é membro da organización, non pode ser engadido como colaborador.
settings.add_webhook=Engadir Webhook
settings.hooks_desc=Os Webhooks permiten a servizos externos recibir notificacións cando sucedan certos eventos en Gogs. Cando sucedan os eventos especificados, enviaremos unha petición POST a cada unha das URLs indicadas. Para obter máis información, consulta a nosa <a target="_blank" href="%s">Guía de Webhooks</a>.
settings.webhook_deletion=Eliminar Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Enviaremos unha petición <code>POST</code> á seguint
settings.payload_url=URL de Payload
settings.content_type=Tipo de contido
settings.secret=Secreto
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Nome da persoa usuaria
settings.slack_icon_url=URL da icona
settings.slack_color=Cor
@@ -750,10 +764,20 @@ settings.event_send_everything=Necesito <strong>todo</strong>.
settings.event_choose=Déixeme elixir o que necesito.
settings.event_create=Crear
settings.event_create_desc=Rama ou etiqueta creada
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request aberto, cerrado, reaberto, editado, asignado, desasignado, etiqueta actualizada, etiqueta borrada, ou sincronizado.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push a un repositorio
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Activo
settings.active_helper=Enviaremos detalles do evento cando este hook se dispare.
settings.add_hook_success=Engadiuse un novo webhook.
@@ -798,7 +822,6 @@ release.releases=Lanzamentos
release.new_release=Novo lanzamento
release.draft=Borrador=Borrador
release.prerelease=Pre-Release=Pre-Lanzamento
release.stable=Estable=Estable
release.edit=editar=editar
release.ahead=<strong>%d</strong> achegas en %s desde este release
release.source_code=Código fonte
@@ -1014,6 +1037,7 @@ repos.private=Privado
repos.watches=Vixilantes
repos.stars=Estrelas
repos.issues=Incidencias
repos.size=Size
auths.auth_manage_panel=Panel de administración de autenticación
auths.new=Engadir nova orixe
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Tempo de espera de operación de pull
config.git_gc_timeout=Tempo de espera de operación de GC
config.log_config=Configuración do log
config.log_mode=Modo do log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tarefas de cron
monitor.name=Nome
@@ -1200,19 +1225,23 @@ notices.delete_success=As notificacións do sistema foron eliminadas satisfactor
[action]
create_repo=creou o repositorio <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repositorio renomeado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
commit_repo=fixo push a <a href="%[1]s/src/%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparación destas %d achegas
transfer_repo=transferiu o repositorio <code>%s</code> a <a href="%s">%s</a>
create_issue=`incidencia aberta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`cerrou a incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reabriu a incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentou na incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`cerrou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabriu o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentou na incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transferiu o repositorio <code>%s</code> a <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=fixo push do tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparación destas %d achegas
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=hai

View File

@@ -48,7 +48,7 @@ cancel=Annulla
install=Installazione
title=Passi d'installazione per il primo avvio
docker_helper=Se stai utilizzando Gogs su Docker, per favore leggi le <a target="_blank" href="%s">Linee guida</a> con attenzione prima di cambiare qualcosa su questa pagina!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs richiede MySQL, PostgreSQL, SQLite3, MSSQL o TiDB.
db_title=Impostazioni Database
db_type=Tipo di database
host=Host
@@ -58,8 +58,8 @@ db_name=Nome del database
db_helper=Utilizza il motore INNODB con codifica utf8_general_ci per MySQL.
ssl_mode=Modalità SSL
path=Percorso
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=Il percorso del file di database di SQLite3. <br>Si prega di utilizzare il percorso assoluto quando si avvia come servizio.
err_empty_db_path=Il percorso del database SQLite3 non può essere vuoto.
no_admin_and_disable_registration=Non puoi disabilitare la registrazione senza aver creato un amministratore.
err_empty_admin_password=La password dell'amministratore non puo' essere vuota.
@@ -74,7 +74,7 @@ domain=Dominio
domain_helper=Questo influisce sugli URL per il clonaggio via SSH.
ssh_port=Porta SSH
ssh_port_helper=Numero di porta utilizzato dal server SSH, lasciare vuoto per disabilitare l'integrazione SSH.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server=Usa il server SSH integrato
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
http_port=Porta HTTP
http_port_helper=Porta di ascolto dell'applicazione.
@@ -201,6 +201,7 @@ Content=Contenuto
require_error=` non può essere vuoto.`
alpha_dash_error=` ammessi solo caratteri alfanumerici o trattini(-_).`
alpha_dash_dot_error=` ammessi solo caratteri alfanumerici o trattini(-_) o punti.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error='deve essere %s.'
min_size_error=` deve contenere almeno %s caratteri.`
max_size_error=` deve contenere massimo %s caratteri.`
@@ -426,6 +427,7 @@ pulls=Pull Requests
labels=Etichette
milestones=Traguardi
commits=Commit
git_branches=Branches
releases=Rilasci
file_raw=Originale
file_history=Cronologia
@@ -434,6 +436,13 @@ file_permalink=Permalink
file_too_large=Questo file è troppo grande per essere mostrato
video_not_supported_in_browser=Il tuo browser non supporta i tag "video" di HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nuovo file
editor.upload_file=Carica File
editor.edit_file=Modifica file
@@ -473,7 +482,7 @@ editor.add_subdir=Aggiungi sottocartella...
editor.unable_to_upload_files=È fallito il caricamento dei file su '%s': %v
editor.upload_files_to_dir=Carica file su '%s'
commits.commit_history=Commit History
commits.commit_history=Cronologia Commit
commits.commits=Commits
commits.search=Ricerca una versione
commits.find=Cerca
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git Hooks
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumeric
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
settings.pulls_desc=Abilita le pull requests per accettare contributi pubblici
settings.danger_zone=Zona Pericolosa
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Il nuovo proprietario ha già un repository con lo stesso nome. Per favore scegli un altro nome.
settings.convert=Converti in Repository Regolare
settings.convert_desc=Puoi convertire questo mirror in un repository regolare. Questa operazione non può essere annullata.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Questo utente non potrà più collaborare a
settings.remove_collaborator_success=Il collaboratore è stato rimosso.
settings.search_user_placeholder=Cerca utente...
settings.org_not_allowed_to_be_collaborator=Un'organizzazione non può essere aggiunta come collaboratore.
settings.user_is_org_member=L'utente è un membro dell'organizzazione che non può essere aggiunto come collaboratore.
settings.add_webhook=Aggiungi Webhook
settings.hooks_desc=I Webhooks sono molto simili a un basilare evento trigger HTTP POST. Ogni volta che qualcosa si verifica in Gogs, tratteremo la notifica all'host di destinazione specificato. Ulteriori informazioni in questa <a target="_blank" href="%s">Guida ai Webhooks</a>.
settings.webhook_deletion=Elimina Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs manderà una richiesta <code>POST</code> all'URL
settings.payload_url=Payload URL
settings.content_type=Content Type
settings.secret=Secret
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Nome utente
settings.slack_icon_url=URL icona
settings.slack_color=Colore
@@ -750,10 +764,20 @@ settings.event_send_everything=Ho bisogno di <strong>tutto</strong>.
settings.event_choose=Lasciami scegliere ciò di cui ho bisogno.
settings.event_create=Crea
settings.event_create_desc=Branch, o tag creato
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request aperta, chiusa, riaperta, modificata, assegnata, riassegnata, etichettata o sincronizzata.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push in un repository
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Attivo
settings.active_helper=Anche i dettagli riguardanti l'evento che ha innescato l'hook saranno inviati.
settings.add_hook_success=Il nuovo webhook è stato aggiunto.
@@ -798,7 +822,6 @@ release.releases=Rilasci
release.new_release=Nuovo Rilascio
release.draft=Bozza
release.prerelease=Pre-Rilascio
release.stable=Stabile
release.edit=modifica
release.ahead=<strong>%d</strong> commits da %s da questo rilascio
release.source_code=Codice Sorgente
@@ -1014,6 +1037,7 @@ repos.private=Privati
repos.watches=Segue
repos.stars=Voti
repos.issues=Problemi
repos.size=Size
auths.auth_manage_panel=Pannello di configurazione dei meccanismi di autenticazione
auths.new=Aggiungi Nuova Origine
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Timeout per il pull
config.git_gc_timeout=Timeout per le operazioni di GC
config.log_config=Configurazione Log
config.log_mode=Modalità Log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Incarici di cron
monitor.name=Nome
@@ -1200,19 +1225,23 @@ notices.delete_success=Gli avvisi di sistema sono stati successivamente eliminat
[action]
create_repo=ha creato il repository <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repository rinominato da <code>%[1]s</code> a <a href="%[2]s">[3]s</a>
commit_repo=ha pushato nel <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
compare_commits=Visualizza comparazione tra questi %d commit
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
create_issue=`ha aperto il problema <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creata pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Visualizza comparazione tra questi %d commit
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=fa

View File

@@ -201,6 +201,7 @@ Content=コンテンツ
require_error=空にできません
alpha_dash_error=アルファベット、数字、ハイフン"-"、アンダースコア"_"のいずれかの必要があります
alpha_dash_dot_error=' アルファベット、数値、ダッシュ(-)、アンダースコア(_) 、ドット(.)のいずれかを入力する必要があります。 '
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=`サイズは %s である必要があります`
min_size_error=' 少なくとも %s 文字の必要があります '
max_size_error=' %s 文字以下の必要があります '
@@ -426,6 +427,7 @@ pulls=プルリクエスト
labels=ラベル
milestones=マイルストーン
commits=コミット
git_branches=Branches
releases=リリース
file_raw=Raw
file_history=履歴
@@ -434,6 +436,13 @@ file_permalink=パーマリンク
file_too_large=このファイルは大きすぎるため、表示できません。
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=ファイルを編集
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git のフック
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumeric
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
settings.pulls_desc=Enable pull requests to accept public contributions
settings.danger_zone=危険地帯
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=新しいオーナーは、既に同じ名前のリポジトリを持っています。
settings.convert=Convert To Regular Repository
settings.convert_desc=You can convert this mirror to a regular repository. This cannot be reversed.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=This user will no longer have collaboration
settings.remove_collaborator_success=共同編集者が削除されました。
settings.search_user_placeholder=Search users
settings.org_not_allowed_to_be_collaborator=組織を共同編集者として追加することはできません。
settings.user_is_org_member=ユーザーは組織の一員なので、共同編集者として追加することはできません。
settings.add_webhook=Webhook を追加
settings.hooks_desc=Webhooksは、Gogsで特定のイベントの発生時に指定された外部サービスに通知を許可します。イベントが発生すると、それぞれ指定されたUrlに、POSTリクエストが送られます。詳細はこちらのの <a target="_blank"href="%s"> Webhooks ガイド</a>をご覧ください。
settings.webhook_deletion=Webhook を削除
@@ -741,6 +754,7 @@ settings.add_webhook_desc=私たちは、指定されたURLに購読されたイ
settings.payload_url=ペイロードの URL
settings.content_type=コンテンツ タイプ
settings.secret=秘密
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=ユーザ名
settings.slack_icon_url=アイコン URL
settings.slack_color=カラー
@@ -750,10 +764,20 @@ settings.event_send_everything=<strong>すべて</strong> が必要です。
settings.event_choose=必要なものを選択しましょう。
settings.event_create=Create
settings.event_create_desc=ブランチ、またはタグを作成
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=プッシュ
settings.event_push_desc=Git リポジトリにプッシュ
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=アクティブ
settings.active_helper=このフックのトリガーが引かれた時に、イベントの詳細を配信します。
settings.add_hook_success=新しい webhook が追加されました。
@@ -798,7 +822,6 @@ release.releases=リリース
release.new_release=新しいリリース
release.draft=ドラフト
release.prerelease=プレリリース
release.stable=安定
release.edit=編集
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
release.source_code=ソース コード
@@ -1014,6 +1037,7 @@ repos.private=プライベート
repos.watches=Watches
repos.stars=Stars
repos.issues=課題
repos.size=Size
auths.auth_manage_panel=認証管理パネル
auths.new=新しいソースを追加
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=ログの構成
config.log_mode=ログ モード
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron タスク
monitor.name=名前
@@ -1200,19 +1225,23 @@ notices.delete_success=システム通知が正常に削除されました。
[action]
create_repo=がリポジトリ <a href="%s"> %s</a> を作成しました
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s</code> から <a href="%[2]s">[3]s</a> にリポジトリ名を変更しました
commit_repo=<a href="%[1]s">%[4]s</a>を<a href="%[1]s/src/%[2]s">%[3]s</a>にプッシュしました
compare_commits=これらの %d コミットの比較を表示
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
create_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> を開きました`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
create_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>を作成`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
merge_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>をマージしました`
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
compare_commits=これらの %d コミットの比較を表示
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=

View File

@@ -48,7 +48,7 @@ cancel=취소
install=설치
title=첫 실행을 위한 설치단계
docker_helper=Gogs를 Docker에서 운영하고 있다면 <a target="_blank" href="%s">안내</a>를 읽고 변경해 주세요!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs MySQL, PostgreSQL, SQLite3, MSSQL 또는 TiDB 를 필요로 합니다.
db_title=데이터베이스 설정
db_type=데이터베이스 유형
host=호스트
@@ -58,8 +58,8 @@ db_name=데이터베이스 이름
db_helper=MySQL에서는 utf8_general_ci 캐릭터셋으로 INNODB엔진을 이용해 주세요
ssl_mode=SSL 모드
path=경로
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=SQLite3 데이터베이스의 경로입니다.<br>서비스를 시작할 때는 반드시 절대 경로를 사용해주세요.
err_empty_db_path=SQLite3 데이터베이스의 경로는 비워둘 수 없습니다.
no_admin_and_disable_registration=관리자 계정을 만들지 않고 등록을 비활성화할 수 없습니다.
err_empty_admin_password=관리자 암호는 비워둘 수 없습니다.
@@ -74,7 +74,7 @@ domain=도메인
domain_helper=Git SSH url에 영향을 미칩니다.
ssh_port=SSH 포트
ssh_port_helper=SSH서버가 실행되고 있는 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server=내장 SSH 서버 사용
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
http_port=HTTP 포트
http_port_helper=포트 번호는 애플리케이션에서 열고 있습니다.
@@ -201,6 +201,7 @@ Content=컨텐츠
require_error=` 비어 있을 수 없습니다.`
alpha_dash_error=`은(는) 숫자, 알파벳, 대시(-_) 문자로만 구성되어야 합니다.`
alpha_dash_dot_error=` 숫자, 알파벳, 점(.), 대시(-_) 문자로만 구성되어야 합니다.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` %s 글자여야 합니다.`
min_size_error=` 최소 %s 글자여야 합니다.`
max_size_error=` %s 글자를 넘을 수 없습니다.`
@@ -426,6 +427,7 @@ pulls=풀 리퀘스트
labels=레이블
milestones=마일스톤
commits=커밋
git_branches=Branches
releases=릴리즈
file_raw=Raw
file_history=히스토리
@@ -434,6 +436,13 @@ file_permalink=고유링크
file_too_large=이 파일은 표시하기엔 너무 큽니다.
video_not_supported_in_browser=이 브라우저는 HTML5 비디오 태그를 지원하지 않습니다.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=파일 생성
editor.upload_file=파일 업로드
editor.edit_file=파일 수정
@@ -473,7 +482,7 @@ editor.add_subdir=하위 디렉토리 추가...
editor.unable_to_upload_files=파일 '%s'를 업로드하는데 실패하였습니다. 에러: %v
editor.upload_files_to_dir=파일 업로드 '%s'
commits.commit_history=Commit History
commits.commit_history=커밋 기록
commits.commits=커밋
commits.search=커밋 검색
commits.find=찾기
@@ -641,22 +650,26 @@ settings.collaboration.admin=관리자
settings.collaboration.write=쓰기
settings.collaboration.read=읽기
settings.collaboration.undefined=미정의
settings.branches=Branches
settings.default_branch=Default Branch
settings.branches=브랜치
settings.default_branch=기본 브랜치
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
settings.choose_a_branch=Choose a branch...
settings.branch_protection=Branch Protection
settings.branch_protection_desc=Please choose protect options for branch <b>%s</b>.
settings.protect_this_branch=Protect this branch
settings.protect_this_branch_desc=Disable force pushes and prevent from deletion.
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.update=업데이트
settings.update_default_branch_success=이 레포지토리의 기본 브랜치가 성공적으로 설정되었습니다!
settings.protected_branches=보호된 브랜치
settings.protected_branches_desc=보호된 브랜치는 force 푸시, 실수로 인한 코드 삭제를 방지하며 코드 커미터를 화이트리스트 합니다.
settings.choose_a_branch=브랜치를 선택하세요...
settings.branch_protection=브랜치 보호
settings.branch_protection_desc=브랜치 <b>%s</b> 의 보호 설정을 선택하세요.
settings.protect_this_branch=이 브랜치를 보호하기
settings.protect_this_branch_desc=Force 푸시와 삭제를 비활성화합니다.
settings.protect_require_pull_request=직접 push 를 하지 않고 Pull Request 를 필요로 하도록 합니다.
settings.protect_require_pull_request_desc=이 브랜치에 직접 푸시를 하는 것을 막고 싶다면 이 옵션을 활성화하세요. 커밋은 다른 비보호 브랜치에 푸시되어야 하며 이 브랜치에는 Pull Request 를 통해 병합될 것입니다.
settings.protect_whitelist_committers=이 브랜치에 푸시할 수 있는 유저
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=이 브랜치에 푸시를 할 수 있는 유저
settings.protect_whitelist_search_users=유저 검색
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git Hooks
@@ -685,6 +698,7 @@ settings.tracker_issue_style.alphanumeric=문자 숫자
settings.tracker_url_format_desc=<code>{user} {repo} {index}</code> 사용자 명, 저장소 명, 이슈 인덱스를 사용하여 표시자를 사용할 수 있습니다.
settings.pulls_desc=끌어오기 요청을 공개적으로 기여받을 수 있도록 활성화합니다.
settings.danger_zone=위험 설정
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=새로운 소유자가 같은 이름의 저장소를 이미 가지고 있습니다. 다른 이름을 선택해주세요.
settings.convert=일반 리파지토리로 변환
settings.convert_desc=이 미러를 일반 리파지토리로 변환할 수 없습니다. 반대로는 할 수 없습니다.
@@ -719,7 +733,6 @@ settings.collaborator_deletion_desc=이 사용자는 더 이상 이 저장소의
settings.remove_collaborator_success=공동작업자가 삭제 되었습니다.
settings.search_user_placeholder=사용자 검색...
settings.org_not_allowed_to_be_collaborator=조직을 공동 작업자로 추가할 수 없습니다.
settings.user_is_org_member=사용자가 조직 구성원이므로 공동 작업자로 추가할 수 없습니다.
settings.add_webhook=Webhook 추가
settings.hooks_desc=웹후크는 기본적인 HTTP POST 이벤트 트리거입니다. Gogs에서 무슨 일이 발생할 때마다, 지정한 대상 호스트에 알림을 보냅니다. <a target="_blank" href="%s">웹후크 안내서</a>에서 자세히 알아보십시오.
settings.webhook_deletion=Webhook 삭제
@@ -742,6 +755,7 @@ settings.add_webhook_desc=Gogs는 발생한 이벤트와 관련하여 지정한
settings.payload_url=페이로드 URL
settings.content_type=컨텐츠 타입
settings.secret=비밀
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=사용자 이름
settings.slack_icon_url=아이콘 URL
settings.slack_color=
@@ -751,10 +765,20 @@ settings.event_send_everything=<strong>모든 것</strong>이 필요합니다.
settings.event_choose=필요한 것을 선택해주세요.
settings.event_create=생성
settings.event_create_desc=브랜치 또는 태그를 생성합니다.
settings.event_pull_request=끌어오기 요청
settings.event_pull_request_desc=끌어오기 요청 열기, 닫기, 다시 열기, 편집, 할당, 할당 해제, 라벨 업데이트, 라벨 지우기 또는 동기화.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=푸시
settings.event_push_desc=깃 저장소로 푸시
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=끌어오기 요청
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=활성
settings.active_helper=후크를 트리거하면 이벤트에 대한 세부 정보도 전달됩니다.
settings.add_hook_success=새로운 웹훅이 생성되었습니다.
@@ -799,7 +823,6 @@ release.releases=릴리즈
release.new_release=새로운 릴리즈
release.draft=초안
release.prerelease=사전 릴리즈
release.stable=안정
release.edit=편집
release.ahead=이 릴리스 이후로 <strong>%d</strong> %s에 커밋합니다.
release.source_code=소스 코드
@@ -1015,6 +1038,7 @@ repos.private=비공개
repos.watches=지켜보기
repos.stars=Stars
repos.issues=이슈
repos.size=Size
auths.auth_manage_panel=인증 관리 패널
auths.new=새로운 소스를 추가
@@ -1172,7 +1196,8 @@ config.git_pull_timeout=끌어오기 작업 시간 제한
config.git_gc_timeout=가비지 콜렉션 작업 시간 제한
config.log_config=로그 설정
config.log_mode=로그 모드
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron 작업
monitor.name=이름
@@ -1201,19 +1226,23 @@ notices.delete_success=시스템 알림들이 성공적으로 삭제되었습니
[action]
create_repo=저장소를 만들었습니다. <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s에서</code>에서 <a href="%[2]s"> %[3]s</a>으로 저장소 이름을 바꾸었습니다.
commit_repo=<a href="%[1]s">%[4]s</a>에서 <a href="%[1]s/src/%[2]s">%[3]s</a>으로 푸시함
compare_commits=이 %d개의 커밋에 대한 비교 보기
transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송되었습니다.
create_issue=`열린 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
close_issue=`닫힌 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
reopen_issue=`다시 열린 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
comment_issue=`이슈에 댓글이 달렸습니다. <a href="%s/issues/%s"> %s #%[2]s</a>`
create_pull_request=`만들어진 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
close_pull_request=`닫힌 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
reopen_pull_request=`다시 열린 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
comment_issue=`이슈에 댓글이 달렸습니다. <a href="%s/issues/%s"> %s #%[2]s</a>`
merge_pull_request=`병합된 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송되었습니다.
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=태그 <a href="%s/src/%s">%[2]s</a>를 <a href="%[1]s">%[3]s</a>로 푸시함
compare_commits=이 %d개의 커밋에 대한 비교 보기
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=

View File

@@ -201,6 +201,7 @@ Content=Saturs
require_error=` nedrīkst būt tukšs.`
alpha_dash_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus vai domuzīmes (-_).`
alpha_dash_dot_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus, domuzīmes (-_) vai punktu.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` jābūt %s simbolus garam.`
min_size_error=` jabūt vismaz %s simbolu garumā.`
max_size_error=` jabūt ne mazāk kā %s simbolu garumā.`
@@ -426,6 +427,7 @@ pulls=Izmaiņu pieprasījumi
labels=Etiķetes
milestones=Atskaites punkti
commits=Revīzijas
git_branches=Branches
releases=Laidieni
file_raw=Neapstrādāts
file_history=Vēsture
@@ -434,6 +436,13 @@ file_permalink=Patstāvīgā saite
file_too_large=Šis fails ir par lielu, lai to parādītu
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Jauns fails
editor.upload_file=Augšupielādēt failu
editor.edit_file=Labot failu
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Tīmekļa āķi
settings.githooks=Git āķi
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Burti un cipari
settings.tracker_url_format_desc=Jūs varat izmantot <code>{user}{repo}{index}</code> lietotājvārdam, repozitorija nosaukumam un problēmas identifikātoram.
settings.pulls_desc=Iespējot izmaiņu pieprasījumus lai saņemtu publiskus ieguldījumus
settings.danger_zone=Bīstamā zona
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Jaunajam īpašniekam jau ir repozitorijs ar šādu nosaukumu.
settings.convert=Konvertēt uz parastu repozitoriju
settings.convert_desc=Šo spoguli ir iespējams konvertēt par parastu repozitoriju. Šī ir neatgriezeniska darbība.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Šim lietotājam pēc dzēšanas vairs nebū
settings.remove_collaborator_success=Līdzstrādnieks tika noņemts.
settings.search_user_placeholder=Meklēt lietotāju...
settings.org_not_allowed_to_be_collaborator=Organizāciju nav atļauts pievienot kā līdzstrādnieku.
settings.user_is_org_member=Lietotājs ir organizācijas biedrs, kas nevar tikt pievienots kā līdzstrādnieks.
settings.add_webhook=Pievienot tīmekļa āķi
settings.hooks_desc=Tīmekļa āķi ļauj paziņot ārējiem servisiem par noteiktiem notikomiem, kas notiek Git servisā. Kad iestāsies kāds notikums, katram ārējā servisa URL tiks nosūtīts POST pieprasījums. Lai uzzinātu sīkāk skatieties <a target="_blank" href="%s">Tīmekļa āķu rokasgrāmatā</a>.
settings.webhook_deletion=Dzēst tīmekļa āķi
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Uz norādīto URL tiks nosūtīts <code>POST</code> pi
settings.payload_url=Vērtuma URL
settings.content_type=Satura tips
settings.secret=Noslēpums
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Lietotājvārds
settings.slack_icon_url=Ikonas URL
settings.slack_color=Krāsa
@@ -750,10 +764,20 @@ settings.event_send_everything=Vēlos saņemt <strong>visu</strong>.
settings.event_choose=Atzīmēt, ko vēlos saņemt.
settings.event_create=Izveidot
settings.event_create_desc=Atzara vai taga izveidošana
settings.event_pull_request=Izmaiņu pieprasījums
settings.event_pull_request_desc=Atvērts, aizvērts, atkāroti atvērts, labots, piešķirts vai noņemts izmaiņu pieprasījums, vai mainīta etiķete, vai veikta sinhronizācija.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Izmaiņu nosūtīšana
settings.event_push_desc=Git izmaiņu nosūtīšana uz repozitoriju
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Izmaiņu pieprasījums
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktīvs
settings.active_helper=Tiks nosūtīti notikuma dati, kad nostrādās šis āķis.
settings.add_hook_success=Jauns tīmekļa āķis tika veiksmīgi pievienots.
@@ -798,7 +822,6 @@ release.releases=Laidieni
release.new_release=Jauns laidiens
release.draft=Melnraksts
release.prerelease=Pirmsizlaides versija
release.stable=Stabila
release.edit=labot
release.ahead=<strong>%d</strong> revīzijas atzarā %s kopš šī laidiena
release.source_code=Izejas kods
@@ -1014,6 +1037,7 @@ repos.private=Privāts
repos.watches=Vērošana
repos.stars=Atzīmētās zvaigznītes
repos.issues=Problēmas
repos.size=Size
auths.auth_manage_panel=Autentifikācijas pārvaldības panelis
auths.new=Pievienot jaunu avotu
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Izmaiņu saņemšanas darbības noilgums
config.git_gc_timeout=GC darbības noilgums
config.log_config=Žurnalizēšanas konfigurācija
config.log_mode=Žurnalizēšanas veids
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron uzdevumi
monitor.name=Nosaukums
@@ -1200,19 +1225,23 @@ notices.delete_success=Sistēmas paziņojumi tika veiksmīgi izdzēstas.
[action]
create_repo=izveidoja repozitoriju <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=pārsauca repozitoriju no <code>%[1]s</code> uz <a href="%[2]s">%[3]s</a>
commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%[1]s/src/%[2]s">%[3]s</a> repozitorijā <a href="%[1]s">%[4]s</a>
compare_commits=Salīdzināt šīs %d revīzijas
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`slēdza problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`atkārtoti atvēra problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`izveidoja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`aizvēra izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`atkārtoti atvēra izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`sapludināja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
compare_commits=Salīdzināt šīs %d revīzijas
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=atpakaļ

View File

@@ -201,6 +201,7 @@ Content=Inhoud
require_error=kan niet leeg zijn.
alpha_dash_error=moet een valide alfanumeriek of dash(-_) karakter zijn.
alpha_dash_dot_error=moet een valide alfanumeriek, dash(-_) of (.) punt karakter zijn.
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=moet groter zijn dan %s
min_size_error=moet minimaal %s karakters bevatten.
max_size_error=mag maximaal %s karakters bevatten.
@@ -426,6 +427,7 @@ pulls=Pull-aanvragen
labels=Labels
milestones=Mijlpalen
commits=Commits
git_branches=Branches
releases=Publicaties
file_raw=Ruwe
file_history=Geschiedenis
@@ -434,6 +436,13 @@ file_permalink=Permalink
file_too_large=Dit bestand is te groot om te worden getoond
video_not_supported_in_browser=Uw browser ondersteunt geen HTML5 video label.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nieuw bestand
editor.upload_file=Bestand uploaden
editor.edit_file=Bewerk bestand
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git-hooks
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanummeriek
settings.tracker_url_format_desc=U kan de aanduidingen <code>{user} {repo} {index}</code> gebruiken voor de gebruikersnaam, de naam van de repository en de lijst van open tickets.
settings.pulls_desc=Schakel 'pull request' in om publieke bijdragen te mogelijk te maken
settings.danger_zone=Gevaren zone
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=De nieuwe eigenaar heeft al een repositorie met deze naam
settings.convert=Converteren naar gewone repository
settings.convert_desc=U kunt deze mirror converteren naar een gewone repository. Dit kan niet ongedaan worden gemaakt.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Deze gebruiker zal niet langer toegang hebbe
settings.remove_collaborator_success=medewerker is verwijderd.
settings.search_user_placeholder=Zoek gebruiker...
settings.org_not_allowed_to_be_collaborator=De organisatie kan niet toegevoegd worden als medewerker.
settings.user_is_org_member=Gebruiker is lid van de organisatie die als een medewerker kan niet worden toegevoegd.
settings.add_webhook=Webhook toevoegen
settings.hooks_desc=Webhooks dat de externe diensten om kennisgevingen te ontvangen wanneer bepaalde gebeurtenissen op Gogs plaatsvinden. Wanneer de opgegeven gebeurtenissen plaatsvinden, sturen we een POST-aanvraag naar elk van de URL's die u opgeeft. Meer informatie vindt u in onze <a target="_blank" href="%s"> Webhooks gids</a>.
settings.webhook_deletion=Webhook verwijderen
@@ -741,6 +754,7 @@ settings.add_webhook_desc=We sturen een <code>POST</code>-aanvraag naar de onder
settings.payload_url=Nettolading URL
settings.content_type=Content type
settings.secret=Geheim
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Gebruikersnaam
settings.slack_icon_url=Icoon URL
settings.slack_color=Kleur
@@ -750,10 +764,20 @@ settings.event_send_everything=Ik moet <strong>alles</strong> hebben.
settings.event_choose=Laat me kiezen wat ik nodig heb.
settings.event_create=Creëer
settings.event_create_desc=Branch, of tag aangemaakt
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request geopend, gesloten, opnieuw geopend, bewerkt, toegewezen, niet-toegewezen, label bijgewerkt, label gewist of gesynchroniseerd.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push naar een repository
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Actief
settings.active_helper=We zullen details van de gebeurtenissen af leveren wanneer deze webhook wordt geactiveerd.
settings.add_hook_success=Nieuwe webhook toegevoegd.
@@ -798,7 +822,6 @@ release.releases=Releases
release.new_release=Nieuwe release
release.draft=Concept
release.prerelease=Voorlopige versie
release.stable=Stabiel
release.edit=bewerken
release.ahead=<strong>%d</strong> aanpassingen aan %s sinds deze versie
release.source_code=Broncode
@@ -1014,6 +1037,7 @@ repos.private=Prive
repos.watches=Volgers
repos.stars=Sterren
repos.issues=Kwesties
repos.size=Size
auths.auth_manage_panel=Authenticatie-beheer paneel
auths.new=Nieuwe bron toevoegen
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Logconfiguratie
config.log_mode=Log-modus
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron-taken
monitor.name=Naam
@@ -1200,19 +1225,23 @@ notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=repositorie aangemaakt in <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=hernoemde repository van <code>%[1]s</code> naar <a href="%[2]s">%[3]s</a>
commit_repo=push update naar <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
compare_commits=Toon vergelijking voor deze %d commits
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
create_issue=`opende issue in <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`sloot kwestie <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`heropende kwestie <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`maakte pull request <a href="%s/issues/%s">%s#%[2]s</a>`
close_pull_request=`sloot pull request <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_pull_request=`heropende pull request <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`voegde pull request samen <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
compare_commits=Toon vergelijking voor deze %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=geleden

View File

@@ -201,6 +201,7 @@ Content=Treść
require_error=` nie może być puste.`
alpha_dash_error=` musi się składać z prawidłowych znaków alfanumerycznych, myślników oraz podkreśleń.`
alpha_dash_dot_error=` musi się składać z prawidłowych znaków alfanumerycznych, myślników, podkreśleń oraz kropek.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` musi być wielkości %s.`
min_size_error=` musi zawierać co najwyżej %s znaków.`
max_size_error=` musi zawierać co najwyżej %s znaków.`
@@ -426,6 +427,7 @@ pulls=Oczekujące zmiany
labels=Etykiety
milestones=Kamienie milowe
commits=Commity
git_branches=Branches
releases=Wydania
file_raw=Czysty
file_history=Historia
@@ -434,6 +436,13 @@ file_permalink=Bezpośredni odnośnik
file_too_large=Ten plik jest zbyt duży, aby go wyświetlić
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nowy plik
editor.upload_file=Załaduj plik
editor.edit_file=Edytuj plik
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooki
settings.githooks=Hooki Git
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumeryczne
settings.tracker_url_format_desc=Symbole zastępcze <code>{user} {repo} {index}</code> mogą być użyte dla nazwy użytkownika, nazwy repozytorium i numeru problemu.
settings.pulls_desc=Włącz obsługę pull request, aby akceptować publiczny wkład
settings.danger_zone=Strefa niebezpieczeństwa
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Nowy właściciel już posiada repozytorium o tej samej nazwie.
settings.convert=Konwersja na repozytorium regularne
settings.convert_desc=Możesz przekonwertować ten mirror na repozytorium regularne. Ta czynność nie może być odwrócona.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Ten użytkownik nie będzie miał dostępu w
settings.remove_collaborator_success=Współpracownik został usunięty.
settings.search_user_placeholder=Szukaj użytkownika...
settings.org_not_allowed_to_be_collaborator=Organizacji nie można dodać jako współpracownika.
settings.user_is_org_member=Użytkownik jest członkiem organizacji, który nie może być dodany jako współpracownik.
settings.add_webhook=Dodaj webhooka
settings.hooks_desc=Webooki działają tak jak proste wywołania HTTP POST. Jeśli cokolwiek zdarzy się w Gogs, wyślemy powiadomienie do wybranego hosta. Więcej informacji można znaleźć w <a target="_blank" href="%s">przewodniku webhooków</a>.
settings.webhook_deletion=Usuń webhooka
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Wyślemy żądanie <code>POST</code> pod poniższy adr
settings.payload_url=URL do wywołania
settings.content_type=Typ zawartości
settings.secret=Sekret
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Użytkownik
settings.slack_icon_url=Adres URL ikony
settings.slack_color=Kolor
@@ -750,10 +764,20 @@ settings.event_send_everything=Potrzebuję <strong>wszystkiego</strong>.
settings.event_choose=Pozwól mi wybrać, czego potrzebuję.
settings.event_create=Utwórz
settings.event_create_desc=Utworzono gałąź lub tag
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Otworzono żądanie pull, zamknięto, otwarto ponownie, zaktualizowano, przypisano, nieprzypisano, zaktualizowano etykietę, wyczyszczono etykietę lub zsynchronizowano.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Wypchnięcie
settings.event_push_desc=Wypchnięcie (push) do repozytorium Git
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktywny
settings.active_helper=Dostarczymy szczegóły zdarzenia, gdy ten webhook zostanie wywołany.
settings.add_hook_success=Nowy webhook został dodany.
@@ -798,7 +822,6 @@ release.releases=Wydania
release.new_release=Nowe wydanie
release.draft=Szkic
release.prerelease=Wersja wstępna
release.stable=Stabilny
release.edit=edytuj
release.ahead=<strong>%d</strong> commitów w %s od tego wydania
release.source_code=Kod źródłowy
@@ -1014,6 +1037,7 @@ repos.private=Prywatne
repos.watches=Obserwujących
repos.stars=Polubienia
repos.issues=Problemy
repos.size=Size
auths.auth_manage_panel=Panel zarządzania uwierzytelnianiem
auths.new=Dodaj nowe źródło
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Limit czasu dla operacji pull
config.git_gc_timeout=Limit czasu odśmiecania pamięci
config.log_config=Konfiguracja dziennika
config.log_mode=Tryb dziennika
config.log_mode=Mode
config.log_options=Options
monitor.cron=Zadania cron
monitor.name=Nazwa
@@ -1200,19 +1225,23 @@ notices.delete_success=Powiadomienia systemowe zostały pomyślnie usunięte.
[action]
create_repo=tworzy repozytorium <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=zmienia nazwę repozytorium <code>%[1]s</code> na <a href="%[2]s">%[3]s</a>
commit_repo=wypycha do <a href="%[1]s/src/%[2]s">%[3]s</a> w <a href="%[1]s">%[4]s</a>
compare_commits=Zobacz porównanie tych %d commitów
transfer_repo=przenosi repozytorium <code>%s</code> do <a href="%s">%s</a>
create_issue=`zgłasza problem <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`zamknięcie problemu <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`ponowne otwarcie problemu <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`komentuje problem <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`tworzy pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`zamknięcie pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`ponowne otwarcie pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`komentuje problem <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`scala pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=przenosi repozytorium <code>%s</code> do <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=taguje <a href="%s/src/%s">%[2]s</a> w <a href="%[1]s">%[3]s</a>
compare_commits=Zobacz porównanie tych %d commitów
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=temu

View File

@@ -201,6 +201,7 @@ Content=Conteúdo
require_error=` não pode estar vazio.`
alpha_dash_error=` devem ser caracteres alfanuméricos, hífen (-) ou sublinhado (_).`
alpha_dash_dot_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=`deve ser do tamanho %s.`
min_size_error=` deve conter pelo menos %s caracteres.`
max_size_error=` deve conter no máximo %s caracteres.`
@@ -426,6 +427,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Milestones
commits=Commits
git_branches=Branches
releases=Versões
file_raw=Raw
file_history=Histórico
@@ -434,6 +436,13 @@ file_permalink=Link permanente
file_too_large=Este arquivo é muito grande para ser exibido
video_not_supported_in_browser=Seu navegador não suporta a tag de vídeo do HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Novo arquivo
editor.upload_file=Enviar arquivo
editor.edit_file=Editar arquivo
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Hooks do Git
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumérico
settings.tracker_url_format_desc=Você pode usar o espaço reservado <code>{user} {repo} {index}</code> para o nome do usuário, índice de nome e a questão do repositório.
settings.pulls_desc=Habilitar Pull Requests para aceitar contribuições públicas
settings.danger_zone=Zona de perigo
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=O novo dono já tem um repositório com o mesmo nome. Por favor, escolha outro nome.
settings.convert=Converter para repositório tradicional
settings.convert_desc=Você pode converter este espelho em um repositório tradicional. Esta ação não pode ser revertida.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Este usuário não terá mais acesso de cola
settings.remove_collaborator_success=O colaborador foi removido.
settings.search_user_placeholder=Pesquisar usuário...
settings.org_not_allowed_to_be_collaborator=Organização não tem permissão para ser adicionada como um colaborador.
settings.user_is_org_member=O usuário é um membro da organização que não pode ser adicionado como um colaborador.
settings.add_webhook=Adicionar Webhook
settings.hooks_desc=Hooks da web ou Webhooks permitem serviços externos serem notificados quando certos eventos acontecem no Gogs. Quando acontecem os eventos especificados, enviaremos uma solicitação POST para cada uma das URLs que você fornecer. Saiba mais no nosso <a target="_blank" href="%s"> Guia de Webhooks</a>.
settings.webhook_deletion=Deletar Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Enviaremos uma solicitação <code>POST</code> para o
settings.payload_url=URL de Payload
settings.content_type=Tipo de conteúdo
settings.secret=Secreto
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Nome de usuário
settings.slack_icon_url=URL do ícone
settings.slack_color=Cor
@@ -750,10 +764,20 @@ settings.event_send_everything=Preciso de <strong>tudo</strong>.
settings.event_choose=Deixe-me escolher o que eu preciso.
settings.event_create=Criar
settings.event_create_desc=Branch ou Tag criado
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request aberto, fechado, reaberto, atribuído, desatribuído, teve etiqueta atualizada ou limpada ou foi sincronizado.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push para o repositório
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Ativo
settings.active_helper=Enviaremos detalhes do evento quando este hook for acionado.
settings.add_hook_success=Novos hooks de web foram adicionados.
@@ -798,7 +822,6 @@ release.releases=Versões
release.new_release=Nova versão
release.draft=Rascunho
release.prerelease=Versão prévia
release.stable=Estável
release.edit=editar
release.ahead=<strong>%d</strong> commits para %s depois desta versão
release.source_code=Código fonte
@@ -1014,6 +1037,7 @@ repos.private=Privado
repos.watches=Observadores
repos.stars=Favoritos
repos.issues=Issues
repos.size=Size
auths.auth_manage_panel=Painel de gerenciamento da autenticação
auths.new=Adicionar nova fonte
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Timeout para operação de pull
config.git_gc_timeout=Timeout para execução do GC
config.log_config=Configuração de log
config.log_mode=Modo do log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tarefas cron
monitor.name=Nome
@@ -1200,19 +1225,23 @@ notices.delete_success=Avisos do sistema foram excluídos com sucesso.
[action]
create_repo=repositório criado <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=renomeou o o repositório <code>%[1]s</code> para <a href="%[2]s">%[3]s</a>
commit_repo=pushed para <a href="%[1]s/src/%[2]s">%[3]s</a> em <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparação entre esses %d commits
transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a>
create_issue=`questão aberta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`questão fechada <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`questão reaberta <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`criou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`fechou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabriu o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`mesclou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=Foi feito push na tag <a href="%s/src/%s">%[2]s</a> para <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparação entre esses %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=atrás

View File

@@ -48,7 +48,7 @@ cancel=Отмена
install=Установка
title=Установочные шаги для первого запуска
docker_helper=Если вы запускаете Gogs внутри Docker, пожалуйста прочтите <a target="_blank" href="%s">эти советы</a> внимательно перед тем как что-либо изменить на этой странице!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs требует наличия MySQL, PostgreSQL, SQLite3, MSSQL или TiDB.
db_title=Настройки базы данных
db_type=Тип базы данных
host=Хост
@@ -58,8 +58,8 @@ db_name=Имя базы данных
db_helper=Для MySQL используйте тип таблиц InnoDB с кодировкой utf8_general_ci.
ssl_mode=Режим SSL
path=Путь
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=Путь к файлу базы данный SQLite3. <br>Пожалуйста, используйте абсолютный путь если Gogs запускается как сервис.
err_empty_db_path=Путь к файлу базы данных SQLite3 не может быть пустым.
no_admin_and_disable_registration=Вы не можете отключить регистрацию до создания учетной записи администратора.
err_empty_admin_password=Пароль администратора не может быть пустым.
@@ -74,8 +74,8 @@ domain=Домен
domain_helper=Влияет на URL-адреса для клонирования по SSH.
ssh_port=SSH порт
ssh_port_helper=Номер порта, который использует SSH сервер. Оставьте пустым, чтобы отключить SSH.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
use_builtin_ssh_server=Использовать встроенный SSH сервер
use_builtin_ssh_server_popup=Запустить встроенный SSH сервер для различения операций Git и системного демона SSH.
http_port=Порт HTTP
http_port_helper=Номер порта, который приложение будет слушать.
app_url=URL приложения
@@ -117,7 +117,7 @@ sqlite3_not_available=Ваша версия не поддерживает SQLite
invalid_db_setting=Настройки базы данных не правильные: %v
invalid_repo_path=Недопустимый путь к корню репозитория: %v
run_user_not_match=Текущий пользователь не является пользователем для запуска: %s -> %s
invalid_smtp_from=SMTP From field is not valid: %v
invalid_smtp_from=Поле SMTP From неправильное: %v
save_config_failed=Не удалось сохранить конфигурацию: %v
invalid_admin_setting=Указан недопустимый параметр учетной записи администратора: %v
install_success=Добро пожаловать! Мы рады, что вы выбрали Gogs. Веселитесь и берегите себя.
@@ -201,6 +201,7 @@ Content=Содержимое
require_error=` не может быть пустым.`
alpha_dash_error=«должен быть допустимым символьным, числовым или dash(-_) значением.»
alpha_dash_dot_error=«должен быть допустимым символьным, числовым или dash(-_) символами, включая точку.»
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` должен быть размер %s.`
min_size_error=«должен содержать по крайней мере %s символов.»
max_size_error=` должен содержать максимум %s символов.`
@@ -391,7 +392,7 @@ migrate_type_helper=Этот репозиторий будет <span class="text
migrate_repo=Перенос репозитория
migrate.clone_address=Скопировать адрес
migrate.clone_address_desc=Это может быть HTTP/HTTPS/GIT URL-адрес.
migrate.clone_address_desc_import_local=You're also allowed to migrate a repository by local server path.
migrate.clone_address_desc_import_local=Вы также можете мигрировать репозиторий по локальному пути на сервере.
migrate.permission_denied=У вас нет прав на импорт локальных репозиториев.
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
migrate.failed=Миграция не удалась: %v
@@ -426,6 +427,7 @@ pulls=Запросы на слияние
labels=Метки
milestones=Этапы
commits=Коммиты
git_branches=Branches
releases=Релизы
file_raw=Исходник
file_history=История
@@ -434,6 +436,13 @@ file_permalink=Постоянная ссылка
file_too_large=Этот файл слишком большой, поэтому он не может быть отображен
video_not_supported_in_browser=Ваш браузер не поддерживает HTML5 видео тэг.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Новый файл
editor.upload_file=Загрузить файл
editor.edit_file=Редактировать файл
@@ -473,7 +482,7 @@ editor.add_subdir=Добавьте подкаталог...
editor.unable_to_upload_files=Не удалось загрузить файлы в «%s» из-за ошибки: %v
editor.upload_files_to_dir=Загрузить файлы '%s'
commits.commit_history=Commit History
commits.commit_history=История коммитов
commits.commits=Коммиты
commits.search=Поиск коммитов
commits.find=Найти
@@ -531,7 +540,7 @@ issues.next=Следующая страница
issues.open_title=Открыто
issues.closed_title=Закрыто
issues.num_comments=комментариев: %d
issues.commented_at=«прокомментировал <a href="#%s"> %s</a>»
issues.commented_at=`прокомментировал <a href="#%s"> %s</a>`
issues.delete_comment_confirm=Вы уверены, что хотите удалить этот комментарий?
issues.no_content=Пока нет содержимого.
issues.close_issue=Закрыть
@@ -640,23 +649,27 @@ settings.collaboration.admin=Администратор
settings.collaboration.write=Запись
settings.collaboration.read=Просмотр
settings.collaboration.undefined=Не определено
settings.branches=Branches
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
settings.choose_a_branch=Choose a branch...
settings.branch_protection=Branch Protection
settings.branch_protection_desc=Please choose protect options for branch <b>%s</b>.
settings.protect_this_branch=Protect this branch
settings.protect_this_branch_desc=Disable force pushes and prevent from deletion.
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.branches=Ветки
settings.default_branch=Ветка по умолчанию
settings.default_branch_desc=Ветка по-умолчанию считается основной для коммитов, запросов на слияние и онлайн-редактирования.
settings.update=Обновить
settings.update_default_branch_success=Ветка по умолчанию для этого репозитория была успешно изменена!
settings.protected_branches=Защищенные ветки
settings.protected_branches_desc=Защитить ветки от принудительного push, случайного удаления и разрешить изменения только коммитерам из белого списка.
settings.choose_a_branch=Выберите ветку...
settings.branch_protection=Защита веток
settings.branch_protection_desc=Пожалуйста, выберите параметры защиты для ветки <b>%s</b>.
settings.protect_this_branch=Защитить эту ветку
settings.protect_this_branch_desc=Выключить принудительный push и защитить от удаления.
settings.protect_require_pull_request=Требовать запрос на слияние вместо прямого push
settings.protect_require_pull_request_desc=Включите этот параметр для запрета прямого push в это ветку. Коммит должен быть запушен в незащищенную ветку и слит в эту ветку через запрос на слияние.
settings.protect_whitelist_committers=Белый список тех, кто может делать push в эту ветку
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Пользователи которые могут делать push в эту ветку
settings.protect_whitelist_search_users=Поиск пользователей
settings.protect_whitelist_teams=Команды, члены которых могут делать push в эту ветку
settings.protect_whitelist_search_teams=Поиск команд
settings.update_protect_branch_success=Параметры защиты этой ветки были успешно обновлены!
settings.hooks=Автоматическое обновление
settings.githooks=Git хуки
settings.basic_settings=Основные параметры
@@ -675,8 +688,8 @@ settings.external_wiki_url_desc=Посетители будут перенапр
settings.issues_desc=Включить систему отслеживания ошибок
settings.use_internal_issue_tracker=Использовать встроенную легковесную систему отслеживания ошибок
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.external_tracker_url=URL внешней системы отслеживания ошибок
settings.external_tracker_url_desc=Посетители будут перенаправлены на URL когда они нажмут на вкладку.
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
settings.tracker_issue_style=Стиль Именования Внешней Системы Учета Задач:
settings.tracker_issue_style.numeric=Цифровой
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Буквенноцифровой
settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера задачи.
settings.pulls_desc=Включить публичные запросы на слияние
settings.danger_zone=Опасная зона
settings.cannot_fork_to_same_owner=Вы не можете ответвить репозиторий его же владельцу.
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
settings.convert=Преобразовать в обычный репозиторий
settings.convert_desc=Это зеркало можно преобразовать в обычный репозиторий. Это не может быть отменено.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Этот пользователь больш
settings.remove_collaborator_success=Соавтор был удален.
settings.search_user_placeholder=Поиск пользователя...
settings.org_not_allowed_to_be_collaborator=Организации не могут быть добавлены как соавторы.
settings.user_is_org_member=Пользователь является членом организации, члены которой не могут быть добавлены в качестве соавтора.
settings.add_webhook=Добавить Webhook
settings.hooks_desc=Webhooks позволяют внешним службам получать уведомления при возникновении определенных событий на Gogs. При возникновении указанных событий мы отправим запрос POST на каждый заданный вами URL. Узнать больше можно в нашем <a target="_blank" href="%s">Руководстве по Webhooks</a>.
settings.webhook_deletion=Удалить веб-хук
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Мы отправим запрос <code>POST</code>
settings.payload_url=URL обработчика
settings.content_type=Тип содержимого
settings.secret=Secret
settings.secret_desc=Секрет будет отправлен как SHA256 HMAC контента в шестнадцатеричном виде в заголовке <code>X-Gogs-Signature</code>.
settings.slack_username=Имя пользователя
settings.slack_icon_url=URL иконки
settings.slack_color=Цвет
@@ -750,10 +764,20 @@ settings.event_send_everything=Мне нужно <strong>все</strong>.
settings.event_choose=Позвольте мне выбрать то, что нужно.
settings.event_create=Создать
settings.event_create_desc=Ветка или тэг созданы
settings.event_pull_request=Запросы на слияние
settings.event_pull_request_desc=Запрос слияния открыт, закрыт, переоткрыт, изменён, назначен, снят, метка обновлена, метка убрана, или синхронизирован.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Push в репозиторий
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Запросы на слияние
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Активен
settings.active_helper=Подробности о событии, вызвавшем срабатывание хука, также будут предоставлены.
settings.add_hook_success=Был добавлен новый webhook.
@@ -763,12 +787,12 @@ settings.delete_webhook=Удалить автоматическое обновл
settings.recent_deliveries=Недавние рассылки
settings.hook_type=Тип перехватчика
settings.add_slack_hook_desc=Добавить интеграцию с <a href="%s">Slack</a> в ваш репозиторий.
settings.add_discord_hook_desc=Add <a href="%s">Discord</a> integration to your repository.
settings.add_discord_hook_desc=Добавить интеграцию с <a href="%s">Discord</a> в ваш репозиторий.
settings.slack_token=Token
settings.slack_domain=Домен
settings.slack_channel=Канал
settings.deploy_keys=Ключи развертывания
settings.deploy_keys_helper=<b>Common Gotcha!</b> If you're looking for adding personal public keys, please add them in your <a href="%s%s">account settings</a>.
settings.deploy_keys_helper=<b>Common Gotcha!</b> Если вы ищите куда добавить персональные публичные ключи, добавьте их в <a href="%s%s">настройках вашего аккаунта</a>.
settings.add_deploy_key=Добавить ключ развертывания
settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта.
settings.no_deploy_keys=Вы не добавляли ключи развертывания.
@@ -798,7 +822,6 @@ release.releases=Релизы
release.new_release=Новый релиз
release.draft=Черновик
release.prerelease=Пре-релиз
release.stable=Стабильный
release.edit=Редактировать
release.ahead=<strong>%d</strong> коммитов %s начиная с этого релиза
release.source_code=Исходный код
@@ -847,7 +870,7 @@ team_permission_desc=Какой уровень разрешений должен
form.name_reserved=Наименование организации '%s' зарезервированно.
form.name_pattern_not_allowed=Шаблон организации '%s' не допускается.
form.team_name_reserved=Team name '%s' is reserved.
form.team_name_reserved=Имя команды '%s' зарезервировано.
settings=Настройки
settings.options=Опции
@@ -938,8 +961,8 @@ dashboard.git_gc_repos=Выполнить сборку мусора на реп
dashboard.git_gc_repos_success=Сборка мусора на всех репозиториях успешно выполнена.
dashboard.resync_all_sshkeys=Переписать файл «.ssh/authorized_keys» (осторожно: не Gogs ключи будут утеряны)
dashboard.resync_all_sshkeys_success=Были успешно переписаны все открытые ключи.
dashboard.resync_all_hooks=Resync pre-receive, update and post-receive hooks of all repositories
dashboard.resync_all_hooks_success=All repositories' pre-receive, update and post-receive hooks have been resynced successfully.
dashboard.resync_all_hooks=Повторная синхронизация хуков pre-receive, update и post-receive во всех репозиториях
dashboard.resync_all_hooks_success=Все хуки pre-receive, update и post-receive во всех репозиториях были успешно повторно синхронизированы.
dashboard.reinit_missing_repos=Реинициализировать все репозитории с утерянными Git файлами
dashboard.reinit_missing_repos_success=Все репозитории с утерянными Git файлами успешно реинициализированы.
@@ -1014,6 +1037,7 @@ repos.private=Приватный
repos.watches=Следят
repos.stars=В избранном
repos.issues=Задачи
repos.size=Size
auths.auth_manage_panel=Панель управления аутнентификациями
auths.new=Добавить новый источник
@@ -1072,7 +1096,7 @@ config.offline_mode=Автономный режим
config.disable_router_log=Отключение журнала маршрутизатора
config.run_user=Запуск пользователем
config.run_mode=Режим выполнения
config.git_version=Git Version
config.git_version=Версия Git
config.static_file_root_path=Статичный путь до файла
config.log_file_root_path=Путь до папки с логами
config.reverse_auth_user=Заголовок с именем пользователя для авторизации на reverse proxy
@@ -1089,15 +1113,15 @@ config.ssh_keygen_path=Путь к генератору ключей ('ssh-keyge
config.ssh_minimum_key_size_check=Минимальный размер ключа проверки
config.ssh_minimum_key_sizes=Минимальные размеры ключа
config.repo_config=Repository Configuration
config.repo_config=Настройка репозитория
config.repo_root_path=Путь до корня репозитория
config.script_type=Тип сценария
config.repo_force_private=Force Private
config.max_creation_limit=Max Creation Limit
config.preferred_licenses=Preferred Licenses
config.disable_http_git=Disable HTTP Git
config.enable_local_path_migration=Enable Local Path Migration
config.commits_fetch_concurrency=Commits Fetch Concurrency
config.repo_force_private=Сделать личным принудительно
config.max_creation_limit=Лимит созданий
config.preferred_licenses=Предпочитаемые лицензии
config.disable_http_git=Выключить HTTP Git
config.enable_local_path_migration=Включить миграцию с локального пути
config.commits_fetch_concurrency=Параллельность получения коммитов
config.db_config=Конфигурация базы данных
config.db_type=Тип
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Время Ожидания Операции Извле
config.git_gc_timeout=Время Ожидания Операции Сборки Мусора
config.log_config=Конфигурация журнала
config.log_mode=Режим журналирования
config.log_mode=Mode
config.log_options=Options
monitor.cron=Задачи cron
monitor.name=Имя
@@ -1200,19 +1225,23 @@ notices.delete_success=Системное уведомление успешно
[action]
create_repo=создал(а) репозиторий <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=переименовал(а) репозиторий из <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=запушил(а) <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
compare_commits=Просмотр сравнение для этих %d коммитов
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
create_issue=`открыл(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`закрыл(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`возобновил(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`прокомментировал(а) вопрос <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`создал запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`закрыл запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`открыл снова запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`прокомментировал(а) вопрос <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`слил пул реквест <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=запушил(а) метку <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
compare_commits=Просмотр сравнение для этих %d коммитов
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=назад

View File

@@ -201,6 +201,7 @@ Content=Садржај
require_error=` не може бити празно.`
alpha_dash_error=` мора се састојати словима, бројевима или dash(-_) карактера.`
alpha_dash_dot_error=` мора се састојати словима, бројевима, dash(-_) карактера, или тачком.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` мора бити величине %s.`
min_size_error=` мора да садржи најмање %s карактера.`
max_size_error=` мора да садржи највише %s карактера.`
@@ -426,6 +427,7 @@ pulls=Захтеви за спајање
labels=Лабеле
milestones=Фазе
commits=Комити
git_branches=Branches
releases=Издања
file_raw=Датотека
file_history=Историја
@@ -434,6 +436,13 @@ file_permalink=Пермалинк
file_too_large=Ова датотека је превише веика да би се приказала
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Нова датотека
editor.upload_file=Отпреми датотеку
editor.edit_file=Ажурирај датотеку
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git хуки
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Алфанумерично
settings.tracker_url_format_desc=Можете да користите шаблон <code>{user} {repo} {index}</code> за корисничко име, спремишта и задатака.
settings.pulls_desc=Омогући систем захтева за спајање да би сте преузели јавних доприноса
settings.danger_zone=Опасна зона
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Нови власник већ има спремиште по истим називом. Молимо вас изаберите друго име.
settings.convert=Претворити у обично спремиште
settings.convert_desc=Можете претворити огледало у обично спремиште, али та операција не може се укинути.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Овај корисник неће имат
settings.remove_collaborator_success=Сарадник је уклоњен.
settings.search_user_placeholder=Претрага корисника...
settings.org_not_allowed_to_be_collaborator=Неможе се додати организација као сарадник.
settings.user_is_org_member=Корисник је члан организације и потом неможе бити додат као сарадник.
settings.add_webhook=Додај Webhook
settings.hooks_desc=Webhooks омогућавају спољашњим услугама да приме обавештења када се нешто одређено догоди на Gogs. Сазнајте више у овом <a target="_blank" href="%s">водичу за Webhooks</a>.
settings.webhook_deletion=Уклони Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Послаћемо захтев <code>POST</code> на
settings.payload_url=URL адреса за слање
settings.content_type=Тип садржаја
settings.secret=Тајна
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Корисничко име
settings.slack_icon_url=URL адреса иконице
settings.slack_color=Боја
@@ -750,10 +764,20 @@ settings.event_send_everything=У <strong>свим</strong> догађајима
settings.event_choose=Изабраћу шта ми је потребно.
settings.event_create=Креирај
settings.event_create_desc=Створена грана или ознака
settings.event_pull_request=Захтев за спајање
settings.event_pull_request_desc=Захтев за спајање отворенo, затворено, додељено, недодељенo, лабела ажурирана, лабела избрисана, или синхронизовано.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push у спремиште
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Захтев за спајање
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Активно
settings.active_helper=Детаљи о догађају што је проузроковало hook ће исто бити испоручено.
settings.add_hook_success=Додат је нови webhook.
@@ -798,7 +822,6 @@ release.releases=Издања
release.new_release=Ново издање
release.draft=Нацрт
release.prerelease=Пред-верзија
release.stable=Стабилно
release.edit=уреди
release.ahead=<strong>%d</strong> комита на %s почев од овог издања
release.source_code=Изворни код
@@ -1014,6 +1037,7 @@ repos.private=Приватно
repos.watches=Watches
repos.stars=Фаворити
repos.issues=Задаци
repos.size=Size
auths.auth_manage_panel=Контролна панела аутентикације
auths.new=Додај нови извор
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Време до отказивања pull операци
config.git_gc_timeout=Време до отказивања cакупљање смећа
config.log_config=Kонфигурација журнала
config.log_mode=Режим журналовања
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron задаци
monitor.name=Име
@@ -1200,19 +1225,23 @@ notices.delete_success=Системска обавештавања су успе
[action]
create_repo=креира спремиште <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=преимензје спремиште од <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=извршује push на <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
compare_commits=Поређење ових %d комита
transfer_repo=преноси спремиште <code>%s</code> на <a href="%s">%s</a>
create_issue=`отвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`затвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`поново отвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`коментарише на задатаку <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`шаље захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`затвара захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`поново отвара захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментарише на задатаку <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`прихваћује захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=преноси спремиште <code>%s</code> на <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=извршује push са ознаком <a href="%s/src/%s">%[2]s</a> на <a href="%[1]s">%[3]s</a>
compare_commits=Поређење ових %d комита
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=пре

View File

@@ -201,6 +201,7 @@ Content=Innehåll
require_error=får inte vara tomt
alpha_dash_error=` får bara innehålla bokstäver, nummer och bindestreck (-_).`
alpha_dash_dot_error=` får bara innehålla bokstäver, nummer, bindestreck (-_) och punkt`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` måste vara av storleken %s`
min_size_error=` måste innehålla minst %s tecken.`
max_size_error=` får inte innehålla mer än %s tecken.`
@@ -426,6 +427,7 @@ pulls=Pull-förfrågningar
labels=Etiketter
milestones=Milstenar
commits=Incheckningar
git_branches=Branches
releases=Släpp
file_raw=
file_history=Historik
@@ -434,6 +436,13 @@ file_permalink=Permalänk
file_too_large=Denna fil är för stor för att visas
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Ny fil
editor.upload_file=Ladda upp fil
editor.edit_file=Redigera fil
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webbhookar
settings.githooks=Githookar
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumerisk
settings.tracker_url_format_desc=Du kan använda platshållaren <code>{user} {repo} {index}</code> för användarnamn, reponamn, och ärendenummer.
settings.pulls_desc=Aktivera pullförfrågningar för att ta emot publika bidrag
settings.danger_zone=Högrisksområde
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Den nya ägaren har redan ett repo med det namnet. Vänligen välj ett annat namn.
settings.convert=Konvertera Till Vanligt Repo
settings.convert_desc=Du kan konvertera denna spegling till ett vanligt förråd. Detta kan inte ångras.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Denna användare kommer förlora sin åtkoms
settings.remove_collaborator_success=Deltagare har tagits bort.
settings.search_user_placeholder=Sök användare...
settings.org_not_allowed_to_be_collaborator=Organisationen kan inte läggas till som en deltagare.
settings.user_is_org_member=Änvändaren är en organisationsmedlem som inte kan bli tillagd som deltagare.
settings.add_webhook=Lägg Till Webbhook
settings.hooks_desc=Webbhookar påminner mycket om vanliga HTTP POST-händelseutlösare. När något inträffar i Gogs, kommer vi att meddela måldatorn som du anger. Läs mera i <a target="_blank" href="%s">Webbhook Guide</a>.
settings.webhook_deletion=Ta Bort Webbhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs kommer skicka <code>POST</code>-anrop till webbad
settings.payload_url=Adress till innehåll
settings.content_type=Typ av innehåll
settings.secret=Hemlighet
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Användarnamn
settings.slack_icon_url=URL för ikon
settings.slack_color=Färg
@@ -750,10 +764,20 @@ settings.event_send_everything=Jag behöver <strong>allt</strong>.
settings.event_choose=Låt mig välja.
settings.event_create=Skapa
settings.event_create_desc=Branch eller tagg skapad
settings.event_pull_request=Hämtningsbegäran
settings.event_pull_request_desc=Hämtningsbegäran öppnad, stängd, återöppnad, redigerad, tilldelad, otilldelad, etikett uppdaterad, etikett rensad eller synkroniserad.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Pusha
settings.event_push_desc=Uppladdning till ett förråd
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Hämtningsbegäran
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktiv
settings.active_helper=Detaljer kring händelsen som triggade kroken kommer också levereras.
settings.add_hook_success=Ny webbkrok har lagts till.
@@ -798,7 +822,6 @@ release.releases=Släpp
release.new_release=Nytt Släpp
release.draft=Utkast
release.prerelease=Försläpp
release.stable=Stabil
release.edit=redigera
release.ahead=<strong>%d</strong> ändringar mot %s sedan detta släpp
release.source_code=Källkod
@@ -1014,6 +1037,7 @@ repos.private=Privat
repos.watches=Vakter
repos.stars=Stjärnor
repos.issues=Ärenden
repos.size=Size
auths.auth_manage_panel=Panel för hantering av autentisering
auths.new=Lägg till ny källa
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Logg-konfiguration
config.log_mode=Loggningsläge
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron-jobb
monitor.name=Namn
@@ -1200,19 +1225,23 @@ notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=skapade utvecklingskatalog <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
commit_repo=pushed to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
compare_commits=View comparison for these %d commits
transfer_repo=transfered repository <code>%s</code> to <a href="%s">%s</a>
create_issue=`opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transfered repository <code>%s</code> to <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_commits=View comparison for these %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=sedan

View File

@@ -201,6 +201,7 @@ Content=Content
require_error=` boş olamaz.`
alpha_dash_error=` sadece karakter, rakam veya çizgi(-_) içermelidir.`
alpha_dash_dot_error=` sadece karakter, rakam, çizgi(-_) veya nokta içermelidir.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` uzunluk en fazla %s olmalıdır.`
min_size_error=` en az %s karakter içermelidir.`
max_size_error=` en fazla %s karakter içermelidir.`
@@ -426,6 +427,7 @@ pulls=Değişiklik İstekleri
labels=Etiketler
milestones=Kilometre Taşları
commits=İşlemeler
git_branches=Branches
releases=Sürümler
file_raw=Ham
file_history=Geçmiş
@@ -434,6 +436,13 @@ file_permalink=Kalıcı Bağlantı
file_too_large=Bu dosya sergilenmek için çok büyük
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=Dosya düzenle
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Web İstekleri
settings.githooks=Git İstekleri
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alfanumerik
settings.tracker_url_format_desc=Kullanıcı adı, depo ismi ve hata indeksi için <code>{kullanıcı} {depo} {indeks}</code> tutucusunu kullanabilirsiniz.
settings.pulls_desc=Herkese açık katkıları kabul etmek için değişiklik isteklerini etkinleştirin
settings.danger_zone=Tehlike Alanı
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=Yeni sahibin aynı isimde başka bir deposu var. Lütfen farklı bir isim seçin.
settings.convert=Düzenli Depoya Dönüştür
settings.convert_desc=Bu yansıyı düzenli bir depoya dönüştürebilirsiniz. Bu işlem geri alınamaz.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Kullanıcı, silme işleminden sonra bu depo
settings.remove_collaborator_success=Katkıcı silindi.
settings.search_user_placeholder=Kullanıcı ara...
settings.org_not_allowed_to_be_collaborator=Organizasyon, bir katkıcı olarak eklenemez.
settings.user_is_org_member=Kullanıcı organizasyon üyesi olduğu için katkıcı olarak eklenemez.
settings.add_webhook=Web İsteği Ekle
settings.hooks_desc=Web istekleri, HTTP POST olay tetikleyicileri gibidirler. Gogs'ta ne zaman bir şey olsa, hedef belirttiğiniz sunuculara bildirim yapabilecek duruma geliriz. Daha fazla bilgiyi <a target="_blank" href="%s">Web İstekleri Kılavuzu</a>'nda bulabilirsiniz.
settings.webhook_deletion=Web İsteğini Sil
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs, meydana gelen olay ile birlikte belirttiğiniz b
settings.payload_url=Yük Bağlantısı
settings.content_type=İçerik Türü
settings.secret=Gizli
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=Kullanıcı Adı
settings.slack_icon_url=Simge Bağlantısı
settings.slack_color=Renk
@@ -750,10 +764,20 @@ settings.event_send_everything=<strong>Her şeye</strong> ihtiyacım var.
settings.event_choose=Neye ihtiyacım olduğunu seçtir.
settings.event_create=Oluştur
settings.event_create_desc=Dal veya biçim imi oluşturuldu
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Bir depoya git push
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktif
settings.active_helper=Bu isteği tetikleyen olaya ilişkin detaylar da gönderilecektir.
settings.add_hook_success=Yeni web isteği eklendi.
@@ -798,7 +822,6 @@ release.releases=Sürümler
release.new_release=Yeni Sürüm
release.draft=Taslak
release.prerelease=Ön Sürüm
release.stable=Kararlı
release.edit=düzenle
release.ahead=%s son sürümden beri <strong>%d</strong> işleme
release.source_code=Kaynak Kodu
@@ -1014,6 +1037,7 @@ repos.private=Özel
repos.watches=İzlemeler
repos.stars=Yıldızlar
repos.issues=Sorunlar
repos.size=Size
auths.auth_manage_panel=Yetkilendirme Yönetim Paneli
auths.new=Yeni Kaynak Ekle
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Log Yapılandırması
config.log_mode=Log Modu
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron Görevleri
monitor.name=İsim
@@ -1200,19 +1225,23 @@ notices.delete_success=Sistem bildirimleri başarıyla silindi.
[action]
create_repo=depo <a href="%s">%s</a> oluşturuldu
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s</code> olan depo adını <a href="%[2]s">%[3]s</a> buna çevirdi
commit_repo=<a href="%[1]s">%[4]s</a> zamanında <a href="%[1]s/src/%[2]s">%[3]s</a> buraya push yaptı
compare_commits=Bu %d işlemeler için karşılaştırmaları görüntüle
transfer_repo=depo <code>%s</code> <a href="%s">%s</a>'a aktarıldı
create_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu açtı`
close_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu kapattı`
reopen_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu tekrar açtı`
comment_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununa yorum yazdı`
create_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini oluşturdu`
close_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini kapattı`
reopen_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini tekrar açtı`
comment_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununa yorum yazdı`
merge_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişim isteğini birleştirdi`
transfer_repo=depo <code>%s</code> <a href="%s">%s</a>'a aktarıldı
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=etiket <a href="%s/src/%s">%[2]s</a> <a href="%[1]s">%[3]s</a>'a itelendi
compare_commits=Bu %d işlemeler için karşılaştırmaları görüntüle
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=önce

View File

@@ -39,8 +39,8 @@ your_profile=Ваш профіль
your_settings=Ваші налаштування
activities=Дії
pull_requests=пропозиція змін
issues=Обговорення
pull_requests=Запити на злиття
issues=Проблеми
cancel=Скасувати
@@ -69,7 +69,7 @@ app_name_helper=Вкажіть назву вашої організації, в
repo_path=Кореневий шлях репозиторія
repo_path_helper=До цього каталогу буде збережено всі зовнішні сховища Git.
run_user=Запустити як
run_user_helper=Користувач повинен мати доступ до папки репозиторіїв і запустити Gogs.
run_user_helper=Користувач мусить мати доступ до кореню репозиторіїв та право на запуск Gogs.
domain=Домен
domain_helper=Це впливає на клонування через SSH.
ssh_port=SSH порт
@@ -192,15 +192,16 @@ AuthName=Назва авторизації
AdminEmail=Електронна пошта адміністратора
NewBranchName=Ім'я нової гілки
CommitSummary=Резюме комміту
CommitMessage=Зафіксувати повідомлення
CommitChoice=Зробити вибір
CommitSummary=Резюме коміту
CommitMessage=Повідомлення коміту
CommitChoice=Зафіксувати вибір
TreeName=Шлях до файлу
Content=Вміст
require_error=' не може бути пустим.'
alpha_dash_error=` має складатись з буков, цифр, або рисок(-_).`
alpha_dash_dot_error=` має складатись з буков, цифр, рисок(-_), або крапок.`
alpha_dash_dot_slash_error=` мусить бути валідною буквою, або цифрою, або рискою(-_), або крапкою, або слешем.`
size_error=` має мати розмір %s.`
min_size_error=' має містити принаймні %s символів.'
max_size_error=' має містити принаймні %s символів.'
@@ -305,7 +306,7 @@ add_email_success=Вашу нову адресу електронної пошт
manage_ssh_keys=Керувати ключами SSH
add_key=Додати ключ
ssh_desc=Це список ключів SSH, пов'язані з вашим обліковим записом. Видаліть будь-які ключі, які не є вашими.
ssh_helper=<strong>Потрібна допомога?</strong> Дивіться наш гід до <a href="%s"> генерації ключів SSH</a> або виправлення <a href="%s"> типових неполадок SSH</a>.
ssh_helper=<strong>Потрібна допомога?</strong> Дивіться гід на GitHub з <a href="%s"> генерації ключів SSH</a> або виправлення <a href="%s">типових неполадок SSH</a>.
add_new_key=Додати SSH ключа
ssh_key_been_used=Було використано публічний ключ.
ssh_key_name_used=Відкритий ключ з таким іменем уже існує.
@@ -422,10 +423,11 @@ filter_branch_and_tag=Фільтрувати гілку або тег
branches=Гілки
tags=Теги
issues=Проблеми
pulls=Пропозиція Змін
pulls=Запити на злиття
labels=Мітка
milestones=Проміжні етапи
commits=Коміти
git_branches=Гілки
releases=Релізи
file_raw=Запис
file_history=Історія
@@ -434,6 +436,13 @@ file_permalink=Постійне посилання
file_too_large=Цей файл завеликий для показу
video_not_supported_in_browser=Ваш браузер не підтримує єлемент HTML5 video.
branches.overview=Огляд
branches.active_branches=Активні гілки
branches.stale_branches=Застарілі гілки
branches.all=Усі гілки
branches.updated_by=Оновлено %[1]s з %[2]s
branches.change_default_branch=Гілку за замовчуванням змінено
editor.new_file=Новий файл
editor.upload_file=Завантажити файл
editor.edit_file=Редагування файла
@@ -449,12 +458,12 @@ editor.name_your_file=Дайте назву файлу...
editor.filename_help=Щоб додати каталог, просто наберіть його ім'я, та натисніть /. Щоб видалити каталог, перейдіь на початок поля й натисніть клавішу backspace.
editor.or=Або
editor.cancel_lower=Скасувати
editor.commit_changes=Порівняти зміни
editor.commit_changes=Зафіксувати зміни
editor.add_tmpl=Додати '%s/<filename>'
editor.add=Додати '%s'
editor.update=Оновити '%s'
editor.delete=Видалити '%s'
editor.commit_message_desc=Додати необов'язкове розширене описання...
editor.commit_message_desc=Додати необов'язковий розширений опис...
editor.commit_directly_to_this_branch=Зробіть комміт прямо в гілку <strong class="branch-name">%s</strong>.
editor.create_new_branch=Створіть <strong>нову гілку</strong> для цього коміту та відкривайте запит на втягування.
editor.new_branch_name_desc=Ім'я нової гілки...
@@ -473,7 +482,7 @@ editor.add_subdir=Додати підкаталогу...
editor.unable_to_upload_files=Не вдалося завантажити файли до '%s' через помилку: %v
editor.upload_files_to_dir=Завантажувати файли до '%s'
commits.commit_history=Commit History
commits.commit_history=Історія комітів
commits.commits=Коміти
commits.search=Знайти коміт
commits.find=Пошук
@@ -515,7 +524,7 @@ issues.filter_assginee_no_select=Етап не обрано
issues.filter_type=Тип
issues.filter_type.all_issues=Всі проблемы
issues.filter_type.assigned_to_you=Призначене вам
issues.filter_type.created_by_you=Створено тобою
issues.filter_type.created_by_you=Створено вами
issues.filter_type.mentioning_you=Вас згадано
issues.filter_sort=Сортування
issues.filter_sort.latest=Найновіші
@@ -655,8 +664,12 @@ settings.protect_this_branch_desc=Вимкнути примусовий push т
settings.protect_require_pull_request=Вимагати запрос на злиття замість прямого push
settings.protect_require_pull_request_desc=Увімкніть цю опцію для заборони прямого push у цю гілку. Коміт має бути запушений у іншу, незахищену гілку та влитий у цю через запрос на злиття.
settings.protect_whitelist_committers=Білий список тих, хто може робити push у цю гілку
settings.protect_whitelist_committers_desc=Додати людей або команди у білий список для виконання push до цієї гілки.
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.protect_whitelist_committers_desc=Додати людей або команди до білого списку тих, хто може робити push у цю гілку. Користувачі з білого списку оминатимуть контроль запитів на злиття.
settings.protect_whitelist_users=Користувачі що можуть виконувати push до цієї гілки
settings.protect_whitelist_search_users=Пошук користувачів
settings.protect_whitelist_teams=Команди, члени яких можуть виконувати push до цієї гілки
settings.protect_whitelist_search_teams=Пошук команд
settings.update_protect_branch_success=Опції захисту цієї гілки було успішно оновлено!
settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Основні налаштування
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Буквено-цифровий
settings.tracker_url_format_desc=Ви можете використовувати заповнювач <code>{user} {repo} {index}</code> для ім'я користувача, назви репозиторію на номеру проблеми.
settings.pulls_desc=Увімкнути публічні запроси на злиття
settings.danger_zone=Небезпечна зона
settings.cannot_fork_to_same_owner=Ви не можете клонувати репозиторій його ж власнику.
settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою.
settings.convert=Перетворити на звичайний репозиторій
settings.convert_desc=Ви можете сконвертувати це дзеркало у звичайний репозиторій. Це не може бути повернуто.
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=Цей користувач більше н
settings.remove_collaborator_success=Співавтора було видалено.
settings.search_user_placeholder=Пошук користувача...
settings.org_not_allowed_to_be_collaborator=Організації не можуть бути додані як співавтори.
settings.user_is_org_member=Користувач входить в організацію, член якої не може бути доданий як співавтор.
settings.add_webhook=Додати Webhook
settings.hooks_desc=Web-хуки схожі на HTTP POST тригери подій. Яка б подія не виникла в Gogs, ми можемо обробити повідомлення про неї на сторонньому хості який ви задаєте. Взнайте більше у <a target="_blank" href="%s">Webhooks Guide</a>.
settings.webhook_deletion=Видалити Webhook
@@ -741,6 +754,7 @@ settings.add_webhook_desc=Gogs відправляє <code>POST</code> запит
settings.payload_url=URL розробника
settings.content_type=Тип змісту
settings.secret=Таємний код
settings.secret_desc=Секрет буде вислано SHA256 HMAC hex-сумою вміста у хідері <code>X-Gogs-Signature</code>.
settings.slack_username=Ім'я користувача
settings.slack_icon_url=URL іконки
settings.slack_color=Колір
@@ -750,10 +764,20 @@ settings.event_send_everything=Мені потрібно <strong>усе</strong>
settings.event_choose=Дозвольте мені вибрати те, що потрібно.
settings.event_create=Створити
settings.event_create_desc=Гілку або тег створено
settings.event_pull_request=Запити до злиття
settings.event_pull_request_desc=Запрос злиття відкрито, закрито, перевідкрито, змінено, призначено, знято, мітку оновлено, мітку прибрано або синхронізовано.
settings.event_delete=Видалити
settings.event_delete_desc=Гілку або мітку було видалено
settings.event_fork=Відгалуження
settings.event_fork_desc=Репозиторій було відгалуджено
settings.event_push=Push
settings.event_push_desc=Git push до репозиторію
settings.event_issues=Проблеми
settings.event_issues_desc=Проблему відкрито, закрито, перевідкрито, відредаговано, призначено, відкріплено, змінено мітку, очищено мітку, створено етап, очищено етап.
settings.event_issue_comment=Коментар проблеми
settings.event_issue_comment_desc=Коментар проблеми створено, видалено чи відредаговано.
settings.event_pull_request=Запити до злиття
settings.event_pull_request_desc=Запрос на злиття відкрито, закрито, перевідкрито, прикріплено, відкріплено, оновлено мітку, очищено мітку, створено етап, очищено етап або синхронізовано.
settings.event_release=Реліз
settings.event_release_desc=Реліз опубліковано у репозиторії.
settings.active=Активний
settings.active_helper=Подробиці події, що викликала спрацювання хука, будуть надані також.
settings.add_hook_success=Новий web-хук було додано.
@@ -783,7 +807,7 @@ settings.deploy_key_deletion_success=Ключі для розгортуванн
diff.browse_source=Переглянути джерело
diff.parent=батько
diff.commit=комміт
diff.commit=коміт
diff.data_not_available=Жодних diff даних не доступно.
diff.show_diff_stats=Показати статистику Diff
diff.show_split_view=Розділений вигляд
@@ -798,7 +822,6 @@ release.releases=Релізи
release.new_release=Новий реліз
release.draft=Чернетка
release.prerelease=Пре-реліз
release.stable=Стабільний
release.edit=редагувати
release.ahead=<strong>%d</strong> коммітів %s після цього релізу
release.source_code=Вихідний код
@@ -1014,6 +1037,7 @@ repos.private=Приватний
repos.watches=Стежать
repos.stars=У обраному
repos.issues=Питання
repos.size=Розмір
auths.auth_manage_panel=Керування автентифікацій
auths.new=Додати нове джерело
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Тайм-аут операції витягання
config.git_gc_timeout=Тайм-аут операції GC
config.log_config=Конфігурація журналу
config.log_mode=Режим журналювання
config.log_mode=Режим
config.log_options=Опції
monitor.cron=Завдання cron
monitor.name=Назва
@@ -1200,19 +1225,23 @@ notices.delete_success=Системні повідомлення було усп
[action]
create_repo=створено репозиторій <a href="%s">%s</a>
fork_repo=відгалуджено репозиторій у <a href="%s">%s</a>
rename_repo=репозиторій перейменовано з <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=запушено до <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
compare_commits=Перегляд порівняння для цих %d комітів
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
create_issue=`відкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`закрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`перевідкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`відкоментовано проблему <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`створено запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`закрито запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`перевідкрито запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`відкоментовано проблему <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`запит на злиття влито <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
create_branch=створено нову гілку <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
delete_branch=видалено гілку <code>%[2]s</code> у <a href="%[1]s">%[3]s</a>
push_tag=заштовхнуто тег <a href="%s/src/%s">%[2]s</a> до <a href="%[1]s">%[3]s</a>
compare_commits=Перегляд порівняння для цих %d комітів
delete_tag=видалено мітку <code>%[2]s</code> у <a href="%[1]s">%[3]s</a>
[tool]
ago=тому

View File

@@ -201,6 +201,7 @@ Content=内容
require_error=不能为空。
alpha_dash_error=必须为英文字母、阿拉伯数字或横线(-_
alpha_dash_dot_error=必须为英文字母、阿拉伯数字、横线(-_或点。
alpha_dash_dot_slash_error=必须为英文字母、阿拉伯数字、横线(-_、点或斜线。
size_error=长度必须为 %s。
min_size_error=长度最小为 %s 个字符。
max_size_error=长度最大为 %s 个字符。
@@ -426,6 +427,7 @@ pulls=合并请求
labels=标签管理
milestones=里程碑
commits=提交历史
git_branches=代码分支
releases=版本发布
file_raw=原始文件
file_history=文件历史
@@ -434,6 +436,13 @@ file_permalink=永久链接
file_too_large=文件过大导致无法显示
video_not_supported_in_browser=您的浏览器不支持使用 HTML5 播放视频。
branches.overview=概况
branches.active_branches=活跃分支
branches.stale_branches=陈旧分支
branches.all=所有分支
branches.updated_by=由 %[2]s 更新于 %[1]s
branches.change_default_branch=更改默认分支
editor.new_file=新的文件
editor.upload_file=上传文件
editor.edit_file=编辑文件
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=禁止强制推送和删除分支。
settings.protect_require_pull_request=要求通过合并请求提交代码
settings.protect_require_pull_request_desc=启用该选项后代码将不能直接被推送到此分支,所有的代码提交都必须通过另一个非保护分支发起合并请求进行合并。
settings.protect_whitelist_committers=限制可以推送代码的成员
settings.protect_whitelist_committers_desc=添加用户或团队到可直接推送代码的白名单。
settings.protect_whitelist_committers_desc=添加用户或团队到可直接推送代码的白名单,列入白名单中的用户将跳过合并请求检查
settings.protect_whitelist_users=允许推送到此分支的用户
settings.protect_whitelist_search_users=搜索用户
settings.protect_whitelist_teams=允许其成员推送到此分支的团队
settings.protect_whitelist_search_teams=搜索团队
settings.update_protect_branch_success=此分支的保护选项更新成功!
settings.hooks=管理 Web 钩子
settings.githooks=管理 Git 钩子
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=英文字母数字组合形式
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分别作为用户名、仓库名和工单索引的占位符。
settings.pulls_desc=启用合并请求以接受社区贡献
settings.danger_zone=危险操作区
settings.cannot_fork_to_same_owner=您不能派生仓库到其当前的所有者。
settings.new_owner_has_same_repo=新的仓库拥有者已经存在同名仓库!
settings.convert=转换为普通仓库
settings.convert_desc=您可以将该镜像仓库转换为普通仓库,且此操作不可逆。
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=此用户被删除后将不再拥有相关
settings.remove_collaborator_success=被操作的协作者已经被收回权限!
settings.search_user_placeholder=搜索用户...
settings.org_not_allowed_to_be_collaborator=组织不允许被添加为仓库协作者!
settings.user_is_org_member=被操作的用户是组织成员,因此无法添加为协作者!
settings.add_webhook=添加 Web 钩子
settings.hooks_desc=Web 钩子允许您设定在 Gogs 上发生指定事件时对指定 URL 发送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文档</a> 获取更多信息。
settings.webhook_deletion=删除 Web 钩子
@@ -741,19 +754,30 @@ settings.add_webhook_desc=我们会通过 <code>POST</code> 请求将订阅事
settings.payload_url=推送地址
settings.content_type=数据格式
settings.secret=密钥文本
settings.secret_desc=密钥文本将被用于计算推送内容的 SHA256 HMAC 哈希值,并设置为 <code>X-Gogs-Signature</code> 请求头的值。
settings.slack_username=服务名称
settings.slack_icon_url=图标 URL
settings.slack_color=颜色代码
settings.event_desc=请设置您希望触发 Web 钩子的事件:
settings.event_push_only=只推送 <code>push</code> 事件。
settings.event_send_everything=请把 <strong>一切</strong> 都给我
settings.event_choose=我的命运自己主宰
settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=选择指定的事件
settings.event_create=创建
settings.event_create_desc=创建分支或标签
settings.event_pull_request=合并请求
settings.event_pull_request_desc=开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签或同步合并请求
settings.event_delete=删除
settings.event_delete_desc=删除分支或标签
settings.event_fork=派生
settings.event_fork_desc=仓库被派生
settings.event_push=推送
settings.event_push_desc=Git 仓库推送
settings.event_issues=工单
settings.event_issues_desc=工单被开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签、设置里程碑或取消设置里程碑
settings.event_issue_comment=工单评论
settings.event_issue_comment_desc=工单评论被创建、编辑和删除
settings.event_pull_request=合并请求
settings.event_pull_request_desc=合并请求被开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签、设置里程碑、取消设置里程碑或代码同步
settings.event_release=版本发布
settings.event_release_desc=仓库发布新的版本
settings.active=是否激活
settings.active_helper=当指定事件发生时我们将会触发此 Web 钩子。
settings.add_hook_success=Web 钩子添加成功!
@@ -798,7 +822,6 @@ release.releases=版本发布
release.new_release=发布新版
release.draft=草稿
release.prerelease=预发行
release.stable=稳定
release.edit=编辑
release.ahead=在该版本发布之后已有 <strong>%d</strong> 次代码提交到 %s 分支
release.source_code=源代码
@@ -1014,6 +1037,7 @@ repos.private=私有库
repos.watches=关注数
repos.stars=点赞数
repos.issues=工单数
repos.size=用量
auths.auth_manage_panel=认证管理面板
auths.new=添加新的源
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=拉取操作超时
config.git_gc_timeout=GC 操作超时
config.log_config=日志配置
config.log_mode=日志模式
config.log_mode=模式
config.log_options=选项
monitor.cron=Cron 任务
monitor.name=任务名称
@@ -1200,19 +1225,23 @@ notices.delete_success=系统提示删除成功!
[action]
create_repo=创建了仓库 <a href="%s">%s</a>
fork_repo=派生了仓库 <a href="%s">%s</a>
rename_repo=重命名仓库 <code>%[1]s</code> 为 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代码到 <a href="%[1]s">%[4]s</a>
compare_commits=对比 %d 次代码提交
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
create_issue=`创建了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`关闭了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`重新开启了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`创建了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`关闭了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`重新开启了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合并了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
create_branch=创建了新的分支 <a href="%[1]s/src/%[2]s">%[3]s</a> 到 <a href="%[1]s">%[4]s</a>
delete_branch=删除了 <a href="%[1]s">%[3]s</a> 的分支 <code>%[2]s</code>
push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=对比 %d 次代码提交
delete_tag=删除了 <a href="%[1]s">%[3]s</a> 的标签 <code>%[2]s</code>
[tool]
ago=之前

View File

@@ -201,6 +201,7 @@ Content=Content
require_error=不能為空。
alpha_dash_error=必須為英文字母、阿拉伯數字或橫線(-_
alpha_dash_dot_error=必須為英文字母、阿拉伯數字、橫線(-_或點。
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=長度必須為 %s。
min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。
@@ -426,6 +427,7 @@ pulls=合併請求
labels=標籤
milestones=里程碑
commits=提交歷史
git_branches=Branches
releases=版本發佈
file_raw=原始文件
file_history=文件歷史
@@ -434,6 +436,13 @@ file_permalink=永久連結
file_too_large=This file is too large to be shown
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=Edit file
@@ -655,7 +664,11 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=管理 Web 鉤子
settings.githooks=管理 Git 鉤子
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumeric
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
settings.pulls_desc=啟用合併請求以接受社區貢獻
settings.danger_zone=危險操作區
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
settings.convert=轉換為正規倉庫
settings.convert_desc=您可以將此鏡像轉成正規倉庫。此動做不可逆。
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=This user will no longer have collaboration
settings.remove_collaborator_success=被操作的協作者已經被收回權限!
settings.search_user_placeholder=搜索用戶...
settings.org_not_allowed_to_be_collaborator=Organization is not allowed to be added as a collaborator.
settings.user_is_org_member=被操作的用戶是組織成員,因此無法添加為協作者!
settings.add_webhook=添加 Web 鉤子
settings.hooks_desc=Web 鉤子允許您設定在 Gogs 上發生指定事件時對指定 URL 發送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文檔</a> 獲取更多信息。
settings.webhook_deletion=刪除 Web 鉤子
@@ -741,6 +754,7 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
settings.payload_url=推送地址
settings.content_type=數據格式
settings.secret=密鑰文本
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.slack_username=服務名稱
settings.slack_icon_url=圖標 URL
settings.slack_color=顏色代碼
@@ -750,10 +764,20 @@ settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=讓我選擇我的需要
settings.event_create=創建
settings.event_create_desc=創建分支或標籤
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=推送
settings.event_push_desc=Git 倉庫推送
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功!
@@ -798,7 +822,6 @@ release.releases=版本發佈
release.new_release=發佈新版本
release.draft=草稿
release.prerelease=預發佈版本
release.stable=穩定
release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼
@@ -1014,6 +1037,7 @@ repos.private=私有庫
repos.watches=關註數
repos.stars=讚好數
repos.issues=問題數
repos.size=Size
auths.auth_manage_panel=認證管理面板
auths.new=添加新認證源
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=日誌配置
config.log_mode=日誌模式
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron 任務
monitor.name=任務名稱
@@ -1200,19 +1225,23 @@ notices.delete_success=系統提示刪除成功!
[action]
create_repo=創建了儲存庫 <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
compare_commits=查看 %d 次提交的內容比對
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的內容比對
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=之前

View File

@@ -201,6 +201,7 @@ Content=內容
require_error=不能為空。
alpha_dash_error=必須為英文字母、阿拉伯數字或橫線(-_
alpha_dash_dot_error=必須為英文字母、阿拉伯數字、橫線(-_或點。
alpha_dash_dot_slash_error=` 必須是合法的英文字母、數字、分隔符號(-_)、半形句點或斜線。`
size_error=長度必須為 %s。
min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。
@@ -426,6 +427,7 @@ pulls=合併請求
labels=標籤
milestones=里程碑
commits=提交歷史
git_branches=分支列表
releases=版本發佈
file_raw=原始文件
file_history=文件歷史
@@ -434,6 +436,13 @@ file_permalink=永久連結
file_too_large=檔案太大,無法顯示
video_not_supported_in_browser=您的瀏覽器不支援 HTML5 影片播放標籤。
branches.overview=概覽
branches.active_branches=活躍分支
branches.stale_branches=陳舊分支
branches.all=所有分支
branches.updated_by=%[2]s 更新了 %[1]s
branches.change_default_branch=變更預設分支
editor.new_file=開新檔案
editor.upload_file=上傳檔案
editor.edit_file=編輯文件
@@ -473,7 +482,7 @@ editor.add_subdir=新增子目錄...
editor.unable_to_upload_files=上傳檔案失敗到 '%s', 錯誤訊息: %v
editor.upload_files_to_dir=上傳檔案到 '%s'
commits.commit_history=Commit History
commits.commit_history=提交歷史
commits.commits=次代碼提交
commits.search=搜索提交歷史
commits.find=查找
@@ -655,8 +664,12 @@ settings.protect_this_branch_desc=停用強制Push及分支刪除。
settings.protect_require_pull_request=請使用 pull request 來更新(合併)程式碼。
settings.protect_require_pull_request_desc=啟用這個選項之後,程式碼將無法直接 Push 到這個分支,所有 Commit 必須先 Push 到另一個非保護的分支,再透過 Pull Request 來要求合併。
settings.protect_whitelist_committers=限制誰可以 Push 到這個分支
settings.protect_whitelist_committers_desc=新增用戶或團隊到可以直接push到這個分支的白名單。
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.protect_whitelist_committers_desc=新增成員或團隊到允許直接 push 到這個分支的白名單。白名單中的使用者將會略過 pull request 的檢查。
settings.protect_whitelist_users=限制那些使用者可以 push 到這個分支
settings.protect_whitelist_search_users=搜尋用戶
settings.protect_whitelist_teams=團隊的成員可以 push 到這個分支
settings.protect_whitelist_search_teams=搜尋團隊
settings.update_protect_branch_success=此分支設置保護已更新成功!
settings.hooks=管理 Web 鉤子
settings.githooks=管理 Git 鉤子
settings.basic_settings=基本設置
@@ -684,6 +697,7 @@ settings.tracker_issue_style.alphanumeric=字母及數字
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
settings.pulls_desc=啟用合併請求以接受社區貢獻
settings.danger_zone=危險操作區
settings.cannot_fork_to_same_owner=你不可以 fork 一個 repository 到它的擁有者。
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
settings.convert=轉換為正規倉庫
settings.convert_desc=您可以將此鏡像轉成正規倉庫。此動做不可逆。
@@ -718,7 +732,6 @@ settings.collaborator_deletion_desc=刪除後此使用者將不再有協同者
settings.remove_collaborator_success=被操作的協作者已經被收回權限!
settings.search_user_placeholder=搜索用戶...
settings.org_not_allowed_to_be_collaborator=組織不允許被加為協同者。
settings.user_is_org_member=被操作的用戶是組織成員,因此無法添加為協作者!
settings.add_webhook=添加 Web 鉤子
settings.hooks_desc=Web 鉤子允許您設定在 Gogs 上發生指定事件時對指定 URL 發送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文檔</a> 獲取更多信息。
settings.webhook_deletion=刪除 Web 鉤子
@@ -741,6 +754,7 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
settings.payload_url=推送地址
settings.content_type=數據格式
settings.secret=密鑰文本
settings.secret_desc=密鑰將會以 SHA256 HMAC 的十六進位數字放進<code>X-Gogs-Signature</code> 標頭中送出。
settings.slack_username=服務名稱
settings.slack_icon_url=圖標 URL
settings.slack_color=顏色代碼
@@ -750,10 +764,20 @@ settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=讓我選擇我的需要
settings.event_create=創建
settings.event_create_desc=創建分支或標籤
settings.event_pull_request=合併請求
settings.event_pull_request_desc=請求打開,關閉,重新打開,編輯,分配,未分配,標籤更新,標籤清除,或同步。
settings.event_delete=刪除
settings.event_delete_desc=分支或標籤已經被刪除
settings.event_fork=Fork
settings.event_fork_desc=Repository 已經 fork
settings.event_push=推送
settings.event_push_desc=Git 倉庫推送
settings.event_issues=Issues
settings.event_issues_desc=已經開啟、關閉、重啟、修改、指派、取消指派、更新標籤、清除標籤、新增里程碑或刪除里程碑的 issue。
settings.event_issue_comment=Issue 評論
settings.event_issue_comment_desc=已經建立、編輯或刪除的 Issue 評論。
settings.event_pull_request=合併請求
settings.event_pull_request_desc=已經開啟、關閉、重啟、編輯、指派、解除指派、更新標籤、清除標籤、新增里程碑、刪除里程碑或同步的 pull request。
settings.event_release=Release
settings.event_release_desc=Release 將發佈在一個 repository 中。
settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功!
@@ -798,7 +822,6 @@ release.releases=版本發佈
release.new_release=發佈新版本
release.draft=草稿
release.prerelease=預發佈版本
release.stable=穩定
release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼
@@ -1014,6 +1037,7 @@ repos.private=私有庫
repos.watches=關註數
repos.stars=讚好數
repos.issues=問題數
repos.size=大小
auths.auth_manage_panel=認證管理面板
auths.new=添加新認證源
@@ -1171,7 +1195,8 @@ config.git_pull_timeout=操作超時
config.git_gc_timeout=GC 操作超時
config.log_config=日誌配置
config.log_mode=日誌模式
config.log_mode=模式
config.log_options=選項
monitor.cron=Cron 任務
monitor.name=任務名稱
@@ -1200,19 +1225,23 @@ notices.delete_success=系統提示刪除成功!
[action]
create_repo=創建了儲存庫 <a href="%s">%s</a>
fork_repo=已經 fork 一個 repository 到 <a href="%s">%s</a>
rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
compare_commits=查看 %d 次提交的內容比對
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`已關閉問題 <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`已重新開啟問題 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`已關閉合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`已重新開啟合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_branch=在 <a href="%[1]s">%[4]s</a> 建立新的分支 <a href="%[1]s/src/%[2]s">%[3]s</a>
delete_branch=已經刪除在 <a href="%[1]s">%[3]s</a> 上的分支 <code>%[2]s</code>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的內容比對
delete_tag=已經刪除在 <a href="%[1]s">%[3]s</a> 上的標籤 <code>%[2]s</code>
[tool]
ago=之前

View File

@@ -65,7 +65,7 @@ $ docker run --name=gogs -p 10022:22 -p 10080:3000 -v gogs-data:/data gogs/gogs
Most of settings are obvious and easy to understand, but there are some settings can be confusing by running Gogs inside Docker:
- **Repository Root Path**: keep it as default value `/home/git/gogs-repositories` because `start.sh` already made a symbolic link for you.
- **Run User**: keep it as default value `git` because `start.sh` already setup a user with name `git`.
- **Run User**: keep it as default value `git` because `build.sh` already setup a user with name `git`.
- **Domain**: fill in with Docker container IP (e.g. `192.168.99.100`). But if you want to access your Gogs instance from a different physical machine, please fill in with the hostname or IP address of the Docker host machine.
- **SSH Port**: Use the exposed port from Docker container. For example, your SSH server listens on `22` inside Docker, **but** you expose it by `10022:22`, then use `10022` for this value. **Builtin SSH server is not recommended inside Docker Container**
- **HTTP Port**: Use port you want Gogs to listen on inside Docker container. For example, your Gogs listens on `3000` inside Docker, **and** you expose it by `10080:3000`, but you still use `3000` for this value.
@@ -112,4 +112,4 @@ Steps to upgrade Gogs with Docker:
## Useful Links
- [Share port 22 between Gogs inside Docker & the local system](http://www.ateijelo.com/blog/2016/07/09/share-port-22-between-docker-gogs-ssh-and-local-system)
- [Share port 22 between Gogs inside Docker & the local system](http://www.ateijelo.com/blog/2016/07/09/share-port-22-between-docker-gogs-ssh-and-local-system)

15
gogs.go
View File

@@ -16,7 +16,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
const APP_VER = "0.9.164.0220 / 0.10 RC"
const APP_VER = "0.10.18.0313"
func init() {
setting.AppVer = APP_VER
@@ -28,13 +28,14 @@ func main() {
app.Usage = "A painless self-hosted Git service"
app.Version = APP_VER
app.Commands = []cli.Command{
cmd.CmdWeb,
cmd.Web,
cmd.Serv,
cmd.CmdHook,
cmd.CmdDump,
cmd.CmdCert,
cmd.CmdAdmin,
cmd.CmdImport,
cmd.Hook,
cmd.Cert,
cmd.Admin,
cmd.Import,
cmd.Backup,
cmd.Restore,
}
app.Flags = append(app.Flags, []cli.Flag{}...)
app.Run(os.Args)

View File

@@ -57,41 +57,45 @@ type Access struct {
Mode AccessMode
}
func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
func accessLevel(e Engine, userID int64, repo *Repository) (AccessMode, error) {
mode := ACCESS_MODE_NONE
// Everyone has read access to public repository
if !repo.IsPrivate {
mode = ACCESS_MODE_READ
}
if u == nil {
if userID <= 0 {
return mode, nil
}
if u.ID == repo.OwnerID {
if userID == repo.OwnerID {
return ACCESS_MODE_OWNER, nil
}
a := &Access{UserID: u.ID, RepoID: repo.ID}
if has, err := e.Get(a); !has || err != nil {
access := &Access{
UserID: userID,
RepoID: repo.ID,
}
if has, err := e.Get(access); !has || err != nil {
return mode, err
}
return a.Mode, nil
return access.Mode, nil
}
// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
// user does not have access. User can be nil!
func AccessLevel(u *User, repo *Repository) (AccessMode, error) {
return accessLevel(x, u, repo)
// user does not have access.
func AccessLevel(userID int64, repo *Repository) (AccessMode, error) {
return accessLevel(x, userID, repo)
}
func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) {
mode, err := accessLevel(e, u, repo)
func hasAccess(e Engine, userID int64, repo *Repository, testMode AccessMode) (bool, error) {
mode, err := accessLevel(e, userID, repo)
return mode >= testMode, err
}
// HasAccess returns true if someone has the request access level. User can be nil!
func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) {
return hasAccess(x, u, repo, testMode)
func HasAccess(userID int64, repo *Repository, testMode AccessMode) (bool, error) {
return hasAccess(x, userID, repo, testMode)
}
// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
@@ -225,7 +229,7 @@ func (repo *Repository) recalculateAccesses(e Engine) error {
return repo.recalculateTeamAccesses(e, 0)
}
accessMap := make(map[int64]AccessMode, 20)
accessMap := make(map[int64]AccessMode, 10)
if err := repo.refreshCollaboratorAccesses(e, accessMap); err != nil {
return fmt.Errorf("refreshCollaboratorAccesses: %v", err)
}

View File

@@ -26,6 +26,7 @@ import (
type ActionType int
// To maintain backward compatibility only append to the end of list
const (
ACTION_CREATE_REPO ActionType = iota + 1 // 1
ACTION_RENAME_REPO // 2
@@ -42,6 +43,10 @@ const (
ACTION_REOPEN_ISSUE // 13
ACTION_CLOSE_PULL_REQUEST // 14
ACTION_REOPEN_PULL_REQUEST // 15
ACTION_CREATE_BRANCH // 16
ACTION_DELETE_BRANCH // 17
ACTION_DELETE_TAG // 18
ACTION_FORK_REPO // 19
)
var (
@@ -66,7 +71,7 @@ func init() {
// Action represents user operation type and other information to repository,
// it implemented interface base.Actioner so that can be used in template render.
type Action struct {
ID int64 `xorm:"pk autoincr"`
ID int64
UserID int64 // Receiver user id.
OpType ActionType
ActUserID int64 // Action user id.
@@ -172,26 +177,26 @@ func (a *Action) GetIssueContent() string {
return issue.Content
}
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
if err = notifyWatchers(e, &Action{
ActUserID: u.ID,
ActUserName: u.Name,
OpType: ACTION_CREATE_REPO,
func newRepoAction(e Engine, doer, owner *User, repo *Repository) (err error) {
opType := ACTION_CREATE_REPO
if repo.IsFork {
opType = ACTION_FORK_REPO
}
return notifyWatchers(e, &Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
OpType: opType,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
}
log.Trace("action.newRepoAction: %s/%s", u.Name, repo.Name)
return err
})
}
// NewRepoAction adds new action for creating repository.
func NewRepoAction(u *User, repo *Repository) (err error) {
return newRepoAction(x, u, repo)
func NewRepoAction(doer, owner *User, repo *Repository) (err error) {
return newRepoAction(x, doer, owner, repo)
}
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
@@ -335,7 +340,12 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
}
refMarked[issue.ID] = true
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, c.Message)
msgLines := strings.Split(c.Message, "\n")
shortMsg := msgLines[0]
if len(msgLines) > 2 {
shortMsg += "..."
}
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, repo.Link(), c.Sha1, shortMsg)
if err = CreateRefComment(doer, repo, issue, message, c.Sha1); err != nil {
return err
}
@@ -453,18 +463,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
return fmt.Errorf("UpdateRepository: %v", err)
}
isNewBranch := false
isNewRef := opts.OldCommitID == git.EMPTY_SHA
isDelRef := opts.NewCommitID == git.EMPTY_SHA
opType := ACTION_COMMIT_REPO
// Check it's tag push or branch.
// Check if it's tag push or branch.
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
opType = ACTION_PUSH_TAG
opts.Commits = &PushCommits{}
} else {
// TODO: detect branch deletion
// if not the first commit, set the compare URL.
if opts.OldCommitID == git.EMPTY_SHA {
isNewBranch = true
} else {
if !isNewRef && !isDelRef {
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
}
@@ -483,38 +491,57 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
}
refName := git.RefEndName(opts.RefFullName)
if err = NotifyWatchers(&Action{
action := &Action{
ActUserID: pusher.ID,
ActUserName: pusher.Name,
OpType: opType,
Content: string(data),
RepoID: repo.ID,
RepoUserName: repo.MustOwner().Name,
RepoName: repo.Name,
RefName: refName,
IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("NotifyWatchers: %v", err)
}
defer func() {
go HookQueue.Add(repo.ID)
}()
apiPusher := pusher.APIFormat()
apiRepo := repo.APIFormat(nil)
apiPusher := pusher.APIFormat()
switch opType {
case ACTION_COMMIT_REPO: // Push
if isDelRef {
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
Ref: refName,
RefType: "branch",
PusherType: api.PUSHER_TYPE_USER,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(delete branch): %v", err)
}
action.OpType = ACTION_DELETE_BRANCH
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(delete branch): %v", err)
}
// Delete branch doesn't have anything to push or compare
return nil
}
compareURL := setting.AppUrl + opts.Commits.CompareURL
if isNewBranch {
if isNewRef {
compareURL = ""
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "branch",
Repo: apiRepo,
Sender: apiPusher,
Ref: refName,
RefType: "branch",
DefaultBranch: repo.DefaultBranch,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks (new branch): %v", err)
return fmt.Errorf("PrepareWebhooks.(new branch): %v", err)
}
action.OpType = ACTION_CREATE_BRANCH
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new branch): %v", err)
}
}
@@ -528,16 +555,47 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
Pusher: apiPusher,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks (new commit): %v", err)
return fmt.Errorf("PrepareWebhooks.(new commit): %v", err)
}
case ACTION_PUSH_TAG: // Create
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
Repo: apiRepo,
Sender: apiPusher,
})
action.OpType = ACTION_COMMIT_REPO
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new commit): %v", err)
}
case ACTION_PUSH_TAG: // Tag
if isDelRef {
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
Ref: refName,
RefType: "tag",
PusherType: api.PUSHER_TYPE_USER,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(delete tag): %v", err)
}
action.OpType = ACTION_DELETE_TAG
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(delete tag): %v", err)
}
return nil
}
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
DefaultBranch: repo.DefaultBranch,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(new tag): %v", err)
}
action.OpType = ACTION_PUSH_TAG
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new tag): %v", err)
}
}
return nil

View File

@@ -110,7 +110,7 @@ func GetAttachmentByUUID(uuid string) (*Attachment, error) {
}
func getAttachmentsByIssueID(e Engine, issueID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
attachments := make([]*Attachment, 0, 5)
return attachments, e.Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
}
@@ -120,15 +120,25 @@ func GetAttachmentsByIssueID(issueID int64) ([]*Attachment, error) {
}
func getAttachmentsByCommentID(e Engine, commentID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
attachments := make([]*Attachment, 0, 5)
return attachments, e.Where("comment_id=?", commentID).Find(&attachments)
}
// GetAttachmentsByCommentID returns all attachments if comment by given ID.
// GetAttachmentsByCommentID returns all attachments of a comment.
func GetAttachmentsByCommentID(commentID int64) ([]*Attachment, error) {
return getAttachmentsByCommentID(x, commentID)
}
func getAttachmentsByReleaseID(e Engine, releaseID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
return attachments, e.Where("release_id = ?", releaseID).Find(&attachments)
}
// GetAttachmentsByReleaseID returns all attachments of a release.
func GetAttachmentsByReleaseID(releaseID int64) ([]*Attachment, error) {
return getAttachmentsByReleaseID(x, releaseID)
}
// DeleteAttachment deletes the given attachment and optionally the associated file.
func DeleteAttachment(a *Attachment, remove bool) error {
_, err := DeleteAttachments([]*Attachment{a}, remove)

View File

@@ -150,9 +150,13 @@ func (c *Comment) APIFormat() *api.Comment {
}
}
func CommentHashTag(id int64) string {
return "issuecomment-" + com.ToStr(id)
}
// HashTag returns unique hash tag for comment.
func (c *Comment) HashTag() string {
return "issuecomment-" + com.ToStr(c.ID)
return CommentHashTag(c.ID)
}
// EventTag returns unique event hash tag for comment.
@@ -330,7 +334,7 @@ func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
// CreateIssueComment creates a plain issue comment.
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
return CreateComment(&CreateCommentOptions{
comment, err := CreateComment(&CreateCommentOptions{
Type: COMMENT_TYPE_COMMENT,
Doer: doer,
Repo: repo,
@@ -338,6 +342,22 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
Content: content,
Attachments: attachments,
})
if err != nil {
return nil, fmt.Errorf("CreateComment: %v", err)
}
comment.Issue = issue
if err = PrepareWebhooks(repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_CREATED,
Issue: issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
return comment, nil
}
// CreateRefComment creates a commit reference comment to issue.
@@ -437,13 +457,33 @@ func GetCommentsByRepoIDSince(repoID, since int64) ([]*Comment, error) {
}
// UpdateComment updates information of comment.
func UpdateComment(c *Comment) error {
_, err := x.Id(c.ID).AllCols().Update(c)
return err
func UpdateComment(doer *User, c *Comment, oldContent string) (err error) {
if _, err = x.Id(c.ID).AllCols().Update(c); err != nil {
return err
}
if err = c.Issue.LoadAttributes(); err != nil {
log.Error(2, "Issue.LoadAttributes [issue_id: %d]: %v", c.IssueID, err)
} else if err = PrepareWebhooks(c.Issue.Repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_EDITED,
Issue: c.Issue.APIFormat(),
Comment: c.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: c.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
}
return nil
}
// DeleteCommentByID deletes the comment by given ID.
func DeleteCommentByID(id int64) error {
func DeleteCommentByID(doer *User, id int64) error {
comment, err := GetCommentByID(id)
if err != nil {
if IsErrCommentNotExist(err) {
@@ -468,5 +508,20 @@ func DeleteCommentByID(id int64) error {
}
}
return sess.Commit()
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
if err = comment.Issue.LoadAttributes(); err != nil {
log.Error(2, "Issue.LoadAttributes [issue_id: %d]: %v", comment.IssueID, err)
} else if err = PrepareWebhooks(comment.Issue.Repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_DELETED,
Issue: comment.Issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: comment.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
return nil
}

12
models/errors/errors.go Normal file
View File

@@ -0,0 +1,12 @@
// Copyright 2017 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.
package errors
import "errors"
// New is a wrapper of real errors.New function.
func New(text string) error {
return errors.New(text)
}

20
models/errors/issue.go Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2017 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.
package errors
import "fmt"
type InvalidIssueReference struct {
Ref string
}
func IsInvalidIssueReference(err error) bool {
_, ok := err.(InvalidIssueReference)
return ok
}
func (err InvalidIssueReference) Error() string {
return fmt.Sprintf("invalid issue reference [ref: %s]", err.Ref)
}

View File

@@ -0,0 +1,33 @@
// Copyright 2017 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.
package errors
import "fmt"
type LoginSourceNotActivated struct {
SourceID int64
}
func IsLoginSourceNotActivated(err error) bool {
_, ok := err.(LoginSourceNotActivated)
return ok
}
func (err LoginSourceNotActivated) Error() string {
return fmt.Sprintf("login source is not activated [source_id: %d]", err.SourceID)
}
type InvalidLoginSourceType struct {
Type interface{}
}
func IsInvalidLoginSourceType(err error) bool {
_, ok := err.(InvalidLoginSourceType)
return ok
}
func (err InvalidLoginSourceType) Error() string {
return fmt.Sprintf("invalid login source type [type: %v]", err.Type)
}

33
models/errors/repo.go Normal file
View File

@@ -0,0 +1,33 @@
// Copyright 2017 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.
package errors
import "fmt"
type InvalidRepoReference struct {
Ref string
}
func IsInvalidRepoReference(err error) bool {
_, ok := err.(InvalidRepoReference)
return ok
}
func (err InvalidRepoReference) Error() string {
return fmt.Sprintf("invalid repository reference [ref: %s]", err.Ref)
}
type MirrorNotExist struct {
RepoID int64
}
func IsMirrorNotExist(err error) bool {
_, ok := err.(MirrorNotExist)
return ok
}
func (err MirrorNotExist) Error() string {
return fmt.Sprintf("mirror does not exist [repo_id: %d]", err.RepoID)
}

31
models/errors/user.go Normal file
View File

@@ -0,0 +1,31 @@
// Copyright 2017 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.
package errors
import "fmt"
type EmptyName struct{}
func IsEmptyName(err error) bool {
_, ok := err.(EmptyName)
return ok
}
func (err EmptyName) Error() string {
return "empty name"
}
type UserNotKeyOwner struct {
KeyID int64
}
func IsUserNotKeyOwner(err error) bool {
_, ok := err.(UserNotKeyOwner)
return ok
}
func (err UserNotKeyOwner) Error() string {
return fmt.Sprintf("user is not the owner of public key [key_id: %d]", err.KeyID)
}

View File

@@ -0,0 +1,33 @@
// Copyright 2017 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.
package errors
import "fmt"
type EmailNotFound struct {
Email string
}
func IsEmailNotFound(err error) bool {
_, ok := err.(EmailNotFound)
return ok
}
func (err EmailNotFound) Error() string {
return fmt.Sprintf("email is not found [email: %s]", err.Email)
}
type EmailNotVerified struct {
Email string
}
func IsEmailNotVerified(err error) bool {
_, ok := err.(EmailNotVerified)
return ok
}
func (err EmailNotVerified) Error() string {
return fmt.Sprintf("email has not been verified [email: %s]", err.Email)
}

View File

@@ -366,8 +366,10 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
case strings.HasPrefix(line, "index"):
if curFile.IsDeleted {
curFile.Index = line[6:46]
} else {
} else if len(line) >= 88 {
curFile.Index = line[49:88]
} else {
curFile.Index = curFile.Name
}
break CHECK_TYPE
case strings.HasPrefix(line, "similarity index 100%"):

View File

@@ -5,16 +5,17 @@
package models
import (
"errors"
"fmt"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
api "github.com/gogits/go-gogs-client"
log "gopkg.in/clog.v1"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
)
@@ -230,7 +231,7 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
if issue.IsPull {
err = issue.PullRequest.LoadIssue()
if err != nil {
log.Error(4, "LoadIssue: %v", err)
log.Error(2, "LoadIssue: %v", err)
return
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -240,11 +241,17 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_LABEL_UPDATED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
}
@@ -334,7 +341,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
if issue.IsPull {
err = issue.PullRequest.LoadIssue()
if err != nil {
log.Error(4, "LoadIssue: %v", err)
log.Error(2, "LoadIssue: %v", err)
return
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -344,11 +351,17 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_LABEL_CLEARED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -470,11 +483,22 @@ func (issue *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (e
apiPullRequest.Action = api.HOOK_ISSUE_REOPENED
}
err = PrepareWebhooks(repo, HOOK_EVENT_PULL_REQUEST, apiPullRequest)
} else {
apiIssues := &api.IssuesPayload{
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: doer.APIFormat(),
}
if isClosed {
apiIssues.Action = api.HOOK_ISSUE_CLOSED
} else {
apiIssues.Action = api.HOOK_ISSUE_REOPENED
}
err = PrepareWebhooks(repo, HOOK_EVENT_ISSUES, apiIssues)
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
} else {
go HookQueue.Add(repo.ID)
log.Error(2, "PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
}
return nil
@@ -490,22 +514,33 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) {
if issue.IsPull {
issue.PullRequest.Issue = issue
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
PullRequest: issue.PullRequest.APIFormat(),
Changes: &api.ChangesPayload{
Title: &api.ChangesFromPayload{
From: oldTitle,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Issue: issue.APIFormat(),
Changes: &api.ChangesPayload{
Title: &api.ChangesFromPayload{
From: oldTitle,
},
},
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -521,22 +556,33 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
if issue.IsPull {
issue.PullRequest.Issue = issue
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
PullRequest: issue.PullRequest.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Issue: issue.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -570,11 +616,22 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
apiPullRequest.Action = api.HOOK_ISSUE_ASSIGNED
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, apiPullRequest)
} else {
apiIssues := &api.IssuesPayload{
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}
if isRemoveAssignee {
apiIssues.Action = api.HOOK_ISSUE_UNASSIGNED
} else {
apiIssues.Action = api.HOOK_ISSUE_ASSIGNED
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, apiIssues)
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, isRemoveAssignee, err)
} else {
go HookQueue.Add(issue.RepoID)
}
return nil
@@ -618,7 +675,7 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
// Assume assignee is invalid and drop silently.
opts.Issue.AssigneeID = 0
if assignee != nil {
valid, err := hasAccess(e, assignee, opts.Repo, ACCESS_MODE_READ)
valid, err := hasAccess(e, assignee.ID, opts.Repo, ACCESS_MODE_READ)
if err != nil {
return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", assignee.ID, opts.Repo.ID, err)
}
@@ -684,7 +741,7 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
return opts.Issue.loadAttributes(e)
}
// NewIssue creates new issue with labels for repository.
// NewIssue creates new issue with labels and attachments for repository.
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
@@ -715,10 +772,20 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
log.Error(4, "NotifyWatchers: %v", err)
log.Error(2, "NotifyWatchers: %v", err)
}
if err = issue.MailParticipants(); err != nil {
log.Error(4, "MailParticipants: %v", err)
log.Error(2, "MailParticipants: %v", err)
}
if err = PrepareWebhooks(repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_OPENED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: issue.Poster.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks: %v", err)
}
return nil
@@ -729,7 +796,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
func GetIssueByRef(ref string) (*Issue, error) {
n := strings.IndexByte(ref, byte('#'))
if n == -1 {
return nil, ErrMissingIssueNumber
return nil, errors.InvalidIssueReference{ref}
}
index, err := com.StrTo(ref[n+1:]).Int64()
@@ -914,6 +981,23 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
return issues, nil
}
// GetParticipantsByIssueID returns all users who are participated in comments of an issue.
func GetParticipantsByIssueID(issueID int64) ([]*User, error) {
userIDs := make([]int64, 0, 5)
if err := x.Table("comment").Cols("poster_id").
Where("issue_id = ?", issueID).
Distinct("poster_id").
Find(&userIDs); err != nil {
return nil, fmt.Errorf("get poster IDs: %v", err)
}
if len(userIDs) == 0 {
return nil, nil
}
users := make([]*User, 0, len(userIDs))
return users, x.In("id", userIDs).Find(&users)
}
// .___ ____ ___
// | | ______ ________ __ ____ | | \______ ___________
// | |/ ___// ___/ | \_/ __ \| | / ___// __ \_ __ \

View File

@@ -240,7 +240,13 @@ func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if issue.IsClosed {
label.NumClosedIssues++
}
return updateLabel(e, label)
if err = updateLabel(e, label); err != nil {
return fmt.Errorf("updateLabel: %v", err)
}
issue.Labels = append(issue.Labels, label)
return nil
}
// NewIssueLabel creates a new issue-label relation.
@@ -313,7 +319,17 @@ func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if issue.IsClosed {
label.NumClosedIssues--
}
return updateLabel(e, label)
if err = updateLabel(e, label); err != nil {
return fmt.Errorf("updateLabel: %v", err)
}
for i := range issue.Labels {
if issue.Labels[i].ID == label.ID {
issue.Labels = append(issue.Labels[:i], issue.Labels[i+1:]...)
break
}
}
return nil
}
// DeleteIssueLabel deletes issue-label relation.

View File

@@ -91,18 +91,30 @@ func NewMailerIssue(issue *Issue) mailer.Issue {
}
// mailIssueCommentToParticipants can be used for both new issue creation and comment.
// This functions sends two list of emails:
// 1. Repository watchers and users who are participated in comments.
// 2. Users who are not in 1. but get mentioned in current issue/comment.
func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string) error {
if !setting.Service.EnableNotifyMail {
return nil
}
// Mail wahtcers.
watchers, err := GetWatchers(issue.RepoID)
if err != nil {
return fmt.Errorf("GetWatchers [%d]: %v", issue.RepoID, err)
return fmt.Errorf("GetWatchers [repo_id: %d]: %v", issue.RepoID, err)
}
participants, err := GetParticipantsByIssueID(issue.ID)
if err != nil {
return fmt.Errorf("GetParticipantsByIssueID [issue_id: %d]: %v", issue.ID, err)
}
tos := make([]string, 0, len(watchers)) // List of email addresses.
// In case the issue poster is not watching the repository,
// even if we have duplicated in watchers, can be safely filtered out.
if issue.PosterID != doer.ID {
participants = append(participants, issue.Poster)
}
tos := make([]string, 0, len(watchers)) // List of email addresses
names := make([]string, 0, len(watchers))
for i := range watchers {
if watchers[i].UserID == doer.ID {
@@ -120,6 +132,16 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
tos = append(tos, to.Email)
names = append(names, to.Name)
}
for i := range participants {
if participants[i].ID == doer.ID {
continue
} else if com.IsSliceContainsStr(names, participants[i].Name) {
continue
}
tos = append(tos, participants[i].Email)
names = append(names, participants[i].Name)
}
mailer.SendIssueCommentMail(NewMailerIssue(issue), NewMailerRepo(issue.Repo), NewMailerUser(doer), tos)
// Mail mentioned people and exclude watchers.

View File

@@ -7,7 +7,6 @@ package models
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net/smtp"
"net/textproto"
@@ -20,6 +19,7 @@ import (
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/modules/auth/ldap"
"github.com/gogits/gogs/modules/auth/pam"
)
@@ -394,7 +394,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
}
return nil
}
return ErrUnsupportedLoginType
return errors.New("Unsupported SMTP authentication method")
}
// LoginViaSMTP queries if login/password is valid against the SMTP,
@@ -416,7 +416,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
} else if cfg.Auth == SMTP_LOGIN {
auth = &smtpLoginAuth{login, password}
} else {
return nil, errors.New("Unsupported SMTP auth type")
return nil, errors.New("Unsupported SMTP authentication type")
}
if err := SMTPAuth(auth, cfg); err != nil {
@@ -489,7 +489,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon
func ExternalUserLogin(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) {
if !source.IsActived {
return nil, ErrLoginSourceNotActived
return nil, errors.LoginSourceNotActivated{source.ID}
}
switch source.Type {
@@ -501,7 +501,7 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
return LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
}
return nil, ErrUnsupportedLoginType
return nil, errors.InvalidLoginSourceType{source.Type}
}
// UserSignIn validates user name and password.

View File

@@ -42,7 +42,7 @@ func (m *migration) Migrate(x *xorm.Engine) error {
// The version table. Should have only one row with id==1
type Version struct {
ID int64 `xorm:"pk autoincr"`
ID int64
Version int64
}
@@ -60,6 +60,8 @@ var migrations = []Migration{
NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
// v14 -> v15:v0.9.147
NewMigration("generate and migrate Git hooks", generateAndMigrateGitHooks),
// v15 -> v16:v0.10.16
NewMigration("update repository sizes", updateRepositorySizes),
}
// Migrate database to current version

77
models/migrations/v16.go Normal file
View File

@@ -0,0 +1,77 @@
// Copyright 2017 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.
package migrations
import (
"fmt"
"path/filepath"
"strings"
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/setting"
)
func updateRepositorySizes(x *xorm.Engine) (err error) {
log.Info("This migration could take up to minutes, please be patient.")
type Repository struct {
ID int64
OwnerID int64
Name string
Size int64
}
type User struct {
ID int64
Name string
}
if err = x.Sync2(new(Repository)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
// For the sake of SQLite3, we can't use x.Iterate here.
offset := 0
for {
repos := make([]*Repository, 0, 10)
if err = x.Sql(fmt.Sprintf("SELECT * FROM `repository` ORDER BY id ASC LIMIT 10 OFFSET %d", offset)).
Find(&repos); err != nil {
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
}
log.Trace("Select [offset: %d, repos: %d]", offset, len(repos))
if len(repos) == 0 {
break
}
offset += 10
for _, repo := range repos {
if repo.Name == "." || repo.Name == ".." {
continue
}
user := new(User)
has, err := x.Where("id = ?", repo.OwnerID).Get(user)
if err != nil {
return fmt.Errorf("query owner of repository [repo_id: %d, owner_id: %d]: %v", repo.ID, repo.OwnerID, err)
} else if !has {
continue
}
repoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".git"
countObject, err := git.GetRepoSize(repoPath)
if err != nil {
log.Warn("GetRepoSize: %v", err)
continue
}
repo.Size = countObject.Size + countObject.SizePack
if _, err = x.Id(repo.ID).Cols("size").Update(repo); err != nil {
return fmt.Errorf("update size: %v", err)
}
}
}
return nil
}

View File

@@ -5,9 +5,11 @@
package models
import (
"fmt"
"time"
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
api "github.com/gogits/go-gogs-client"
@@ -272,6 +274,8 @@ func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64)
} else if _, err = e.Exec("UPDATE `issue_user` SET milestone_id = 0 WHERE issue_id = ?", issue.ID); err != nil {
return err
}
issue.Milestone = nil
}
if issue.MilestoneID > 0 {
@@ -290,13 +294,15 @@ func changeMilestoneAssign(e *xorm.Session, issue *Issue, oldMilestoneID int64)
} else if _, err = e.Exec("UPDATE `issue_user` SET milestone_id = ? WHERE issue_id = ?", m.ID, issue.ID); err != nil {
return err
}
issue.Milestone = m
}
return updateIssue(e, issue)
}
// ChangeMilestoneAssign changes assignment of milestone for issue.
func ChangeMilestoneAssign(issue *Issue, oldMilestoneID int64) (err error) {
func ChangeMilestoneAssign(doer *User, issue *Issue, oldMilestoneID int64) (err error) {
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
@@ -306,7 +312,45 @@ func ChangeMilestoneAssign(issue *Issue, oldMilestoneID int64) (err error) {
if err = changeMilestoneAssign(sess, issue, oldMilestoneID); err != nil {
return err
}
return sess.Commit()
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
var hookAction api.HookIssueAction
if issue.MilestoneID > 0 {
hookAction = api.HOOK_ISSUE_MILESTONED
} else {
hookAction = api.HOOK_ISSUE_DEMILESTONED
}
if issue.IsPull {
err = issue.PullRequest.LoadIssue()
if err != nil {
log.Error(2, "LoadIssue: %v", err)
return
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
Action: hookAction,
Index: issue.Index,
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: hookAction,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
}
// DeleteMilestoneOfRepoByID deletes a milestone from a repository.

View File

@@ -16,6 +16,7 @@ import (
"github.com/gogits/git-module"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
@@ -55,7 +56,7 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
case "repo_id":
m.Repo, err = GetRepositoryByID(m.RepoID)
if err != nil {
log.Error(3, "GetRepositoryByID[%d]: %v", m.ID, err)
log.Error(3, "GetRepositoryByID [%d]: %v", m.ID, err)
}
case "updated_unix":
m.Updated = time.Unix(m.UpdatedUnix, 0).Local()
@@ -76,7 +77,7 @@ func (m *Mirror) readAddress() {
cfg, err := ini.Load(m.Repo.GitConfigPath())
if err != nil {
log.Error(4, "Load: %v", err)
log.Error(2, "Load: %v", err)
return
}
m.address = cfg.Section("remote \"origin\"").Key("url").Value()
@@ -142,9 +143,9 @@ func (m *Mirror) runSync() bool {
URL: m.FullAddress(),
Timeout: 10 * time.Second,
}) {
desc := fmt.Sprintf("Mirror repository URL is not accessible: %s", m.MosaicsAddress())
desc := fmt.Sprintf("Source URL of mirror repository '%s' is not accessible: %s", m.Repo.FullName(), m.MosaicsAddress())
if err := CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
@@ -157,9 +158,9 @@ func (m *Mirror) runSync() bool {
timeout, repoPath, fmt.Sprintf("Mirror.runSync: %s", repoPath),
"git", gitArgs...); err != nil {
desc := fmt.Sprintf("Fail to update mirror repository '%s': %s", repoPath, stderr)
log.Error(4, desc)
log.Error(2, desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
@@ -168,9 +169,9 @@ func (m *Mirror) runSync() bool {
timeout, wikiPath, fmt.Sprintf("Mirror.runSync: %s", wikiPath),
"git", "remote", "update", "--prune"); err != nil {
desc := fmt.Sprintf("Fail to update mirror wiki repository '%s': %s", wikiPath, stderr)
log.Error(4, desc)
log.Error(2, desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
@@ -185,7 +186,7 @@ func getMirrorByRepoID(e Engine, repoID int64) (*Mirror, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrMirrorNotExist
return nil, errors.MirrorNotExist{repoID}
}
return m, nil
}
@@ -222,14 +223,14 @@ func MirrorUpdate() {
if err := x.Where("next_update_unix<=?", time.Now().Unix()).Iterate(new(Mirror), func(idx int, bean interface{}) error {
m := bean.(*Mirror)
if m.Repo == nil {
log.Error(4, "Disconnected mirror repository found: %d", m.ID)
log.Error(2, "Disconnected mirror repository found: %d", m.ID)
return nil
}
MirrorQueue.Add(m.RepoID)
return nil
}); err != nil {
log.Error(4, "MirrorUpdate: %v", err)
log.Error(2, "MirrorUpdate: %v", err)
}
}
@@ -243,7 +244,7 @@ func SyncMirrors() {
m, err := GetMirrorByRepoID(com.StrTo(repoID).MustInt64())
if err != nil {
log.Error(4, "GetMirrorByRepoID [%s]: %v", repoID, err)
log.Error(2, "GetMirrorByRepoID [%s]: %v", m.RepoID, err)
continue
}
@@ -253,9 +254,14 @@ func SyncMirrors() {
m.ScheduleNextUpdate()
if err = UpdateMirror(m); err != nil {
log.Error(4, "UpdateMirror [%s]: %v", repoID, err)
log.Error(2, "UpdateMirror [%s]: %v", m.RepoID, err)
continue
}
// Update repository last updated time
if _, err = x.Exec("UPDATE repository SET updated_unix = ? WHERE id = ?", time.Now().Unix(), m.RepoID); err != nil {
log.Error(2, "Update repository 'updated_unix' [%s]: %v", m.RepoID, err)
}
}
}

View File

@@ -5,7 +5,9 @@
package models
import (
"bufio"
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/url"
@@ -13,6 +15,7 @@ import (
"path"
"strings"
"github.com/Unknwon/com"
_ "github.com/denisenkom/go-mssqldb"
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core"
@@ -66,7 +69,7 @@ func init() {
new(Issue), new(PullRequest), new(Comment), new(Attachment), new(IssueUser),
new(Label), new(IssueLabel), new(Milestone),
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(HookTask),
new(ProtectBranch),
new(ProtectBranch), new(ProtectBranchWhitelist),
new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
new(Notice), new(EmailAddress))
@@ -262,7 +265,89 @@ func Ping() error {
return x.Ping()
}
// DumpDatabase dumps all data from database to file system.
func DumpDatabase(filePath string) error {
return x.DumpAllToFile(filePath)
// The version table. Should have only one row with id==1
type Version struct {
ID int64
Version int64
}
// DumpDatabase dumps all data from database to file system in JSON format.
func DumpDatabase(dirPath string) (err error) {
os.MkdirAll(dirPath, os.ModePerm)
// Purposely create a local variable to not modify global variable
tables := append(tables, new(Version))
for _, table := range tables {
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
tableFile := path.Join(dirPath, tableName+".json")
f, err := os.Create(tableFile)
if err != nil {
return fmt.Errorf("fail to create JSON file: %v", err)
}
if err = x.Asc("id").Iterate(table, func(idx int, bean interface{}) (err error) {
enc := json.NewEncoder(f)
return enc.Encode(bean)
}); err != nil {
f.Close()
return fmt.Errorf("fail to dump table '%s': %v", tableName, err)
}
f.Close()
}
return nil
}
// ImportDatabase imports data from backup archive.
func ImportDatabase(dirPath string) (err error) {
// Purposely create a local variable to not modify global variable
tables := append(tables, new(Version))
for _, table := range tables {
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
tableFile := path.Join(dirPath, tableName+".json")
if !com.IsExist(tableFile) {
continue
}
if err = x.DropTables(table); err != nil {
return fmt.Errorf("fail to drop table '%s': %v", tableName, err)
} else if err = x.Sync2(table); err != nil {
return fmt.Errorf("fail to sync table '%s': %v", tableName, err)
}
f, err := os.Open(tableFile)
if err != nil {
return fmt.Errorf("fail to open JSON file: %v", err)
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
switch bean := table.(type) {
case *LoginSource:
meta := make(map[string]interface{})
if err = json.Unmarshal(scanner.Bytes(), &meta); err != nil {
return fmt.Errorf("fail to unmarshal to map: %v", err)
}
tp := LoginType(com.StrTo(com.ToStr(meta["Type"])).MustInt64())
switch tp {
case LOGIN_LDAP, LOGIN_DLDAP:
bean.Cfg = new(LDAPConfig)
case LOGIN_SMTP:
bean.Cfg = new(SMTPConfig)
case LOGIN_PAM:
bean.Cfg = new(PAMConfig)
default:
return fmt.Errorf("unrecognized login source type:: %v", tp)
}
table = bean
}
if err = json.Unmarshal(scanner.Bytes(), table); err != nil {
return fmt.Errorf("fail to unmarshal to struct: %v", err)
}
if _, err = x.Insert(table); err != nil {
return fmt.Errorf("fail to insert strcut: %v", err)
}
}
}
return nil
}

View File

@@ -10,10 +10,8 @@ import (
"os"
"strings"
"github.com/go-xorm/builder"
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/base"
)
var (
@@ -22,8 +20,8 @@ var (
)
// IsOwnedBy returns true if given user is in the owner team.
func (org *User) IsOwnedBy(uid int64) bool {
return IsOrganizationOwner(org.ID, uid)
func (org *User) IsOwnedBy(userID int64) bool {
return IsOrganizationOwner(org.ID, userID)
}
// IsOrgMember returns true if given user is member of organization.
@@ -32,10 +30,10 @@ func (org *User) IsOrgMember(uid int64) bool {
}
func (org *User) getTeam(e Engine, name string) (*Team, error) {
return getTeam(e, org.ID, name)
return getTeamOfOrgByName(e, org.ID, name)
}
// GetTeam returns named team of organization.
// GetTeamOfOrgByName returns named team of organization.
func (org *User) GetTeam(name string) (*Team, error) {
return org.getTeam(x, name)
}
@@ -49,8 +47,9 @@ func (org *User) GetOwnerTeam() (*Team, error) {
return org.getOwnerTeam(x)
}
func (org *User) getTeams(e Engine) error {
return e.Where("org_id=?", org.ID).Find(&org.Teams)
func (org *User) getTeams(e Engine) (err error) {
org.Teams, err = getTeamsByOrgID(e, org.ID)
return err
}
// GetTeams returns all teams that belong to organization.
@@ -58,6 +57,11 @@ func (org *User) GetTeams() error {
return org.getTeams(x)
}
// TeamsHaveAccessToRepo returns all teamsthat have given access level to the repository.
func (org *User) TeamsHaveAccessToRepo(repoID int64, mode AccessMode) ([]*Team, error) {
return GetTeamsHaveAccessToRepo(org.ID, repoID, mode)
}
// GetMembers returns all members of organization.
func (org *User) GetMembers() error {
ous, err := GetOrgUsersByOrgID(org.ID)
@@ -242,8 +246,8 @@ type OrgUser struct {
}
// IsOrganizationOwner returns true if given user is in the owner team.
func IsOrganizationOwner(orgId, uid int64) bool {
has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
func IsOrganizationOwner(orgID, userID int64) bool {
has, _ := x.Where("is_owner = ?", true).And("uid = ?", userID).And("org_id = ?", orgID).Get(new(OrgUser))
return has
}
@@ -299,16 +303,15 @@ func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
}
// GetOrgUsersByUserID returns all organization-user relations by user ID.
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
ous := make([]*OrgUser, 0, 10)
sess := x.Where("uid=?", uid)
if !all {
// Only show public organizations
sess.And("is_public=?", true)
// GetOrgIDsByUserID returns a list of organization IDs that user belongs to.
// The showPrivate indicates whether to include private memberships.
func GetOrgIDsByUserID(userID int64, showPrivate bool) ([]int64, error) {
orgIDs := make([]int64, 0, 5)
sess := x.Table("org_user").Where("uid = ?", userID)
if !showPrivate {
sess.And("is_public = ?", true)
}
err := sess.Find(&ous)
return ous, err
return orgIDs, sess.Distinct("org_id").Find(&orgIDs)
}
func getOrgUsersByOrgID(e Engine, orgID int64) ([]*OrgUser, error) {
@@ -483,8 +486,7 @@ func (org *User) GetUserTeams(userID int64) ([]*Team, error) {
return org.getUserTeams(x, userID)
}
// GetUserRepositories returns a range of repositories in organization
// that the user with the given userID has access to,
// GetUserRepositories returns a range of repositories in organization which the user has access to,
// and total number of records based on given condition.
func (org *User) GetUserRepositories(userID int64, page, pageSize int) ([]*Repository, int64, error) {
teamIDs, err := org.GetUserTeamIDs(userID)
@@ -493,43 +495,43 @@ func (org *User) GetUserRepositories(userID int64, page, pageSize int) ([]*Repos
}
if len(teamIDs) == 0 {
// user has no team but "IN ()" is invalid SQL
teamIDs = []int64{-1} // there is no repo with id=-1
teamIDs = []int64{-1} // there is no team with id=-1
}
var teamRepoIDs []int64
if err = x.Table("team_repo").In("team_id", teamIDs).Distinct("repo_id").Find(&teamRepoIDs); err != nil {
return nil, 0, fmt.Errorf("get team repository IDs: %v", err)
}
if len(teamRepoIDs) == 0 {
// team has no repo but "IN ()" is invalid SQL
teamRepoIDs = []int64{-1} // there is no repo with id=-1
}
if page <= 0 {
page = 1
}
repos := make([]*Repository, 0, pageSize)
// FIXME: use XORM chain operations instead of raw SQL.
if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
INNER JOIN team_repo
ON team_repo.repo_id = repository.id
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
GROUP BY repository.id
ORDER BY updated_unix DESC
LIMIT %d OFFSET %d`,
strings.Join(base.Int64sToStrings(teamIDs), ","), pageSize, (page-1)*pageSize),
org.ID, false).Find(&repos); err != nil {
return nil, 0, fmt.Errorf("get repositories: %v", err)
if err = x.Where("owner_id = ?", org.ID).
And("is_private = ?", false).
Or(builder.In("id", teamRepoIDs)).
Desc("updated_unix").
Limit(pageSize, (page-1)*pageSize).
Find(&repos); err != nil {
return nil, 0, fmt.Errorf("get user repositories: %v", err)
}
results, err := x.Query(fmt.Sprintf(`SELECT repository.id FROM repository
INNER JOIN team_repo
ON team_repo.repo_id = repository.id
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
GROUP BY repository.id
ORDER BY updated_unix DESC`,
strings.Join(base.Int64sToStrings(teamIDs), ",")),
org.ID, false)
repoCount, err := x.Where("owner_id = ?", org.ID).
And("is_private = ?", false).
Or(builder.In("id", teamRepoIDs)).
Count(new(Repository))
if err != nil {
log.Error(4, "count user repositories in organization: %v", err)
return nil, 0, fmt.Errorf("count user repositories: %v", err)
}
return repos, int64(len(results)), nil
return repos, repoCount, nil
}
// GetUserRepositories returns mirror repositories of the organization
// that the user with the given userID has access to.
// GetUserMirrorRepositories returns mirror repositories of the organization which the user has access to.
func (org *User) GetUserMirrorRepositories(userID int64) ([]*Repository, error) {
teamIDs, err := org.GetUserTeamIDs(userID)
if err != nil {
@@ -539,16 +541,24 @@ func (org *User) GetUserMirrorRepositories(userID int64) ([]*Repository, error)
teamIDs = []int64{-1}
}
var teamRepoIDs []int64
err = x.Table("team_repo").In("team_id", teamIDs).Distinct("repo_id").Find(&teamRepoIDs)
if err != nil {
return nil, fmt.Errorf("get team repository ids: %v", err)
}
if len(teamRepoIDs) == 0 {
// team has no repo but "IN ()" is invalid SQL
teamRepoIDs = []int64{-1} // there is no repo with id=-1
}
repos := make([]*Repository, 0, 10)
if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
INNER JOIN team_repo
ON team_repo.repo_id = repository.id AND repository.is_mirror = ?
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
GROUP BY repository.id
ORDER BY updated_unix DESC`,
strings.Join(base.Int64sToStrings(teamIDs), ",")),
true, org.ID, false).Find(&repos); err != nil {
return nil, fmt.Errorf("get repositories: %v", err)
if err = x.Where("owner_id = ?", org.ID).
And("is_private = ?", false).
Or(builder.In("id", teamRepoIDs)).
And("is_mirror = ?", true). // Don't move up because it's an independent condition
Desc("updated_unix").
Find(&repos); err != nil {
return nil, fmt.Errorf("get user repositories: %v", err)
}
return repos, nil
}

View File

@@ -43,9 +43,14 @@ func (t *Team) IsOwnerTeam() bool {
return t.Name == OWNER_TEAM
}
// HasWriteAccess returns true if team has at least write level access mode.
func (t *Team) HasWriteAccess() bool {
return t.Authorize >= ACCESS_MODE_WRITE
}
// IsTeamMember returns true if given user is a member of team.
func (t *Team) IsMember(uid int64) bool {
return IsTeamMember(t.OrgID, t.ID, uid)
func (t *Team) IsMember(userID int64) bool {
return IsTeamMember(t.OrgID, t.ID, userID)
}
func (t *Team) getRepositories(e Engine) (err error) {
@@ -166,15 +171,15 @@ func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (e
if err = t.getMembers(e); err != nil {
return fmt.Errorf("get team members: %v", err)
}
for _, u := range t.Members {
has, err := hasAccess(e, u, repo, ACCESS_MODE_READ)
for _, member := range t.Members {
has, err := hasAccess(e, member.ID, repo, ACCESS_MODE_READ)
if err != nil {
return err
} else if has {
continue
}
if err = watchRepo(e, u.ID, repo.ID, false); err != nil {
if err = watchRepo(e, member.ID, repo.ID, false); err != nil {
return err
}
}
@@ -260,9 +265,9 @@ func NewTeam(t *Team) error {
return sess.Commit()
}
func getTeam(e Engine, orgId int64, name string) (*Team, error) {
func getTeamOfOrgByName(e Engine, orgID int64, name string) (*Team, error) {
t := &Team{
OrgID: orgId,
OrgID: orgID,
LowerName: strings.ToLower(name),
}
has, err := e.Get(t)
@@ -274,14 +279,14 @@ func getTeam(e Engine, orgId int64, name string) (*Team, error) {
return t, nil
}
// GetTeam returns team by given team name and organization.
func GetTeam(orgId int64, name string) (*Team, error) {
return getTeam(x, orgId, name)
// GetTeamOfOrgByName returns team by given team name and organization.
func GetTeamOfOrgByName(orgID int64, name string) (*Team, error) {
return getTeamOfOrgByName(x, orgID, name)
}
func getTeamByID(e Engine, teamId int64) (*Team, error) {
func getTeamByID(e Engine, teamID int64) (*Team, error) {
t := new(Team)
has, err := e.Id(teamId).Get(t)
has, err := e.Id(teamID).Get(t)
if err != nil {
return nil, err
} else if !has {
@@ -291,8 +296,18 @@ func getTeamByID(e Engine, teamId int64) (*Team, error) {
}
// GetTeamByID returns team by given ID.
func GetTeamByID(teamId int64) (*Team, error) {
return getTeamByID(x, teamId)
func GetTeamByID(teamID int64) (*Team, error) {
return getTeamByID(x, teamID)
}
func getTeamsByOrgID(e Engine, orgID int64) ([]*Team, error) {
teams := make([]*Team, 0, 3)
return teams, e.Where("org_id = ?", orgID).Find(&teams)
}
// GetTeamsByOrgID returns all teams belong to given organization.
func GetTeamsByOrgID(orgID int64) ([]*Team, error) {
return getTeamsByOrgID(x, orgID)
}
// UpdateTeam updates information of team.
@@ -429,39 +444,34 @@ func GetTeamMembers(teamID int64) ([]*User, error) {
return getTeamMembers(x, teamID)
}
func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) {
tus := make([]*TeamUser, 0, 5)
if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil {
func getUserTeams(e Engine, orgID, userID int64) ([]*Team, error) {
teamUsers := make([]*TeamUser, 0, 5)
if err := e.Where("uid = ?", userID).And("org_id = ?", orgID).Find(&teamUsers); err != nil {
return nil, err
}
ts := make([]*Team, len(tus))
for i, tu := range tus {
t := new(Team)
has, err := e.Id(tu.TeamID).Get(t)
if err != nil {
return nil, err
} else if !has {
return nil, ErrTeamNotExist
}
ts[i] = t
teamIDs := make([]int64, len(teamUsers))
for i := range teamUsers {
teamIDs[i] = teamUsers[i].TeamID
}
return ts, nil
teams := make([]*Team, 0, len(teamIDs))
return teams, e.Where("org_id = ?", orgID).In("id", teamIDs).Find(&teams)
}
// GetUserTeams returns all teams that user belongs to in given organization.
func GetUserTeams(orgId, uid int64) ([]*Team, error) {
return getUserTeams(x, orgId, uid)
func GetUserTeams(orgID, userID int64) ([]*Team, error) {
return getUserTeams(x, orgID, userID)
}
// AddTeamMember adds new membership of given team to given organization,
// the user will have membership to given organization automatically when needed.
func AddTeamMember(orgID, teamID, uid int64) error {
if IsTeamMember(orgID, teamID, uid) {
func AddTeamMember(orgID, teamID, userID int64) error {
if IsTeamMember(orgID, teamID, userID) {
return nil
}
if err := AddOrgUser(orgID, uid); err != nil {
if err := AddOrgUser(orgID, userID); err != nil {
return err
}
@@ -483,7 +493,7 @@ func AddTeamMember(orgID, teamID, uid int64) error {
}
tu := &TeamUser{
UID: uid,
UID: userID,
OrgID: orgID,
TeamID: teamID,
}
@@ -502,7 +512,7 @@ func AddTeamMember(orgID, teamID, uid int64) error {
// We make sure it exists before.
ou := new(OrgUser)
if _, err = sess.Where("uid = ?", uid).And("org_id = ?", orgID).Get(ou); err != nil {
if _, err = sess.Where("uid = ?", userID).And("org_id = ?", orgID).Get(ou); err != nil {
return err
}
ou.NumTeams++
@@ -600,18 +610,18 @@ func RemoveTeamMember(orgID, teamID, uid int64) error {
// TeamRepo represents an team-repository relation.
type TeamRepo struct {
ID int64 `xorm:"pk autoincr"`
ID int64
OrgID int64 `xorm:"INDEX"`
TeamID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
}
func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool {
has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo))
has, _ := e.Where("org_id = ?", orgID).And("team_id = ?", teamID).And("repo_id = ?", repoID).Get(new(TeamRepo))
return has
}
// HasTeamRepo returns true if given repository belongs to team.
// HasTeamRepo returns true if given team has access to the repository of the organization.
func HasTeamRepo(orgID, teamID, repoID int64) bool {
return hasTeamRepo(x, orgID, teamID, repoID)
}
@@ -642,3 +652,13 @@ func removeTeamRepo(e Engine, teamID, repoID int64) error {
func RemoveTeamRepo(teamID, repoID int64) error {
return removeTeamRepo(x, teamID, repoID)
}
// GetTeamsHaveAccessToRepo returns all teams in an organization that have given access level to the repository.
func GetTeamsHaveAccessToRepo(orgID, repoID int64, mode AccessMode) ([]*Team, error) {
teams := make([]*Team, 0, 5)
return teams, x.Where("team.authorize >= ?", mode).
Join("INNER", "team_repo", "team_repo.team_id = team.id").
And("team_repo.org_id = ?", orgID).
And("team_repo.repo_id = ?", repoID).
Find(&teams)
}

View File

@@ -329,14 +329,6 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
return nil
}
// patchConflicts is a list of conflit description from Git.
var patchConflicts = []string{
"patch does not apply",
"already exists in working directory",
"unrecognized input",
"error:",
}
// testPatch checks if patch can be merged to base repository without conflit.
// FIXME: make a mechanism to clean up stable local copies.
func (pr *PullRequest) testPatch() (err error) {
@@ -372,16 +364,9 @@ func (pr *PullRequest) testPatch() (err error) {
fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
"git", "apply", "--check", patchPath)
if err != nil {
for i := range patchConflicts {
if strings.Contains(stderr, patchConflicts[i]) {
log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
}
}
return fmt.Errorf("git apply --check: %v - %s", err, stderr)
log.Trace("PullRequest[%d].testPatch (apply): has conflit\n%s", pr.ID, stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
}
return nil
}
@@ -437,9 +422,10 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
log.Error(4, "NotifyWatchers: %v", err)
} else if err = pull.MailParticipants(); err != nil {
log.Error(4, "MailParticipants: %v", err)
log.Error(2, "NotifyWatchers: %v", err)
}
if err = pull.MailParticipants(); err != nil {
log.Error(2, "MailParticipants: %v", err)
}
pr.Issue = pull
@@ -451,9 +437,8 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
Repository: repo.APIFormat(nil),
Sender: pull.Poster.APIFormat(),
}); err != nil {
log.Error(4, "PrepareWebhooks: %v", err)
log.Error(2, "PrepareWebhooks: %v", err)
}
go HookQueue.Add(repo.ID)
return nil
}

View File

@@ -11,8 +11,10 @@ import (
"time"
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/process"
)
@@ -21,6 +23,7 @@ import (
type Release struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64
Repo *Repository `xorm:"-"`
PublisherID int64
Publisher *User `xorm:"-"`
TagName string
@@ -36,6 +39,8 @@ type Release struct {
Created time.Time `xorm:"-"`
CreatedUnix int64
Attachments []*Attachment `xorm:"-"`
}
func (r *Release) BeforeInsert() {
@@ -51,6 +56,56 @@ func (r *Release) AfterSet(colName string, _ xorm.Cell) {
}
}
func (r *Release) loadAttributes(e Engine) (err error) {
if r.Repo == nil {
r.Repo, err = getRepositoryByID(e, r.RepoID)
if err != nil {
return fmt.Errorf("getRepositoryByID [repo_id: %d]: %v", r.RepoID, err)
}
}
if r.Publisher == nil {
r.Publisher, err = getUserByID(e, r.PublisherID)
if err != nil {
if IsErrUserNotExist(err) {
r.PublisherID = -1
r.Publisher = NewGhostUser()
} else {
return fmt.Errorf("getUserByID.(Publisher) [publisher_id: %d]: %v", r.PublisherID, err)
}
}
}
if r.Attachments == nil {
r.Attachments, err = getAttachmentsByReleaseID(e, r.ID)
if err != nil {
return fmt.Errorf("getAttachmentsByReleaseID [%d]: %v", r.ID, err)
}
}
return nil
}
func (r *Release) LoadAttributes() error {
return r.loadAttributes(x)
}
// This method assumes some fields assigned with values:
// Required - Publisher
func (r *Release) APIFormat() *api.Release {
return &api.Release{
ID: r.ID,
TagName: r.TagName,
TargetCommitish: r.Target,
Name: r.Title,
Body: r.Note,
Draft: r.IsDraft,
Prerelease: r.IsPrerelease,
Author: r.Publisher.APIFormat(),
Created: r.Created,
}
}
// IsReleaseExist returns true if release with given tag name already exists.
func IsReleaseExist(repoID int64, tagName string) (bool, error) {
if len(tagName) == 0 {
@@ -60,31 +115,31 @@ func IsReleaseExist(repoID int64, tagName string) (bool, error) {
return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
}
func createTag(gitRepo *git.Repository, rel *Release) error {
func createTag(gitRepo *git.Repository, r *Release) error {
// Only actual create when publish.
if !rel.IsDraft {
if !gitRepo.IsTagExist(rel.TagName) {
commit, err := gitRepo.GetBranchCommit(rel.Target)
if !r.IsDraft {
if !gitRepo.IsTagExist(r.TagName) {
commit, err := gitRepo.GetBranchCommit(r.Target)
if err != nil {
return fmt.Errorf("GetBranchCommit: %v", err)
}
// Trim '--' prefix to prevent command line argument vulnerability.
rel.TagName = strings.TrimPrefix(rel.TagName, "--")
if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
r.TagName = strings.TrimPrefix(r.TagName, "--")
if err = gitRepo.CreateTag(r.TagName, commit.ID.String()); err != nil {
if strings.Contains(err.Error(), "is not a valid tag name") {
return ErrInvalidTagName{rel.TagName}
return ErrInvalidTagName{r.TagName}
}
return err
}
} else {
commit, err := gitRepo.GetTagCommit(rel.TagName)
commit, err := gitRepo.GetTagCommit(r.TagName)
if err != nil {
return fmt.Errorf("GetTagCommit: %v", err)
}
rel.Sha1 = commit.ID.String()
rel.NumCommits, err = commit.CommitsCount()
r.Sha1 = commit.ID.String()
r.NumCommits, err = commit.CommitsCount()
if err != nil {
return fmt.Errorf("CommitsCount: %v", err)
}
@@ -93,21 +148,61 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
return nil
}
// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *Release) error {
isExist, err := IsReleaseExist(rel.RepoID, rel.TagName)
func (r *Release) preparePublishWebhooks() {
if err := PrepareWebhooks(r.Repo, HOOK_EVENT_RELEASE, &api.ReleasePayload{
Action: api.HOOK_RELEASE_PUBLISHED,
Release: r.APIFormat(),
Repository: r.Repo.APIFormat(nil),
Sender: r.Publisher.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks: %v", err)
}
}
// NewRelease creates a new release with attachments for repository.
func NewRelease(gitRepo *git.Repository, r *Release, uuids []string) error {
isExist, err := IsReleaseExist(r.RepoID, r.TagName)
if err != nil {
return err
} else if isExist {
return ErrReleaseAlreadyExist{rel.TagName}
return ErrReleaseAlreadyExist{r.TagName}
}
if err = createTag(gitRepo, rel); err != nil {
if err = createTag(gitRepo, r); err != nil {
return err
}
rel.LowerTagName = strings.ToLower(rel.TagName)
_, err = x.InsertOne(rel)
return err
r.LowerTagName = strings.ToLower(r.TagName)
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if _, err = sess.Insert(r); err != nil {
return fmt.Errorf("Insert: %v", err)
}
if len(uuids) > 0 {
if _, err = sess.In("uuid", uuids).Cols("release_id").Update(&Attachment{ReleaseID: r.ID}); err != nil {
return fmt.Errorf("link attachments: %v", err)
}
}
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
// Only send webhook when actually published, skip drafts
if r.IsDraft {
return nil
}
r, err = GetReleaseByID(r.ID)
if err != nil {
return fmt.Errorf("GetReleaseByID: %v", err)
}
r.preparePublishWebhooks()
return nil
}
// GetRelease returns release by given ID.
@@ -119,63 +214,109 @@ func GetRelease(repoID int64, tagName string) (*Release, error) {
return nil, ErrReleaseNotExist{0, tagName}
}
rel := &Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}
_, err = x.Get(rel)
return rel, err
r := &Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}
if _, err = x.Get(r); err != nil {
return nil, fmt.Errorf("Get: %v", err)
}
return r, r.LoadAttributes()
}
// GetReleaseByID returns release with given ID.
func GetReleaseByID(id int64) (*Release, error) {
rel := new(Release)
has, err := x.Id(id).Get(rel)
r := new(Release)
has, err := x.Id(id).Get(r)
if err != nil {
return nil, err
} else if !has {
return nil, ErrReleaseNotExist{id, ""}
}
return rel, nil
return r, r.LoadAttributes()
}
// GetReleasesByRepoID returns a list of releases of repository.
func GetReleasesByRepoID(repoID int64) (rels []*Release, err error) {
err = x.Desc("created_unix").Find(&rels, Release{RepoID: repoID})
return rels, err
// GetPublishedReleasesByRepoID returns a list of published releases of repository.
// If matches is not empty, only published releases in matches will be returned.
// In any case, drafts won't be returned by this function.
func GetPublishedReleasesByRepoID(repoID int64, matches ...string) ([]*Release, error) {
sess := x.Where("repo_id = ?", repoID).And("is_draft = ?", false).Desc("created_unix")
if len(matches) > 0 {
sess.In("tag_name", matches)
}
releases := make([]*Release, 0, 5)
return releases, sess.Find(&releases, new(Release))
}
// GetDraftReleasesByRepoID returns all draft releases of repository.
func GetDraftReleasesByRepoID(repoID int64) ([]*Release, error) {
releases := make([]*Release, 0)
return releases, x.Where("repo_id = ?", repoID).And("is_draft = ?", true).Find(&releases)
}
type ReleaseSorter struct {
rels []*Release
releases []*Release
}
func (rs *ReleaseSorter) Len() int {
return len(rs.rels)
return len(rs.releases)
}
func (rs *ReleaseSorter) Less(i, j int) bool {
diffNum := rs.rels[i].NumCommits - rs.rels[j].NumCommits
diffNum := rs.releases[i].NumCommits - rs.releases[j].NumCommits
if diffNum != 0 {
return diffNum > 0
}
return rs.rels[i].Created.After(rs.rels[j].Created)
return rs.releases[i].Created.After(rs.releases[j].Created)
}
func (rs *ReleaseSorter) Swap(i, j int) {
rs.rels[i], rs.rels[j] = rs.rels[j], rs.rels[i]
rs.releases[i], rs.releases[j] = rs.releases[j], rs.releases[i]
}
// SortReleases sorts releases by number of commits and created time.
func SortReleases(rels []*Release) {
sorter := &ReleaseSorter{rels: rels}
sorter := &ReleaseSorter{releases: rels}
sort.Sort(sorter)
}
// UpdateRelease updates information of a release.
func UpdateRelease(gitRepo *git.Repository, rel *Release) (err error) {
if err = createTag(gitRepo, rel); err != nil {
func UpdateRelease(doer *User, gitRepo *git.Repository, r *Release, isPublish bool, uuids []string) (err error) {
if err = createTag(gitRepo, r); err != nil {
return fmt.Errorf("createTag: %v", err)
}
r.PublisherID = doer.ID
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
_, err = x.Id(rel.ID).AllCols().Update(rel)
return err
if _, err = sess.Id(r.ID).AllCols().Update(r); err != nil {
return fmt.Errorf("Update: %v", err)
}
// Unlink all current attachments and link back later if still valid
if _, err = sess.Exec("UPDATE attachment SET release_id = 0 WHERE release_id = ?", r.ID); err != nil {
return fmt.Errorf("unlink current attachments: %v", err)
}
if len(uuids) > 0 {
if _, err = sess.In("uuid", uuids).Cols("release_id").Update(&Attachment{ReleaseID: r.ID}); err != nil {
return fmt.Errorf("link attachments: %v", err)
}
}
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
if !isPublish {
return nil
}
r.Publisher = doer
r.preparePublishWebhooks()
return nil
}
// DeleteReleaseOfRepoByID deletes a release and corresponding Git tag by given ID.

View File

@@ -6,7 +6,6 @@ package models
import (
"bytes"
"errors"
"fmt"
"html/template"
"io/ioutil"
@@ -29,6 +28,7 @@ import (
git "github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/process"
@@ -38,14 +38,6 @@ import (
var repoWorkingPool = sync.NewExclusivePool()
var (
ErrRepoFileNotExist = errors.New("Repository file does not exist")
ErrRepoFileNotLoaded = errors.New("Repository file not loaded")
ErrMirrorNotExist = errors.New("Mirror does not exist")
ErrInvalidReference = errors.New("Invalid reference specified")
ErrNameEmpty = errors.New("Name is empty")
)
var (
Gitignores, Licenses, Readmes, LabelTemplates []string
@@ -148,7 +140,7 @@ func NewRepoContext() {
RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(setting.AppDataPath, "tmp"))
}
// Repository represents a git repository.
// Repository contains information of a repository.
type Repository struct {
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"UNIQUE(s)"`
@@ -158,6 +150,7 @@ type Repository struct {
Description string
Website string
DefaultBranch string
Size int64 `xorm:"NOT NULL DEFAULT 0"`
NumWatches int
NumStars int
@@ -300,6 +293,19 @@ func (repo *Repository) mustOwner(e Engine) *User {
return repo.Owner
}
func (repo *Repository) UpdateSize() error {
countObject, err := git.GetRepoSize(repo.RepoPath())
if err != nil {
return fmt.Errorf("GetRepoSize: %v", err)
}
repo.Size = countObject.Size + countObject.SizePack
if _, err = x.Id(repo.ID).Cols("size").Update(repo); err != nil {
return fmt.Errorf("update size: %v", err)
}
return nil
}
// ComposeMetas composes a map of metas for rendering external issue tracker URL.
func (repo *Repository) ComposeMetas() map[string]string {
if !repo.EnableExternalTracker {
@@ -329,14 +335,14 @@ func (repo *Repository) DeleteWiki() {
}
}
// getAssignees returns a list of users who can be assigned to issues in this repository.
func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
// getUsersWithAccesMode returns users that have at least given access mode to the repository.
func (repo *Repository) getUsersWithAccesMode(e Engine, mode AccessMode) (_ []*User, err error) {
if err = repo.getOwner(e); err != nil {
return nil, err
}
accesses := make([]*Access, 0, 10)
if err = e.Where("repo_id = ? AND mode >= ?", repo.ID, ACCESS_MODE_READ).Find(&accesses); err != nil {
if err = e.Where("repo_id = ? AND mode >= ?", repo.ID, mode).Find(&accesses); err != nil {
return nil, err
}
@@ -360,7 +366,12 @@ func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
return users, nil
}
// GetAssignees returns all users that have write access and can be assigned to issues
// getAssignees returns a list of users who can be assigned to issues in this repository.
func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
return repo.getUsersWithAccesMode(e, ACCESS_MODE_READ)
}
// GetAssignees returns all users that have read access and can be assigned to issues
// of the repository,
func (repo *Repository) GetAssignees() (_ []*User, err error) {
return repo.getAssignees(x)
@@ -371,6 +382,11 @@ func (repo *Repository) GetAssigneeByID(userID int64) (*User, error) {
return GetAssigneeByID(repo, userID)
}
// GetWriters returns all users that have write access to the repository.
func (repo *Repository) GetWriters() (_ []*User, err error) {
return repo.getUsersWithAccesMode(x, ACCESS_MODE_WRITE)
}
// GetMilestoneByID returns the milestone belongs to repository by given ID.
func (repo *Repository) GetMilestoneByID(milestoneID int64) (*Milestone, error) {
return GetMilestoneByRepoID(repo.ID, milestoneID)
@@ -419,8 +435,8 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin
return fmt.Sprintf("%s/%s/compare/%s...%s", repo.MustOwner().Name, repo.Name, oldCommitID, newCommitID)
}
func (repo *Repository) HasAccess(u *User) bool {
has, _ := HasAccess(u, repo, ACCESS_MODE_READ)
func (repo *Repository) HasAccess(userID int64) bool {
has, _ := HasAccess(userID, repo, ACCESS_MODE_READ)
return has
}
@@ -618,8 +634,8 @@ func wikiRemoteURL(remote string) string {
}
// MigrateRepository migrates a existing repository from other project hosting.
func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
repo, err := CreateRepository(u, CreateRepoOptions{
func MigrateRepository(doer, owner *User, opts MigrateRepoOptions) (*Repository, error) {
repo, err := CreateRepository(doer, owner, CreateRepoOptions{
Name: opts.Name,
Description: opts.Description,
IsPrivate: opts.IsPrivate,
@@ -629,11 +645,11 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
return nil, err
}
repoPath := RepoPath(u.Name, opts.Name)
wikiPath := WikiPath(u.Name, opts.Name)
repoPath := RepoPath(owner.Name, opts.Name)
wikiPath := WikiPath(owner.Name, opts.Name)
if u.IsOrganization() {
t, err := u.GetOwnerTeam()
if owner.IsOrganization() {
t, err := owner.GetOwnerTeam()
if err != nil {
return nil, err
}
@@ -655,14 +671,14 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
wikiRemotePath := wikiRemoteURL(opts.RemoteAddr)
if len(wikiRemotePath) > 0 {
RemoveAllWithNotice("Repository wiki path erase before creation", repoPath)
RemoveAllWithNotice("Repository wiki path erase before creation", wikiPath)
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{
Mirror: true,
Quiet: true,
Timeout: migrateTimeout,
}); err != nil {
log.Trace("Fail to clone wiki: %v", err)
RemoveAllWithNotice("Delete repository wiki for initialization failure", repoPath)
RemoveAllWithNotice("Delete repository wiki for initialization failure", wikiPath)
}
}
@@ -872,8 +888,8 @@ func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRep
return nil
}
// InitRepository initializes README and .gitignore if needed.
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) (err error) {
// initRepository performs initial commit with chosen setup files on behave of doer.
func initRepository(e Engine, repoPath string, doer *User, repo *Repository, opts CreateRepoOptions) (err error) {
// Somehow the directory could exist.
if com.IsExist(repoPath) {
return fmt.Errorf("initRepository: path already exists: %s", repoPath)
@@ -898,7 +914,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
}
// Apply changes and commit.
if err = initRepoCommit(tmpDir, u.NewGitSig()); err != nil {
if err = initRepoCommit(tmpDir, doer.NewGitSig()); err != nil {
return fmt.Errorf("initRepoCommit: %v", err)
}
}
@@ -931,32 +947,32 @@ func IsUsableRepoName(name string) error {
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
}
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err error) {
if err = IsUsableRepoName(repo.Name); err != nil {
return err
}
has, err := isRepositoryExist(e, u, repo.Name)
has, err := isRepositoryExist(e, owner, repo.Name)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{u.Name, repo.Name}
return ErrRepoAlreadyExist{owner.Name, repo.Name}
}
if _, err = e.Insert(repo); err != nil {
return err
}
u.NumRepos++
owner.NumRepos++
// Remember visibility preference.
u.LastRepoVisibility = repo.IsPrivate
if err = updateUser(e, u); err != nil {
owner.LastRepoVisibility = repo.IsPrivate
if err = updateUser(e, owner); err != nil {
return fmt.Errorf("updateUser: %v", err)
}
// Give access to all members in owner team.
if u.IsOrganization() {
t, err := u.getOwnerTeam(e)
if owner.IsOrganization() {
t, err := owner.getOwnerTeam(e)
if err != nil {
return fmt.Errorf("getOwnerTeam: %v", err)
} else if err = t.addRepository(e, repo); err != nil {
@@ -969,9 +985,9 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
}
}
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
if err = watchRepo(e, owner.ID, repo.ID, true); err != nil {
return fmt.Errorf("watchRepo: %v", err)
} else if err = newRepoAction(e, u, repo); err != nil {
} else if err = newRepoAction(e, doer, owner, repo); err != nil {
return fmt.Errorf("newRepoAction: %v", err)
}
@@ -979,14 +995,14 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
}
// CreateRepository creates a repository for given user or organization.
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
if !u.CanCreateRepo() {
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) {
if !owner.CanCreateRepo() {
return nil, ErrReachLimitOfRepo{owner.MaxRepoCreation}
}
repo := &Repository{
OwnerID: u.ID,
Owner: u,
OwnerID: owner.ID,
Owner: owner,
Name: opts.Name,
LowerName: strings.ToLower(opts.Name),
Description: opts.Description,
@@ -1002,23 +1018,23 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
return nil, err
}
if err = createRepository(sess, u, repo); err != nil {
if err = createRepository(sess, doer, owner, repo); err != nil {
return nil, err
}
// No need for init mirror.
if !opts.IsMirror {
repoPath := RepoPath(u.Name, repo.Name)
if err = initRepository(sess, repoPath, u, repo, opts); err != nil {
repoPath := RepoPath(owner.Name, repo.Name)
if err = initRepository(sess, repoPath, doer, repo, opts); err != nil {
RemoveAllWithNotice("Delete repository for initialization failure", repoPath)
return nil, fmt.Errorf("initRepository: %v", err)
}
_, stderr, err := process.ExecDir(-1,
repoPath, fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath),
repoPath, fmt.Sprintf("CreateRepository 'git update-server-info': %s", repoPath),
"git", "update-server-info")
if err != nil {
return nil, errors.New("CreateRepository(git update-server-info): " + stderr)
return nil, fmt.Errorf("CreateRepository 'git update-server-info': %s", stderr)
}
}
@@ -1391,6 +1407,8 @@ func DeleteRepository(uid, repoID int64) error {
&Release{RepoID: repoID},
&Collaboration{RepoID: repoID},
&PullRequest{BaseRepoID: repoID},
&ProtectBranch{RepoID: repoID},
&ProtectBranchWhitelist{RepoID: repoID},
); err != nil {
return fmt.Errorf("deleteBeans: %v", err)
}
@@ -1462,7 +1480,7 @@ func DeleteRepository(uid, repoID int64) error {
func GetRepositoryByRef(ref string) (*Repository, error) {
n := strings.IndexByte(ref, byte('/'))
if n < 2 {
return nil, ErrInvalidReference
return nil, errors.InvalidRepoReference{ref}
}
userName, repoName := ref[:n], ref[n+1:]
@@ -1552,6 +1570,7 @@ func GetRepositoryCount(u *User) (int64, error) {
type SearchRepoOptions struct {
Keyword string
OwnerID int64
UserID int64 // When set results will contain all public/private repositories user has access to
OrderBy string
Private bool // Include private repositories in results
Page int
@@ -1571,14 +1590,22 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int
}
repos = make([]*Repository, 0, opts.PageSize)
// Append conditions
sess := x.Where("LOWER(lower_name) LIKE ?", "%"+opts.Keyword+"%")
if opts.OwnerID > 0 {
sess.And("owner_id = ?", opts.OwnerID)
sess := x.Alias("repo")
// Attempt to find repositories that opts.UserID has access to,
// this does not include other people's private repositories even if opts.UserID is an admin.
if !opts.Private && opts.UserID > 0 {
sess.Join("LEFT", "access", "access.repo_id = repo.id").
Where("repo.lower_name LIKE ? AND (repo.owner_id = ? OR access.user_id = ? OR repo.is_private = ?)",
"%"+opts.Keyword+"%", opts.UserID, opts.UserID, false)
} else {
sess.Where("repo.lower_name LIKE ?", "%"+opts.Keyword+"%")
// Only return public repositories if opts.Private is not set
if !opts.Private {
sess.And("repo.is_private = ?", false)
}
}
if !opts.Private {
sess.And("is_private=?", false)
if opts.OwnerID > 0 {
sess.And("repo.owner_id = ?", opts.OwnerID)
}
var countSess xorm.Session
@@ -1589,7 +1616,7 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int
}
if len(opts.OrderBy) > 0 {
sess.OrderBy(opts.OrderBy)
sess.OrderBy("repo." + opts.OrderBy)
}
return repos, count, sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&repos)
}
@@ -2056,25 +2083,28 @@ func (repo *Repository) GetWatchers(page int) ([]*User, error) {
func notifyWatchers(e Engine, act *Action) error {
// Add feeds for user self and all watchers.
watches, err := getWatchers(e, act.RepoID)
watchers, err := getWatchers(e, act.RepoID)
if err != nil {
return fmt.Errorf("get watchers: %v", err)
return fmt.Errorf("getWatchers: %v", err)
}
// Reset ID to reuse Action object
act.ID = 0
// Add feed for actioner.
act.UserID = act.ActUserID
if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new actioner: %v", err)
if _, err = e.Insert(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
for i := range watches {
if act.ActUserID == watches[i].UserID {
for i := range watchers {
if act.ActUserID == watchers[i].UserID {
continue
}
act.ID = 0
act.UserID = watches[i].UserID
if _, err = e.InsertOne(act); err != nil {
act.UserID = watchers[i].UserID
if _, err = e.Insert(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
}
@@ -2149,24 +2179,26 @@ func (repo *Repository) GetStargazers(page int) ([]*User, error) {
// \___ / \____/|__| |__|_ \
// \/ \/
// HasForkedRepo checks if given user has already forked a repository with given ID.
// HasForkedRepo checks if given user has already forked a repository.
// When user has already forked, it returns true along with the repository.
func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
repo := new(Repository)
has, _ := x.Where("owner_id=? AND fork_id=?", ownerID, repoID).Get(repo)
has, _ := x.Where("owner_id = ? AND fork_id = ?", ownerID, repoID).Get(repo)
return repo, has
}
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
// ForkRepository creates a fork of target repository under another user domain.
func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string) (_ *Repository, err error) {
repo := &Repository{
OwnerID: u.ID,
Owner: u,
OwnerID: owner.ID,
Owner: owner,
Name: name,
LowerName: strings.ToLower(name),
Description: desc,
DefaultBranch: oldRepo.DefaultBranch,
IsPrivate: oldRepo.IsPrivate,
DefaultBranch: baseRepo.DefaultBranch,
IsPrivate: baseRepo.IsPrivate,
IsFork: true,
ForkID: oldRepo.ID,
ForkID: baseRepo.ID,
}
sess := x.NewSession()
@@ -2175,18 +2207,16 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
return nil, err
}
if err = createRepository(sess, u, repo); err != nil {
if err = createRepository(sess, doer, owner, repo); err != nil {
return nil, err
} else if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", baseRepo.ID); err != nil {
return nil, err
}
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil {
return nil, err
}
repoPath := RepoPath(u.Name, repo.Name)
repoPath := repo.repoPath(sess)
_, stderr, err := process.ExecTimeout(10*time.Minute,
fmt.Sprintf("ForkRepository 'git clone': %s/%s", u.Name, repo.Name),
"git", "clone", "--bare", oldRepo.RepoPath(), repoPath)
fmt.Sprintf("ForkRepository 'git clone': %s/%s", owner.Name, repo.Name),
"git", "clone", "--bare", baseRepo.RepoPath(), repoPath)
if err != nil {
return nil, fmt.Errorf("git clone: %v", stderr)
}
@@ -2200,6 +2230,12 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
if err = createDelegateHooks(repoPath); err != nil {
return nil, fmt.Errorf("createDelegateHooks: %v", err)
} else if err = prepareWebhooks(sess, baseRepo, HOOK_EVENT_FORK, &api.ForkPayload{
Forkee: repo.APIFormat(nil),
Repo: baseRepo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
return nil, fmt.Errorf("prepareWebhooks: %v", err)
}
return repo, sess.Commit()

View File

@@ -6,13 +6,20 @@ package models
import (
"fmt"
"strings"
"github.com/Unknwon/com"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base"
)
type Branch struct {
Path string
Name string
RepoPath string
Name string
IsProtected bool
Commit *git.Commit
}
func GetBranchesByPath(path string) ([]*Branch, error) {
@@ -29,8 +36,8 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
branches := make([]*Branch, len(brs))
for i := range brs {
branches[i] = &Branch{
Path: path,
Name: brs[i],
RepoPath: path,
Name: brs[i],
}
}
return branches, nil
@@ -41,8 +48,8 @@ func (repo *Repository) GetBranch(br string) (*Branch, error) {
return nil, ErrBranchNotExist{br}
}
return &Branch{
Path: repo.RepoPath(),
Name: br,
RepoPath: repo.RepoPath(),
Name: br,
}, nil
}
@@ -51,13 +58,27 @@ func (repo *Repository) GetBranches() ([]*Branch, error) {
}
func (br *Branch) GetCommit() (*git.Commit, error) {
gitRepo, err := git.OpenRepository(br.Path)
gitRepo, err := git.OpenRepository(br.RepoPath)
if err != nil {
return nil, err
}
return gitRepo.GetBranchCommit(br.Name)
}
type ProtectBranchWhitelist struct {
ID int64
ProtectBranchID int64
RepoID int64 `xorm:"UNIQUE(protect_branch_whitelist)"`
Name string `xorm:"UNIQUE(protect_branch_whitelist)"`
UserID int64 `xorm:"UNIQUE(protect_branch_whitelist)"`
}
// IsUserInProtectBranchWhitelist returns true if given user is in the whitelist of a branch in a repository.
func IsUserInProtectBranchWhitelist(repoID, userID int64, branch string) bool {
has, err := x.Where("repo_id = ?", repoID).And("user_id = ?", userID).And("name = ?", branch).Get(new(ProtectBranchWhitelist))
return has && err == nil
}
// ProtectBranch contains options of a protected branch.
type ProtectBranch struct {
ID int64
@@ -65,6 +86,9 @@ type ProtectBranch struct {
Name string `xorm:"UNIQUE(protect_branch)"`
Protected bool
RequirePullRequest bool
EnableWhitelist bool
WhitelistUserIDs string `xorm:"TEXT"`
WhitelistTeamIDs string `xorm:"TEXT"`
}
// GetProtectBranchOfRepoByName returns *ProtectBranch by branch name in given repostiory.
@@ -94,15 +118,134 @@ func IsBranchOfRepoRequirePullRequest(repoID int64, name string) bool {
// UpdateProtectBranch saves branch protection options.
// If ID is 0, it creates a new record. Otherwise, updates existing record.
func UpdateProtectBranch(protectBranch *ProtectBranch) (err error) {
if protectBranch.ID == 0 {
if _, err = x.Insert(protectBranch); err != nil {
return fmt.Errorf("Insert: %v", err)
}
return
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
_, err = x.Id(protectBranch.ID).AllCols().Update(protectBranch)
return err
if protectBranch.ID == 0 {
if _, err = sess.Insert(protectBranch); err != nil {
return fmt.Errorf("Insert: %v", err)
}
}
if _, err = sess.Id(protectBranch.ID).AllCols().Update(protectBranch); err != nil {
return fmt.Errorf("Update: %v", err)
}
return sess.Commit()
}
// UpdateOrgProtectBranch saves branch protection options of organizational repository.
// If ID is 0, it creates a new record. Otherwise, updates existing record.
// This function also performs check if whitelist user and team's IDs have been changed
// to avoid unnecessary whitelist delete and regenerate.
func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whitelistUserIDs, whitelistTeamIDs string) (err error) {
if err = repo.GetOwner(); err != nil {
return fmt.Errorf("GetOwner: %v", err)
} else if !repo.Owner.IsOrganization() {
return fmt.Errorf("expect repository owner to be an organization")
}
hasUsersChanged := false
validUserIDs := base.StringsToInt64s(strings.Split(protectBranch.WhitelistUserIDs, ","))
if protectBranch.WhitelistUserIDs != whitelistUserIDs {
hasUsersChanged = true
userIDs := base.StringsToInt64s(strings.Split(whitelistUserIDs, ","))
validUserIDs = make([]int64, 0, len(userIDs))
for _, userID := range userIDs {
has, err := HasAccess(userID, repo, ACCESS_MODE_WRITE)
if err != nil {
return fmt.Errorf("HasAccess [user_id: %d, repo_id: %d]: %v", userID, protectBranch.RepoID, err)
} else if !has {
continue // Drop invalid user ID
}
validUserIDs = append(validUserIDs, userID)
}
protectBranch.WhitelistUserIDs = strings.Join(base.Int64sToStrings(validUserIDs), ",")
}
hasTeamsChanged := false
validTeamIDs := base.StringsToInt64s(strings.Split(protectBranch.WhitelistTeamIDs, ","))
if protectBranch.WhitelistTeamIDs != whitelistTeamIDs {
hasTeamsChanged = true
teamIDs := base.StringsToInt64s(strings.Split(whitelistTeamIDs, ","))
teams, err := GetTeamsHaveAccessToRepo(repo.OwnerID, repo.ID, ACCESS_MODE_WRITE)
if err != nil {
return fmt.Errorf("GetTeamsHaveAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
}
validTeamIDs = make([]int64, 0, len(teams))
for i := range teams {
if teams[i].HasWriteAccess() && com.IsSliceContainsInt64(teamIDs, teams[i].ID) {
validTeamIDs = append(validTeamIDs, teams[i].ID)
}
}
protectBranch.WhitelistTeamIDs = strings.Join(base.Int64sToStrings(validTeamIDs), ",")
}
// Merge users and members of teams
var whitelists []*ProtectBranchWhitelist
if hasUsersChanged || hasTeamsChanged {
mergedUserIDs := make(map[int64]bool)
for _, userID := range validUserIDs {
// Empty whitelist users can cause an ID with 0
if userID != 0 {
mergedUserIDs[userID] = true
}
}
for _, teamID := range validTeamIDs {
members, err := GetTeamMembers(teamID)
if err != nil {
return fmt.Errorf("GetTeamMembers [team_id: %d]: %v", teamID, err)
}
for i := range members {
mergedUserIDs[members[i].ID] = true
}
}
whitelists = make([]*ProtectBranchWhitelist, 0, len(mergedUserIDs))
for userID := range mergedUserIDs {
whitelists = append(whitelists, &ProtectBranchWhitelist{
ProtectBranchID: protectBranch.ID,
RepoID: repo.ID,
Name: protectBranch.Name,
UserID: userID,
})
}
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if protectBranch.ID == 0 {
if _, err = sess.Insert(protectBranch); err != nil {
return fmt.Errorf("Insert: %v", err)
}
}
if _, err = sess.Id(protectBranch.ID).AllCols().Update(protectBranch); err != nil {
return fmt.Errorf("Update: %v", err)
}
// Refresh whitelists
if hasUsersChanged || hasTeamsChanged {
if _, err = sess.Delete(&ProtectBranchWhitelist{ProtectBranchID: protectBranch.ID}); err != nil {
return fmt.Errorf("delete old protect branch whitelists: %v", err)
} else if _, err = sess.Insert(whitelists); err != nil {
return fmt.Errorf("insert new protect branch whitelists: %v", err)
}
}
return sess.Commit()
}
// GetProtectBranchesByRepoID returns a list of *ProtectBranch in given repostiory.

View File

@@ -62,17 +62,10 @@ func (repo *Repository) AddCollaborator(u *User) error {
return err
}
if _, err = sess.InsertOne(collaboration); err != nil {
if _, err = sess.Insert(collaboration); err != nil {
return err
}
if repo.Owner.IsOrganization() {
err = repo.recalculateTeamAccesses(sess, 0)
} else {
err = repo.recalculateAccesses(sess)
}
if err != nil {
return fmt.Errorf("recalculateAccesses 'team=%v': %v", repo.Owner.IsOrganization(), err)
} else if err = repo.recalculateAccesses(sess); err != nil {
return fmt.Errorf("recalculateAccesses [repo_id: %v]: %v", repo.ID, err)
}
return sess.Commit()
@@ -148,6 +141,19 @@ func (repo *Repository) ChangeCollaborationAccessMode(userID int64, mode AccessM
}
collaboration.Mode = mode
// If it's an organizational repository, merge with team access level for highest permission
if repo.Owner.IsOrganization() {
teams, err := GetUserTeams(repo.OwnerID, userID)
if err != nil {
return fmt.Errorf("GetUserTeams: [org_id: %d, user_id: %d]: %v", repo.OwnerID, userID, err)
}
for i := range teams {
if mode < teams[i].Authorize {
mode = teams[i].Authorize
}
}
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
@@ -173,7 +179,7 @@ func (repo *Repository) ChangeCollaborationAccessMode(userID int64, mode AccessM
_, err = sess.Insert(access)
}
if err != nil {
return fmt.Errorf("update access table: %v", err)
return fmt.Errorf("update/insert access table: %v", err)
}
return sess.Commit()

View File

@@ -527,6 +527,7 @@ func RewriteAllPublicKeys() error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
os.MkdirAll(setting.SSH.RootPath, os.ModePerm)
fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
tmpPath := fpath + ".tmp"
f, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
@@ -736,7 +737,7 @@ func DeleteDeployKey(doer *User, id int64) error {
if err != nil {
return fmt.Errorf("GetRepositoryByID: %v", err)
}
yes, err := HasAccess(doer, repo, ACCESS_MODE_ADMIN)
yes, err := HasAccess(doer.ID, repo, ACCESS_MODE_ADMIN)
if err != nil {
return fmt.Errorf("HasAccess: %v", err)
} else if !yes {

View File

@@ -10,8 +10,6 @@ import (
"os/exec"
"strings"
log "gopkg.in/clog.v1"
git "github.com/gogits/git-module"
)
@@ -29,6 +27,10 @@ func CommitToPushCommit(commit *git.Commit) *PushCommit {
}
func ListToPushCommits(l *list.List) *PushCommits {
if l == nil {
return &PushCommits{}
}
commits := make([]*PushCommit, 0)
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
@@ -68,12 +70,6 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
}
if isDelRef {
log.Trace("Reference '%s' has been deleted from '%s/%s' by %s",
opts.RefFullName, opts.RepoUserName, opts.RepoName, opts.PusherName)
return nil
}
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
@@ -89,7 +85,11 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
return fmt.Errorf("GetRepositoryByName: %v", err)
}
// Push tags.
if err = repo.UpdateSize(); err != nil {
return fmt.Errorf("UpdateSize: %v", err)
}
// Push tags
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
if err := CommitRepoAction(CommitRepoActionOptions{
PusherName: opts.PusherName,
@@ -100,27 +100,30 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
NewCommitID: opts.NewCommitID,
Commits: &PushCommits{},
}); err != nil {
return fmt.Errorf("CommitRepoAction (tag): %v", err)
return fmt.Errorf("CommitRepoAction.(tag): %v", err)
}
return nil
}
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
return fmt.Errorf("gitRepo.GetCommit: %v", err)
}
// Push new branch.
var l *list.List
if isNewRef {
l, err = newCommit.CommitsBeforeLimit(10)
// Skip read parent commits when delete branch
if !isDelRef {
// Push new branch
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
return fmt.Errorf("GetCommit [commit_id: %s]: %v", opts.NewCommitID, err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
if isNewRef {
l, err = newCommit.CommitsBeforeLimit(10)
if err != nil {
return fmt.Errorf("CommitsBeforeLimit [commit_id: %s]: %v", newCommit.ID, err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
return fmt.Errorf("CommitsBeforeUntil [commit_id: %s]: %v", opts.OldCommitID, err)
}
}
}
@@ -133,7 +136,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
NewCommitID: opts.NewCommitID,
Commits: ListToPushCommits(l),
}); err != nil {
return fmt.Errorf("CommitRepoAction (branch): %v", err)
return fmt.Errorf("CommitRepoAction.(branch): %v", err)
}
return nil
}

View File

@@ -10,7 +10,6 @@ import (
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
"errors"
"fmt"
"image"
_ "image/jpeg"
@@ -30,6 +29,7 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/markdown"
@@ -43,15 +43,6 @@ const (
USER_TYPE_ORGANIZATION
)
var (
ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
ErrEmailNotExist = errors.New("E-mail does not exist")
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
ErrUserNameIllegal = errors.New("User name contains illegal characters")
ErrLoginSourceNotActived = errors.New("Login source is not actived")
ErrUnsupportedLoginType = errors.New("Login source is unknown")
)
// User represents the object of individual and member of organization.
type User struct {
ID int64 `xorm:"pk autoincr"`
@@ -385,18 +376,18 @@ func (u *User) DeleteAvatar() error {
// IsAdminOfRepo returns true if user has admin or higher access of repository.
func (u *User) IsAdminOfRepo(repo *Repository) bool {
has, err := HasAccess(u, repo, ACCESS_MODE_ADMIN)
has, err := HasAccess(u.ID, repo, ACCESS_MODE_ADMIN)
if err != nil {
log.Error(3, "HasAccess: %v", err)
log.Error(2, "HasAccess: %v", err)
}
return has
}
// IsWriterOfRepo returns true if user has write access to given repository.
func (u *User) IsWriterOfRepo(repo *Repository) bool {
has, err := HasAccess(u, repo, ACCESS_MODE_WRITE)
has, err := HasAccess(u.ID, repo, ACCESS_MODE_WRITE)
if err != nil {
log.Error(3, "HasAccess: %v", err)
log.Error(2, "HasAccess: %v", err)
}
return has
}
@@ -448,18 +439,18 @@ func (u *User) GetOwnedOrganizations() (err error) {
}
// GetOrganizations returns all organizations that user belongs to.
func (u *User) GetOrganizations(all bool) error {
ous, err := GetOrgUsersByUserID(u.ID, all)
func (u *User) GetOrganizations(showPrivate bool) error {
orgIDs, err := GetOrgIDsByUserID(u.ID, showPrivate)
if err != nil {
return err
return fmt.Errorf("GetOrgIDsByUserID: %v", err)
}
if len(orgIDs) == 0 {
return nil
}
u.Orgs = make([]*User, len(ous))
for i, ou := range ous {
u.Orgs[i], err = GetUserByID(ou.OrgID)
if err != nil {
return err
}
u.Orgs = make([]*User, 0, len(orgIDs))
if err = x.Where("type = ?", USER_TYPE_ORGANIZATION).In("id", orgIDs).Find(&u.Orgs); err != nil {
return err
}
return nil
}
@@ -519,7 +510,7 @@ var (
func isUsableName(names, patterns []string, name string) error {
name = strings.TrimSpace(strings.ToLower(name))
if utf8.RuneCountInString(name) == 0 {
return ErrNameEmpty
return errors.EmptyName{}
}
for i := range names {
@@ -685,7 +676,13 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return fmt.Errorf("Delete repository wiki local copy: %v", err)
}
return os.Rename(UserPath(u.Name), UserPath(newUserName))
// Rename or create user base directory
baseDir := UserPath(u.Name)
newBaseDir := UserPath(newUserName)
if com.IsExist(baseDir) {
return os.Rename(baseDir, newBaseDir)
}
return os.MkdirAll(newBaseDir, os.ModePerm)
}
func updateUser(e Engine, u *User) error {
@@ -884,11 +881,11 @@ func UserPath(userName string) string {
func GetUserByKeyID(keyID int64) (*User, error) {
user := new(User)
has, err := x.Sql("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyID).Get(user)
has, err := x.SQL("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyID).Get(user)
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotKeyOwner
return nil, errors.UserNotKeyOwner{keyID}
}
return user, nil
}
@@ -911,7 +908,7 @@ func GetUserByID(id int64) (*User, error) {
// GetAssigneeByID returns the user with write access of repository by given ID.
func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
has, err := HasAccess(&User{ID: userID}, repo, ACCESS_MODE_READ)
has, err := HasAccess(userID, repo, ACCESS_MODE_READ)
if err != nil {
return nil, err
} else if !has {

View File

@@ -7,6 +7,8 @@ package models
import (
"fmt"
"strings"
"github.com/gogits/gogs/models/errors"
)
// EmailAdresses is the list of all email addresses of a user. Can contain the
@@ -163,11 +165,11 @@ func MakeEmailPrimary(email *EmailAddress) error {
if err != nil {
return err
} else if !has {
return ErrEmailNotExist
return errors.EmailNotFound{email.Email}
}
if !email.IsActivated {
return ErrEmailNotActivated
return errors.EmailNotVerified{email.Email}
}
user := &User{ID: email.UID}

View File

@@ -5,7 +5,10 @@
package models
import (
"crypto/hmac"
"crypto/sha256"
"crypto/tls"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
@@ -59,9 +62,14 @@ func IsValidHookContentType(name string) bool {
}
type HookEvents struct {
Create bool `json:"create"`
Push bool `json:"push"`
PullRequest bool `json:"pull_request"`
Create bool `json:"create"`
Delete bool `json:"delete"`
Fork bool `json:"fork"`
Push bool `json:"push"`
Issues bool `json:"issues"`
IssueComment bool `json:"issue_comment"`
PullRequest bool `json:"pull_request"`
Release bool `json:"release"`
}
// HookEvent represents events that will delivery hook.
@@ -118,7 +126,7 @@ func (w *Webhook) AfterSet(colName string, _ xorm.Cell) {
case "events":
w.HookEvent = &HookEvent{}
if err = json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
log.Error(3, "Unmarshal[%d]: %v", w.ID, err)
log.Error(3, "Unmarshal [%d]: %v", w.ID, err)
}
case "created_unix":
w.Created = time.Unix(w.CreatedUnix, 0).Local()
@@ -130,7 +138,7 @@ func (w *Webhook) AfterSet(colName string, _ xorm.Cell) {
func (w *Webhook) GetSlackHook() *SlackMeta {
s := &SlackMeta{}
if err := json.Unmarshal([]byte(w.Meta), s); err != nil {
log.Error(4, "webhook.GetSlackHook(%d): %v", w.ID, err)
log.Error(2, "GetSlackHook [%d]: %v", w.ID, err)
}
return s
}
@@ -153,28 +161,69 @@ func (w *Webhook) HasCreateEvent() bool {
(w.ChooseEvents && w.HookEvents.Create)
}
// HasDeleteEvent returns true if hook enabled delete event.
func (w *Webhook) HasDeleteEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Delete)
}
// HasForkEvent returns true if hook enabled fork event.
func (w *Webhook) HasForkEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Fork)
}
// HasPushEvent returns true if hook enabled push event.
func (w *Webhook) HasPushEvent() bool {
return w.PushOnly || w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Push)
}
// HasIssuesEvent returns true if hook enabled issues event.
func (w *Webhook) HasIssuesEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Issues)
}
// HasIssueCommentEvent returns true if hook enabled issue comment event.
func (w *Webhook) HasIssueCommentEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.IssueComment)
}
// HasPullRequestEvent returns true if hook enabled pull request event.
func (w *Webhook) HasPullRequestEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequest)
}
// HasReleaseEvent returns true if hook enabled release event.
func (w *Webhook) HasReleaseEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Release)
}
type eventChecker struct {
checker func() bool
typ HookEventType
}
func (w *Webhook) EventsArray() []string {
events := make([]string, 0, 3)
if w.HasCreateEvent() {
events = append(events, "create")
events := make([]string, 0, 7)
eventCheckers := []eventChecker{
{w.HasCreateEvent, HOOK_EVENT_CREATE},
{w.HasDeleteEvent, HOOK_EVENT_DELETE},
{w.HasForkEvent, HOOK_EVENT_FORK},
{w.HasPushEvent, HOOK_EVENT_PUSH},
{w.HasIssuesEvent, HOOK_EVENT_ISSUES},
{w.HasIssueCommentEvent, HOOK_EVENT_ISSUE_COMMENT},
{w.HasPullRequestEvent, HOOK_EVENT_PULL_REQUEST},
{w.HasReleaseEvent, HOOK_EVENT_RELEASE},
}
if w.HasPushEvent() {
events = append(events, "push")
}
if w.HasPullRequestEvent() {
events = append(events, "pull_request")
for _, c := range eventCheckers {
if c.checker() {
events = append(events, string(c.typ))
}
}
return events
}
@@ -197,8 +246,17 @@ func getWebhook(bean *Webhook) (*Webhook, error) {
return bean, nil
}
// GetWebhookByRepoID returns webhook of repository by given ID.
func GetWebhookByRepoID(repoID, id int64) (*Webhook, error) {
// GetWebhookByID returns webhook by given ID.
// Use this function with caution of accessing unauthorized webhook,
// which means should only be used in non-user interactive functions.
func GetWebhookByID(id int64) (*Webhook, error) {
return getWebhook(&Webhook{
ID: id,
})
}
// GetWebhookOfRepoByID returns webhook of repository by given ID.
func GetWebhookOfRepoByID(repoID, id int64) (*Webhook, error) {
return getWebhook(&Webhook{
ID: id,
RepoID: repoID,
@@ -213,10 +271,10 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
})
}
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
// getActiveWebhooksByRepoID returns all active webhooks of repository.
func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
return webhooks, x.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
return webhooks, e.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
}
// GetWebhooksByRepoID returns all webhooks of a repository.
@@ -271,10 +329,10 @@ func GetWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
return ws, err
}
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
err = x.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
return ws, err
// getActiveWebhooksByOrgID returns all active webhooks for an organization.
func getActiveWebhooksByOrgID(e Engine, orgID int64) ([]*Webhook, error) {
ws := make([]*Webhook, 0, 3)
return ws, e.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
}
// ___ ___ __ ___________ __
@@ -293,8 +351,9 @@ const (
)
var hookTaskTypes = map[string]HookTaskType{
"gogs": GOGS,
"slack": SLACK,
"gogs": GOGS,
"slack": SLACK,
"discord": DISCORD,
}
// ToHookTaskType returns HookTaskType by given name.
@@ -308,6 +367,8 @@ func (t HookTaskType) Name() string {
return "gogs"
case SLACK:
return "slack"
case DISCORD:
return "discord"
}
return ""
}
@@ -321,9 +382,14 @@ func IsValidHookTaskType(name string) bool {
type HookEventType string
const (
HOOK_EVENT_CREATE HookEventType = "create"
HOOK_EVENT_PUSH HookEventType = "push"
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
HOOK_EVENT_CREATE HookEventType = "create"
HOOK_EVENT_DELETE HookEventType = "delete"
HOOK_EVENT_FORK HookEventType = "fork"
HOOK_EVENT_PUSH HookEventType = "push"
HOOK_EVENT_ISSUES HookEventType = "issues"
HOOK_EVENT_ISSUE_COMMENT HookEventType = "issue_comment"
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
HOOK_EVENT_RELEASE HookEventType = "release"
)
// HookRequest represents hook task request information.
@@ -346,6 +412,7 @@ type HookTask struct {
UUID string
Type HookTaskType
URL string `xorm:"TEXT"`
Signature string `xorm:"TEXT"`
api.Payloader `xorm:"-"`
PayloadContent string `xorm:"TEXT"`
ContentType HookContentType
@@ -414,16 +481,16 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Where("hook_id=?", hookID).Desc("id").Find(&tasks)
}
// CreateHookTask creates a new hook task,
// createHookTask creates a new hook task,
// it handles conversion from Payload to PayloadContent.
func CreateHookTask(t *HookTask) error {
func createHookTask(e Engine, t *HookTask) error {
data, err := t.Payloader.JSONPayload()
if err != nil {
return err
}
t.UUID = gouuid.NewV4().String()
t.PayloadContent = string(data)
_, err = x.Insert(t)
_, err = e.Insert(t)
return err
}
@@ -433,42 +500,47 @@ func UpdateHookTask(t *HookTask) error {
return err
}
// PrepareWebhooks adds new webhooks to task queue for given payload.
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
ws, err := GetActiveWebhooksByRepoID(repo.ID)
if err != nil {
return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
}
// check if repo belongs to org and append additional webhooks
if repo.MustOwner().IsOrganization() {
// get hooks for org
orgws, err := GetActiveWebhooksByOrgID(repo.OwnerID)
if err != nil {
return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
}
ws = append(ws, orgws...)
}
if len(ws) == 0 {
// prepareHookTasks adds list of webhooks to task queue.
func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
if len(webhooks) == 0 {
return nil
}
var payloader api.Payloader
for _, w := range ws {
for _, w := range webhooks {
switch event {
case HOOK_EVENT_CREATE:
if !w.HasCreateEvent() {
continue
}
case HOOK_EVENT_DELETE:
if !w.HasDeleteEvent() {
continue
}
case HOOK_EVENT_FORK:
if !w.HasForkEvent() {
continue
}
case HOOK_EVENT_PUSH:
if !w.HasPushEvent() {
continue
}
case HOOK_EVENT_ISSUES:
if !w.HasIssuesEvent() {
continue
}
case HOOK_EVENT_ISSUE_COMMENT:
if !w.HasIssueCommentEvent() {
continue
}
case HOOK_EVENT_PULL_REQUEST:
if !w.HasPullRequestEvent() {
continue
}
case HOOK_EVENT_RELEASE:
if !w.HasReleaseEvent() {
continue
}
}
// Use separate objects so modifcations won't be made on payload on non-Gogs type hooks.
@@ -484,32 +556,81 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
return fmt.Errorf("GetDiscordPayload: %v", err)
}
default:
p.SetSecret(w.Secret)
payloader = p
}
if err = CreateHookTask(&HookTask{
var signature string
if len(w.Secret) > 0 {
data, err := payloader.JSONPayload()
if err != nil {
log.Error(2, "prepareWebhooks.JSONPayload: %v", err)
}
sig := hmac.New(sha256.New, []byte(w.Secret))
sig.Write(data)
signature = hex.EncodeToString(sig.Sum(nil))
}
if err = createHookTask(e, &HookTask{
RepoID: repo.ID,
HookID: w.ID,
Type: w.HookTaskType,
URL: w.URL,
Signature: signature,
Payloader: payloader,
ContentType: w.ContentType,
EventType: event,
IsSSL: w.IsSSL,
}); err != nil {
return fmt.Errorf("CreateHookTask: %v", err)
return fmt.Errorf("createHookTask: %v", err)
}
}
// It's safe to fail when the whole function is called during hook execution
// because resource released after exit.
// FIXME: need a more safe way to not call this function if it's during hook execution.
go HookQueue.Add(repo.ID)
return nil
}
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error {
webhooks, err := getActiveWebhooksByRepoID(e, repo.ID)
if err != nil {
return fmt.Errorf("getActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
}
// check if repo belongs to org and append additional webhooks
if repo.mustOwner(e).IsOrganization() {
// get hooks for org
orgws, err := getActiveWebhooksByOrgID(e, repo.OwnerID)
if err != nil {
return fmt.Errorf("getActiveWebhooksByOrgID [%d]: %v", repo.OwnerID, err)
}
webhooks = append(webhooks, orgws...)
}
return prepareHookTasks(e, repo, event, p, webhooks)
}
// PrepareWebhooks adds all active webhooks to task queue.
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
return prepareWebhooks(x, repo, event, p)
}
// TestWebhook adds the test webhook matches the ID to task queue.
func TestWebhook(repo *Repository, event HookEventType, p api.Payloader, webhookID int64) error {
webhook, err := GetWebhookOfRepoByID(repo.ID, webhookID)
if err != nil {
return fmt.Errorf("GetWebhookOfRepoByID [repo_id: %d, id: %d]: %v", repo.ID, webhookID, err)
}
return prepareHookTasks(x, repo, event, p, []*Webhook{webhook})
}
func (t *HookTask) deliver() {
t.IsDelivered = true
timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second
req := httplib.Post(t.URL).SetTimeout(timeout, timeout).
Header("X-Gogs-Delivery", t.UUID).
Header("X-Gogs-Signature", t.Signature).
Header("X-Gogs-Event", string(t.EventType)).
SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify})
@@ -541,9 +662,9 @@ func (t *HookTask) deliver() {
}
// Update webhook last delivery status.
w, err := GetWebhookByRepoID(t.RepoID, t.HookID)
w, err := GetWebhookByID(t.HookID)
if err != nil {
log.Error(5, "GetWebhookByID: %v", err)
log.Error(3, "GetWebhookByID: %v", err)
return
}
if t.IsSucceed {
@@ -552,7 +673,7 @@ func (t *HookTask) deliver() {
w.LastStatus = HOOK_STATUS_FAILED
}
if err = UpdateWebhook(w); err != nil {
log.Error(5, "UpdateWebhook: %v", err)
log.Error(3, "UpdateWebhook: %v", err)
return
}
}()

View File

@@ -12,6 +12,8 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/setting"
)
type DiscordEmbedFooterObject struct {
@@ -46,8 +48,6 @@ type DiscordPayload struct {
Embeds []*DiscordEmbedObject `json:"embeds"`
}
func (p *DiscordPayload) SetSecret(_ string) {}
func (p *DiscordPayload) JSONPayload() ([]byte, error) {
data, err := json.MarshalIndent(p, "", " ")
if err != nil {
@@ -56,6 +56,10 @@ func (p *DiscordPayload) JSONPayload() ([]byte, error) {
return data, nil
}
func DiscordTextFormatter(s string) string {
return strings.Split(s, "\n")[0]
}
func DiscordLinkFormatter(url string, text string) string {
return fmt.Sprintf("[%s](%s)", text, url)
}
@@ -64,21 +68,50 @@ func DiscordSHALinkFormatter(url string, text string) string {
return fmt.Sprintf("[`%s`](%s)", text, url)
}
func getDiscordCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*DiscordPayload, error) {
// Created tag/branch
// getDiscordCreatePayload composes Discord payload for create new branch or tag.
func getDiscordCreatePayload(p *api.CreatePayload) (*DiscordPayload, error) {
refName := git.RefEndName(p.Ref)
repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
refLink := DiscordLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
content := fmt.Sprintf("Created new %s: %s/%s", p.RefType, repoLink, refLink)
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
return &DiscordPayload{
Username: slack.Username,
AvatarURL: slack.IconURL,
Embeds: []*DiscordEmbedObject{{
Description: content,
Color: int(color),
URL: setting.AppUrl + p.Sender.UserName,
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
},
}},
}, nil
}
// getDiscordDeletePayload composes Discord payload for delete a branch or tag.
func getDiscordDeletePayload(p *api.DeletePayload) (*DiscordPayload, error) {
refName := git.RefEndName(p.Ref)
repoLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
content := fmt.Sprintf("Deleted %s: %s/%s", p.RefType, repoLink, refName)
return &DiscordPayload{
Embeds: []*DiscordEmbedObject{{
Description: content,
URL: setting.AppUrl + p.Sender.UserName,
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
},
}},
}, nil
}
// getDiscordForkPayload composes Discord payload for forked by a repository.
func getDiscordForkPayload(p *api.ForkPayload) (*DiscordPayload, error) {
baseLink := DiscordLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
forkLink := DiscordLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
content := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
return &DiscordPayload{
Embeds: []*DiscordEmbedObject{{
Description: content,
URL: setting.AppUrl + p.Sender.UserName,
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
@@ -113,7 +146,7 @@ func getDiscordPushPayload(p *api.PushPayload, slack *SlackMeta) (*DiscordPayloa
// for each commit, generate attachment text
for i, commit := range p.Commits {
content += fmt.Sprintf("%s %s - %s", DiscordSHALinkFormatter(commit.URL, commit.ID[:7]), SlackShortTextFormatter(commit.Message), commit.Author.Name)
content += fmt.Sprintf("%s %s - %s", DiscordSHALinkFormatter(commit.URL, commit.ID[:7]), DiscordTextFormatter(commit.Message), commit.Author.Name)
// add linebreak to each commit but the last
if i < len(p.Commits)-1 {
content += "\n"
@@ -126,6 +159,7 @@ func getDiscordPushPayload(p *api.PushPayload, slack *SlackMeta) (*DiscordPayloa
AvatarURL: slack.IconURL,
Embeds: []*DiscordEmbedObject{{
Description: content,
URL: setting.AppUrl + p.Sender.UserName,
Color: int(color),
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
@@ -135,6 +169,117 @@ func getDiscordPushPayload(p *api.PushPayload, slack *SlackMeta) (*DiscordPayloa
}, nil
}
func getDiscordIssuesPayload(p *api.IssuesPayload, slack *SlackMeta) (*DiscordPayload, error) {
title := fmt.Sprintf("#%d %s", p.Index, p.Issue.Title)
url := fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Index)
content := ""
fields := make([]*DiscordEmbedFieldObject, 0, 1)
switch p.Action {
case api.HOOK_ISSUE_OPENED:
title = "New issue: " + title
content = p.Issue.Body
case api.HOOK_ISSUE_CLOSED:
title = "Issue closed: " + title
case api.HOOK_ISSUE_REOPENED:
title = "Issue re-opened: " + title
case api.HOOK_ISSUE_EDITED:
title = "Issue edited: " + title
content = p.Issue.Body
case api.HOOK_ISSUE_ASSIGNED:
title = "Issue assigned: " + title
fields = []*DiscordEmbedFieldObject{{
Name: "New Assignee",
Value: p.Issue.Assignee.UserName,
}}
case api.HOOK_ISSUE_UNASSIGNED:
title = "Issue unassigned: " + title
case api.HOOK_ISSUE_LABEL_UPDATED:
title = "Issue labels updated: " + title
labels := make([]string, len(p.Issue.Labels))
for i := range p.Issue.Labels {
labels[i] = p.Issue.Labels[i].Name
}
if len(labels) == 0 {
labels = []string{"<empty>"}
}
fields = []*DiscordEmbedFieldObject{{
Name: "Labels",
Value: strings.Join(labels, ", "),
}}
case api.HOOK_ISSUE_LABEL_CLEARED:
title = "Issue labels cleared: " + title
case api.HOOK_ISSUE_SYNCHRONIZED:
title = "Issue synchronized: " + title
case api.HOOK_ISSUE_MILESTONED:
title = "Issue milestoned: " + title
fields = []*DiscordEmbedFieldObject{{
Name: "New Milestone",
Value: p.Issue.Milestone.Title,
}}
case api.HOOK_ISSUE_DEMILESTONED:
title = "Issue demilestoned: " + title
}
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
return &DiscordPayload{
Username: slack.Username,
AvatarURL: slack.IconURL,
Embeds: []*DiscordEmbedObject{{
Title: title,
Description: content,
URL: url,
Color: int(color),
Footer: &DiscordEmbedFooterObject{
Text: p.Repository.FullName,
},
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
},
Fields: fields,
}},
}, nil
}
func getDiscordIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) (*DiscordPayload, error) {
title := fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title)
url := fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID))
content := ""
fields := make([]*DiscordEmbedFieldObject, 0, 1)
switch p.Action {
case api.HOOK_ISSUE_COMMENT_CREATED:
title = "New comment: " + title
content = p.Comment.Body
case api.HOOK_ISSUE_COMMENT_EDITED:
title = "Comment edited: " + title
content = p.Comment.Body
case api.HOOK_ISSUE_COMMENT_DELETED:
title = "Comment deleted: " + title
url = fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index)
content = p.Comment.Body
}
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
return &DiscordPayload{
Username: slack.Username,
AvatarURL: slack.IconURL,
Embeds: []*DiscordEmbedObject{{
Title: title,
Description: content,
URL: url,
Color: int(color),
Footer: &DiscordEmbedFooterObject{
Text: p.Repository.FullName,
},
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
},
Fields: fields,
}},
}, nil
}
func getDiscordPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*DiscordPayload, error) {
title := fmt.Sprintf("#%d %s", p.Index, p.PullRequest.Title)
url := fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index)
@@ -177,6 +322,14 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (
title = "Pull request labels cleared: " + title
case api.HOOK_ISSUE_SYNCHRONIZED:
title = "Pull request synchronized: " + title
case api.HOOK_ISSUE_MILESTONED:
title = "Pull request milestoned: " + title
fields = []*DiscordEmbedFieldObject{{
Name: "New Milestone",
Value: p.PullRequest.Milestone.Title,
}}
case api.HOOK_ISSUE_DEMILESTONED:
title = "Pull request demilestoned: " + title
}
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
@@ -200,22 +353,56 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (
}, nil
}
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (*DiscordPayload, error) {
d := new(DiscordPayload)
func getDiscordReleasePayload(p *api.ReleasePayload) (*DiscordPayload, error) {
repoLink := DiscordLinkFormatter(p.Repository.HTMLURL, p.Repository.Name)
refLink := DiscordLinkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
content := fmt.Sprintf("Published new release %s of %s", refLink, repoLink)
return &DiscordPayload{
Embeds: []*DiscordEmbedObject{{
Description: content,
URL: setting.AppUrl + p.Sender.UserName,
Author: &DiscordEmbedAuthorObject{
Name: p.Sender.UserName,
IconURL: p.Sender.AvatarUrl,
},
}},
}, nil
}
func GetDiscordPayload(p api.Payloader, event HookEventType, meta string) (payload *DiscordPayload, err error) {
slack := &SlackMeta{}
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
return d, fmt.Errorf("GetDiscordPayload meta json: %v", err)
return nil, fmt.Errorf("json.Unmarshal: %v", err)
}
switch event {
case HOOK_EVENT_CREATE:
return getDiscordCreatePayload(p.(*api.CreatePayload), slack)
payload, err = getDiscordCreatePayload(p.(*api.CreatePayload))
case HOOK_EVENT_DELETE:
payload, err = getDiscordDeletePayload(p.(*api.DeletePayload))
case HOOK_EVENT_FORK:
payload, err = getDiscordForkPayload(p.(*api.ForkPayload))
case HOOK_EVENT_PUSH:
return getDiscordPushPayload(p.(*api.PushPayload), slack)
payload, err = getDiscordPushPayload(p.(*api.PushPayload), slack)
case HOOK_EVENT_ISSUES:
payload, err = getDiscordIssuesPayload(p.(*api.IssuesPayload), slack)
case HOOK_EVENT_ISSUE_COMMENT:
payload, err = getDiscordIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
case HOOK_EVENT_PULL_REQUEST:
return getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
payload, err = getDiscordPullRequestPayload(p.(*api.PullRequestPayload), slack)
case HOOK_EVENT_RELEASE:
payload, err = getDiscordReleasePayload(p.(*api.ReleasePayload))
}
if err != nil {
return nil, fmt.Errorf("event '%s': %v", event, err)
}
return d, nil
payload.Username = slack.Username
payload.AvatarURL = slack.IconURL
if len(payload.Embeds) > 0 {
color, _ := strconv.ParseInt(strings.TrimLeft(slack.Color, "#"), 16, 32)
payload.Embeds[0].Color = int(color)
}
return payload, nil
}

View File

@@ -39,8 +39,6 @@ type SlackPayload struct {
Attachments []*SlackAttachment `json:"attachments"`
}
func (p *SlackPayload) SetSecret(_ string) {}
func (p *SlackPayload) JSONPayload() ([]byte, error) {
data, err := json.MarshalIndent(p, "", " ")
if err != nil {
@@ -71,19 +69,34 @@ func SlackLinkFormatter(url string, text string) string {
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
}
func getSlackCreatePayload(p *api.CreatePayload, slack *SlackMeta) (*SlackPayload, error) {
// Created tag/branch
// getSlackCreatePayload composes Slack payload for create new branch or tag.
func getSlackCreatePayload(p *api.CreatePayload) (*SlackPayload, error) {
refName := git.RefEndName(p.Ref)
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
refLink := SlackLinkFormatter(p.Repo.HTMLURL+"/src/"+refName, refName)
text := fmt.Sprintf("[%s:%s] %s created by %s", repoLink, refLink, p.RefType, p.Sender.UserName)
return &SlackPayload{
Channel: slack.Channel,
Text: text,
Username: slack.Username,
IconURL: slack.IconURL,
Text: text,
}, nil
}
// getSlackDeletePayload composes Slack payload for delete a branch or tag.
func getSlackDeletePayload(p *api.DeletePayload) (*SlackPayload, error) {
refName := git.RefEndName(p.Ref)
repoLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
text := fmt.Sprintf("[%s:%s] %s deleted by %s", repoLink, refName, p.RefType, p.Sender.UserName)
return &SlackPayload{
Text: text,
}, nil
}
// getSlackForkPayload composes Slack payload for forked by a repository.
func getSlackForkPayload(p *api.ForkPayload) (*SlackPayload, error) {
baseLink := SlackLinkFormatter(p.Repo.HTMLURL, p.Repo.Name)
forkLink := SlackLinkFormatter(p.Forkee.HTMLURL, p.Forkee.FullName)
text := fmt.Sprintf("%s is forked to %s", baseLink, forkLink)
return &SlackPayload{
Text: text,
}, nil
}
@@ -132,6 +145,86 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
}, nil
}
func getSlackIssuesPayload(p *api.IssuesPayload, slack *SlackMeta) (*SlackPayload, error) {
senderLink := SlackLinkFormatter(setting.AppUrl+p.Sender.UserName, p.Sender.UserName)
titleLink := SlackLinkFormatter(fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Index),
fmt.Sprintf("#%d %s", p.Index, p.Issue.Title))
var text, title, attachmentText string
switch p.Action {
case api.HOOK_ISSUE_OPENED:
text = fmt.Sprintf("[%s] New issue created by %s", p.Repository.FullName, senderLink)
title = titleLink
attachmentText = SlackTextFormatter(p.Issue.Body)
case api.HOOK_ISSUE_CLOSED:
text = fmt.Sprintf("[%s] Issue closed: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_REOPENED:
text = fmt.Sprintf("[%s] Issue re-opened: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_EDITED:
text = fmt.Sprintf("[%s] Issue edited: %s by %s", p.Repository.FullName, titleLink, senderLink)
attachmentText = SlackTextFormatter(p.Issue.Body)
case api.HOOK_ISSUE_ASSIGNED:
text = fmt.Sprintf("[%s] Issue assigned to %s: %s by %s", p.Repository.FullName,
SlackLinkFormatter(setting.AppUrl+p.Issue.Assignee.UserName, p.Issue.Assignee.UserName),
titleLink, senderLink)
case api.HOOK_ISSUE_UNASSIGNED:
text = fmt.Sprintf("[%s] Issue unassigned: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_LABEL_UPDATED:
text = fmt.Sprintf("[%s] Issue labels updated: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_LABEL_CLEARED:
text = fmt.Sprintf("[%s] Issue labels cleared: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_MILESTONED:
text = fmt.Sprintf("[%s] Issue milestoned: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_DEMILESTONED:
text = fmt.Sprintf("[%s] Issue demilestoned: %s by %s", p.Repository.FullName, titleLink, senderLink)
}
return &SlackPayload{
Channel: slack.Channel,
Text: text,
Username: slack.Username,
IconURL: slack.IconURL,
Attachments: []*SlackAttachment{{
Color: slack.Color,
Title: title,
Text: attachmentText,
}},
}, nil
}
func getSlackIssueCommentPayload(p *api.IssueCommentPayload, slack *SlackMeta) (*SlackPayload, error) {
senderLink := SlackLinkFormatter(setting.AppUrl+p.Sender.UserName, p.Sender.UserName)
titleLink := SlackLinkFormatter(fmt.Sprintf("%s/issues/%d#%s", p.Repository.HTMLURL, p.Issue.Index, CommentHashTag(p.Comment.ID)),
fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title))
var text, title, attachmentText string
switch p.Action {
case api.HOOK_ISSUE_COMMENT_CREATED:
text = fmt.Sprintf("[%s] New comment created by %s", p.Repository.FullName, senderLink)
title = titleLink
attachmentText = SlackTextFormatter(p.Comment.Body)
case api.HOOK_ISSUE_COMMENT_EDITED:
text = fmt.Sprintf("[%s] Comment edited by %s", p.Repository.FullName, senderLink)
title = titleLink
attachmentText = SlackTextFormatter(p.Comment.Body)
case api.HOOK_ISSUE_COMMENT_DELETED:
text = fmt.Sprintf("[%s] Comment deleted by %s", p.Repository.FullName, senderLink)
title = SlackLinkFormatter(fmt.Sprintf("%s/issues/%d", p.Repository.HTMLURL, p.Issue.Index),
fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title))
attachmentText = SlackTextFormatter(p.Comment.Body)
}
return &SlackPayload{
Channel: slack.Channel,
Text: text,
Username: slack.Username,
IconURL: slack.IconURL,
Attachments: []*SlackAttachment{{
Color: slack.Color,
Title: title,
Text: attachmentText,
}},
}, nil
}
func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*SlackPayload, error) {
senderLink := SlackLinkFormatter(setting.AppUrl+p.Sender.UserName, p.Sender.UserName)
titleLink := SlackLinkFormatter(fmt.Sprintf("%s/pulls/%d", p.Repository.HTMLURL, p.Index),
@@ -165,6 +258,10 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
text = fmt.Sprintf("[%s] Pull request labels cleared: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_SYNCHRONIZED:
text = fmt.Sprintf("[%s] Pull request synchronized: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_MILESTONED:
text = fmt.Sprintf("[%s] Pull request milestoned: %s by %s", p.Repository.FullName, titleLink, senderLink)
case api.HOOK_ISSUE_DEMILESTONED:
text = fmt.Sprintf("[%s] Pull request demilestoned: %s by %s", p.Repository.FullName, titleLink, senderLink)
}
return &SlackPayload{
@@ -180,22 +277,49 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
}, nil
}
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (*SlackPayload, error) {
s := new(SlackPayload)
func getSlackReleasePayload(p *api.ReleasePayload) (*SlackPayload, error) {
repoLink := SlackLinkFormatter(p.Repository.HTMLURL, p.Repository.Name)
refLink := SlackLinkFormatter(p.Repository.HTMLURL+"/src/"+p.Release.TagName, p.Release.TagName)
text := fmt.Sprintf("[%s] new release %s published by %s", repoLink, refLink, p.Sender.UserName)
return &SlackPayload{
Text: text,
}, nil
}
func GetSlackPayload(p api.Payloader, event HookEventType, meta string) (payload *SlackPayload, err error) {
slack := &SlackMeta{}
if err := json.Unmarshal([]byte(meta), &slack); err != nil {
return s, fmt.Errorf("GetSlackPayload meta json: %v", err)
return nil, fmt.Errorf("json.Unmarshal: %v", err)
}
switch event {
case HOOK_EVENT_CREATE:
return getSlackCreatePayload(p.(*api.CreatePayload), slack)
payload, err = getSlackCreatePayload(p.(*api.CreatePayload))
case HOOK_EVENT_DELETE:
payload, err = getSlackDeletePayload(p.(*api.DeletePayload))
case HOOK_EVENT_FORK:
payload, err = getSlackForkPayload(p.(*api.ForkPayload))
case HOOK_EVENT_PUSH:
return getSlackPushPayload(p.(*api.PushPayload), slack)
payload, err = getSlackPushPayload(p.(*api.PushPayload), slack)
case HOOK_EVENT_ISSUES:
payload, err = getSlackIssuesPayload(p.(*api.IssuesPayload), slack)
case HOOK_EVENT_ISSUE_COMMENT:
payload, err = getSlackIssueCommentPayload(p.(*api.IssueCommentPayload), slack)
case HOOK_EVENT_PULL_REQUEST:
return getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
payload, err = getSlackPullRequestPayload(p.(*api.PullRequestPayload), slack)
case HOOK_EVENT_RELEASE:
payload, err = getSlackReleasePayload(p.(*api.ReleasePayload))
}
if err != nil {
return nil, fmt.Errorf("event '%s': %v", event, err)
}
return s, nil
payload.Channel = slack.Channel
payload.Username = slack.Username
payload.IconURL = slack.IconURL
if len(payload.Attachments) > 0 {
payload.Attachments[0].Color = slack.Color
}
return payload, nil
}

View File

@@ -5,12 +5,9 @@
package auth
import (
"reflect"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"github.com/go-macaron/session"
gouuid "github.com/satori/go.uuid"
log "gopkg.in/clog.v1"
@@ -147,130 +144,3 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool)
}
return u, false
}
type Form interface {
binding.Validator
}
func init() {
binding.SetNameMapper(com.ToSnakeCase)
}
// AssignForm assign form values back to the template data.
func AssignForm(form interface{}, data map[string]interface{}) {
typ := reflect.TypeOf(form)
val := reflect.ValueOf(form)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
} else if len(fieldName) == 0 {
fieldName = com.ToSnakeCase(field.Name)
}
data[fieldName] = val.Field(i).Interface()
}
}
func getRuleBody(field reflect.StructField, prefix string) string {
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
if strings.HasPrefix(rule, prefix) {
return rule[len(prefix) : len(rule)-1]
}
}
return ""
}
func GetSize(field reflect.StructField) string {
return getRuleBody(field, "Size(")
}
func GetMinSize(field reflect.StructField) string {
return getRuleBody(field, "MinSize(")
}
func GetMaxSize(field reflect.StructField) string {
return getRuleBody(field, "MaxSize(")
}
func GetInclude(field reflect.StructField) string {
return getRuleBody(field, "Include(")
}
// FIXME: struct contains a struct
func validateStruct(obj interface{}) binding.Errors {
return nil
}
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
if errs.Len() == 0 {
return errs
}
data["HasError"] = true
AssignForm(f, data)
typ := reflect.TypeOf(f)
val := reflect.ValueOf(f)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
}
if errs[0].FieldNames[0] == field.Name {
data["Err_"+field.Name] = true
trName := field.Tag.Get("locale")
if len(trName) == 0 {
trName = l.Tr("form." + field.Name)
} else {
trName = l.Tr(trName)
}
switch errs[0].Classification {
case binding.ERR_REQUIRED:
data["ErrorMsg"] = trName + l.Tr("form.require_error")
case binding.ERR_ALPHA_DASH:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
case binding.ERR_ALPHA_DASH_DOT:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
case binding.ERR_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
case binding.ERR_MIN_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
case binding.ERR_MAX_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
case binding.ERR_EMAIL:
data["ErrorMsg"] = trName + l.Tr("form.email_error")
case binding.ERR_URL:
data["ErrorMsg"] = trName + l.Tr("form.url_error")
case binding.ERR_INCLUDE:
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
default:
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
}
return errs
}
}
return errs
}

View File

@@ -1,55 +0,0 @@
// Copyright 2014 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.
package auth
import (
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
// ________ .__ __ .__
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
// \/ /_____/ \/ \/ \/ \/ \/
type CreateOrgForm struct {
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
}
func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type UpdateOrgSettingForm struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
}
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
// ___________
// \__ ___/___ _____ _____
// | |_/ __ \\__ \ / \
// | |\ ___/ / __ \| Y Y \
// |____| \___ >____ /__|_| /
// \/ \/ \/
type CreateTeamForm struct {
TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `binding:"MaxSize(255)"`
Permission string
}
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -186,7 +186,7 @@ func AvatarLink(email string) (url string) {
var err error
url, err = setting.LibravatarService.FromEmail(email)
if err != nil {
log.Error(2, "LibravatarService.FromEmail [%s]: %v", email, err)
log.Warn("AvatarLink.LibravatarService.FromEmail [%s]: %v", email, err)
}
}
if len(url) == 0 && !setting.DisableGravatar {
@@ -372,7 +372,7 @@ func logn(n, b float64) float64 {
func humanateBytes(s uint64, base float64, sizes []string) string {
if s < 10 {
return fmt.Sprintf("%dB", s)
return fmt.Sprintf("%d B", s)
}
e := math.Floor(logn(float64(s), base))
suffix := sizes[int(e)]
@@ -382,7 +382,7 @@ func humanateBytes(s uint64, base float64, sizes []string) string {
f = "%.1f"
}
return fmt.Sprintf(f+"%s", val, suffix)
return fmt.Sprintf(f+" %s", val, suffix)
}
// FileSize calculates the file size and generate user-friendly string.

File diff suppressed because one or more lines are too long

View File

@@ -32,7 +32,7 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) {
}
if status == 500 {
log.Error(4, "%s: %s", title, message)
log.Error(3, "%s: %s", title, message)
}
ctx.JSON(status, map[string]string{

View File

@@ -22,6 +22,7 @@ import (
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/form"
"github.com/gogits/gogs/modules/setting"
)
@@ -78,9 +79,9 @@ func (ctx *Context) HTML(status int, name base.TplName) {
}
// RenderWithErr used for page has form validation but need to prompt error to users.
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
if form != nil {
auth.AssignForm(form, ctx.Data)
func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, f interface{}) {
if f != nil {
form.Assign(f, ctx.Data)
}
ctx.Flash.ErrorMsg = msg
ctx.Data["Flash"] = ctx.Flash
@@ -158,6 +159,9 @@ func Contexter() macaron.Handler {
if len(setting.HTTP.AccessControlAllowOrigin) > 0 {
ctx.Header().Set("Access-Control-Allow-Origin", setting.HTTP.AccessControlAllowOrigin)
ctx.Header().Set("'Access-Control-Allow-Credentials' ", "true")
ctx.Header().Set("Access-Control-Max-Age", "3600")
ctx.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
}
// Compute current URL for real-time change language.

View File

@@ -98,6 +98,16 @@ func (r *Repository) GetEditorconfig() (*editorconfig.Editorconfig, error) {
return editorconfig.ParseBytes(data)
}
// PullRequestURL returns URL for composing a pull request.
// This function does not check if the repository can actually compose a pull request.
func (r *Repository) PullRequestURL(baseBranch, headBranch string) string {
repoLink := r.RepoLink
if r.PullRequest.BaseRepo != nil {
repoLink = r.PullRequest.BaseRepo.Link()
}
return fmt.Sprintf("%s/compare/%s...%s:%s", repoLink, baseBranch, r.Owner.Name, headBranch)
}
func RetrieveBaseRepo(ctx *Context, repo *models.Repository) {
// Non-fork repository will not return error in this method.
if err := repo.GetBaseRepo(); err != nil {
@@ -196,7 +206,11 @@ func RepoAssignment(args ...bool) macaron.Handler {
if ctx.IsSigned && ctx.User.IsAdmin {
ctx.Repo.AccessMode = models.ACCESS_MODE_OWNER
} else {
mode, err := models.AccessLevel(ctx.User, repo)
var userID int64
if ctx.IsSigned {
userID = ctx.User.ID
}
mode, err := models.AccessLevel(userID, repo)
if err != nil {
ctx.Handle(500, "AccessLevel", err)
return
@@ -442,13 +456,6 @@ func RepoRef() macaron.Handler {
}
}
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
if err != nil {
ctx.Handle(500, "CommitsCount", err)
return
}
ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
}
}

View File

@@ -2,15 +2,14 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
package form
import (
"gopkg.in/macaron.v1"
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
type AdminCrateUserForm struct {
type AdminCrateUser struct {
LoginType string `binding:"Required"`
LoginName string
UserName string `binding:"Required;AlphaDashDot;MaxSize(35)"`
@@ -19,11 +18,11 @@ type AdminCrateUserForm struct {
SendNotify bool
}
func (f *AdminCrateUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *AdminCrateUser) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type AdminEditUserForm struct {
type AdminEditUser struct {
LoginType string `binding:"Required"`
LoginName string
FullName string `binding:"MaxSize(100)"`
@@ -39,6 +38,6 @@ type AdminEditUserForm struct {
ProhibitLogin bool
}
func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *AdminEditUser) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -2,14 +2,14 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
package form
import (
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
type AuthenticationForm struct {
type Authentication struct {
ID int64
Type int `binding:"Range(2,5)"`
Name string `binding:"Required;MaxSize(30)"`
@@ -37,6 +37,6 @@ type AuthenticationForm struct {
PAMServiceName string
}
func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *Authentication) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

155
modules/form/form.go Normal file
View File

@@ -0,0 +1,155 @@
// Copyright 2017 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.
package form
import (
"fmt"
"reflect"
"regexp"
"strings"
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
const ERR_ALPHA_DASH_DOT_SLASH = "AlphaDashDotSlashError"
var AlphaDashDotSlashPattern = regexp.MustCompile("[^\\d\\w-_\\./]")
func init() {
binding.SetNameMapper(com.ToSnakeCase)
binding.AddRule(&binding.Rule{
IsMatch: func(rule string) bool {
return rule == "AlphaDashDotSlash"
},
IsValid: func(errs binding.Errors, name string, v interface{}) (bool, binding.Errors) {
if AlphaDashDotSlashPattern.MatchString(fmt.Sprintf("%v", v)) {
errs.Add([]string{name}, ERR_ALPHA_DASH_DOT_SLASH, "AlphaDashDotSlash")
return false, errs
}
return true, errs
},
})
}
type Form interface {
binding.Validator
}
// Assign assign form values back to the template data.
func Assign(form interface{}, data map[string]interface{}) {
typ := reflect.TypeOf(form)
val := reflect.ValueOf(form)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
} else if len(fieldName) == 0 {
fieldName = com.ToSnakeCase(field.Name)
}
data[fieldName] = val.Field(i).Interface()
}
}
func getRuleBody(field reflect.StructField, prefix string) string {
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
if strings.HasPrefix(rule, prefix) {
return rule[len(prefix) : len(rule)-1]
}
}
return ""
}
func getSize(field reflect.StructField) string {
return getRuleBody(field, "Size(")
}
func getMinSize(field reflect.StructField) string {
return getRuleBody(field, "MinSize(")
}
func getMaxSize(field reflect.StructField) string {
return getRuleBody(field, "MaxSize(")
}
func getInclude(field reflect.StructField) string {
return getRuleBody(field, "Include(")
}
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
if errs.Len() == 0 {
return errs
}
data["HasError"] = true
Assign(f, data)
typ := reflect.TypeOf(f)
val := reflect.ValueOf(f)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
}
if errs[0].FieldNames[0] == field.Name {
data["Err_"+field.Name] = true
trName := field.Tag.Get("locale")
if len(trName) == 0 {
trName = l.Tr("form." + field.Name)
} else {
trName = l.Tr(trName)
}
switch errs[0].Classification {
case binding.ERR_REQUIRED:
data["ErrorMsg"] = trName + l.Tr("form.require_error")
case binding.ERR_ALPHA_DASH:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
case binding.ERR_ALPHA_DASH_DOT:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
case ERR_ALPHA_DASH_DOT_SLASH:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_slash_error")
case binding.ERR_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.size_error", getSize(field))
case binding.ERR_MIN_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", getMinSize(field))
case binding.ERR_MAX_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", getMaxSize(field))
case binding.ERR_EMAIL:
data["ErrorMsg"] = trName + l.Tr("form.email_error")
case binding.ERR_URL:
data["ErrorMsg"] = trName + l.Tr("form.url_error")
case binding.ERR_INCLUDE:
data["ErrorMsg"] = trName + l.Tr("form.include_error", getInclude(field))
default:
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
}
return errs
}
}
return errs
}

41
modules/form/org.go Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2014 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.
package form
import (
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
type CreateOrg struct {
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
}
func (f *CreateOrg) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type UpdateOrgSetting struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
}
func (f *UpdateOrgSetting) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type CreateTeam struct {
TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `binding:"MaxSize(255)"`
Permission string
}
func (f *CreateTeam) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
package form
import (
"net/url"
@@ -22,8 +22,8 @@ import (
// |____|_ /_______ / |____| \_______ /_______ /|___| |____| \_______ /____|_ // ______|
// \/ \/ \/ \/ \/ \/ \/
type CreateRepoForm struct {
Uid int64 `binding:"Required"`
type CreateRepo struct {
UserID int64 `binding:"Required"`
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Private bool
Description string `binding:"MaxSize(255)"`
@@ -33,11 +33,11 @@ type CreateRepoForm struct {
Readme string
}
func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *CreateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type MigrateRepoForm struct {
type MigrateRepo struct {
CloneAddr string `json:"clone_addr" binding:"Required"`
AuthUsername string `json:"auth_username"`
AuthPassword string `json:"auth_password"`
@@ -48,7 +48,7 @@ type MigrateRepoForm struct {
Description string `json:"description" binding:"MaxSize(255)"`
}
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *MigrateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -56,7 +56,7 @@ func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
// and returns composed URL with needed username and password.
// It also checks if given user has permission when remote address
// is actually a local path.
func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
func (f MigrateRepo) ParseRemoteAddr(user *models.User) (string, error) {
remoteAddr := strings.TrimSpace(f.CloneAddr)
// Remote address can be HTTP/HTTPS/Git URL or local path.
@@ -80,7 +80,7 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
return remoteAddr, nil
}
type RepoSettingForm struct {
type RepoSetting struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
@@ -102,7 +102,7 @@ type RepoSettingForm struct {
EnablePulls bool
}
func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *RepoSetting) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -113,12 +113,15 @@ func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
// |______ / |__| (____ /___| /\___ >___| /
// \/ \/ \/ \/ \/
type ProtectBranchForm struct {
type ProtectBranch struct {
Protected bool
RequirePullRequest bool
EnableWhitelist bool
WhitelistUsers string
WhitelistTeams string
}
func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *ProtectBranch) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -129,59 +132,64 @@ func (f *ProtectBranchForm) Validate(ctx *macaron.Context, errs binding.Errors)
// \__/\ / \___ >___ /___| /___| /\____/|__|_ \
// \/ \/ \/ \/ \/ \/
type WebhookForm struct {
Events string
Create bool
Push bool
PullRequest bool
Active bool
type Webhook struct {
Events string
Create bool
Delete bool
Fork bool
Push bool
Issues bool
IssueComment bool
PullRequest bool
Release bool
Active bool
}
func (f WebhookForm) PushOnly() bool {
func (f Webhook) PushOnly() bool {
return f.Events == "push_only"
}
func (f WebhookForm) SendEverything() bool {
func (f Webhook) SendEverything() bool {
return f.Events == "send_everything"
}
func (f WebhookForm) ChooseEvents() bool {
func (f Webhook) ChooseEvents() bool {
return f.Events == "choose_events"
}
type NewWebhookForm struct {
type NewWebhook struct {
PayloadURL string `binding:"Required;Url"`
ContentType int `binding:"Required"`
Secret string
WebhookForm
Webhook
}
func (f *NewWebhookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewWebhook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type NewSlackHookForm struct {
type NewSlackHook struct {
PayloadURL string `binding:"Required;Url"`
Channel string `binding:"Required"`
Username string
IconURL string
Color string
WebhookForm
Webhook
}
func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewSlackHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type NewDiscordHookForm struct {
type NewDiscordHook struct {
PayloadURL string `binding:"Required;Url"`
Username string
IconURL string
Color string
WebhookForm
Webhook
}
func (f *NewDiscordHookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewDiscordHook) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -192,7 +200,7 @@ func (f *NewDiscordHookForm) Validate(ctx *macaron.Context, errs binding.Errors)
// |___/____ >____ >____/ \___ >
// \/ \/ \/
type CreateIssueForm struct {
type NewIssue struct {
Title string `binding:"Required;MaxSize(255)"`
LabelIDs string `form:"label_ids"`
MilestoneID int64
@@ -201,17 +209,17 @@ type CreateIssueForm struct {
Files []string
}
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewIssue) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type CreateCommentForm struct {
type CreateComment struct {
Content string
Status string `binding:"OmitEmpty;In(reopen,close)"`
Files []string
}
func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *CreateComment) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -222,13 +230,13 @@ func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors)
// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
// \/ \/ \/ \/ \/
type CreateMilestoneForm struct {
type CreateMilestone struct {
Title string `binding:"Required;MaxSize(50)"`
Content string
Deadline string
}
func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *CreateMilestone) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -239,21 +247,21 @@ func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors
// |_______ (____ /___ /\___ >____/
// \/ \/ \/ \/
type CreateLabelForm struct {
type CreateLabel struct {
ID int64
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_name"`
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
}
func (f *CreateLabelForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *CreateLabel) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type InitializeLabelsForm struct {
type InitializeLabels struct {
TemplateName string `binding:"Required"`
}
func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *InitializeLabels) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -264,27 +272,29 @@ func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Error
// |____|_ /\___ >____/\___ >____ /____ >\___ >
// \/ \/ \/ \/ \/ \/
type NewReleaseForm struct {
type NewRelease struct {
TagName string `binding:"Required"`
Target string `form:"tag_target" binding:"Required"`
Title string `binding:"Required"`
Content string
Draft string
Prerelease bool
Files []string
}
func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type EditReleaseForm struct {
Title string `form:"title" binding:"Required"`
Content string `form:"content"`
Draft string `form:"draft"`
Prerelease bool `form:"prerelease"`
type EditRelease struct {
Title string `binding:"Required"`
Content string
Draft string
Prerelease bool
Files []string
}
func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *EditRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -295,7 +305,7 @@ func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
// \__/\ / |__|__|_ \__|
// \/ \/
type NewWikiForm struct {
type NewWiki struct {
OldTitle string
Title string `binding:"Required"`
Content string `binding:"Required"`
@@ -303,7 +313,7 @@ type NewWikiForm struct {
}
// FIXME: use code generation to generate this method.
func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewWiki) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -314,29 +324,29 @@ func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
// /_______ /\____ | |__||__|
// \/ \/
type EditRepoFileForm struct {
type EditRepoFile struct {
TreePath string `binding:"Required;MaxSize(500)"`
Content string `binding:"Required"`
CommitSummary string `binding:"MaxSize(100)`
CommitMessage string
CommitChoice string `binding:"Required;MaxSize(50)"`
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
NewBranchName string `binding:"AlphaDashDotSlash;MaxSize(100)"`
LastCommit string
}
func (f *EditRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *EditRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
func (f *EditRepoFileForm) IsNewBrnach() bool {
func (f *EditRepoFile) IsNewBrnach() bool {
return f.CommitChoice == "commit-to-new-branch"
}
type EditPreviewDiffForm struct {
type EditPreviewDiff struct {
Content string
}
func (f *EditPreviewDiffForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *EditPreviewDiff) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -348,7 +358,7 @@ func (f *EditPreviewDiffForm) Validate(ctx *macaron.Context, errs binding.Errors
// |__| \/ \/
//
type UploadRepoFileForm struct {
type UploadRepoFile struct {
TreePath string `binding:MaxSize(500)"`
CommitSummary string `binding:"MaxSize(100)`
CommitMessage string
@@ -357,19 +367,19 @@ type UploadRepoFileForm struct {
Files []string
}
func (f *UploadRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *UploadRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
func (f *UploadRepoFileForm) IsNewBrnach() bool {
func (f *UploadRepoFile) IsNewBrnach() bool {
return f.CommitChoice == "commit-to-new-branch"
}
type RemoveUploadFileForm struct {
type RemoveUploadFile struct {
File string `binding:"Required;MaxSize(50)"`
}
func (f *RemoveUploadFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *RemoveUploadFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -380,17 +390,17 @@ func (f *RemoveUploadFileForm) Validate(ctx *macaron.Context, errs binding.Error
// /_______ /\___ >____/\___ >__| \___ >
// \/ \/ \/ \/
type DeleteRepoFileForm struct {
type DeleteRepoFile struct {
CommitSummary string `binding:"MaxSize(100)`
CommitMessage string
CommitChoice string `binding:"Required;MaxSize(50)"`
NewBranchName string `binding:"AlphaDashDot;MaxSize(100)"`
}
func (f *DeleteRepoFileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *DeleteRepoFile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
func (f *DeleteRepoFileForm) IsNewBrnach() bool {
func (f *DeleteRepoFile) IsNewBrnach() bool {
return f.CommitChoice == "commit-to-new-branch"
}

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
package form
import (
"mime/multipart"
@@ -11,7 +11,7 @@ import (
"gopkg.in/macaron.v1"
)
type InstallForm struct {
type Install struct {
DbType string `binding:"Required"`
DbHost string
DbUser string
@@ -50,7 +50,7 @@ type InstallForm struct {
AdminEmail string `binding:"OmitEmpty;MinSize(3);MaxSize(254);Include(@)" locale:"install.admin_email"`
}
func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *Install) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -61,24 +61,24 @@ func (f *InstallForm) Validate(ctx *macaron.Context, errs binding.Errors) bindin
// \____|__ /______/ |____| \___|_ /
// \/ \/
type RegisterForm struct {
type Register struct {
UserName string `binding:"Required;AlphaDashDot;MaxSize(35)"`
Email string `binding:"Required;Email;MaxSize(254)"`
Password string `binding:"Required;MaxSize(255)"`
Retype string
}
func (f *RegisterForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *Register) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type SignInForm struct {
type SignIn struct {
UserName string `binding:"Required;MaxSize(254)"`
Password string `binding:"Required;MaxSize(255)"`
Remember bool
}
func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *SignIn) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -89,15 +89,15 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding
// /_______ //_______ / |____| |____| |___\____|__ /\______ /_______ /
// \/ \/ \/ \/ \/
type UpdateProfileForm struct {
Name string `binding:"OmitEmpty;MaxSize(35)"`
type UpdateProfile struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(35)"`
FullName string `binding:"MaxSize(100)"`
Email string `binding:"Required;Email;MaxSize(254)"`
Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"`
}
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *UpdateProfile) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
@@ -106,48 +106,48 @@ const (
AVATAR_BYMAIL string = "bymail"
)
type AvatarForm struct {
type Avatar struct {
Source string
Avatar *multipart.FileHeader
Gravatar string `binding:"OmitEmpty;Email;MaxSize(254)"`
Federavatar bool
}
func (f *AvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *Avatar) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type AddEmailForm struct {
type AddEmail struct {
Email string `binding:"Required;Email;MaxSize(254)"`
}
func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *AddEmail) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type ChangePasswordForm struct {
OldPassword string `form:"old_password" binding:"Required;MinSize(1);MaxSize(255)"`
Password string `form:"password" binding:"Required;MaxSize(255)"`
Retype string `form:"retype"`
type ChangePassword struct {
OldPassword string `binding:"Required;MinSize(1);MaxSize(255)"`
Password string `binding:"Required;MaxSize(255)"`
Retype string
}
func (f *ChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *ChangePassword) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type AddSSHKeyForm struct {
type AddSSHKey struct {
Title string `binding:"Required;MaxSize(50)"`
Content string `binding:"Required"`
}
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *AddSSHKey) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type NewAccessTokenForm struct {
type NewAccessToken struct {
Name string `binding:"Required"`
}
func (f *NewAccessTokenForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *NewAccessToken) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -139,7 +139,7 @@ func (r *Request) Debug(isdebug bool) *Request {
return r
}
// SetTimeout sets connect time out and read-write time out for BeegoRequest.
// SetTimeout sets connect time out and read-write time out for Request.
func (r *Request) SetTimeout(connectTimeout, readWriteTimeout time.Duration) *Request {
r.setting.ConnectTimeout = connectTimeout
r.setting.ReadWriteTimeout = readWriteTimeout

View File

@@ -36,16 +36,18 @@ func NewMessageFrom(to []string, from, subject, htmlBody string) *Message {
msg.SetHeader("Subject", subject)
msg.SetDateHeader("Date", time.Now())
body, err := html2text.FromString(htmlBody)
if err != nil {
log.Error(4, "html2text.FromString: %v", err)
msg.SetBody("text/html", htmlBody)
} else {
msg.SetBody("text/plain", body)
if setting.MailService.EnableHTMLAlternative {
msg.AddAlternative("text/html", htmlBody)
contentType := "text/html"
body := htmlBody
if setting.MailService.UsePlainText {
plainBody, err := html2text.FromString(htmlBody)
if err != nil {
log.Error(2, "html2text.FromString: %v", err)
} else {
contentType = "text/plain"
body = plainBody
}
}
msg.SetBody(contentType, body)
return &Message{
Message: msg,

View File

@@ -192,42 +192,11 @@ func (options *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
// Note: this section is for purpose of increase performance and
// reduce memory allocation at runtime since they are constant literals.
var (
svgSuffix = []byte(".svg")
svgSuffixWithMark = []byte(".svg?")
spaceBytes = []byte(" ")
spaceEncodedBytes = []byte("%20")
pound = []byte("#")
space = " "
spaceEncoded = "%20"
pound = []byte("#")
space = " "
spaceEncoded = "%20"
)
// Image defines how images should be processed to produce corresponding HTML elements.
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := strings.Replace(r.urlPrefix, "/src/", "/raw/", 1)
if len(link) > 0 {
if isLink(link) {
// External link with .svg suffix usually means CI status.
// TODO: define a keyword to allow non-svg images render as external link.
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) {
r.Renderer.Image(out, link, title, alt)
return
}
} else {
if link[0] != '/' {
prefix += "/"
}
link = bytes.Replace([]byte((prefix + string(link))), spaceBytes, spaceEncodedBytes, -1)
fmt.Println(333, string(link))
}
}
out.WriteString(`<a href="`)
out.Write(link)
out.WriteString(`">`)
r.Renderer.Image(out, link, title, alt)
out.WriteString("</a>")
}
// cutoutVerbosePrefix cutouts URL prefix including sub-path to
// return a clean unified string of request URL path.
func cutoutVerbosePrefix(prefix string) string {
@@ -325,6 +294,23 @@ func RenderRaw(body []byte, urlPrefix string) []byte {
htmlFlags := 0
htmlFlags |= blackfriday.HTML_SKIP_STYLE
htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
if setting.Smartypants.Enabled {
htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
if setting.Smartypants.Fractions {
htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
}
if setting.Smartypants.Dashes {
htmlFlags |= blackfriday.HTML_SMARTYPANTS_DASHES
}
if setting.Smartypants.LatexDashes {
htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
}
if setting.Smartypants.AngledQuotes {
htmlFlags |= blackfriday.HTML_SMARTYPANTS_ANGLED_QUOTES
}
}
renderer := &Renderer{
Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""),
urlPrefix: urlPrefix,
@@ -353,14 +339,72 @@ var (
rightAngleBracket = []byte(">")
)
var noEndTags = []string{"img", "input", "br", "hr"}
var noEndTags = []string{"input", "br", "hr", "img"}
// wrapImgWithLink warps link to standalone <img> tags.
func wrapImgWithLink(urlPrefix string, buf *bytes.Buffer, token html.Token) {
var src, alt string
// Extract "src" and "alt" attributes
for i := range token.Attr {
switch token.Attr[i].Key {
case "src":
src = token.Attr[i].Val
case "alt":
alt = token.Attr[i].Val
}
}
// Skip in case the "src" is empty
if len(src) == 0 {
buf.WriteString(token.String())
return
}
// Prepend repository base URL for internal links
needPrepend := !isLink([]byte(src))
if needPrepend {
urlPrefix = strings.Replace(urlPrefix, "/src/", "/raw/", 1)
if src[0] != '/' {
urlPrefix += "/"
}
}
buf.WriteString(`<a href="`)
if needPrepend {
buf.WriteString(urlPrefix)
buf.WriteString(src)
} else {
buf.WriteString(src)
}
buf.WriteString(`">`)
if needPrepend {
src = strings.Replace(urlPrefix+string(src), " ", "%20", -1)
buf.WriteString(`<img src="`)
buf.WriteString(src)
buf.WriteString(`"`)
if len(alt) > 0 {
buf.WriteString(` alt="`)
buf.WriteString(alt)
buf.WriteString(`"`)
}
buf.WriteString(`>`)
} else {
buf.WriteString(token.String())
}
buf.WriteString(`</a>`)
}
// PostProcess treats different types of HTML differently,
// and only renders special links for plain text blocks.
func PostProcess(rawHtml []byte, urlPrefix string, metas map[string]string) []byte {
func PostProcess(rawHTML []byte, urlPrefix string, metas map[string]string) []byte {
startTags := make([]string, 0, 5)
var buf bytes.Buffer
tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml))
buf := bytes.NewBuffer(nil)
tokenizer := html.NewTokenizer(bytes.NewReader(rawHTML))
OUTER_LOOP:
for html.ErrorToken != tokenizer.Next() {
@@ -370,8 +414,14 @@ OUTER_LOOP:
buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix, metas))
case html.StartTagToken:
buf.WriteString(token.String())
tagName := token.Data
if tagName == "img" {
wrapImgWithLink(urlPrefix, buf, token)
continue OUTER_LOOP
}
buf.WriteString(token.String())
// If this is an excluded tag, we skip processing all output until a close tag is encountered.
if strings.EqualFold("a", tagName) || strings.EqualFold("code", tagName) || strings.EqualFold("pre", tagName) {
stackNum := 1
@@ -381,14 +431,14 @@ OUTER_LOOP:
// Copy the token to the output verbatim
buf.WriteString(token.String())
if token.Type == html.StartTagToken {
// Stack number doesn't increate for tags without end tags.
if token.Type == html.StartTagToken && !com.IsSliceContainsStr(noEndTags, token.Data) {
stackNum++
}
// If this is the close tag to the outer-most, we are done
if token.Type == html.EndTagToken {
stackNum--
if stackNum <= 0 && strings.EqualFold(tagName, token.Data) {
break
}
@@ -397,8 +447,8 @@ OUTER_LOOP:
continue OUTER_LOOP
}
if !com.IsSliceContainsStr(noEndTags, token.Data) {
startTags = append(startTags, token.Data)
if !com.IsSliceContainsStr(noEndTags, tagName) {
startTags = append(startTags, tagName)
}
case html.EndTagToken:
@@ -422,7 +472,7 @@ OUTER_LOOP:
// If we are not at the end of the input, then some other parsing error has occurred,
// so return the input verbatim.
return rawHtml
return rawHTML
}
// Render renders Markdown to HTML with special links.

View File

@@ -7,7 +7,7 @@
package setting
import (
_ "github.com/kardianos/minwinsvc"
_ "github.com/gogits/minwinsvc"
)
func init() {

View File

@@ -107,15 +107,6 @@ var (
UsePostgreSQL bool
UseMSSQL bool
// Webhook settings
Webhook struct {
QueueLength int
DeliverTimeout int
SkipTLSVerify bool
Types []string
PagingNum int
}
// Repository settings
Repository struct {
AnsiCharset string
@@ -146,6 +137,26 @@ var (
RepoRootPath string
ScriptType string
// Webhook settings
Webhook struct {
Types []string
QueueLength int
DeliverTimeout int
SkipTLSVerify bool `ini:"SKIP_TLS_VERIFY"`
PagingNum int
}
// Release settigns
Release struct {
Attachment struct {
Enabled bool
TempPath string
AllowedTypes []string `delim:"|"`
MaxSize int64
MaxFiles int
} `ini:"-"`
}
// Markdown sttings
Markdown struct {
EnableHardLineBreak bool
@@ -153,6 +164,15 @@ var (
FileExtensions []string
}
// Smartypants settings
Smartypants struct {
Enabled bool
Fractions bool
Dashes bool
LatexDashes bool
AngledQuotes bool
}
// Admin settings
Admin struct {
DisableRegularOrgCreation bool
@@ -187,7 +207,7 @@ var (
// Session settings
SessionConfig session.Options
CSRFCookieName = "_csrf"
CSRFCookieName string
// Cron tasks
Cron struct {
@@ -579,8 +599,14 @@ func NewContext() {
if err = Cfg.Section("http").MapTo(&HTTP); err != nil {
log.Fatal(2, "Fail to map HTTP settings: %v", err)
} else if err = Cfg.Section("webhook").MapTo(&Webhook); err != nil {
log.Fatal(2, "Fail to map Webhook settings: %v", err)
} else if err = Cfg.Section("release.attachment").MapTo(&Release.Attachment); err != nil {
log.Fatal(2, "Fail to map Release.Attachment settings: %v", err)
} else if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil {
log.Fatal(2, "Fail to map Markdown settings: %v", err)
} else if err = Cfg.Section("smartypants").MapTo(&Smartypants); err != nil {
log.Fatal(2, "Fail to map Smartypants settings: %v", err)
} else if err = Cfg.Section("admin").MapTo(&Admin); err != nil {
log.Fatal(2, "Fail to map Admin settings: %v", err)
} else if err = Cfg.Section("cron").MapTo(&Cron); err != nil {
@@ -742,24 +768,25 @@ func newSessionService() {
SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool()
SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400)
SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400)
CSRFCookieName = Cfg.Section("session").Key("CSRF_COOKIE_NAME").MustString("_csrf")
log.Info("Session Service Enabled")
}
// Mailer represents mail service.
type Mailer struct {
QueueLength int
Name string
Host string
From string
FromEmail string
User, Passwd string
DisableHelo bool
HeloHostname string
SkipVerify bool
UseCertificate bool
CertFile, KeyFile string
EnableHTMLAlternative bool
QueueLength int
Subject string
Host string
From string
FromEmail string
User, Passwd string
DisableHelo bool
HeloHostname string
SkipVerify bool
UseCertificate bool
CertFile, KeyFile string
UsePlainText bool
}
var (
@@ -774,18 +801,18 @@ func newMailService() {
}
MailService = &Mailer{
QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
Name: sec.Key("NAME").MustString(AppName),
Host: sec.Key("HOST").String(),
User: sec.Key("USER").String(),
Passwd: sec.Key("PASSWD").String(),
DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
HeloHostname: sec.Key("HELO_HOSTNAME").String(),
SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
CertFile: sec.Key("CERT_FILE").String(),
KeyFile: sec.Key("KEY_FILE").String(),
EnableHTMLAlternative: sec.Key("ENABLE_HTML_ALTERNATIVE").MustBool(),
QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100),
Subject: sec.Key("SUBJECT").MustString(AppName),
Host: sec.Key("HOST").String(),
User: sec.Key("USER").String(),
Passwd: sec.Key("PASSWD").String(),
DisableHelo: sec.Key("DISABLE_HELO").MustBool(),
HeloHostname: sec.Key("HELO_HOSTNAME").String(),
SkipVerify: sec.Key("SKIP_VERIFY").MustBool(),
UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(),
CertFile: sec.Key("CERT_FILE").String(),
KeyFile: sec.Key("KEY_FILE").String(),
UsePlainText: sec.Key("USE_PLAIN_TEXT").MustBool(),
}
MailService.From = sec.Key("FROM").MustString(MailService.User)
@@ -822,15 +849,6 @@ func newNotifyMailService() {
log.Info("Notify Mail Service Enabled")
}
func newWebhookService() {
sec := Cfg.Section("webhook")
Webhook.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000)
Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
Webhook.Types = []string{"gogs", "slack", "discord"}
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
}
func NewService() {
newService()
}
@@ -843,5 +861,4 @@ func NewServices() {
newMailService()
newRegisterMailService()
newNotifyMailService()
newWebhookService()
}

View File

@@ -242,12 +242,14 @@ func ActionIcon(opType int) string {
switch opType {
case 1, 8: // Create and transfer repository
return "repo"
case 5, 9: // Commit repository
case 5: // Commit repository
return "git-commit"
case 6: // Create issue
return "issue-opened"
case 7: // New pull request
return "git-pull-request"
case 9: // Push tag
return "tag"
case 10: // Comment issue
return "comment-discussion"
case 11: // Merge pull request
@@ -256,6 +258,12 @@ func ActionIcon(opType int) string {
return "issue-closed"
case 13, 15: // Reopen issue or pull request
return "issue-reopened"
case 16: // Create branch
return "git-branch"
case 17, 18: // Delete branch or tag
return "alert"
case 19: // Fork a repository
return "repo-forked"
default:
return "invalid type"
}

View File

@@ -1 +1 @@
web: ./gogs web
web: ./gogs web -p ${PORT:=3000}

View File

@@ -22,8 +22,8 @@
},
"\/css\/semantic-2.2.7.min.css": {
"fileType": 16,
"ignore": 1,
"ignoreWasSetByUser": 1,
"ignore": 0,
"ignoreWasSetByUser": 0,
"inputAbbreviatedPath": "\/css\/semantic-2.2.7.min.css",
"outputAbbreviatedPath": "No Output Path",
"outputPathIsOutsideProject": 0,
@@ -66,7 +66,7 @@
"fileType": 32768,
"ignore": 0,
"ignoreWasSetByUser": 0,
"initialSize": 4048,
"initialSize": 514087,
"inputAbbreviatedPath": "\/img\/avatar_default.png",
"outputAbbreviatedPath": "\/img\/avatar_default.png",
"outputPathIsOutsideProject": 0,
@@ -163,8 +163,8 @@
},
"\/js\/semantic-2.2.7.min.js": {
"fileType": 64,
"ignore": 1,
"ignoreWasSetByUser": 1,
"ignore": 0,
"ignoreWasSetByUser": 0,
"inputAbbreviatedPath": "\/js\/semantic-2.2.7.min.js",
"outputAbbreviatedPath": "\/js\/min\/semantic-2.2.7.min-min.js",
"outputPathIsOutsideProject": 0,

Some files were not shown because too many files have changed in this diff Show More