Compare commits

..

604 Commits

Author SHA1 Message Date
Unknwon
0ea0c5ec4f Prepare release 2016-03-06 19:55:38 -05:00
Unknwon
58f0c68151 Some minor changes 2016-03-06 16:40:04 -05:00
Unknwon
12b5a76b0d Minor fix for #2772 2016-03-06 15:37:49 -05:00
Unknwon
a4452864ea Merge pull request #2772 from OhDaeto/master
Add ru-RU to home template
2016-03-06 15:36:40 -05:00
OhDaeto
d57be01485 Merge pull request #1 from xDShot/patch-1
Small correction
2016-03-06 23:02:55 +03:00
xDShot
d8738f5bfd минимальные -> низкие (системные требования) 2016-03-06 22:59:49 +03:00
Unknwon
9cf7f3e46f Remove duplicated of code 2016-03-06 14:44:22 -05:00
Lourens
14aba3489e Add ru-RU to home template 2016-03-06 22:22:41 +03:00
Unknwon
13bd16af92 Minor fixes for #2766 2016-03-06 13:24:42 -05:00
Unknwon
922a6f13a3 Merge pull request #2766 from moltam/feature/delete-org-avatar
Added: Ability to delete org avatar.
2016-03-06 13:20:37 -05:00
Tamás Molnár
9c91e27933 Added: Ability to delete org avatar. 2016-03-06 17:36:30 +01:00
Unknwon
c2ca103d30 #2623 fix wrong font for webhook history 2016-03-05 23:09:16 -05:00
Unknwon
c18f67ac6a Add Finnish support 2016-03-05 21:13:04 -05:00
Unknwon
a5b0400be7 #1146 finish new access rights for collaborators 2016-03-05 20:45:23 -05:00
Unknwon
045f14fbd0 #1146 finsih UI work for access mode of collaborators
Collaborators have write access as default, and can be changed via repository
collaboration settings page to change between read, write and admin.
2016-03-05 18:08:42 -05:00
Unknwon
05d8664f15 Merge pull request #2762 from rom1504/patch-1
Fix grammar in README
2016-03-05 14:18:17 -05:00
Romain Beaumont
52fdecf97b Fix grammar in README 2016-03-05 19:46:32 +01:00
Unknwon
9c0f84cee8 Update README notes 2016-03-05 13:09:31 -05:00
Unknwon
414eb22ef9 #1597 fix activitity feeds for pull requests 2016-03-05 12:58:51 -05:00
Unknwon
a2f13eae55 #1157 some avatar setting changes
- Allow to delete current avatar
2016-03-05 00:51:51 -05:00
Unknwon
2a931937a8 Update locales 2016-03-04 18:51:18 -05:00
Unknwon
dfd6f8f7ab Merge pull request #2757 from joshfng/fix-fork-relative-url
Use relative url when showing forked from
2016-03-04 18:37:42 -05:00
Josh Frye
275464e7fb Use relative url when showing forked from 2016-03-04 18:32:30 -05:00
Unknwon
e2d370f0da #1597 fix pull request remote head can't update with force push 2016-03-04 16:53:03 -05:00
Unknwon
4cb8bf1b75 #1597 fix premission logic check of pull request 2016-03-04 16:14:02 -05:00
Unknwon
5335e671be #2743 more fixes on SQL errors 2016-03-04 16:00:00 -05:00
Unknwon
2d2d85bba4 #1597 support pull requests in same repository 2016-03-04 15:43:01 -05:00
Unknwon
9df6ce48c5 Minor fixes for #2746 2016-03-04 13:32:17 -05:00
Unknwon
4d5911dbcf Merge pull request #2746 from joshfng/feature-delete-wiki-pages
Add ability to delete single wiki pages.
2016-03-04 13:14:37 -05:00
Unknwon
d57a2b908a #2743 and #2751 fix bad SQL generated by XORM
Use hand-written SQL to do complex query
2016-03-04 13:08:47 -05:00
Josh Frye
2f228ddf31 Update delete wiki page route 2016-03-04 09:26:52 -05:00
Josh Frye
1ca171dbe9 Add ability to delete single wiki pages. 2016-03-04 09:26:52 -05:00
Unknwon
f6759a731a #2748 fix redirect loop with auto-signin 2016-03-04 09:15:11 -05:00
Unknwon
dfbda48afc Merge pull request #2738 from andreynering/emogify
Render emojis in more places.
2016-03-03 23:38:20 -05:00
Unknwon
260723e2cc Minor fixes for #2745 2016-03-03 23:24:22 -05:00
Unknwon
1cbc5b49e3 Merge pull request #2745 from joshfng/delete-wiki-option
Repo setting to delete and disable wiki
2016-03-03 23:04:35 -05:00
Josh Frye
f3358f5927 Repo setting to delete and disable wiki 2016-03-03 16:12:48 -05:00
Unknwon
f946040fa9 #1891 attempt to fix expected invalid CSRF token
- Remove unused config settings `[picture] service`
2016-03-03 15:09:43 -05:00
Unknwon
434614506e Merge pull request #2744 from joshfng/mirror-default-branch
Set DefaultBranch to master when importing a new repo.
2016-03-03 14:22:45 -05:00
Josh Frye
7f2733fa1b Return errors instead of just logging them. 2016-03-03 12:43:23 -05:00
Josh Frye
edb7967dc7 Set DefaultBranch to master when importing a new repo if possible 2016-03-03 12:23:45 -05:00
Unknwon
c9901bbba5 #2743 workaround to fix XORM problem 2016-03-03 10:57:27 -05:00
Unknwon
4d930f3598 Merge pull request #2719 from mblacktree/patch-1
update README.md
2016-03-03 10:35:59 -05:00
Andrey Nering
13e71acadf Render emojis in more places. 2016-03-02 21:54:05 -03:00
Unknwon
37ac743da7 Update TRANSLATORS and remove tip for CI 2016-03-02 16:43:32 -05:00
Unknwon
c47a6c1510 Merge pull request #2736 from neolit123/patch
ISSUE_TEMPLATE: suggestion to test at try.gogs.io
2016-03-02 13:53:49 -05:00
Lubomir I. Ivanov
94f9ff1ac9 ISSUE_TEMPLATE: suggestion to test at try.gogs.io
I've noticed that a lot of issues cannot be reproduced on http://try.gogs.io,
which either hints about specific database type problems or
hints about bugs which are already solved in the newer version
(as http://try.gogs.io is usually a newer build).

This patch adds the suggestion to test the issue at http://try.gogs.io in
the Github "issue template". The user can answer: "Yes", "No", "Not relevant".

"Not relevant" is an option where testing on http://try.gogs.io makes no sense as
the bug is unrelated to the Web UI or is very specific in nature.
2016-03-02 20:12:14 +02:00
Unknwon
97429a25ab #2727 make IN clause compatible with Postgres 2016-03-01 14:39:28 -05:00
Unknwon
9e89584cb4 Allow setting git operations timeouts
- Migrate: #2704 #2653
- Clone: #2701
- Mirror, Pull
2016-02-29 19:29:49 -05:00
Unknwon
ea80274229 #2700 fix sqlite3 can't create issue with more than one label 2016-02-29 18:45:12 -05:00
Unknwon
42a556a082 Merge pull request #2722 from chriswatt/hidewikidlbutton
Hide the download archive button when viewing wiki pages
2016-02-29 13:36:22 -05:00
chriswatt
a71a5bfeb4 Remove download archive button on wiki pages 2016-02-29 15:45:55 +00:00
Unknwon
6cee434b04 Merge pull request #2717 from chriswatt/prtabs
Change colour of numbers on pull request tabs if greater than zero
2016-02-29 00:51:58 -05:00
Mike
9d44cd79ee update README.md
minor grammar fix
2016-02-28 21:17:19 -05:00
chriswatt
548440b48f Change colour of numbers on pull request tabs if greater than zero 2016-02-28 23:27:41 +00:00
Unknwon
8055a0bdac Post work for #2637
Improve test cases, config settings, also show SSH config settings on admin config panel.
2016-02-27 20:48:39 -05:00
Unknwon
83c74878df Merge pull request #2637 from Gibheer/ssh-publickeys
allow native and ssh-keygen public key check
2016-02-27 18:55:14 -05:00
Unknwon
d320915ad2 Minor fix for #2710 2016-02-27 11:31:24 -05:00
Unknwon
8e160edbd5 Merge pull request #2710 from lukasdietrich/develop
Add ForegroundColor for labels to resolve #2033
2016-02-27 11:10:57 -05:00
Lukas Dietrich
c0eaae200e Add ForegroundColor for labels 2016-02-27 13:59:11 +01:00
Unknwon
79ae163296 Merge pull request #2706 from ChubbyNinja/develop
Image attachments keep aspect ratio
2016-02-26 14:24:38 -05:00
Unknwon
7a91d7e776 Merge pull request #2694 from mhartkorn/pullrefs
Improved Pull Request refs
2016-02-26 14:21:31 -05:00
Unknwon
6465adfe5c Merge pull request #2707 from gogits/docker/update
Docker Container update
2016-02-26 12:25:32 -05:00
Jean-Philippe Roemer
db14949209 Update Docker REAMDE.md
- Remove the known issue about `.dockerignore` being ignored during DockerHub automated build as this has been fixed
- Added a note on the fact that we currently do no support building the container on RPi1
2016-02-26 17:07:31 +00:00
ChubbyNinja
ab4bc653ab Image attachments keep aspect ratio 2016-02-26 14:09:37 +00:00
Jean-Philippe Roemer
ab4eacd15f Update .dockerignore to add new unneeded files from the Docker Context 2016-02-25 20:43:41 +00:00
Jean-Philippe Roemer
7845075bd2 Dockerfile & Dockerfile.pi updates
- Upgrade of gosu to v1.7
- Change in docker/build.sh to use `--no-cache` to prevent APKINDEX creation when installing dev dependencies
- Manual upgrade of Alpine on Raspberry Pi when building to make sure the environment is the same as the standard Dockerfile
2016-02-25 20:43:40 +00:00
Unknwon
129638117f #2697 fix panic when close issue via commit message 2016-02-25 14:17:55 -05:00
Unknwon
4438b7793b Add new config option for builtin SSH server
Config option [server] SSH_LISTEN_PORT to the port the builtin SSH server will be listen.
It can be different from SSH_PORT which is supposed to be exposed in the clone URL.
This should solve the problem when user runs Gogs inside Docker container
and still want to use builtin SSH server.
2016-02-25 00:21:48 -05:00
Unknwon
baaf6046a1 Minor fix for #2660 2016-02-24 23:59:17 -05:00
Unknwon
5418c2c5e4 Merge pull request #2660 from joshfng/config-test-mailer
Test mailer button. Addresses #1531
2016-02-24 23:26:32 -05:00
Josh Frye
c27038e392 Test mailer button. Addresses #1531 2016-02-24 09:48:05 -05:00
Martin Hartkorn
51f15880d1 Call PushToBaseRepo() also on Pull Request creation and not only on git push 2016-02-24 13:56:54 +01:00
Unknwon
d324500959 Prepare to release 2016-02-24 01:14:43 -05:00
Unknwon
3d218861e2 Merge pull request #2693 from appleboy/patch-2
test the latest version.
2016-02-24 00:19:01 -05:00
Gibheer
e721c5cf86 use StartSSHServer instead of DisableSSH
DisableSSH doesn't check the kind of ssh server to use, so that was
wrong. Use StartSSHServer instead.
2016-02-23 15:43:52 +01:00
Gibheer
e3570ae45d seperate ssh constants from schema constants
The contants were placed in the same section as the scheme ones, which
may lead to confusion.
2016-02-23 15:41:44 +01:00
Gibheer
2f27ee2232 variable should not use ALL_CAPS 2016-02-23 15:39:05 +01:00
Bo-Yi Wu
c65bd65254 test the latest version. 2016-02-23 16:04:40 +08:00
Unknwon
72ce06eab8 #2682 fix missing slash for go-get meta 2016-02-23 00:12:04 -05:00
Unknwon
912f7b51e9 #1821 add actions for close and reopen issues 2016-02-22 12:40:00 -05:00
Unknwon
90fab0be6b Merge pull request #2665 from muhmuhten/develop
Dockerfile cleanup for Alpine 3.3
2016-02-22 11:59:18 -05:00
Unknwon
c9516c4c60 Fix wrong place to check disable SSH 2016-02-21 21:55:59 -05:00
Unknwon
6e74dd4388 Merge pull request #2674 from andreynering/highlight-little-refactoring
Little refactoring of diff highlight.
2016-02-21 17:07:17 -05:00
Andrey Nering
d160c7e565 Little refactoring of diff highlight.
Moving cache variable to template instead of in the struct.
2016-02-21 18:45:24 -03:00
Unknwon
8ac04a3f29 Merge pull request #2672 from louwers/patch-1
Removed duplicate of paragraph
2016-02-21 16:16:54 -05:00
Bart
b91b35b565 Removed duplicate of paragraph 2016-02-21 16:02:00 +01:00
Unknwon
ac78bae7b5 Replace uuid module with original package 2016-02-20 18:13:12 -05:00
Unknwon
926e75d721 #2334 strip whitespace for migrate URL
Also fix a possible race condition while install
2016-02-20 17:32:34 -05:00
Unknwon
d5a3021a7d Make markdown as an independent module 2016-02-20 17:10:05 -05:00
Unknwon
d8a994ef24 Move cron module to independent package
Make it easier to keep track of upstream changes and bug fixes
2016-02-20 15:58:09 -05:00
Unknwon
7140dbac95 Fix #857 2016-02-20 15:10:34 -05:00
Unknwon
acf094fb07 Minor fix for #2634
Add AttributesInBind option in new auth source form.
2016-02-20 14:56:27 -05:00
Unknwon
7e0baf4136 Merge pull request #2634 from nanoant/patch/ldap-attributes-in-bind
LDAP: Fetch attributes in Bind DN context
2016-02-20 14:44:21 -05:00
Unknwon
a703f7d7b4 Merge pull request #2647 from andreynering/issue-template
Implement issue and pull request templates
2016-02-20 14:12:15 -05:00
Adam Strzelecki
a9981d8099 Update bindata for LDAP changes 2016-02-20 14:17:24 +01:00
Adam Strzelecki
5649556a33 LDAP: Make a bit more detailed log traces
This is useful especially to check whether we fetch right attributes, using
right LDAP search base and in right order.
2016-02-20 14:12:32 +01:00
Adam Strzelecki
834d92a47b LDAP: Fetch attributes in Bind DN context option
This is feature is workaround for #2628 (JumpCloud) and some other services
that allow LDAP search only under BindDN user account, but not allow any LDAP
search query in logged user DN context.

Such approach is an alternative to minimal permissions security pattern for
BindDN user.
2016-02-20 14:12:32 +01:00
Adam Strzelecki
e2f95c2845 LDAP: Use single connection in BindDN mode auth
According to RFC 4511 4.2.1. Processing of the Bind Request "Clients may send
multiple Bind requests to change the authentication and/or security
associations or to complete a multi-stage Bind process. Authentication from
earlier binds is subsequently ignored."

Therefore we should not use 2 connections, but single one just sending two bind
requests.
2016-02-20 14:01:47 +01:00
Muh Muhten
5609585ec1 update alpine package dependencies
- s6 is in main in 3.3, so we no longer need to mangle the repos file
- official image is periodically updated, so it's not preferred to do
  upgrades downstream (usually harmless, but inelegant)
- apk-tools in 3.3 supports --no-cache to avoid leaving the APKINDEX
  files in the image
2016-02-19 23:07:20 -05:00
Unknwon
b7f3d94cd0 Minor fix for #2524 2016-02-19 22:16:26 -05:00
Unknwon
f6c98465c7 Merge pull request #2524 from mhartkorn/pullrefs
Enable a way to checkout Pull Requests from remote refs
2016-02-19 22:00:25 -05:00
Unknwon
aa12135b97 Fix panic when view profile without signin
Also fix that no matter who, still able to see organizations with private membership.
2016-02-19 18:10:03 -05:00
Unknwon
f38d5e57dd Remove border-bottom for tabs header divider 2016-02-19 17:49:48 -05:00
Unknwon
341da3cea7 Fix inappropriate markdown post process end tag check
When <code> is nested inside <pre>, the next end tag token would not able to be the same
as outer-most start tag. So we only check outer-most start and end tag token to be the same.
2016-02-19 17:39:50 -05:00
Unknwon
7162095635 Merge pull request #2664 from jwdeitch/patch-1
Update contributing guidlines link
2016-02-19 16:09:43 -05:00
jwdeitch
0b54035d7a Update README.md 2016-02-19 16:07:15 -05:00
jwdeitch
dbd4697001 Update contributing guidlines link
previously displays 404
2016-02-19 15:25:23 -05:00
Unknwon
2408df3f35 Merge pull request #2663 from Download-Fritz/MirrorForks
#2505 Allow to fork and disallow to create PRs for mirrors.
2016-02-19 15:04:50 -05:00
Download-Fritz
a1b28fc33c Rename MustEnablePulls() to MustAllowPulls() and simplify the contained check to AllowsPulls(). 2016-02-19 20:48:32 +01:00
Download-Fritz
a467184e13 #2505 Allow to fork and disallow to create PRs for mirrors. 2016-02-19 20:33:06 +01:00
Andrey Nering
658bfc2704 Implement issue and pull request templates.
Similar to GitHub:
https://github.com/blog/2111-issue-and-pull-request-templates

Priority:
- root
- .gogs
- .github
2016-02-18 21:21:30 -02:00
Unknwon
736a46dff9 Merge pull request #2659 from joshfng/fix-issue-email-format
Fix issue email formatting. Addresses #2331
2016-02-18 16:19:23 -05:00
Josh Frye
0f1b26ed1e Fix issue email formatting. Addresses #2331 2016-02-18 16:08:20 -05:00
Unknwon
60896c66af Merge pull request #2658 from fnkr/fix-chmod
Fix chmod for several files in conf/locale/ and public/
2016-02-18 14:39:27 -05:00
Florian Kaiser
eb009923f4 Fix chmod for several files in conf/locale/ and public/ 2016-02-18 19:31:23 +00:00
Unknwon
338af89d56 #2650 fix possbility that use email as pusher user name
Remove the possibility of using email as user name when user actually push
through combination of email and password with HTTP.

Also refactor update action function to replcae tons of arguments with
single PushUpdateOptions struct.
And define the user who pushes code as pusher, therefore variable names shouldn't
be confusing any more.
2016-02-17 22:47:06 -05:00
Unknwon
2fdf8fc938 Add issue and pull request template 2016-02-17 21:22:58 -05:00
Unknwon
89d6b18dad Merge pull request #2649 from andreynering/gh-issue-template
Add GitHub's issue and pull request templates.
2016-02-17 18:29:35 -05:00
Andrey Nering
b97780ba51 Add GitHub's issue and pull request templates. 2016-02-17 21:15:11 -02:00
Unknwon
ccc94dd11c #2646 fix panic on pushing repositor 2016-02-17 15:17:52 -05:00
Unknwon
d5ca913b2f #2639 add branch prefix for test webhook 2016-02-17 15:05:07 -05:00
Gibheer
dab74f21b7 remove ed25519 test for now
TravisCI is too old for ed25519, so it can't be tested correctly.
2016-02-17 11:30:48 +01:00
Gibheer
9eef2e706c fix ssh public key tests
The old API was using []byte, but was changed to string without running
the tests again.
It also sets the variables from the configuration to make them work.
Maybe there is a better way to do this.
2016-02-17 09:33:41 +01:00
Gibheer
12403bdfb0 allow native and ssh-keygen public key check
This commit adds the possibibility to use either the native golang
libraries or ssh-keygen to check public keys. The check is adjusted
depending on the settings, so that only supported keys are let through.

This commit also brings back the blacklist feature, which was removed in
7ef9a05588. This allows to blacklist
algorythms or keys based on the key length. This works with the native
and the ssh-keygen way.

Because of #2179 it also includes a way to adjust the path to
ssh-keygen and the working directory for ssh-keygen. With this,
sysadmins should be able to adjust the settings in a way, that SELinux
is okay with it. In the worst case, they can switch to the native
implementation and only loose support for ed25519 keys at the moment.
There are some other places which need adjustment to utilize the
parameters and the native implementation, but this sets the ground work.
2016-02-16 23:01:56 +01:00
Unknwon
3af1d3c581 #2633 fix removed config option 2016-02-16 13:27:02 -05:00
Unknwon
24829f314b Merge pull request #2635 from lunny/develop
fix dependency broken because xorm's API changed
2016-02-16 13:23:44 -05:00
Lunny Xiao
779b71eda4 fix dependency broken because xorm's API changed 2016-02-16 22:35:08 +08:00
Unknwon
9cf4fe043b Add env var check for update 2016-02-15 23:11:22 -05:00
Unknwon
2765b5c7cf #2630 fix wrong user avatar link in webhook
Was using the wrong method and now uses the method which checks if
the avatar link is relative or not.
2016-02-15 15:18:53 -05:00
Unknwon
632c27802c Minor fix for #2624 2016-02-15 14:57:15 -05:00
Unknwon
dc89c51f3e Merge pull request #2624 from mhartkorn/convert-mirror-to-repo
Convert mirrors to regular repositories
2016-02-15 14:26:21 -05:00
Martin Hartkorn
bb595666ac Moved UpdateRepository() to CleanUpMigrateInfo() and correctly delete mirror from database 2016-02-15 14:59:24 +01:00
Unknwon
e9b9e6eb53 Setup CI with testing 2016-02-14 23:20:07 -05:00
Unknwon
58e004f7da Remove cache avatar support and add its tests 2016-02-14 23:14:55 -05:00
Unknwon
fd92d91da3 Minor fix for #2578 2016-02-14 20:36:03 -05:00
Unknwon
d8631b616e Merge pull request #2578 from exmex/develop
Admins and user itself sees private org relations on profile
2016-02-14 20:34:53 -05:00
Unknwon
aa5e837c65 fix #2454 2016-02-14 20:26:49 -05:00
Unknwon
4f6c3e8bb2 Hijack #2388 2016-02-14 20:19:00 -05:00
Unknwon
a1d97e8f5c Minor fix for #2567 2016-02-14 20:07:42 -05:00
Unknwon
daa43cfb6e Merge pull request #2567 from fnkr/hide-other-teams-activity-from-dashboard
Only show activities and repositories on the dashboard, that the user has access to
2016-02-14 19:57:49 -05:00
Unknwon
9adfe453d5 #2569 delete repo local copy when transfer
Remote repository path is renamed but does not delete
outdated local copy which still has old repository path
as remote.
2016-02-14 19:42:38 -05:00
Unknwon
29cd8ac270 Merge pull request #2617 from chriswatt/bgcolor
Change main content area bg to white, keep area above tabs grey
2016-02-14 18:33:17 -05:00
chriswatt
d710b5e791 Fix when repo is empty 2016-02-14 23:26:47 +00:00
chriswatt
c47866b34a Add grey bg to tabs on repo page 2016-02-14 23:09:33 +00:00
Martin Hartkorn
15d37b7a95 Refactored according to suggestions 2016-02-14 22:40:39 +01:00
Martin Hartkorn
15394f613f Add missing safety check 2016-02-14 21:22:36 +01:00
Martin Hartkorn
3650bd8528 Convert mirrors to regular repositories. 2016-02-14 21:12:00 +01:00
Unknwon
de3be370f7 Remove unused tests
Module httplib will be replaced a well done third-party package
soon, so remove its unused tests
2016-02-13 18:11:15 -05:00
Unknwon
364874937e Merge pull request #2614 from joshfng/add-default-branch-to-repo-payload
Add default branch to repo payload
2016-02-12 16:51:46 -05:00
Unknwon
10e4887b2b Merge pull request #2612 from Eriner/master
update .gopmfile to reflect git-module update
2016-02-12 14:50:03 -05:00
Matt Hamilton
643acdd32d update .gopmfile to reflect git-module update
Updated to reflect version increment in commit 47adc0e.
2016-02-12 12:40:35 -05:00
Josh Frye
8662990746 Add default branch to repo payload 2016-02-12 11:04:46 -05:00
Unknwon
25845ea1a5 Merge pull request #2609 from joshfng/add-config-log-path
Add install option for log path
2016-02-12 10:21:46 -05:00
Josh Frye
d3ca5accfd Remove redundant nil check. 2016-02-12 10:15:47 -05:00
Josh Frye
8ab5399e83 Make log path required 2016-02-12 10:10:02 -05:00
Josh Frye
ec478b4b06 Set default log path if empty during install 2016-02-12 10:03:04 -05:00
Josh Frye
1feecd6beb Add helper text for log path. 2016-02-12 09:24:09 -05:00
Josh Frye
a3e8c32a30 Add install option for log path 2016-02-12 09:19:45 -05:00
Unknwon
779bb890fa Minor docs update for #2605 2016-02-12 08:18:12 -05:00
Unknwon
1fa4fe706a Merge pull request #2605 from 0rax/develop
Add the ability to run crond inside the Docker container
2016-02-12 08:14:26 -05:00
Jean-Philippe Roemer
f4bc9263d9 Add the ability to run crond inside the Docker container
- Add the crond init script for s6
- Add the RUN_CROND configuration variable to setup crond
- Crond will not be run by default (hence the `down` file in the service directory)
- `start.sh` check if RUN_CROND = "true" || "1" and remove this file to tell s6 to run the initscript
- Resolves #2597
2016-02-12 02:48:55 +00:00
Unknwon
600d8edaca Merge pull request #2604 from joshfng/fix-wiki-transfer
Remove local wiki copy on repo transfer. Fixes #2558
2016-02-11 19:57:19 -05:00
Josh Frye
ce3708b3ea Remove local wiki copy on repo transfer. Fixes #2558 2016-02-11 19:26:51 -05:00
Unknwon
23bc9a2911 Merge pull request #2603 from joshfng/bump-git-module-version
Bump git-module. Fixes #2589
2016-02-11 17:09:06 -05:00
Josh Frye
47adc0e8f7 Bump git-module. Fixes #2589 2016-02-11 17:03:39 -05:00
Unknwon
5258ee3740 Update locales and update sponsor 2016-02-11 13:34:21 -05:00
Unknwon
59745c62b4 #1577 fix missing SQL query placeholder 2016-02-10 17:30:24 -05:00
Unknwon
0ad5f51059 Merge pull request #2599 from mhartkorn/fix-release-error-deleted-user
Fix for server error on release page when a user deleted their account
2016-02-10 16:11:56 -05:00
Martin Hartkorn
6b3e47b103 Removed HTTP 500 error on the release page when a user deleted their account 2016-02-10 22:04:11 +01:00
Unknwon
297e772c20 #2485 fix payloads mixed up for webhook
When repository contains a Slack type hook,
it changes original payload content.

This patch fixes it by using a local object to store
newly created Slack payload instead of assigning
back to the same variable.
2016-02-10 15:21:39 -05:00
Unknwon
8bf3032b16 Merge pull request #2585 from andreynering/theme-color-meta-tag
Implementing the "theme-color" meta tag.
2016-02-08 15:03:08 -05:00
Andrey Nering
e40d94bb4f Implementing the "theme-color" meta tag.
Used by Android >= 5.0 to make the top bar colored.

Reference: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
2016-02-08 17:03:18 -02:00
Unknwon
7ffe845c61 Merge pull request #2582 from chriswatt/tabindex
Fix tab index on new issue/comment form
2016-02-07 17:18:30 -05:00
chriswatt
af8e323248 Fix tab index on new issue/comment form 2016-02-07 22:14:33 +00:00
Unknwon
b09ddc72d2 Merge pull request #2581 from chriswatt/committab
Make commits tab active when on diff page
2016-02-07 15:37:22 -05:00
chriswatt
a881f776d0 Make commits tab active when on diff page 2016-02-07 20:11:25 +00:00
ExMex
40f9d4f920 Reverted showing (private) on private org relations 2016-02-07 20:30:15 +01:00
Unknwon
dd7608a36e Merge pull request #2580 from fnkr/smaller-issue-title
Make issue title smaller
2016-02-07 14:30:04 -05:00
Florian Kaiser
662482d366 Make issue title smaller 2016-02-07 19:23:26 +00:00
Unknwon
08ff1b7d4b Merge pull request #2579 from nanoant/patch/fix-ldap-username
Fix #2221 LDAP username attribute must be fetched
2016-02-07 12:27:10 -05:00
Adam Strzelecki
3808638df1 Fix #2221 LDAP username attribute must be fetched
This is fix-up for 573305f. Forgot to fetch AttributeUsername value from the
LDAP server, so the setting was effectively not working as intended.
2016-02-07 18:18:29 +01:00
Unknwon
ee53204e02 Improve db path prompt when install 2016-02-07 11:51:53 -05:00
Unknwon
f15a2f9b25 Merge pull request #2528 from andreynering/diff-sintax-highlight-733
Enable syntax highlighting on diff view
2016-02-07 11:49:11 -05:00
Unknwon
3b102a71a2 Merge pull request #2576 from chriswatt/commentarrows
Add avatar arrows to both pull request and issue forms
2016-02-07 11:45:37 -05:00
chriswatt
133397ee0d Rename #avatararrow to #avatar-arrow 2016-02-07 16:41:11 +00:00
Unknwon
e2b4a24cb6 Merge pull request #2570 from andreynering/fix-1738
Workaround delete folder on Windows.
2016-02-07 10:46:23 -05:00
Andrey Nering
d37cf09ccd Workaroud delete folder on Windows. Fix #1738 2016-02-07 13:39:32 -02:00
ExMex
2cfe6f8c60 Admins and user itself sees private org relations on profile 2016-02-07 10:20:58 +01:00
chriswatt
16270ee9a4 Add avatar arrow to pull request form 2016-02-07 06:10:57 +00:00
chriswatt
1dfead1eef Add avatar arrows to new both new issue comment forms 2016-02-07 04:20:11 +00:00
Unknwon
894946c319 Merge pull request #2573 from prologic/add-note-wrt-ssh-on-docker#2409
Add an important note about mapping the ssh port on the container to the host
2016-02-06 20:22:43 -05:00
Florian Kaiser
45db167f7a Only show activities for repositories on dashboard, that the user has access to 2016-02-06 07:52:21 +00:00
Unknwon
10fbb1aa2f Merge pull request #2565 from tkausl/issue2563
fixes #2563
2016-02-05 19:15:54 -05:00
Tobias Kunicke
bc0eee48d5 parse milestone.deadline as local time 2016-02-06 00:10:32 +01:00
Tobias Kunicke
fa5a1cb54f regulate timezone for milestone.deadline 2016-02-06 00:08:02 +01:00
Unknwon
e797a225b6 Fix #2564 file ignored by git 2016-02-05 17:19:32 -05:00
Unknwon
6d5c986d4f Merge pull request #2562 from Eriner/master
optipng
2016-02-05 16:18:52 -05:00
Matt Hamilton
45659d0fd2 optipng 2016-02-05 16:04:11 -05:00
Unknwon
acfc942ad7 Generate CSS for #2561 2016-02-05 14:53:45 -05:00
Unknwon
db150f2e42 Merge pull request #2561 from chriswatt/develop
Add small arrows on issue comments pointing to users avatar
2016-02-05 14:50:49 -05:00
chriswatt
9fe9cd8b5c Add small user arrows on issue comments pointing to users avatar 2016-02-05 19:24:23 +00:00
Unknwon
f8182ac521 #2558 delete local wiki copy when rename repo and user 2016-02-05 14:11:53 -05:00
Unknwon
4e96a4a62b Merge pull request #2406 from bkcsoft/feature/markdown-custom-url-scheme
Feature/markdown custom url scheme
2016-02-05 13:11:45 -05:00
Florian Kaiser
90e9e3c89d Only show repositories on organization dashboard, that the user has access to 2016-02-05 15:49:01 +00:00
Unknwon
d4583ebd4b Add YunoHost link to README 2016-02-05 10:19:37 -05:00
Unknwon
b024de7bf5 Merge pull request #2559 from Techwolf12/develop
Fixes small typo
2016-02-05 09:32:52 -05:00
techwolf12
4a0d2edc3d Fixes small typo 2016-02-05 15:11:25 +01:00
Unknwon
8e40f86d2c #2556 handle space in image URL 2016-02-04 22:51:40 -05:00
Andrey Nering
2bfb8bb5fd Enable sintax highlighting on diff view. Close #733 2016-02-04 18:21:47 -02:00
Andrey Nering
137a49e834 go fmt models/git_diff_test.go 2016-02-04 17:55:17 -02:00
Martin Hartkorn
a3bdede2ce Removed unused method GetUnmergedPullRequestByRepoPathAndHeadBranch 2016-02-04 19:15:21 +01:00
Unknwon
ddf9fa06c7 Minor fix for #2530 2016-02-04 13:03:34 -05:00
Martin Hartkorn
d91004ee71 Removed dependency on post-receive hook and use TriggerTask instead 2016-02-04 19:00:42 +01:00
Unknwon
739d5aa1d3 Merge pull request #2530 from fnkr/hide-other-teams-repos-from-org-page
Hide other teams & repos from organization page
2016-02-04 12:52:11 -05:00
Unknwon
04be8c0de5 #2554 reinitialize all repos from the db
- Update locales
2016-02-04 12:51:00 -05:00
Florian Kaiser
c3ff476ed6 Remove unnecessary else-block 2016-02-04 17:13:56 +00:00
Florian Kaiser
fb1708e1af Remove unnecessary private functions 2016-02-04 17:08:25 +00:00
Unknwon
a47baa1b7a Add missing patch conflit pattern 2016-02-03 12:28:03 -05:00
Unknwon
995487e822 Minor fix for #2506 2016-02-02 17:07:40 -05:00
Unknwon
5e97693e0e Merge pull request #2506 from sapk/add-branche-api-support
Implement API for branches listing
2016-02-02 16:51:14 -05:00
Unknwon
452bc385fe Merge pull request #2548 from fnkr/fix-unescaped-regex
Escape unescaped periods in route regular expression
2016-02-02 13:30:08 -05:00
Florian Kaiser
71bb7f6053 Escape unescaped periods in route regular expression 2016-02-02 17:39:56 +00:00
Unknwon
0255e6a703 Merge pull request #2546 from fnkr/pretty-404-pages
Use pretty 404 pages in repo.HTTPBackend
2016-02-02 10:35:46 -05:00
Unknwon
5a27aea8e0 Fix random avatar does not work on Windows
path.Dir can't handle Windows case, must use filepath.Dir
2016-02-02 10:22:27 -05:00
Florian Kaiser
0e4ae27caa Use pretty 404 pages in repo.HTTPBackend 2016-02-02 14:09:47 +00:00
Unknwon
1c74612b3c Minor fix for #2444 2016-02-01 20:55:12 -05:00
Unknwon
d3ba246693 Merge pull request #2444 from bkcsoft/feature/participants
Implemented participant-listing for issue-pages (Fixes #2377)
2016-02-01 20:31:54 -05:00
Unknwon
a93af59b36 Merge pull request #2542 from fnkr/fix-markdown-code-blocks-issue-comment-save
Fix syntax highlighting for markdown code blocks on issue description/comment save
2016-02-01 18:12:17 -05:00
Florian Kaiser
0d41827f23 Fix syntax highlighting for markdown code blocks on issue description/comment save 2016-02-01 22:50:22 +00:00
Unknwon
32efc3ec0a Merge pull request #2540 from JohnMaguire/bugfix/2447-delete-public-key-authorized_keys
Fixes #2447 (delete public key from authorized_keys)
2016-02-01 16:32:30 -05:00
Unknwon
d33ed36fb4 Merge pull request #2539 from redoz/develop
Change en-us localization "mirror from"  to "mirror of"
2016-02-01 16:25:44 -05:00
Patrik
9d67528c82 Change en-us localization "mirror from" to "mirror of" 2016-02-01 21:59:48 +01:00
Unknwon
66d2ba1b4e Merge pull request #2537 from fnkr/remember-clone-protocol
Remember last selected clone protocol
2016-02-01 15:58:01 -05:00
Florian Kaiser
84749736a8 Select HTTPS if remembered clone protocol is SSH but SSH is disabled now 2016-02-01 20:42:10 +00:00
Unknwon
857b340498 Merge pull request #2538 from fnkr/issue-markdown-code-block-highlighted
Make highlighted markdown code blocks work on issue pages
2016-02-01 15:31:05 -05:00
Florian Kaiser
3e0a27157c Make highlighted markdown code blocks work on issue pages 2016-02-01 19:53:58 +00:00
Unknwon
3abad75a1b Fix one user may block entire listen loop for builtin SSH 2016-02-01 12:10:49 -05:00
Florian Kaiser
d568019306 Remember last selected clone protocol, and establish uniform order (https, ssh) 2016-02-01 17:04:58 +00:00
John Maguire
b3e0efc0c3 Trim whitespace when adding SSH keys (fixes #2447) 2016-01-31 22:02:36 -05:00
John Maguire
caa4ca46c0 Add debug log when SSH key for deletion isn't found 2016-01-31 22:02:23 -05:00
Unknwon
5d192c2ebf Merge pull request #2533 from fnkr/icon-fork-private-collision
Use icon repo-forked instead of repo-lock for private, forked repos
2016-01-31 19:41:21 -05:00
Florian Kaiser
29c3e9f428 Undo change in templates/explore/repo_list.tmpl 2016-01-31 21:59:18 +00:00
Florian Kaiser
532f9fdd99 Use icon repo-forked instead of repo-lock for private, forked repos 2016-01-31 20:41:57 +00:00
Unknwon
4848620594 #2229 adjust URL verbose depth for reverse proxy sub-path 2016-01-31 15:38:20 -05:00
Florian Kaiser
bead46363b Evaulate org/team permissions when using the issue/PR view 2016-01-31 20:12:03 +00:00
Unknwon
57c10aae33 Merge pull request #2531 from andreynering/home-template-pt-BR
Add portuguese-BR to home template.
2016-01-31 15:10:21 -05:00
Andrey Nering
0e0cd9100b Add portuguese-BR to home template. 2016-01-31 17:58:51 -02:00
Florian Kaiser
90780a0d90 Use invalid value (-1) instead of 0 to prevent bug if auto increment starts with 0 2016-01-31 19:17:58 +00:00
Florian Kaiser
fdad234445 Remove unnecessary comments 2016-01-31 19:08:20 +00:00
Florian Kaiser
bba1847a8e Everyone can see public repos 2016-01-31 18:37:50 +00:00
Unknwon
a9d68a6884 fix #2529 2016-01-31 13:33:36 -05:00
Florian Kaiser
9cf95e4e37 Organization owners see all repositories & teams 2016-01-31 16:14:24 +00:00
Florian Kaiser
8c4588c4c9 Refactor .IsAdminTeam to .IsTeamAdmin and requireAdminTeam to requireTeamAdmin 2016-01-31 15:30:07 +00:00
Florian Kaiser
e35791b2b2 Only show teams the user has access to 2016-01-31 15:30:07 +00:00
Florian Kaiser
5eafe2b17e Only show repositories the user has access to, on the organization home 2016-01-31 15:29:45 +00:00
Unknwon
1c1246fcb9 Merge pull request #2527 from fnkr/hide-private-orgs-from-profile
Show all orgs on user profile, except the private one's
2016-01-31 08:56:21 -05:00
Unknwon
8436d69eaf Update and reorganize front-end resources 2016-01-30 22:10:20 -05:00
Martin Hartkorn
20403f75fb Enable a way to checkout Pull Requests from remote refs 2016-01-30 23:56:38 +01:00
Florian Kaiser
295de51b99 Show all orgs on user profile, except the private one's 2016-01-30 21:53:58 +00:00
Unknwon
6e03f61617 Update .gopmfile 2016-01-30 10:12:23 -05:00
Unknwon
055c1ea02d Merge pull request #2517 from fnkr/issue-2516
Allow modification of a release if Content is empty (fix #2516)
2016-01-30 09:47:37 -05:00
Florian Kaiser
abc5abce30 Allow modification of a release if Content is empty (fix #2516) 2016-01-30 13:39:02 +00:00
Unknwon
112a7cab31 #2497 incorrect error handle for team name 2016-01-29 17:06:14 -05:00
Unknwon
ee814bf8d6 #2491 minor fix for sr on dashboard 2016-01-29 15:28:24 -05:00
Unknwon
a4a23c0268 Merge pull request #2508 from MilesPong/develop
Fixed gravatar url
2016-01-29 05:44:00 -05:00
Unknwon
cd89d387b6 Merge pull request #2509 from 0rax/develop
Update Docker container with Alpine 3.3 & Fix RPi2 build
2016-01-29 05:15:08 -05:00
miles@Oscar
beefc53e59 Using https for gravatar 2016-01-29 13:06:17 +08:00
miles@Oscar
1becf01cfa Fixed gravatar url 2016-01-29 11:05:41 +08:00
Jean-Philippe Roemer
9fbf54ee6b Update Dockerfile.rpi to better match Dockerfile:
- Dockerfile.rpi now uses hypriot/rpi-alpine-scratch as base (build script are available w/ a better maintainer & more updates)
- Dockerfile.rpi updates alpine from v3.2 to v3.3 to be on par with Dockerfile
2016-01-28 21:31:45 +00:00
Jean-Philippe Roemer
12c8953381 Update Dockerfile to update alpine to v3.3 & fix virtual package and repository pinning on RPi
- Dockerfile now uses alpine:3.3 as base
- Dockerfile.rpi now uses v3.3/community repository without pinning
- Go package is no longer fetched using repository pinning
- Fixes problem while using repository pinning & virtual package at the same time
2016-01-28 21:31:45 +00:00
Antoine GIRARD
b7b30cd85e Corrections following recommendations 2016-01-28 20:51:19 +01:00
Antoine GIRARD
81e5722bcc Handling error for the API request and add commments
[ci skip]
2016-01-28 20:51:19 +01:00
Antoine GIRARD
303d091ea9 Update link for documentation (Temporary https://gist.github.com/sapk/df64347ff218baf4a277)
[ci skip]
2016-01-28 20:51:19 +01:00
Antoine GIRARD
c11c3b6c11 Near ready 2016-01-28 20:51:19 +01:00
Unknwon
566163ab82 Merge pull request #2502 from bkcsoft/fix/split-view-diff
Split view fixed
2016-01-28 10:11:45 -05:00
Unknwon
e2dde6eb0a Record error when fail to health check repository 2016-01-28 06:46:25 -05:00
Unknwon
b900150b1d Update locales 2016-01-28 06:15:49 -05:00
Unknwon
4deb876343 Minor fix for #2494
- Change tooltip size from mini to tiny in profile page
2016-01-28 06:07:16 -05:00
Unknwon
0617720c0c Merge pull request #2494 from mhartkorn/pullreq-name-change
Change user name in Pull Requests to avoid errors (fixes #2495)
2016-01-28 05:58:37 -05:00
Unknwon
9b8ad01bc0 Merge pull request #2493 from andreynering/fix-2489
Refactoring of inline diff computing to prevent empty diff box.
2016-01-28 05:33:27 -05:00
Kim "BKC" Carlbäcker
96dee1c354 Split view fixed 2016-01-27 23:52:42 +01:00
Martin Hartkorn
674c5c37be Change user name in Pull Requests 2016-01-27 22:45:03 +01:00
Andrey Nering
5deb726f3f Refactoring of inline diff computing to prevent empty diff box. Fix #2489 2016-01-27 18:54:08 -02:00
Kim "BKC" Carlbäcker
1ab8a60d73 Not working, but slightly better... 2016-01-27 21:48:57 +01:00
Unknwon
8eb0577791 Merge pull request #2492 from SarenCurrie/patch-1
Fix grammar in deploy key section
2016-01-27 15:46:51 -05:00
Kim "BKC" Carlbäcker
85335c5f56 Go-ism :D 2016-01-27 20:11:07 +01:00
Unknwon
93f40995b3 Merge pull request #2483 from bkcsoft/fix/mysql-webhook-url-length
Fixed Webhook URL-length Issue #2465
2016-01-27 04:04:01 -05:00
Saren Currie
646e90d833 Fix grammar in deploy key section 2016-01-27 15:32:47 +13:00
Kim "BKC" Carlbäcker
d943429672 Added example to conf/app.ini 2016-01-27 02:05:53 +01:00
Kim "BKC" Carlbäcker
3a9fd81f59 Custom URL-Schemas for Markdown 2016-01-27 02:02:03 +01:00
Kim "BKC" Carlbäcker
edc414c584 Fixed Webhook URL-length Issue #2465 2016-01-27 01:40:35 +01:00
Unknwon
a849ac0164 Merge pull request #2446 from jgsqware/develop
Add Docker Volume from 1.9
2016-01-26 13:45:24 -05:00
Kim "BKC" Carlbäcker
b31c7fe074 Fixed Poster/Commenter-bug and clean-up 2016-01-26 17:55:54 +01:00
Kim "BKC" Carlbäcker
2665728ee7 Fix OP not 'participating' until commented 2016-01-26 17:55:54 +01:00
Kim Carlbäcker
f65dedc3be Optimize participant-fetching 2016-01-26 17:55:54 +01:00
Kim "BKC" Carlbäcker
b921161666 Name popup 2016-01-26 17:55:54 +01:00
Kim "BKC" Carlbäcker
2cc1ee3fc0 Implemented participant-listing for issue-pages 2016-01-26 17:55:54 +01:00
Unknwon
ab0ba4bbae Merge pull request #2425 from andreynering/make-test
Add command to run the test suite in Makefile.
2016-01-26 03:14:19 -05:00
Unknwon
86f841dd71 Merge pull request #2433 from xxxtonixxx/develop
To add spanish translation to home template
2016-01-26 03:11:54 -05:00
Unknwon
e3075865e4 Merge pull request #2480 from andreynering/fix-2462
Compute inline diff for pull request view, too. Fix #2462
2016-01-26 03:07:47 -05:00
Unknwon
3509f1f610 Merge pull request #2475 from 0rax/develop
Update Dockerfile & build script and add /etc/nsswitch.conf
2016-01-26 02:32:40 -05:00
Unknwon
7ca1821725 fix #2416 2016-01-26 02:00:16 -05:00
Andrey Nering
ee5d6fb025 Compute inline diff for pull request view, too. Fix #2462 2016-01-25 20:56:27 -02:00
Unknwon
1372cab35a Merge pull request #2445 from bkcsoft/feature/fix-2442
Admins are allowed to create repos for arbitrary Orgs
2016-01-25 15:11:56 -05:00
Unknwon
e33ddac9bf Minor fix for #2396 2016-01-25 14:04:46 -05:00
Unknwon
71b9537393 Merge pull request #2396 from bkcsoft/feature/markdown-checklist
[Feature] Markdown Checklist-rendering
2016-01-25 13:56:13 -05:00
Unknwon
b33abc6280 Merge pull request #2432 from nd/develop
Fix #2431 - handle requests waiting for reply
2016-01-25 13:16:32 -05:00
Jean-Philippe Roemer
9032bd097b Update Dockerfile & build script and add /etc/nsswitch.conf:
- Add nsswitch.conf to configure LibC Name Service inside the container
- Change my email in the Dockerfile
- Update build script to install software as a `build-deps` virtual package so that adding a package to it will be automatically	removed at the end of the build script
2016-01-25 13:07:37 +00:00
Unknwon
38efa72146 Update locales 2016-01-25 02:33:52 -05:00
Unknwon
4ae7e64e2a Merge pull request #2467 from pdan/patch-1
Fixed forgotten err variable assignment
2016-01-25 02:33:09 -05:00
Pourya Daneshvar
863ff19e1f Fixed forgotten err variable assignment 2016-01-24 10:24:21 +03:30
juliengarcia
eb14fbf95f Add Docker Volume from 1.9 2016-01-20 16:54:38 +01:00
Kim "BKC" Carlbäcker
a3eab8185d Admins are allowed to create repos for arbitrary Orgs 2016-01-20 14:46:45 +01:00
James Mills
f36c82c3b3 Add an important note about mapping the ssh port on the container to the host 2016-01-19 22:24:40 -08:00
Toni Villena
1105a3139f Add es-ES to home template 2016-01-18 17:49:17 +01:00
Dmitry Neverov
fb99d50fa1 Fix #2431 - handle requests waiting for reply
According to the docs [1], the Reply method must be called for all
requests where WantReply is true. This fixes a hanging java ssh
implementation (jsch) which sets WantReply flag and waits for reply from
the server.

[1] https://godoc.org/golang.org/x/crypto/ssh#Request.Reply
2016-01-18 16:54:10 +01:00
Andrey Nering
b8d0367a6c Add command to run the test suite in Makefile. 2016-01-16 16:13:54 -02:00
Unknwon
7ef9a05588 #2179 use Go sub-repo ssh to verify public key content 2016-01-15 18:39:51 +08:00
Unknwon
c631a4a9b9 URL fix for #2287 2016-01-15 18:00:39 +08:00
Unknwon
dccfadf7b8 hide section with user has no organizations 2016-01-14 21:29:25 +08:00
Unknwon
d1675c2701 fix CSS of branch dropdown when view commits under revision 2016-01-14 21:27:36 +08:00
Unknwon
29b07693dd minor fix to #2383
- add tooltip for organization name in profile
2016-01-14 21:21:56 +08:00
Unknwon
f75b5f4287 Merge pull request #2383 from exmex/develop
Added organization display on profile
2016-01-14 21:07:17 +08:00
ExMex
40413c5c6c Added improvement from Unknwon 2016-01-14 11:48:24 +01:00
Unknwon
a72f57374d Merge pull request #2403 from ddelpero/master
Update repo.go
2016-01-14 14:55:45 +08:00
Unknwon
98306a5d8a Merge pull request #2399 from nanoant/patch/osx-launchd-script
OS X launchd script
2016-01-14 14:42:55 +08:00
Unknwon
cb92af4a6c Merge pull request #2398 from nanoant/patch/fix-refurl-arg
commit.RefUrl expects AppUrl argument
2016-01-14 14:41:13 +08:00
Unknwon
ae2c6d42fd Merge pull request #2393 from sapk/fix-issue-2375
Correction for issue #2375
2016-01-14 14:32:32 +08:00
Unknwon
ab89be33a9 fix #2385 2016-01-14 14:28:07 +08:00
Kim "BKC" Carlbäcker
a1a4f1103c Made Sanitizer-setup cleaner 2016-01-14 03:00:05 +01:00
Adam Strzelecki
653e1506ad OS X launchd script
Using this script:

1. Copy scripts/launchd/io.gogs.web.plist into /Library/LaunchDaemons

2. The script assumes Gogs is running under 'gogs' user and group, modify
   /Library/LaunchDaemons/io.gogs.web.plist if you want to user different user.

3. The script assumes Gogs is installed in /Users/git/gogs, modify
   /Library/LaunchDaemons/io.gogs.web.plist if you installed Gogs in different
   location.

4. Once you are sure that running Gogs manually via `gogs web` works fine, run
   it as a launchd service with:

       sudo launchctl load -F /Library/LaunchDaemons/io.gogs.web.plist

From now on launchd will ensure Gogs is running, eg. when system is restarted.
2016-01-13 19:32:07 +01:00
Adam Strzelecki
41fdaabcf7 commit.RefUrl expects AppUrl argument
This is fixup for ea375c0dcc. The bug was not
visible because commit.RefUrl was always returning empty url due regression
described in https://github.com/gogits/git-module/pull/4
2016-01-13 19:09:50 +01:00
Kim "BKC" Carlbäcker
8e09e03127 Checklist-rendering implemented 2016-01-13 13:25:52 +01:00
Antoine GIRARD
688fc515f8 Fix username display in lower-cased for comment in Dashboard 2016-01-12 21:30:14 +01:00
ExMex
53a63de9dc Added links to org profile icons 2016-01-12 03:19:46 +01:00
ExMex
f610bfa8a2 Added organization display on profile
Fixed "Follower" Icon too big
2016-01-12 03:09:59 +01:00
Unknwon
fc4a4d38d1 Merge pull request #2381 from philippechataignon/develop
Add fr-FR to home template
2016-01-11 23:59:45 +08:00
Philippe Chataignon
939d96813c Add fr-FR to home template 2016-01-11 13:55:52 +01:00
Unknwon
f43cc90841 #2287 Truncate repository name if too long 2016-01-11 20:41:43 +08:00
Unknwon
a2ef9a2b64 update locale 2016-01-11 18:30:44 +08:00
Unknwon
c199703e2a #2349 fix convert type 2016-01-11 15:47:23 +08:00
Unknwon
db719abff2 stop compile bindata for TRANSLATORS
- update required version of git-module for #2373
2016-01-11 15:01:38 +08:00
Unknwon
91bab801aa #2349 try to handle []int8 case 2016-01-11 14:34:32 +08:00
Unknwon
17c4400b12 Merge pull request #2374 from l2dy/develop
Minor fix (extra space)
2016-01-10 17:36:07 +08:00
l2dy
efa0e7b27a Minor fix 2016-01-10 17:29:33 +08:00
Unknwon
cd966787f3 Merge pull request #2369 from koenwtje/fix-freebsd-init-script
Fix status command in FreeBSD init script
2016-01-10 13:28:24 +08:00
Unknwon
e2f0587ca3 Merge pull request #2370 from andreynering/fix-tests
Fix test case after 86bce4a2ae.
2016-01-10 13:19:24 +08:00
Andrey Nering
9620f48ed0 Fix test case after 86bce4a2ae. 2016-01-09 17:05:21 -02:00
Koen Wilde
4db0e1d340 Fix status command in FreeBSD init script
If the init script is called with `status`, the rc.subr(8) routines check if
the first argument associated with the pid in the pidfile is equal to
`procname`. By default, `procname` is equal to the value of `command`. In our
case, `command` contains a space (i.e. has multiple arguments), so `procname`
can never be equal to the first argument of the command associated with the
pid.

Set `procname` to the first argument of `command` to fix the `status` command
of the init script.
2016-01-09 13:31:45 +01:00
Unknwon
8a93113192 roll back a small change 2016-01-09 15:04:28 +08:00
Unknwon
86bce4a2ae minor fix to #2335 2016-01-09 14:51:17 +08:00
Unknwon
21d7b5acaf fix #2367 2016-01-09 14:45:06 +08:00
Unknwon
bcf6aed452 Merge pull request #2335 from andreynering/highlight-diff
Highlight diff
2016-01-09 13:39:18 +08:00
Unknwon
4331d1d2a0 require token for list my orgs 2016-01-09 13:32:19 +08:00
Unknwon
62edc5c59a fix cannot show user public ssh keys 2016-01-09 13:28:05 +08:00
Unknwon
cc8c67ff29 fix markdown autolink error 2016-01-09 10:59:04 +08:00
Andrey Nering
697b0e2aba Fix: now highlights in diff view are getting the correct lines. 2016-01-08 16:33:27 -02:00
Unknwon
03427fb005 fix #2360 2016-01-08 08:49:03 +08:00
ddelpero
7655337a1f Update repo.go
Release download file name doesn't include tag number #2339
Download: Changed to use refName instead of commit.ID for downloaded file name
2016-01-07 14:28:38 -06:00
Andrey Nering
bf11ad19ea Semantic fixes. 2016-01-07 11:27:35 -02:00
Unknwon
e0f0f72a36 #2345 disallow access of some pages for empty repo 2016-01-07 11:07:17 +08:00
Unknwon
ca35ddd078 fix #2350 2016-01-07 09:24:19 +08:00
Unknwon
f4309bbb05 Merge pull request #2352 from zhuharev/develop
typo fix
2016-01-07 09:22:41 +08:00
Unknwon
6dc407c7d9 Merge pull request #2347 from ivanmarban/develop
Remove RSA1 keys as only SSH version 2 is used
2016-01-07 09:11:10 +08:00
Andrey Nering
81ed5c4bee Declaring specific types for enums constants.
This makes the code more strict since you can't assign or compare
values of different types without proper cast.
2016-01-06 18:00:40 -02:00
Andrey Nering
73474c043b Highlighting differences of lines in the diff view. 2016-01-06 17:46:56 -02:00
zhuharev
0d5dc8a064 typo fix 2016-01-06 22:41:42 +03:00
Unknwon
0cb7396840 update locale 2016-01-06 18:44:57 +08:00
Ivan Marban
4ea75dfcbe Remove RSA1 keys as only SSH version 2 is used 2016-01-06 10:26:37 +01:00
Unknwon
cc22c8a1ae update dep lib version requirement 2016-01-06 13:34:34 +08:00
Unknwon
2481fe2f56 Merge pull request #2296 from bkcsoft/feature/split-diff
Implement Split Diff-View
2016-01-06 13:31:36 +08:00
Kim "BKC" Carlbäcker
2087156119 Removed opticon-fold 2016-01-06 02:21:20 +01:00
Kim "BKC" Carlbäcker
3870a7a3c8 merged split/unified templates 2016-01-06 00:08:50 +01:00
Unknwon
19c234db39 Merge pull request #2336 from andreynering/scroll-always-visible
Making scroll always visible.
2016-01-06 04:57:14 +08:00
Kim "BKC" Carlbäcker
8fe5d887ae Changed name from inline to unified 2016-01-05 19:21:50 +01:00
Kim "BKC" Carlbäcker
4e6d048ba1 i18n-fix for split-view 2016-01-05 19:21:49 +01:00
Kim "BKC" Carlbäcker
0df39b33eb Implement Split Diff-View
- Unified/Inline Diff-View Selectable
2016-01-05 19:21:41 +01:00
Unknwon
7392b6a755 fix #2327 2016-01-05 12:43:19 +08:00
Andrey Nering
cb8134da52 Making scroll always visible. 2016-01-04 16:38:10 -02:00
Unknwon
590637246b Merge pull request #2323 from ggramlich/develop
Update s6 path in Dockerfile.rpi
2016-01-02 15:24:30 -06:00
Gregor Gramlich
053d1424b2 Update s6 path in Dockerfile.rpi
Apply the change from 0cbf56855a to the Dockerfile.rpi as well
2016-01-02 11:02:33 +01:00
Unknwon
4993ab1a76 #2185 fall back to use custom chardet lib 2015-12-31 22:13:47 -05:00
Unknwon
a62290de52 #2311 improve HTTP auth error message 2015-12-30 21:29:30 -05:00
Unknwon
8d58e06ad8 more fix on #2268 2015-12-30 18:47:32 -05:00
Unknwon
b8fbf6559d Merge pull request #2294 from joaopms/patch-1
Fix the description on head.tmpl
2015-12-27 17:28:25 -05:00
Unknwon
44637f03cc #2282 fast detection of utf-8 2015-12-27 17:02:36 -05:00
João Pedro
7bab3d682f Lowercase "Service" 2015-12-27 18:53:52 +00:00
João Pedro
34f01aab5e Update head.tmpl 2015-12-27 18:44:18 +00:00
Unknwon
240fe07287 #2273 URL consistency on webhook payload 2015-12-25 07:11:58 -05:00
Unknwon
93f03707a7 #2283 set text/plain for non-binary files in raw mode 2015-12-25 05:45:07 -05:00
Unknwon
85af36332b #2282 fix utf-8 recognized as windows-1252 2015-12-25 05:25:47 -05:00
Unknwon
13fe733037 #2264 use monospaced font for commit IDs in news feeds 2015-12-24 20:43:45 -05:00
Unknwon
4c896bb620 Merge pull request #2270 from novaeye/develop
PR for fix #2268
2015-12-24 10:30:24 -05:00
Unknwon
157d868254 Merge pull request #2262 from angus-g/fixes/user-following-migration
Add default for NumFollowing field (fixes #2261)
2015-12-24 10:13:13 -05:00
Unknwon
e16042010e Merge pull request #2257 from Jofkos/patch-1
Wiki pages containing question marks in their name weren't loading
2015-12-24 10:00:03 -05:00
novaeye
227dcc3cb9 fix #2268 2015-12-23 17:50:14 +08:00
Angus Gibson
e914969e4c Add default for NumFollowing field (fixes #2261)
We set the default value for the non-NULL field NumFollowing of the User
model to 0, which stops an error when the ORM tries to sync.
2015-12-22 11:09:28 +11:00
Unknwon
a49af93faf #1692 APIs: Users Followers
- User profile un/follow
- List user's followers/following
2015-12-21 04:24:11 -08:00
Jofkos
76d4af891f Removed empty line, multi return args 2015-12-20 21:13:12 +01:00
Jofkos
0721095944 Wiki pages containing question marks in their name weren't loading
(untested)
2015-12-20 18:02:54 +01:00
Unknwon
c62a6b7a12 #2014 allow switch branches between two orgs in compose PR 2015-12-20 01:06:54 -05:00
Unknwon
cadf03db68 #2180 fix avatar link when disable gravatar 2015-12-19 22:21:00 -05:00
Unknwon
5ff6eedf5e #2251 fix button name 2015-12-19 22:07:06 -05:00
Unknwon
53eb37d529 fix #1436 2015-12-19 21:43:32 -05:00
Unknwon
3bcdb3855c #2250 Use HTTP/HTTPS as default clone option 2015-12-19 21:12:13 -05:00
Unknwon
f00fef0cd0 #2251 show commits count in PR tabs 2015-12-19 21:09:03 -05:00
Unknwon
2d3ecbe5b2 make mailer log more verbose 2015-12-19 02:44:34 -05:00
Unknwon
09c981846b update locales 2015-12-18 07:54:44 -05:00
Unknwon
037a01c4e4 fix #2189 2015-12-18 05:49:28 -05:00
Unknwon
1d95844d55 prepare release 2015-12-18 00:54:27 -05:00
Unknwon
1c9dd11ba7 #1692 API: admin create repo 2015-12-17 22:57:41 -05:00
Unknwon
1e7e092992 #2103 Ability to map extensions for syntax highlighting in config 2015-12-17 22:31:34 -05:00
Unknwon
33a99d587a fix #2223 2015-12-17 21:57:34 -05:00
Unknwon
9cd16c5b12 #1692 add organization APIs 2015-12-17 02:28:47 -05:00
Unknwon
6673dcb038 #2103 #2181 improvments of highlight class name 2015-12-16 22:13:12 -05:00
Unknwon
71142929cc Merge pull request #2218 from xxxtonixxx/patch-2
Minor typo in en-US locale
2015-12-16 19:28:42 -05:00
Toni
d7b924f17d Minor typo in en-US locale
metadata*
2015-12-16 22:52:38 +01:00
Unknwon
b117befc2b #1692 add user email APIs 2015-12-15 22:57:18 -05:00
Unknwon
7786cb76f3 fix #2205 2015-12-15 21:32:17 -05:00
Unknwon
eb918c2368 fix only admin can view milestone desc 2015-12-15 21:25:38 -05:00
Unknwon
8ecbf0f16d fix #2204 2015-12-15 19:42:20 -05:00
Unknwon
b13caa23d9 Merge pull request #2203 from xxxtonixxx/patch-1
Minor typo in en-US locale
2015-12-15 18:52:23 -05:00
Toni
fd79fad2ec Fix typo
take*
2015-12-16 00:31:28 +01:00
Unknwon
19423957b1 rename import path 2015-12-15 17:25:45 -05:00
Unknwon
3362b3a44f fix possible disclosure 2015-12-14 17:06:54 -05:00
Unknwon
50264200f0 fix huge diff hangs 2015-12-14 09:38:21 -05:00
Unknwon
7436ce6403 emojify.js: ignore_emoticons 2015-12-14 06:04:24 -05:00
Unknwon
91789930bc #2176 fix 500 on /watchers & /stars for pg 2015-12-14 02:40:23 -05:00
Unknwon
ea375c0dcc new template func 2015-12-13 23:16:58 -05:00
Unknwon
7509fa2c33 improve get commits performance 2015-12-13 22:58:12 -05:00
Unknwon
acdb4d8bdd Drop Go 1.3 support 2015-12-13 20:20:52 -05:00
Unknwon
95f9c85bcc #2185 use Go sub-repo to detect encoding 2015-12-13 19:56:33 -05:00
Unknwon
79dcd7ee6e #2167 able to identify git version on Windows 2015-12-13 18:20:39 -05:00
Unknwon
ed001d70e4 #2171 fix wiki preview does not work on Firefox 2015-12-13 17:55:13 -05:00
Unknwon
42a8c15ad0 Merge pull request #2169 from bclermont/develop
Ignore invalid env for SSH Server (OSX fix)
2015-12-13 07:21:45 -05:00
Bruno
9a27e5ccdc ignore invalid env 2015-12-13 20:17:47 +08:00
Unknwon
71123c816d update hightlight.js 2015-12-13 00:58:30 -05:00
Unknwon
168c69273f fix #1720 2015-12-13 00:46:28 -05:00
Unknwon
4df378b892 fix markdown header margin-top 2015-12-12 22:04:52 -05:00
Unknwon
351dfc95a9 prepare release 2015-12-12 21:58:54 -05:00
Unknwon
837155577a #2159 use icon+tooltip to replace text 2015-12-12 16:53:16 -05:00
Unknwon
7e88420bc6 #2161 fix wrong regexp 2015-12-12 16:13:18 -05:00
Unknwon
5911fc3512 #2161 No issue linking in commits when issue number in brackets 2015-12-12 16:01:54 -05:00
Unknwon
4108c12092 #2156 add edit org link in admin panel 2015-12-12 15:47:59 -05:00
Unknwon
e444a67d59 update locales 2015-12-12 14:47:11 -05:00
Unknwon
0cce4439ce #2154 minor fix 2015-12-11 21:23:19 -05:00
Unknwon
59c965a5ec #2156 admin able to edit organization max repo creation 2015-12-11 19:24:57 -05:00
Unknwon
76bdbcc969 #2152 fix SMTP authentication makes invalid assumption on protocol 2015-12-11 18:57:45 -05:00
Unknwon
477b4d3b50 #2154 fix form submit error 2015-12-11 18:52:28 -05:00
Unknwon
4d31eb2c0d #2155 fix org max repo limit default to -1 2015-12-11 15:48:02 -05:00
Unknwon
d0b0d24f22 #2154 disable change user for non-local users
- #2153 remove require for gravatar
2015-12-11 15:31:02 -05:00
Unknwon
5d95ffe3eb #2155 The owner has reached maximum creation limit of 0 repositories 2015-12-11 15:11:13 -05:00
Unknwon
98da7241a0 fix sqlite3 cannot create repo 2015-12-11 10:13:19 -05:00
Unknwon
bc17f2f759 #2147 fix rewrites authorized_keys when builtin SSH server is enabled 2015-12-11 05:02:33 -05:00
Unknwon
40f3142264 #2114 External URL for wiki 2015-12-11 04:55:08 -05:00
Unknwon
b21160a13a Merge pull request #2146 from roidelapluie/develop
Minor typo in en-US locale: gloabl -> global
2015-12-11 03:42:21 -05:00
Julien Pivotto
5b2afd8ec8 Minor typo in en-US locale: gloabl -> global 2015-12-11 09:31:02 +01:00
Unknwon
7a3eccc709 Drop 0.5.x support 2015-12-10 19:52:06 -05:00
Unknwon
2a8d71367d #2029 not show content of issue in activity timeline 2015-12-10 19:13:51 -05:00
Unknwon
3d5d61778a #1938 #1374 disable password change for non-local users 2015-12-10 19:02:57 -05:00
Unknwon
ddcc8d998c fix markdown table header CSS 2015-12-10 16:45:16 -05:00
Unknwon
99e9bbef6c fix bool check for repo max limit and fix hang when push repo with tons of commits 2015-12-10 16:27:47 -05:00
Unknwon
0e96a46020 fix user repo limit default value 2015-12-10 12:48:45 -05:00
Unknwon
df5ed64cca #1301 "read-only" users 2015-12-10 12:46:05 -05:00
Unknwon
2a0bb1fa90 #1575 Limit repo creation 2015-12-10 12:37:53 -05:00
Unknwon
c6083c335e #1612 Ability to send mail when a new pull request is submitted 2015-12-10 11:18:56 -05:00
Unknwon
2e9c4ddedb Merge pull request #2143 from pkgr/fix-packaging-postinstall
Fix postinstall to use GOGS_CUSTOM instead of symlinking
2015-12-10 10:00:26 -05:00
Cyril Rohr
fa8bf0f1d7 Fix postinstall to use GOGS_CUSTOM instead of symlinking 2015-12-10 09:02:58 +00:00
Unknwon
9a2e43bff2 move out git module and #1573 send push hook 2015-12-09 20:46:05 -05:00
Unknwon
bd5dc626e8 Merge pull request #2139 from angus-g/fixes/pr-messages
Reword messages for PR auto merging (#2117)
2015-12-09 17:31:46 -05:00
Angus Gibson
626dc1f0bd Reword messages for PR auto merging (#2117) 2015-12-10 09:28:49 +11:00
Unknwon
1b0ef0ec0b Merge pull request #2137 from nanoant/patch/ssh-trigger-via-local-url
LOCAL_ROOT_URL for workers accessing web service
2015-12-09 17:22:37 -05:00
Adam Strzelecki
e4a092fb5a Make serv/update use LOCAL_ROOT_URL instead public
The reasoning for that is in the previous commit.
2015-12-09 23:11:07 +01:00
Adam Strzelecki
b886fb4bf0 LOCAL_ROOT_URL for workers accessing web service
Local (DMZ) URL for gogs workers (such as ssh update) accessing web service. In
most cases you do not need to change default http://localhost:HTTP_PORT/. You
may need to alter it only if your ssh server node is not the same as http node,
eg. running behind proxy on different node than web server.

                     --- 80 public port -> 8080 -- web server node
                    /
    public proxy --<
                    \
                     --- 22 public port -> 10022 -- ssh server node

This option is not intended to be accessible via web GUI settings, since it is
unlikely someone needs to change it to somethings else than default
http://localhost:HTTP_PORT/ which should work for most of the cases.

But this should land into the documentation somewhere.

fixup
2015-12-09 23:11:07 +01:00
Unknwon
fa5e372f75 Merge pull request #2138 from SlavikZ/master
LDAP parameters UI: bind_dn and bind_password are not required
2015-12-09 16:47:03 -05:00
Unknwon
356f1438a6 Merge pull request #2133 from kardianos/develop
gogs: add import that lets gogs run as a stand-alone windows service
2015-12-09 16:12:43 -05:00
SlavikZ
a19aaa439d LDAP parameters UI: bind_dn and bind_password are not required 2015-12-09 21:02:19 +02:00
Daniel Theophanes
0d469f261e gogs: add import that lets gogs run as a stand-alone windows service
Updates #630
2015-12-09 09:04:10 -08:00
Unknwon
c3440c4dd3 #2035 Show author e-mail in commit diff 2015-12-09 11:46:39 -05:00
Unknwon
718d3ae258 #1943 Able to config fsck timeout 2015-12-09 11:38:12 -05:00
Unknwon
b8d48bdb62 #2037 Add "New Mirror" button on Dashboard 2015-12-09 11:24:56 -05:00
Unknwon
15d62bba82 Merge pull request #2132 from nanoant/patch/do-not-fail-on-missing-lessc
Makefile: Do not fail build on missing lessc
2015-12-09 08:07:18 -05:00
Adam Strzelecki
eb6c634475 Makefile: Do not fail build on missing lessc
This is achieved by adding public/css/gogs.css to special .IGNORE target, which
makes inability to generate/update gogs.css non-fatal and not stopping whole
build process. User is still notified about missing lessc command though, since
inability to update CSS may lead to potential problems:

    lessc public/less/gogs.less public/css/gogs.css
    make: lessc: No such file or directory
    make: [public/css/gogs.css] Error 1 (ignored)

More info at:

  https://www.gnu.org/software/make/manual/html_node/Special-Targets.html
2015-12-09 13:32:43 +01:00
Unknwon
eec06fb3df Merge pull request #2126 from angus-g/fixes/commits-branches
Dropdown on commits page to choose branch #1846
2015-12-09 01:42:26 -05:00
Angus Gibson
df05134494 Break branch-selection dropdown into a template
We only handle branch selection for repo home and commits pages, so the
redirection URL is based on PageIsCommits
2015-12-09 17:15:58 +11:00
Angus Gibson
9bd3ebe207 Dropdown on commits page to choose branch #1846
I've mostly duplicated the dropdown code from repo/home.tmpl, which
basically only required a change to the URL. This could probably be
broken out into something more modular.
2015-12-09 16:37:04 +11:00
Unknwon
a576224d0e unified name: IsViewBranch, IsViewCommit and IsViewTag 2015-12-09 00:32:53 -05:00
Unknwon
989f30eb41 Merge pull request #2125 from angus-g/fixes/compare-commits
Only show comparison link for >2 commits, fixes #1110
2015-12-08 23:16:03 -05:00
Angus Gibson
06d293a84e Only show comparison link for >2 commits #1110
We can look at the PushCommits object to see how many commits were
included in a commit, and add some template logic to only show the
comparison link when there are at least 2 commits in a push. We also
correct the link to display the number of commits.
2015-12-09 14:36:39 +11:00
Unknwon
120cd4e471 #1984 Better mirror repo management 2015-12-08 20:06:12 -05:00
Unknwon
1cbd4c01fb #2115 more precise error message 2015-12-08 01:11:40 -05:00
Unknwon
2528c482e9 #1627 auto login after install if admin is configured 2015-12-08 00:59:14 -05:00
Unknwon
b1a53f6d8e add quay.io as another Docker option 2015-12-07 19:40:24 -05:00
Unknwon
fde9c69679 Merge pull request #2122 from nanoant/patch/add-pre-receive-hook
Allow pre-receive hook customization
2015-12-07 19:31:16 -05:00
Adam Strzelecki
3df5dcc1dc Allow pre-receive hook customization
This hook can be used for example to reject too large commits and it is
executed before "update" hook, used exclusively by Gogs to update its state.

https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
2015-12-08 01:28:32 +01:00
Unknwon
14080dd61d Merge pull request #2121 from nanoant/patch/less-n-template-indent
Consistent tab indentation for all source files
2015-12-07 19:04:13 -05:00
Adam Strzelecki
da2585c11e Indent all templates with tabs
This commit improves templates readability, since all of them use consistent
indent with all template command blocks indented too.

1. Indents both HTML containers such as <div>, <p> and Go HTML template blocks
   such as {{if}} {{with}}

2. Cleans all trailing white-space

3. Adds trailing last line-break to each file
2015-12-08 00:57:46 +01:00
Adam Strzelecki
dd8a06a397 LESS: Use tabs for indent in all files
This does not change any content and generated gogs.css is still the same.
2015-12-07 21:20:54 +01:00
Unknwon
4e0c697aaf force new INI version 2015-12-07 11:33:04 -05:00
Unknwon
3ffbb54337 minor fix for #2113 and other locales 2015-12-07 00:10:08 -05:00
Unknwon
67cfb6735b Merge pull request #2113 from OhDaeto/patch-1
Update Russian translation
2015-12-07 00:05:36 -05:00
OhDaeto
b7508b06fa Update locale_ru-RU.ini 2015-12-07 08:02:16 +03:00
OhDaeto
2a0db47935 Update Russian translation 2015-12-07 07:27:17 +03:00
Unknwon
dce2a9e7e1 fix wrong slack webhook payload URL 2015-12-06 23:07:02 -05:00
Unknwon
abb02889f2 Merge pull request #2112 from nanoant/patch/better-git-message-display
Render commit msg as header + verbatim description
2015-12-06 20:06:23 -05:00
Adam Strzelecki
e2ca53029e Render commit msg as header + verbatim description
Most commit in Git are expected to follow standard of single header line,
followed by description paragraphs, separated by empty line from previous block.

Previously Gogs were treating everything as single header. Now we are trying to
render only first line as header, but following lines (description chunks) as a
verbatim.
2015-12-07 01:50:45 +01:00
Unknwon
b5f6206a65 prepare release 2015-12-06 15:34:17 -05:00
Unknwon
3de9c11ea7 Merge pull request #2110 from msoedov/misspellings
Fix misspelled words
2015-12-06 15:27:11 -05:00
Alex Myasoedov
ae54d878c0 Fix misspelled words 2015-12-06 16:42:23 +02:00
Unknwon
89244b74c6 remember page number when delete repo 2015-12-05 17:49:46 -05:00
Unknwon
ca8ce793d1 #2063 Ability to delete repo from admin panel 2015-12-05 17:39:29 -05:00
Unknwon
978dc00305 APIs: admin users 2015-12-05 17:13:13 -05:00
Unknwon
bf26808fb3 update README 2015-12-05 13:50:43 -05:00
Unknwon
404867f206 fix #2105 and fix #1857 2015-12-05 13:24:13 -05:00
Unknwon
f0ee33267c fix #2102 2015-12-05 11:46:42 -05:00
Unknwon
f3eaa4c592 Set default language for i18n 2015-12-05 01:20:11 -05:00
Unknwon
f41360d864 #2052 advanced select ops for system notices 2015-12-05 01:09:14 -05:00
Unknwon
e82ee40e9e init with all enabled 2015-12-04 21:34:37 -05:00
Unknwon
1ee7c33e93 template fix 2015-12-04 21:32:33 -05:00
Unknwon
e538ff2770 fix #1829 and fix #890 2015-12-04 21:30:33 -05:00
Unknwon
76d4b9288b #2045 have fallback but empty value 2015-12-04 19:01:34 -05:00
Unknwon
05ba8622f0 #2045 move fallback to empty string 2015-12-04 18:31:45 -05:00
Unknwon
4795fa01d8 fix #2101 2015-12-04 17:30:32 -05:00
Unknwon
942fd6be53 fix panic for #2045 2015-12-04 17:20:23 -05:00
Unknwon
56dd430a10 refactor API routes and some work for #976 2015-12-04 17:16:42 -05:00
Unknwon
e0bae9547a more fixes on #2045 2015-12-04 15:41:56 -05:00
Unknwon
bfe6027266 Merge branch 'develop' of github.com:gogits/gogs into develop 2015-12-03 18:10:54 -05:00
Unknwon
4d9499c2d3 fix broken link 2015-12-03 18:10:45 -05:00
Unknwon
98e989d52c minor JS and UI fix 2015-12-03 15:01:15 -05:00
Unknwon
5742f9fe69 fix #2095 2015-12-03 14:31:31 -05:00
Unknwon
1802d52362 Merge pull request #2094 from nanoant/patch/less-pronounced-sha-labels
UI: Use more subtle grey SHA1 labels
2015-12-03 14:28:30 -05:00
Adam Strzelecki
cab2911f23 UI: More subtle strips on commits list
With grey SHA1 labels, we should consider having also more subtle strips on
commits list. As current strips blend too much with grey SHA1 labels and top
bar, making hard to distinguish headers from content.
2015-12-03 20:26:06 +01:00
Unknwon
81133d45a1 work on #2093 2015-12-03 14:21:13 -05:00
Unknwon
a51acf1751 Merge pull request #2092 from nanoant/patch/non-bold-last-commit-sha
UI: Remove CSS rule making last-commit SHA bold
2015-12-03 13:14:57 -05:00
Adam Strzelecki
edbb67cb3f UI: Use more subtle grey SHA1 labels
Current green SHA1 labels are more pronounced than other UI elements attracting
attention as if they were most important thing in the UI, while they are not as
important, especially without real Git client.

Using grey SHA1 labels makes the UI more balanced, less aggressive and lets
user to focus on other content elements.

NOTE: Neither GitHub or Bitbucket uses so heavy pronunciation as Gogs.
2015-12-03 14:21:20 +01:00
Adam Strzelecki
c5e249c0be UI: Remove CSS rule making last-commit SHA bold
This removes remains from old design, that was not cleaned by previous #2068 PR.
2015-12-03 13:30:16 +01:00
Unknwon
37a372f6f5 500 when wiki not exists 2015-12-03 02:08:25 -05:00
Unknwon
f122d0856e fix #2090 2015-12-03 01:59:32 -05:00
Unknwon
4a6016f5af fix #2087 2015-12-03 01:03:06 -05:00
Unknwon
cc8f5add6e fix #976 2015-12-03 00:24:37 -05:00
Unknwon
ec2423ad7c more UI minor fixes 2015-12-02 20:56:26 -05:00
Unknwon
c4bab163cb Merge pull request #2088 from nanoant/patch/further-layout-fixes
Further layout fixes
2015-12-02 20:26:48 -05:00
Adam Strzelecki
0068b8106b CSS: Octicons 16px fix outside of _octicons.less
Otherwise the fix will be overwritten by next _octicons.less update.

This is follow-up for 22b0dfbb35.
2015-12-03 02:18:38 +01:00
Adam Strzelecki
2580e7b57e UI: Always show menu on repo pages
Merges repo/sidebar.tmpl with repo/header.tmpl and makes every repo page use
middleware.RepoRef() necessary to display information on this menu.
2015-12-03 02:16:18 +01:00
Unknwon
3d3498bda1 clean test data 2015-12-02 20:10:47 -05:00
Unknwon
29375059e1 minor CSS fix 2015-12-02 20:10:00 -05:00
Unknwon
85449b2f11 minor CSS fix for #2068 2015-12-02 19:53:39 -05:00
Unknwon
b83cb36049 minor fix for #2086 2015-12-02 19:45:43 -05:00
Unknwon
73d9eebf01 Merge pull request #2068 from nanoant/patch/repo-file-list-layout
Repo file list layout & misc fixes
2015-12-02 19:44:16 -05:00
Adam Strzelecki
b73241ceb1 UI: Display last-commit header without 2nd column
This uses a CSS trick making first th to be relative block with width equal to
first two columns, effectively working around inability to use colspan="2" on
first row that was breaking "fixed-layout" for tables.

Also use grey header for last-commit SHA1 tag.
2015-12-03 01:15:40 +01:00
Unknwon
e350d74c8a fix #2085 2015-12-02 18:58:13 -05:00
Unknwon
149e540322 Merge pull request #2086 from nanoant/patch/translation-add-code-entry
Translation: Add missing entry for new "code" tab
2015-12-02 18:53:38 -05:00
Adam Strzelecki
314664892c UI: Keep repo URL action right of ref combo & path
Just use secondary menu instead custom ".head.meta", which simplifies code.

Also do not display repo URL action when we are in subdirectory or viewing a
file.
2015-12-02 23:48:36 +01:00
Adam Strzelecki
a9a386a1e5 Translation: Add missing entry for new "code" tab
We have new tab, but we had no entry. That's why it was showing "code"
(lowercase) as this is text id, where we were expecting properly title cased
"Code" to be shown in English version.

Also add Polish translation "code=Kod".
2015-12-02 23:00:23 +01:00
Adam Strzelecki
3eae4ecde7 UI: Make repository menu divide header and content
This is more inline with way GitHub looks like and feels much more natural and
in style with rest of the interface.
2015-12-02 22:40:22 +01:00
Adam Strzelecki
ec98deeb8c UI: Keep repository settings menu button right 2015-12-02 22:06:50 +01:00
Adam Strzelecki
61fdd8c571 Commits & files UI: SUI fixed single line table
Instead using own ellipsis, uses Semantic UI fixed single line table which
effectively applies ellipsis to all overflowing table cells.

NOTE: File list cannot use colspan="2" for 1st "Last commit" elements,
otherwise layout breaks with fixed table.
2015-12-02 21:57:39 +01:00
Adam Strzelecki
4813665d0a CSS: Reduce .sha.label font size to 13px 2015-12-02 21:43:30 +01:00
Adam Strzelecki
640dce12a8 CSS: .repository .sha.label -> .ui .sha.label
This is because SHA1 label is used in many other places, not only inside
.repository container.
2015-12-02 21:42:31 +01:00
Adam Strzelecki
99b958db43 UI: Mark top menu icons blue only when non-zero 2015-12-02 21:38:52 +01:00
Adam Strzelecki
22b0dfbb35 CSS: Ensure Octicons are used with 16px font size
Semantic UI .icon 1em font-size has priority over .octicon 16px, resulting
octicons rendered at 14px font-size, which is not okay since Octicons are meant
to be shown sizes that are multiples of 16px.
2015-12-02 21:33:32 +01:00
Unknwon
4a64ae4abf fix #2083 2015-12-02 13:47:22 -05:00
Unknwon
926e91820a #2071 Diff is not showing full content when has super long one line 2015-12-02 01:10:13 -05:00
Unknwon
91ae2ad28b Merge pull request #2081 from angus-g/en-trans
Update English translations
2015-12-01 23:46:05 -05:00
Angus Gibson
db30ea03d8 Fix casing in English translation 2015-12-02 15:43:56 +11:00
Unknwon
0be8b1b1a1 #2052 Ability to batch delete system notices 2015-12-01 23:33:08 -05:00
Angus Gibson
d45302a6ba Update English translations
Just some phrasing changes to make the English translations sound more natural.
2015-12-02 15:27:08 +11:00
Unknwon
834d38a8fb #2045 add short version as fallback to Slack payload 2015-12-01 21:16:19 -05:00
Unknwon
5572884c6b fix #2057 2015-12-01 20:51:31 -05:00
Unknwon
3460ec1039 update REMADE and locale 2015-12-01 19:53:19 -05:00
Unknwon
53bf23d965 Merge pull request #2079 from nanoant/patch/ldap-custom-username-attr
LDAP: Optional user name attribute specification
2015-12-01 18:23:12 -05:00
Adam Strzelecki
573305f3d3 LDAP: Optional user name attribute specification
Consider following LDAP search query example:

    (&(objectClass=Person)(|(uid=%s)(mail=%s)))

Right now on first login attempt Gogs will use the text supplied on login form
as the newly created user name. In example query above the text matches against
both e-mail or user name. So if user puts the e-mail then the new Gogs user
name will be e-mail which may be undesired.

Using optional user name attribute setting we can explicitly say we want Gogs
user name to be certain LDAP attribute eg. `uid`, so even user will use e-mail
to login 1st time, the new account will receive correct user name.
2015-12-02 00:20:14 +01:00
Unknwon
7ccce4d110 Merge pull request #2078 from nanoant/patch/makefile-improvements
Makefile improvements
2015-12-01 17:26:25 -05:00
Unknwon
9ed60d96a9 fix API 2015-12-01 16:33:45 -05:00
Unknwon
b6d2b96259 Merge pull request #2076 from Gibheer/new_mirror
add new mirror button to dashboard
2015-12-01 16:33:00 -05:00
Adam Strzelecki
e5fe367b82 scripts: Remove less.sh superseded by Makefile
We no longer need to manually build CSS files as Makefile keeps track of it.
2015-12-01 22:28:21 +01:00
Adam Strzelecki
19e8ce0354 Makefile: Remove trailing whitespace & add last LF
This is pure cleanup commit.
2015-12-01 22:20:21 +01:00
Adam Strzelecki
f907a5c98b Makefile: Auto-build CSS & bin-data when necessary
This will ensure that running `make` we will get all necessary files built and
we do not need manually remember to rebuild them.
2015-12-01 22:18:30 +01:00
Adam Strzelecki
da607c611d Makefile: Copy installed binary instead 2nd build
This speeds up single build/rebuild rather than install & build which compiles
everything twice, we just copy installed binary back to the project root.
2015-12-01 22:16:00 +01:00
Gibheer
3d54f6c0a4 add new mirror button to dashboard
This adds the button to create a new mirror on the dashboard at the same
place where "new repository" and "new organization" already exist.
2015-12-01 21:10:36 +01:00
Unknwon
2093586241 Merge pull request #2016 from raxetul/develop
Dockerfile for RaspberryPi is added.
2015-12-01 14:46:03 -05:00
Unknwon
117afe7620 Merge pull request #2069 from nanoant/patch/admin-see-all-organizations
Admin should be able to see all organizations
2015-11-30 21:18:33 -05:00
Unknwon
d3a5ff7b6b fix #2042 2015-11-30 20:50:40 -05:00
Unknwon
dcb391d341 Merge branch 'feature/wiki' into develop 2015-11-30 20:46:19 -05:00
Unknwon
830d000667 finish wiki 2015-11-30 20:45:55 -05:00
Unknwon
5a14c3cf98 Merge pull request #2053 from kakwa/develop
various fixes in gogs dump command
2015-11-30 16:18:18 -05:00
Adam Strzelecki
e57b2dffa4 Admin should be able to see all organizations
This is follow-up for 56c66ee486 allowing admin
to see private repositories, even when not being member of them.
2015-11-30 21:46:01 +01:00
Unknwon
ca96e04e5f #1681 carry --config flag for builtin SSH 2015-11-30 15:40:05 -05:00
Unknwon
9950f5a5bd add line break after SSH error message 2015-11-30 10:00:52 -05:00
kakwa
1d7a1b6034 add name of the dump file in last log message 2015-11-28 15:22:10 +01:00
kakwa
a59b1fcc21 Fix dump of log and custom directory in dump cmd
Now, the dump cmd uses setting.CustomPath and setting.LogRootPath
instead of setting.WorkDir which was kind of broken if the gogs
binary was in a different directory than gogs data.
Additionally, the backup of setting.CustomPath directory is only done
if it exists.
2015-11-28 15:08:50 +01:00
kakwa
c5a9be9115 Using a tmp dir to generate db and repo dumps
Using a tmp dir makes gogs dump more robust to concurrent runs.

It also permits an easier cleaning of the tmp files (gogs-db.sql and
gog-repo.zip) by just removing the tmp dir.

As a side effect, it partially fix bugs on workdir.
Previously, 'gogs dump' created the archives in the current directory,
and tried to include these archives from the directory where the
gogs binary lies.
ex: if gogs binary is in /usr/bin/gogs, and gogs dump is run from /tmp/,
/tmp/gog-repo.zip is created, but gogs dump tried to include
/usr/bin/gogs-repo.zip.
2015-11-28 14:07:51 +01:00
kakwa
f86afb04a2 Adding more error handling in dump cmd
The dump cmd did not check the return value of the z.AddFile or
z.AddDir when building the final archive.
It caused the dump command to succeed even if an error occurred.
The resulted dump archive could be corrupted/empty.
(errors could be various: removal by a concurrent process, disk full,
bugs in the dump cmd itself)
2015-11-28 12:11:38 +01:00
Unknwon
5d1f5f32d0 wiki: finish pages 2015-11-27 02:16:12 -05:00
Unknwon
e42fcb033d wiki: finish edit 2015-11-27 01:50:38 -05:00
Unknwon
392f3ee210 wiki: finish new 2015-11-27 00:24:24 -05:00
Unknwon
c50a3503e6 introduce git-shell 2015-11-26 17:33:45 -05:00
Unknwon
aaa3f1b2b9 Use better LDAP lib and should fix #1139 2015-11-26 14:04:58 -05:00
Unknwon
2b10fdc4dc Wiki: UI for page new 2015-11-25 20:10:25 -05:00
Unknwon
2f28a0310b Merge branch '0.8.0' of github.com:gogits/gogs into develop 2015-11-25 11:01:40 -05:00
Unknwon
eb30cbab81 add unsupported migration prompt 2015-11-25 09:27:27 -05:00
Emrah URHAN
737da1a374 Latest develop updates is merged with my RaspberryPi Dockerfile version.
Merge branch 'develop' of https://github.com/gogits/gogs into develop
2015-11-22 19:40:18 +02:00
Emrah URHAN
f63a468dfc Dockerfile for RaspberryPi is added. 2015-11-22 17:14:08 +02:00
1292 changed files with 20829 additions and 23730 deletions

View File

@@ -1,6 +1,6 @@
[run]
init_cmds = [
#["grep", "-rn", "FIXME", "."],
["make", "build-dev", "TAGS=sqlite"],
["./gogs", "web"]
]
watch_all = true
@@ -11,9 +11,9 @@ watch_dirs = [
"$WORKDIR/routers"
]
watch_exts = [".go"]
ignore_files = [".+_test.go"]
build_delay = 1500
cmds = [
["go", "install", "-race"], # sqlite redis memcache cert pam tidb
["go", "build", "-race"],
["make", "build-dev", "TAGS=sqlite"], # cert pam tidb
["./gogs", "web"]
]

View File

@@ -1,20 +1,21 @@
.git
.git/
.git/*
.git/**
conf
conf/
conf/*
conf/**
packager
packager/
packager/*
packager/**
scripts
scripts/
scripts/*
scripts/**
.github/
.github/**
config.codekit
LICENSE
Makefile
.dockerignore
*.yml
*.md
.bra.toml
.editorconfig
.gitignore
.gopmfile
config.codekit
LICENSE
Dockerfile*

View File

@@ -42,21 +42,11 @@ There is no standard form of making a feature request. Just try to describe the
### Pull Request
Pull requests are always welcome, but note that **ALL PULL REQUESTS MUST APPLY TO THE `develop` BRANCH**.
We are always thrilled to receive pull requests, and do our best to process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it.
If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve.
We're trying very hard to keep Gogs lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature. We believe you do like to discuss with us first in [Gitter](https://gitter.im/gogits/gogs).
Please read detailed information on [Wiki](https://github.com/gogits/gogs/wiki/Contributing-Code).
### Ask For Help
Before opening an issue, please make sure your problem isn't already addressed on the [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md) and [FAQs](http://gogs.io/docs/intro/faqs.html) pages.
## Things To Notice
Please take a moment to check that an issue on [GitHub](https://github.com/gogits/gogs/issues) or card on [Trello](https://trello.com/b/uxAoeLUl/gogs-go-git-service) doesn't already exist documenting your bug report or improvement proposal. If it does, it never hurts to add a quick "+1" or "I have this problem too". This will help prioritize the most common problems and requests.
Before opening an issue, please make sure your problem isn't already addressed on the [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.html) and [FAQs](http://gogs.io/docs/intro/faqs.html) pages.
## Code of conduct

22
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,22 @@
We DO NOT take questions or config/deploy problems on GitHub, please use our forum: https://discuss.gogs.io
Please take a moment to search that an issue doesn't already exist.
For bug reports, please give the relevant info:
- Gogs version (or commit ref):
- Git version:
- Operating system:
- Database:
- [ ] PostgreSQL
- [ ] MySQL
- [ ] SQLite
- Can you reproduce the bug at http://try.gogs.io:
- [ ] Yes
- [ ] No
- [ ] Not relevant
- Log gist:
## Description
...

4
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,4 @@
Please, make sure you are targeting the `develop` branch!
More instructions about contributing with Gogs code can be found here:
https://github.com/gogits/gogs/wiki/Contributing-Code

22
.gitignore vendored
View File

@@ -8,32 +8,12 @@ data/
.idea/
*.iml
public/img/avatar/
files/
*.o
*.a
*.so
_obj
_test
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.exe~
/gogs
profile/
__pycache__
*.pem
output*
.brackets.json
docker/fig.yml
docker/docker/Dockerfile
docker/docker/init_gogs.sh
gogs.sublime-project
gogs.sublime-workspace
.tags*
release
/release

View File

@@ -2,44 +2,51 @@
path = github.com/gogits/gogs
[deps]
github.com/bradfitz/gomemcache = commit:72a68649ba
github.com/codegangsta/cli = commit:0302d39
github.com/go-macaron/binding = commit:864a5ce
github.com/bradfitz/gomemcache = commit:fb1f79c
github.com/codegangsta/cli = commit:a294348
github.com/go-macaron/binding = commit:a68f342
github.com/go-macaron/cache = commit:5617353
github.com/go-macaron/captcha = commit:8aa5919
github.com/go-macaron/csrf = commit:3372b25
github.com/go-macaron/gzip = commit:4938e9b
github.com/go-macaron/i18n = commit:5e728b6
github.com/go-macaron/csrf = commit:546646c
github.com/go-macaron/gzip = commit:cad1c65
github.com/go-macaron/i18n = commit:d2d3329
github.com/go-macaron/inject = commit:c5ab7bf
github.com/go-macaron/session = commit:66031fc
github.com/go-macaron/toolbox = commit:ab30a81
github.com/go-sql-driver/mysql = commit:d512f20
github.com/go-xorm/core = commit:3e10003353
github.com/go-xorm/xorm = commit:c643188
github.com/go-macaron/toolbox = commit:82b5115
github.com/go-sql-driver/mysql = commit:0f2db9e
github.com/go-xorm/core = commit:5021584
github.com/go-xorm/xorm = commit:1045aa0
github.com/gogits/chardet = commit:2404f77725
github.com/gogits/go-gogs-client = commit:7c02c95
github.com/issue9/identicon = commit:5a61672
github.com/klauspost/compress = commit:bbfa9dc
github.com/klauspost/cpuid = commit:8d9fe96
github.com/klauspost/crc32 = commit:3e5c38b
github.com/lib/pq = commit:83c4f41
github.com/mattn/go-sqlite3 = commit:5651a9d
github.com/gogits/cron = commit:3abc0f8
github.com/gogits/git-module = commit:76e8cce
github.com/gogits/go-gogs-client = commit:d584b1e
github.com/issue9/identicon = commit:f8c0d2c
github.com/kardianos/minwinsvc = commit:cad6b2b
github.com/klauspost/compress = commit:2d3d403
github.com/klauspost/cpuid = commit:09cded8
github.com/klauspost/crc32 = commit:19b0b33
github.com/lib/pq = commit:165a352
github.com/mattn/go-sqlite3 = commit:45f056c
github.com/mcuadros/go-version = commit:d52711f
github.com/microcosm-cc/bluemonday = commit:4ac6f27
github.com/msteinert/pam = commit:6534f23b39
github.com/nfnt/resize = commit:dc93e1b98c
github.com/russross/blackfriday = commit:300106c
github.com/msteinert/pam = commit:02ccfbf
github.com/nfnt/resize = commit:4d93a29
github.com/russross/blackfriday = commit:006144a
github.com/satori/go.uuid = commit:e673fdd
github.com/sergi/go-diff = commit:ec7fdbb
github.com/shurcooL/sanitized_anchor_name = commit:10ef21a
github.com/Unknwon/cae = commit:7f5e046
github.com/Unknwon/com = commit:28b053d
github.com/Unknwon/i18n = commit:7457d88830
github.com/Unknwon/i18n = commit:3b48b66
github.com/Unknwon/paginater = commit:7748a72
golang.org/x/net =
golang.org/x/text =
golang.org/x/crypto =
gopkg.in/gomail.v2 = commit:df6fc79
gopkg.in/ini.v1 = commit:2e44421
gopkg.in/macaron.v1 = commit:1c6dd87
golang.org/x/net = commit:a4bbce9
golang.org/x/text = commit:a71fd10
golang.org/x/crypto = commit:5dc8cb4
gopkg.in/asn1-ber.v1 = commit:4e86f43
gopkg.in/gomail.v2 = commit:5ceb8e6
gopkg.in/ini.v1 = commit:776aa73
gopkg.in/ldap.v2 = commit:07a7330
gopkg.in/macaron.v1 = commit:b9eee38
gopkg.in/redis.v2 = commit:e617904962
[res]

View File

@@ -24,4 +24,4 @@ before:
- mv packager/.godir .
after:
- mv bin/main gogs
after_install: ./packager/debian/postinst
after_install: ./packager/hooks/postinst

View File

@@ -1,9 +1,9 @@
language: go
go:
- 1.3
- 1.4
- 1.5
- 1.6
before_install:
- sudo apt-get update -qq
@@ -13,7 +13,9 @@ before_install:
install:
- go get -t -v ./...
script: go build -v -tags "pam"
script:
- go build -v -tags "pam"
- go test -v -cover -race ./...
notifications:
email:

View File

@@ -1,13 +1,10 @@
FROM alpine:3.2
MAINTAINER roemer.jp@gmail.com
FROM alpine:3.3
MAINTAINER jp@roemer.im
# Install system utils & Gogs runtime dependencies
ADD https://github.com/tianon/gosu/releases/download/1.6/gosu-amd64 /usr/sbin/gosu
RUN echo "@edge http://dl-4.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories \
&& echo "@community http://dl-4.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories \
&& apk -U --no-progress upgrade \
&& apk -U --no-progress add ca-certificates bash git linux-pam s6@edge curl openssh socat \
&& chmod +x /usr/sbin/gosu
ADD https://github.com/tianon/gosu/releases/download/1.7/gosu-amd64 /usr/sbin/gosu
RUN chmod +x /usr/sbin/gosu \
&& apk --no-cache --no-progress add ca-certificates bash git linux-pam s6 curl openssh socat
ENV GOGS_CUSTOM /data/gogs
@@ -15,6 +12,9 @@ COPY . /app/gogs/
WORKDIR /app/gogs/
RUN ./docker/build.sh
# Configure LibC Name Service
COPY docker/nsswitch.conf /etc/nsswitch.conf
# Configure Docker Container
VOLUME ["/data"]
EXPOSE 22 3000

25
Dockerfile.rpi Normal file
View File

@@ -0,0 +1,25 @@
FROM hypriot/rpi-alpine-scratch:v3.2
MAINTAINER jp@roemer.im, raxetul@gmail.com
# Install system utils & Gogs runtime dependencies
ADD https://github.com/tianon/gosu/releases/download/1.7/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
ENV GOGS_CUSTOM /data/gogs
COPY . /app/gogs/
WORKDIR /app/gogs/
RUN ./docker/build.sh
# Configure LibC Name Service
COPY docker/nsswitch.conf /etc/nsswitch.conf
# Configure Docker Container
VOLUME ["/data"]
EXPOSE 22 3000
ENTRYPOINT ["docker/start.sh"]
CMD ["/bin/s6-svscan", "/app/gogs/docker/s6/"]

View File

@@ -1,21 +1,31 @@
LDFLAGS += -X "github.com/gogits/gogs/modules/setting.BuildTime=$(shell date -u '+%Y-%m-%d %I:%M:%S %Z')"
LDFLAGS += -X "github.com/gogits/gogs/modules/setting.BuildGitHash=$(shell git rev-parse HEAD)"
DATA_FILES := $(shell find conf | sed 's/ /\\ /g')
LESS_FILES := $(wildcard public/less/gogs.less public/less/_*.less)
GENERATED := modules/bindata/bindata.go public/css/gogs.css
TAGS = ""
RELEASE_ROOT = "release"
RELEASE_GOGS = "release/gogs"
NOW = $(shell date -u '+%Y%m%d%I%M%S')
.PHONY: build pack release bindata clean
.PHONY: build pack release bindata clean
build:
go install -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
go build -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
.IGNORE: public/css/gogs.css
build: $(GENERATED)
go install -v -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
cp '$(GOPATH)/bin/gogs' .
govet:
go tool vet -composites=false -methods=false -structtags=false .
build-dev: $(GENERATED) govet
go install -v -race -tags '$(TAGS)'
cp '$(GOPATH)/bin/gogs' .
pack:
rm -rf $(RELEASE_GOGS)
mkdir -p $(RELEASE_GOGS)
@@ -25,11 +35,27 @@ pack:
release: build pack
bindata:
go-bindata -o=modules/bindata/bindata.go -ignore="\\.DS_Store|README.md" -pkg=bindata conf/...
bindata: modules/bindata/bindata.go
modules/bindata/bindata.go: $(DATA_FILES)
go-bindata -o=$@ -ignore="\\.DS_Store|README.md|TRANSLATORS" -pkg=bindata conf/...
less: public/css/gogs.css
public/css/gogs.css: $(LESS_FILES)
lessc $< $@
clean:
go clean -i ./...
clean-mac: clean
find . -name ".DS_Store" -print0 | xargs -0 rm
find . -name ".DS_Store" -print0 | xargs -0 rm
test:
go test -cover -race ./...
fixme:
grep -rnw "FIXME" routers models modules
todo:
grep -rnw "TODO" routers models modules

View File

@@ -1,39 +1,24 @@
Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs)
Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/gogs/localized.svg)](https://crowdin.com/project/gogs) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
=====================
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
![](public/img/gogs-large-resize.png)
##### Current version: 0.9.0
##### Current version: 0.7.22 Beta
| Web | UI | Preview |
|:-------------:|:-------:|:-------:|
|![Dashboard](https://gogs.io/img/screenshots/1.png)|![Repository](https://gogs.io/img/screenshots/2.png)|![Commits History](https://gogs.io/img/screenshots/3.png)|
|![Profile](https://gogs.io/img/screenshots/4.png)|![Admin Dashboard](https://gogs.io/img/screenshots/5.png)|![Diff](https://gogs.io/img/screenshots/6.png)|
|![Issues](https://gogs.io/img/screenshots/7.png)|![Releases](https://gogs.io/img/screenshots/8.png)|![Organization](https://gogs.io/img/screenshots/9.png)|
<table>
<tr>
<td width="33%"><img src="https://gogs.io/img/screenshots/1.png"></td>
<td width="33%"><img src="https://gogs.io/img/screenshots/2.png"></td>
<td width="33%"><img src="https://gogs.io/img/screenshots/3.png"></td>
</tr>
<tr>
<td><img src="https://gogs.io/img/screenshots/4.png"></td>
<td><img src="https://gogs.io/img/screenshots/5.png"></td>
<td><img src="https://gogs.io/img/screenshots/6.png"></td>
</tr>
<tr>
<td><img src="https://gogs.io/img/screenshots/7.png"></td>
<td><img src="https://gogs.io/img/screenshots/8.png"></td>
<td><img src="https://gogs.io/img/screenshots/9.png"></td>
</tr>
</table>
### Important Notes
### NOTICES
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
- The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
- :bangbang:<span style="color: red">You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing an issue or making a Pull Request, and **MUST** discuss with us on [Gitter](https://gitter.im/gogits/gogs) for UI changes, otherwise it's high possibilities that we are not going to merge it.</span>:bangbang:
- Please [start discussion](http://forum.gogs.io/category/2/general-discussion) or [ask a question](http://forum.gogs.io/category/4/getting-help) on [the forum](http://forum.gogs.io/). GitHub issue tracker only keeps **bugs** and **feature requests**, all other topics will be closed without reason.
- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks!
- If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki).
- If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means.
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!
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](http://gogs.io), contact us by any means.
[简体中文](README_ZH.md)
@@ -45,8 +30,8 @@ The goal of this project is to make the easiest, fastest, and most painless way
- Please see the [Documentation](http://gogs.io/docs/intro) for common usages and change log.
- See the [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team.
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/gogs/gogs) or go down to the **Installation -> Install from binary** section!
- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.html).
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/gogs/gogs)!
- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.html) or [User Forum](https://discuss.gogs.io/).
- Want to help with localization? Check out the [guide](http://gogs.io/docs/features/i18n.html)!
## Features
@@ -58,14 +43,13 @@ The goal of this project is to make the easiest, fastest, and most painless way
- Account/Organization/Repository management
- Repository/Organization webhooks (including Slack)
- Repository Git hooks/deploy keys
- Repository issues and pull requests
- Repository issues, pull requests and wiki
- Add/Remove repository collaborators
- Gravatar and custom source
- Mail service
- Administration panel
- CI integration: [Drone](https://github.com/drone/drone)
- Supports MySQL, PostgreSQL, SQLite3 and [TiDB](https://github.com/pingcap/tidb) (experimental)
- Multi-language support ([14 languages](https://crowdin.com/project/gogs))
- Multi-language support ([15 languages](https://crowdin.com/project/gogs))
## System Requirements
@@ -97,10 +81,11 @@ There are 5 ways to install Gogs:
- [阿里云上 Ubuntu 14.04 64 位安装 Gogs](http://my.oschina.net/luyao/blog/375654) (Chinese)
- [Installing Gogs on FreeBSD](https://www.codejam.info/2015/03/installing-gogs-on-freebsd.html)
- [Gogs on Raspberry Pi](http://blog.meinside.pe.kr/Gogs-on-Raspberry-Pi/)
- [Cloudflare Full SSL with GOGS (Go Git Service) using NGINX](http://www.listekconsulting.com/articles/cloudflare-full-ssl-with-gogs-go-git-service-using-nginx/)
### Screencasts
- [Instalando Gogs no Ubuntu](http://blog.linuxpro.com.br/2015/08/14/instalando-gogs-no-ubuntu/) (Português)
- [Instalando Gogs no Ubuntu](https://www.youtube.com/watch?v=4UkHAR1F7ZA) (Português)
### Deploy to Cloud
@@ -109,6 +94,17 @@ There are 5 ways to install Gogs:
- [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)
## Software and Service Support
- [Drone](https://github.com/drone/drone) (CI)
- [Fabric8](http://fabric8.io/) (DevOps)
- [Taiga](https://taiga.io/) (Project Management)
- [Puppet](https://forge.puppetlabs.com/Siteminds/gogs) (IT)
- [Kanboard](http://kanboard.net/plugin/gogs-webhook) (Project Management)
- [BearyChat](https://bearychat.com/) (Team Communication)
### Product Support
@@ -118,11 +114,11 @@ There are 5 ways to install Gogs:
## Acknowledgments
- Router and middleware mechanism of [Macaron](https://github.com/go-macaron/macaron).
- Modules design is inspired by [WeTalk](https://github.com/beego/wetalk).
- System Monitor Status is inspired by [GoBlog](https://github.com/fuxiaohei/goblog).
- Thanks [lavachen](http://www.lavachen.cn/) and [Rocker](http://weibo.com/rocker1989) 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.
- Thanks [KeyCDN](https://www.keycdn.com/) for providing CDN service.
## Contributors

View File

@@ -11,8 +11,8 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- 有关基本用法和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。
- 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。
- 想要先睹为快?通过 [在线体验](https://try.gogs.io/gogs/gogs) 或查看 **安装部署 -> 二进制安装** 小节
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面获取帮助。
- 想要先睹为快?直接去 [在线体验](https://try.gogs.io/gogs/gogs) 。
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面或 [用户论坛](https://discuss.gogs.io/) 获取帮助。
- 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)
## 功能特性
@@ -24,14 +24,13 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- 支持用户、组织和仓库管理系统
- 支持仓库和组织级别 Web 钩子(包括 Slack 集成)
- 支持仓库 Git 钩子和部署密钥
- 支持仓库工单Issue合并请求Pull Request
- 支持仓库工单Issue合并请求Pull Request以及 Wiki
- 支持添加和删除仓库协作者
- 支持 Gravatar 以及自定义源
- 支持邮件服务
- 支持后台管理面板
- 支持 CI 集成:[Drone](https://github.com/drone/drone)
- 支持 MySQL、PostgreSQL、SQLite3 和 [TiDB](https://github.com/pingcap/tidb)(实验性支持) 数据库
- 支持多语言本地化([14 种语言]([more](https://crowdin.com/project/gogs))
- 支持多语言本地化([15 种语言]([more](https://crowdin.com/project/gogs))
## 系统要求
@@ -67,6 +66,17 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- [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)
## 软件及服务支持
- [Drone](https://github.com/drone/drone)CI
- [Fabric8](http://fabric8.io/)DevOps
- [Taiga](https://taiga.io/)(项目管理)
- [Puppet](https://forge.puppetlabs.com/Siteminds/gogs)IT
- [Kanboard](http://kanboard.net/plugin/gogs-webhook)(项目管理)
- [BearyChat](https://bearychat.com/)(团队交流)
### 产品支持
@@ -76,11 +86,11 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
## 特别鸣谢
- 基于 [Macaron](https://github.com/go-macaron/macaron) 的路由与中间件机制。
- 基于 [WeTalk](https://github.com/beego/wetalk) 修改的模块设计。
- 基于 [GoBlog](https://github.com/fuxiaohei/goblog) 修改的系统监视状态。
- 感谢 [lavachen](http://www.lavachen.cn/) 和 [Rocker](http://weibo.com/rocker1989) 设计的 Logo。
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
- 感谢 [DigitalOcean](https://www.digitalocean.com) 提供主站和体验站点的服务器赞助。
- 感谢 [KeyCDN](https://www.keycdn.com/) 提供 CDN 服务赞助。
## 贡献成员

View File

@@ -14,11 +14,10 @@ import (
)
var CmdCert = cli.Command{
Name: "cert",
Usage: "Generate self-signed certificate",
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,
Name: "cert",
Usage: "Generate self-signed certificate",
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
Action: runCert,
}
func runCert(ctx *cli.Context) {

View File

@@ -11,6 +11,8 @@ import (
"path"
"time"
"io/ioutil"
"github.com/Unknwon/cae/zip"
"github.com/codegangsta/cli"
@@ -38,16 +40,23 @@ func runDump(ctx *cli.Context) {
models.LoadConfigs()
models.SetEngine()
TmpWorkDir, err := ioutil.TempDir(os.TempDir(), "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")
defer os.Remove("gogs-repo.zip")
if err := zip.PackTo(setting.RepoRootPath, "gogs-repo.zip", true); err != nil {
if err := zip.PackTo(setting.RepoRootPath, reposDump, true); err != nil {
log.Fatalf("Fail to dump local repositories: %v", err)
}
log.Printf("Dumping database...")
defer os.Remove("gogs-db.sql")
if err := models.DumpDatabase("gogs-db.sql"); err != nil {
if err := models.DumpDatabase(dbDump); err != nil {
log.Fatalf("Fail to dump database: %v", err)
}
@@ -59,16 +68,30 @@ func runDump(ctx *cli.Context) {
log.Fatalf("Fail to create %s: %v", fileName, err)
}
workDir, _ := setting.WorkDir()
z.AddFile("gogs-repo.zip", path.Join(workDir, "gogs-repo.zip"))
z.AddFile("gogs-db.sql", path.Join(workDir, "gogs-db.sql"))
z.AddDir("custom", path.Join(workDir, "custom"))
z.AddDir("log", path.Join(workDir, "log"))
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)
}
// FIXME: SSH key file.
if err = z.Close(); err != nil {
os.Remove(fileName)
log.Fatalf("Fail to save %s: %v", fileName, err)
}
log.Println("Finish dumping!")
log.Printf("Removing tmp work dir: %s", TmpWorkDir)
os.RemoveAll(TmpWorkDir)
log.Printf("Finish dumping in file %s", fileName)
}

View File

@@ -15,12 +15,13 @@ import (
"github.com/Unknwon/com"
"github.com/codegangsta/cli"
gouuid "github.com/satori/go.uuid"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/uuid"
)
const (
@@ -41,11 +42,6 @@ func setup(logPath string) {
setting.NewContext()
log.NewGitLogger(filepath.Join(setting.LogRootPath, logPath))
if setting.DisableSSH {
println("Gogs: SSH has been disabled")
os.Exit(1)
}
models.LoadConfigs()
if setting.UseSQLite3 || setting.UseTiDB {
@@ -77,7 +73,7 @@ func fail(userMessage, logMessage string, args ...interface{}) {
if len(logMessage) > 0 {
if !setting.ProdMode {
fmt.Fprintf(os.Stderr, logMessage, args...)
fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
}
log.GitLogger.Fatal(3, logMessage, args...)
return
@@ -87,7 +83,7 @@ func fail(userMessage, logMessage string, args ...interface{}) {
os.Exit(1)
}
func handleUpdateTask(uuid string, user *models.User, repoUserName, repoName string) {
func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string, isWiki bool) {
task, err := models.GetUpdateTaskByUUID(uuid)
if err != nil {
if models.IsErrUpdateTaskNotExist(err) {
@@ -95,20 +91,29 @@ func handleUpdateTask(uuid string, user *models.User, repoUserName, repoName str
return
}
log.GitLogger.Fatal(2, "GetUpdateTaskByUUID: %v", err)
}
if err = models.Update(task.RefName, task.OldCommitID, task.NewCommitID,
user.Name, repoUserName, repoName, user.Id); err != nil {
log.GitLogger.Error(2, "Update: %v", err)
}
if err = models.DeleteUpdateTaskByUUID(uuid); err != nil {
} else if err = models.DeleteUpdateTaskByUUID(uuid); err != nil {
log.GitLogger.Fatal(2, "DeleteUpdateTaskByUUID: %v", err)
}
if isWiki {
return
}
if err = models.PushUpdate(models.PushUpdateOptions{
RefName: task.RefName,
OldCommitID: task.OldCommitID,
NewCommitID: task.NewCommitID,
PusherID: user.Id,
PusherName: user.Name,
RepoUserName: repoUser.Name,
RepoName: reponame,
}); err != nil {
log.GitLogger.Error(2, "Update: %v", err)
}
// Ask for running deliver hook and test pull request tasks.
reqURL := setting.AppUrl + repoUserName + "/" + repoName + "/tasks/trigger?branch=" +
strings.TrimPrefix(task.RefName, "refs/heads/")
reqURL := setting.LocalURL + repoUser.Name + "/" + reponame + "/tasks/trigger?branch=" +
strings.TrimPrefix(task.RefName, "refs/heads/") + "&secret=" + base.EncodeMD5(repoUser.Salt)
log.GitLogger.Trace("Trigger task: %s", reqURL)
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
@@ -128,8 +133,14 @@ func runServ(c *cli.Context) {
if c.IsSet("config") {
setting.CustomConf = c.String("config")
}
setup("serv.log")
if setting.SSH.Disabled {
println("Gogs: SSH has been disabled")
return
}
if len(c.Args()) < 1 {
fail("Not enough arguments", "Not enough arguments")
}
@@ -147,21 +158,27 @@ func runServ(c *cli.Context) {
if len(rr) != 2 {
fail("Invalid repository path", "Invalid repository path: %v", args)
}
repoUserName := strings.ToLower(rr[0])
repoName := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
username := strings.ToLower(rr[0])
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
repoUser, err := models.GetUserByName(repoUserName)
if err != nil {
if models.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", repoUserName)
}
fail("Internal error", "Failed to get repository owner(%s): %v", repoUserName, err)
isWiki := false
if strings.HasSuffix(reponame, ".wiki") {
isWiki = true
reponame = reponame[:len(reponame)-5]
}
repo, err := models.GetRepositoryByName(repoUser.Id, repoName)
repoUser, err := models.GetUserByName(username)
if err != nil {
if models.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", username)
}
fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
}
repo, err := models.GetRepositoryByName(repoUser.Id, reponame)
if err != nil {
if models.IsErrRepoNotExist(err) {
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, repoName)
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, reponame)
}
fail("Internal error", "Failed to get repository: %v", err)
}
@@ -200,7 +217,7 @@ func runServ(c *cli.Context) {
}
// Check if this deploy key belongs to current repository.
if !models.HasDeployKey(key.ID, repo.ID) {
fail("Key access denied", "Key access denied: %d-%d", key.ID, repo.ID)
fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
}
// Update deploy key activity.
@@ -234,7 +251,7 @@ func runServ(c *cli.Context) {
}
}
uuid := uuid.NewV4().String()
uuid := gouuid.NewV4().String()
os.Setenv("uuid", uuid)
// Special handle for Windows.
@@ -258,7 +275,7 @@ func runServ(c *cli.Context) {
}
if requestedMode == models.ACCESS_MODE_WRITE {
handleUpdateTask(uuid, user, repoUserName, repoName)
handleUpdateTask(uuid, user, repoUser, reponame, isWiki)
}
// Update user key activity.

View File

@@ -16,7 +16,7 @@ import (
var CmdUpdate = cli.Command{
Name: "update",
Usage: "This command should only be called by SSH shell",
Usage: "This command should only be called by Git hook",
Description: `Update get pushed info and insert into database`,
Action: runUpdate,
Flags: []cli.Flag{
@@ -28,18 +28,19 @@ func runUpdate(c *cli.Context) {
if c.IsSet("config") {
setting.CustomConf = c.String("config")
}
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
if cmd == "" {
return
}
setup("update.log")
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
log.GitLogger.Trace("SSH_ORIGINAL_COMMAND is empty")
return
}
args := c.Args()
if len(args) != 3 {
log.GitLogger.Fatal(2, "received less 3 parameters")
} else if args[0] == "" {
log.GitLogger.Fatal(2, "refName is empty, shouldn't use")
log.GitLogger.Fatal(2, "Arguments received are not equal to three")
} else if len(args[0]) == 0 {
log.GitLogger.Fatal(2, "First argument 'refName' is empty, shouldn't use")
}
task := models.UpdateTask{

View File

@@ -7,7 +7,6 @@ package cmd
import (
"crypto/tls"
"fmt"
gotmpl "html/template"
"io/ioutil"
"net/http"
"net/http/fcgi"
@@ -29,12 +28,11 @@ import (
"gopkg.in/ini.v1"
"gopkg.in/macaron.v1"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/git-module"
"github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/auth/apiv1"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware"
@@ -42,7 +40,7 @@ import (
"github.com/gogits/gogs/modules/template"
"github.com/gogits/gogs/routers"
"github.com/gogits/gogs/routers/admin"
"github.com/gogits/gogs/routers/api/v1"
apiv1 "github.com/gogits/gogs/routers/api/v1"
"github.com/gogits/gogs/routers/dev"
"github.com/gogits/gogs/routers/org"
"github.com/gogits/gogs/routers/repo"
@@ -80,19 +78,21 @@ func checkVersion() {
// Check dependency version.
checkers := []VerChecker{
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"},
{"github.com/Unknwon/macaron", macaron.Version, "0.5.4"},
{"github.com/go-macaron/binding", binding.Version, "0.1.0"},
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.2.0304"},
{"github.com/go-macaron/binding", binding.Version, "0.2.1"},
{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
{"github.com/go-macaron/csrf", csrf.Version, "0.0.3"},
{"github.com/go-macaron/i18n", i18n.Version, "0.0.7"},
{"github.com/go-macaron/csrf", csrf.Version, "0.0.5"},
{"github.com/go-macaron/i18n", i18n.Version, "0.2.0"},
{"github.com/go-macaron/session", session.Version, "0.1.6"},
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
{"gopkg.in/ini.v1", ini.Version, "1.3.4"},
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
{"gopkg.in/macaron.v1", macaron.Version, "0.8.0"},
{"github.com/gogits/git-module", git.Version, "0.2.9"},
{"github.com/gogits/go-gogs-client", gogs.Version, "0.7.3"},
}
for _, c := range checkers {
if !version.Compare(c.Version(), c.Expected, ">=") {
log.Fatal(4, "Package '%s' version is too old(%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected)
log.Fatal(4, "Package '%s' version is too old (%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected)
}
}
}
@@ -125,7 +125,7 @@ func newMacaron() *macaron.Macaron {
))
m.Use(macaron.Renderer(macaron.RenderOptions{
Directory: path.Join(setting.StaticRootPath, "templates"),
Funcs: []gotmpl.FuncMap{template.Funcs},
Funcs: template.NewFuncMap(),
IndentJSON: macaron.Env != macaron.PROD,
}))
@@ -143,6 +143,7 @@ func newMacaron() *macaron.Macaron {
CustomDirectory: path.Join(setting.CustomPath, "conf/locale"),
Langs: setting.Langs,
Names: setting.Names,
DefaultLang: "en-US",
Redirect: true,
}))
m.Use(cache.Cacher(cache.Options{
@@ -186,9 +187,10 @@ func runWeb(ctx *cli.Context) {
ignSignInAndCsrf := middleware.Toggle(&middleware.ToggleOptions{DisableCsrf: true})
reqSignOut := middleware.Toggle(&middleware.ToggleOptions{SignOutRequire: true})
bind := binding.Bind
bindIgnErr := binding.BindIgnErr
// FIXME: not all routes need go through same middlewares.
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
m.Get("/", ignSignIn, routers.Home)
m.Get("/explore", ignSignIn, routers.Explore)
@@ -197,61 +199,8 @@ func runWeb(ctx *cli.Context) {
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
// ***** START: API *****
// FIXME: custom form error response.
m.Group("/api", func() {
m.Group("/v1", func() {
// Miscellaneous.
m.Post("/markdown", bindIgnErr(apiv1.MarkdownForm{}), v1.Markdown)
m.Post("/markdown/raw", v1.MarkdownRaw)
// Users.
m.Group("/users", func() {
m.Get("/search", v1.SearchUsers)
m.Group("/:username", func() {
m.Get("", v1.GetUserInfo)
m.Group("/tokens", func() {
m.Combo("").Get(v1.ListAccessTokens).
Post(bind(v1.CreateAccessTokenForm{}), v1.CreateAccessToken)
}, middleware.ApiReqBasicAuth())
})
})
// Repositories.
m.Combo("/user/repos", middleware.ApiReqToken()).Get(v1.ListMyRepos).
Post(bind(api.CreateRepoOption{}), v1.CreateRepo)
m.Post("/org/:org/repos", middleware.ApiReqToken(), bind(api.CreateRepoOption{}), v1.CreateOrgRepo)
m.Group("/repos", func() {
m.Get("/search", v1.SearchRepos)
})
m.Group("/repos", func() {
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), v1.MigrateRepo)
m.Combo("/:username/:reponame").Get(v1.GetRepo).
Delete(v1.DeleteRepo)
m.Group("/:username/:reponame", func() {
m.Combo("/hooks").Get(v1.ListRepoHooks).
Post(bind(api.CreateHookOption{}), v1.CreateRepoHook)
m.Patch("/hooks/:id:int", bind(api.EditHookOption{}), v1.EditRepoHook)
m.Get("/raw/*", middleware.RepoRef(), v1.GetRepoRawFile)
m.Get("/archive/*", v1.GetRepoArchive)
m.Group("/keys", func() {
m.Combo("").Get(v1.ListRepoDeployKeys).
Post(bind(api.CreateDeployKeyOption{}), v1.CreateRepoDeployKey)
m.Combo("/:id").Get(v1.GetRepoDeployKey).
Delete(v1.DeleteRepoDeploykey)
})
}, middleware.ApiRepoAssignment())
}, middleware.ApiReqToken())
m.Any("/*", func(ctx *middleware.Context) {
ctx.Error(404)
})
})
apiv1.RegisterRoutes(m)
}, ignSignIn)
// ***** END: API *****
@@ -269,6 +218,7 @@ func runWeb(ctx *cli.Context) {
m.Get("", user.Settings)
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), user.SettingsAvatar)
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
m.Combo("/email").Get(user.SettingsEmails).
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
m.Post("/email/delete", user.DeleteEmail)
@@ -296,25 +246,19 @@ func runWeb(ctx *cli.Context) {
})
// ***** END: User *****
// Gravatar service.
avt := avatar.CacheServer("public/img/avatar/", "public/img/avatar_default.jpg")
os.MkdirAll("public/img/avatar/", os.ModePerm)
m.Get("/avatar/:hash", avt.ServeHTTP)
adminReq := middleware.Toggle(&middleware.ToggleOptions{SignInRequire: true, AdminRequire: true})
// ***** START: Admin *****
m.Group("/admin", func() {
m.Get("", adminReq, admin.Dashboard)
m.Get("/config", admin.Config)
m.Post("/config/test_mail", admin.SendTestMail)
m.Get("/monitor", admin.Monitor)
m.Group("/users", func() {
m.Get("", admin.Users)
m.Get("/new", admin.NewUser)
m.Post("/new", bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
m.Get("/:userid", admin.EditUser)
m.Post("/:userid", bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
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.Post("/:userid/delete", admin.DeleteUser)
})
@@ -323,13 +267,13 @@ func runWeb(ctx *cli.Context) {
})
m.Group("/repos", func() {
m.Get("", admin.Repositories)
m.Get("", admin.Repos)
m.Post("/delete", admin.DeleteRepo)
})
m.Group("/auths", func() {
m.Get("", admin.Authentications)
m.Get("/new", admin.NewAuthSource)
m.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Combo("/:authid").Get(admin.EditAuthSource).
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
m.Post("/:authid/delete", admin.DeleteAuthSource)
@@ -337,13 +281,20 @@ func runWeb(ctx *cli.Context) {
m.Group("/notices", func() {
m.Get("", admin.Notices)
m.Get("/:id:int/delete", admin.DeleteNotice)
m.Post("/delete", admin.DeleteNotices)
m.Get("/empty", admin.EmptyNotices)
})
}, adminReq)
// ***** END: Admin *****
m.Group("", func() {
m.Get("/:username", user.Profile)
m.Group("/:username", func() {
m.Get("", user.Profile)
m.Get("/followers", user.Followers)
m.Get("/following", user.Following)
m.Get("/stars", user.Stars)
})
m.Get("/attachments/:uuid", func(ctx *middleware.Context) {
attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid"))
if err != nil {
@@ -373,11 +324,16 @@ func runWeb(ctx *cli.Context) {
m.Post("/issues/attachments", repo.UploadIssueAttachment)
}, ignSignIn)
m.Group("/:username", func() {
m.Get("/action/:action", user.Action)
}, reqSignIn)
if macaron.Env == macaron.DEV {
m.Get("/template/*", dev.TemplatePreview)
}
reqRepoAdmin := middleware.RequireRepoAdmin()
reqRepoWriter := middleware.RequireRepoWriter()
// ***** START: Organization *****
m.Group("/org", func() {
@@ -391,11 +347,14 @@ func runWeb(ctx *cli.Context) {
m.Get("/members/action/:action", org.MembersAction)
m.Get("/teams", org.Teams)
}, middleware.OrgAssignment(true))
m.Group("/:org", func() {
m.Get("/teams/:team", org.TeamMembers)
m.Get("/teams/:team/repositories", org.TeamRepositories)
m.Route("/teams/:team/action/:action", "GET,POST", org.TeamsAction)
m.Route("/teams/:team/action/repo/:action", "GET,POST", org.TeamsRepoAction)
}, middleware.OrgAssignment(true))
}, middleware.OrgAssignment(true, false, true))
m.Group("/:org", func() {
m.Get("/teams/new", org.NewTeam)
@@ -408,6 +367,7 @@ func runWeb(ctx *cli.Context) {
m.Combo("").Get(org.Settings).
Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), org.SettingsAvatar)
m.Post("/avatar/delete", org.SettingsDeleteAvatar)
m.Group("/hooks", func() {
m.Get("", org.Webhooks)
@@ -442,7 +402,11 @@ func runWeb(ctx *cli.Context) {
m.Group("/settings", func() {
m.Combo("").Get(repo.Settings).
Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
m.Route("/collaboration", "GET,POST", repo.Collaboration)
m.Group("/collaboration", func() {
m.Combo("").Get(repo.Collaboration).Post(repo.CollaborationPost)
m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
m.Post("/delete", repo.DeleteCollaboration)
})
m.Group("/hooks", func() {
m.Get("", repo.Webhooks)
@@ -451,6 +415,7 @@ func runWeb(ctx *cli.Context) {
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
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)
@@ -470,13 +435,12 @@ func runWeb(ctx *cli.Context) {
}, func(ctx *middleware.Context) {
ctx.Data["PageIsSettings"] = true
})
}, reqSignIn, middleware.RepoAssignment(true), reqRepoAdmin, middleware.RepoRef())
}, reqSignIn, middleware.RepoAssignment(), reqRepoAdmin, middleware.RepoRef())
m.Get("/:username/:reponame/action/:action", reqSignIn, middleware.RepoAssignment(), repo.Action)
m.Group("/:username/:reponame", func() {
m.Get("/action/:action", repo.Action)
m.Group("/issues", func() {
m.Combo("/new").Get(repo.NewIssue).
m.Combo("/new", repo.MustEnableIssues).Get(middleware.RepoRef(), repo.NewIssue).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
m.Combo("/:index/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
@@ -484,7 +448,7 @@ func runWeb(ctx *cli.Context) {
m.Post("/label", repo.UpdateIssueLabel)
m.Post("/milestone", repo.UpdateIssueMilestone)
m.Post("/assignee", repo.UpdateIssueAssignee)
}, reqRepoAdmin)
}, reqRepoWriter)
m.Group("/:index", func() {
m.Post("/title", repo.UpdateIssueTitle)
@@ -496,15 +460,15 @@ func runWeb(ctx *cli.Context) {
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
m.Post("/delete", repo.DeleteLabel)
}, reqRepoAdmin)
}, reqRepoWriter, middleware.RepoRef())
m.Group("/milestones", func() {
m.Get("/new", repo.NewMilestone)
m.Post("/new", bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
m.Combo("/new").Get(repo.NewMilestone).
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
m.Get("/:id/edit", repo.EditMilestone)
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
m.Get("/:id/:action", repo.ChangeMilestonStatus)
m.Post("/delete", repo.DeleteMilestone)
}, reqRepoAdmin)
}, reqRepoWriter, middleware.RepoRef())
m.Group("/releases", func() {
m.Get("/new", repo.NewRelease)
@@ -512,51 +476,64 @@ func runWeb(ctx *cli.Context) {
m.Get("/edit/:tagname", repo.EditRelease)
m.Post("/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
m.Post("/delete", repo.DeleteRelease)
}, reqRepoAdmin, middleware.RepoRef())
}, reqRepoWriter, middleware.RepoRef())
m.Combo("/compare/*").Get(repo.CompareAndPullRequest).
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
}, reqSignIn, middleware.RepoAssignment(true))
}, reqSignIn, middleware.RepoAssignment(), repo.MustBeNotBare)
m.Group("/:username/:reponame", func() {
m.Group("", func() {
m.Get("/releases", repo.Releases)
m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues)
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue)
m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
m.Get("/milestones", repo.Milestones)
}, middleware.RepoRef(),
func(ctx *middleware.Context) {
ctx.Data["PageIsList"] = true
})
m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue)
}, middleware.RepoRef())
// m.Get("/branches", repo.Branches)
m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki)
m.Get("/_pages", repo.WikiPages)
m.Group("", func() {
m.Combo("/_new").Get(repo.NewWiki).
Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost)
m.Combo("/:page/_edit").Get(repo.EditWiki).
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
m.Post("/:page/delete", repo.DeleteWikiPagePost)
}, reqSignIn, reqRepoWriter)
}, repo.MustEnableWiki, middleware.RepoRef())
m.Get("/branches", repo.Branches)
m.Get("/archive/*", repo.Download)
m.Group("/pulls/:index", func() {
m.Get("/commits", repo.ViewPullCommits)
m.Get("/files", repo.ViewPullFiles)
m.Post("/merge", reqRepoAdmin, repo.MergePullRequest)
})
m.Get("/commits", middleware.RepoRef(), repo.ViewPullCommits)
m.Get("/files", middleware.RepoRef(), repo.ViewPullFiles)
m.Post("/merge", reqRepoWriter, repo.MergePullRequest)
}, repo.MustAllowPulls)
m.Group("", func() {
m.Get("/src/*", repo.Home)
m.Get("/raw/*", repo.SingleDownload)
m.Get("/commits/*", repo.RefCommits)
m.Get("/commit/*", repo.Diff)
m.Get("/stars", repo.Stars)
m.Get("/watchers", repo.Watchers)
m.Get("/forks", repo.Forks)
}, middleware.RepoRef())
m.Get("/compare/:before([a-z0-9]{40})...:after([a-z0-9]{40})", repo.CompareDiff)
}, ignSignIn, middleware.RepoAssignment(true))
m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.CompareDiff)
}, ignSignIn, middleware.RepoAssignment(), repo.MustBeNotBare)
m.Group("/:username/:reponame", func() {
m.Get("/stars", repo.Stars)
m.Get("/watchers", repo.Watchers)
}, ignSignIn, middleware.RepoAssignment(), middleware.RepoRef())
m.Group("/:username", func() {
m.Group("/:reponame", func() {
m.Get("", repo.Home)
m.Get("\\.git$", repo.Home)
}, ignSignIn, middleware.RepoAssignment(true, true), middleware.RepoRef())
}, ignSignIn, middleware.RepoAssignment(true), middleware.RepoRef())
m.Group("/:reponame", func() {
m.Any("/*", ignSignInAndCsrf, repo.HTTP)

View File

@@ -1,7 +1,3 @@
Execute following command in ROOT directory when anything is changed:
$ go-bindata -o=modules/bindata/bindata.go -ignore="\\.DS_Store|README.md" -pkg=bindata conf/...
Add -debug flag to make life easier in development(somehow isn't working):
$ go-bindata -debug -o=modules/bindata/bindata.go -ignore="\\.DS_Store|README.md" -pkg=bindata conf/...
$ make bindata

View File

@@ -15,6 +15,8 @@ SCRIPT_TYPE = bash
ANSI_CHARSET =
; Force every new repository to be private
FORCE_PRIVATE = false
; Global maximum creation limit of repository per user, -1 means no limit
MAX_CREATION_LIMIT = -1
; Patch test queue length, make it as large as possible
PULL_REQUEST_QUEUE_LENGTH = 10000
@@ -25,6 +27,10 @@ EXPLORE_PAGING_NUM = 20
ISSUE_PAGING_NUM = 10
; Number of maximum commits showed in one activity feed
FEED_MAX_COMMIT_NUM = 5
; Value of `theme-color` meta tag, used by Android >= 5.0
; An invalid color like "none" or "disable" will have the default style
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
THEME_COLOR_META_TAG = `#ff5343`
[ui.admin]
; Number of users that are showed in one page
@@ -32,13 +38,16 @@ USER_PAGING_NUM = 50
; Number of repos that are showed in one page
REPO_PAGING_NUM = 50
; Number of notices that are showed in one page
NOTICE_PAGING_NUM = 50
NOTICE_PAGING_NUM = 25
; Number of organization that are showed in one page
ORG_PAGING_NUM = 50
[markdown]
; Enable hard line break extension
ENABLE_HARD_LINE_BREAK = false
; List of custom URL-Schemes that are allowed as links when rendering Markdown
; for example git,magnet
CUSTOM_URL_SCHEMES =
[server]
PROTOCOL = http
@@ -46,16 +55,33 @@ DOMAIN = localhost
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
HTTP_ADDR =
HTTP_PORT = 3000
; Local (DMZ) URL for Gogs workers (such as SSH update) accessing web service.
; In most cases you do not need to change the default value.
; Alter it only if your SSH server node is not the same as HTTP node.
LOCAL_ROOT_URL = http://localhost:%(HTTP_PORT)s/
; Disable SSH feature when not available
DISABLE_SSH = false
; Whether use builtin SSH server or not.
START_SSH_SERVER = false
; Domain name to be exposed in clone URL
SSH_DOMAIN = %(DOMAIN)s
; Port number to be exposed in clone URL
SSH_PORT = 22
; Port number builtin SSH server listens on
SSH_LISTEN_PORT = %(SSH_PORT)s
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
SSH_ROOT_PATH =
; Directory to create temporary files when test publick key using ssh-keygen,
; default is system temporary directory.
SSH_KEY_TEST_PATH =
; Path to ssh-keygen, default is 'ssh-keygen' and let shell find out which one to call.
SSH_KEYGEN_PATH = ssh-keygen
; Indicate whether to check minimum key size with corresponding type
MINIMUM_KEY_SIZE_CHECK = false
; Disable CDN even in "prod" mode
OFFLINE_MODE = false
DISABLE_ROUTER_LOG = false
; Generate steps:
; $ cd path/to/gogs/custom/https
; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com
;
; Or from a .pfx file exported from the Windows certificate store (do
@@ -72,6 +98,13 @@ ENABLE_GZIP = false
; Landing page for non-logged users, can be "home" or "explore"
LANDING_PAGE = home
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
[ssh.minimum_key_sizes]
ED25519 = 256
ECDSA = 256
RSA = 2048
DSA = 1024
[database]
; Either "mysql", "postgres" or "sqlite3", it's your choice
DB_TYPE = mysql
@@ -81,7 +114,7 @@ USER = root
PASSWD =
; For "postgres" only, either "disable", "require" or "verify-full"
SSL_MODE = disable
; For "sqlite3" and "tidb"
; For "sqlite3" and "tidb", use absolute path when you start as service
PATH = data/gogs.db
[admin]
@@ -106,28 +139,14 @@ REGISTER_EMAIL_CONFIRM = false
DISABLE_REGISTRATION = false
; User must sign in to view anything.
REQUIRE_SIGNIN_VIEW = false
; Cache avatar as picture
ENABLE_CACHE_AVATAR = false
; Mail notification
ENABLE_NOTIFY_MAIL = false
; More detail: https://github.com/gogits/gogs/issues/165
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
; Do not check minimum key size with corresponding type
DISABLE_MINIMUM_KEY_SIZE_CHECK = false
; Enable captcha validation for registration
ENABLE_CAPTCHA = true
; used to filter keys which are too short
[service.minimum_key_sizes]
ED25519 = 256
ECDSA = 256
NTRU = 1087
MCE = 1702
McE = 1702
RSA = 1024
DSA = 1024
[webhook]
; Hook task queue length
QUEUE_LENGTH = 1000
@@ -196,8 +215,6 @@ GC_INTERVAL_TIME = 86400
SESSION_LIFE_TIME = 86400
[picture]
; The place to picture data, either "server" or "qiniu", default is "server"
SERVICE = server
AVATAR_UPLOAD_PATH = data/avatars
; Chinese users can choose "duoshuo"
; or a custom avatar source, like: http://cn.gravatar.com/avatar/
@@ -265,8 +282,8 @@ ADDR =
; For "smtp" mode only
[log.smtp]
LEVEL =
; Name displayed in mail title, default is "Diagnostic message from serve"
SUBJECT = Diagnostic message from serve
; Name displayed in mail title, default is "Diagnostic message from server"
SUBJECT = Diagnostic message from server
; Mail server
HOST =
; Mailer user name and password
@@ -296,7 +313,8 @@ SCHEDULE = @every 1h
; Repository health check
[cron.repo_health_check]
SCHEDULE = @every 24h
; Arguments for command 'git fsck', e.g.: "--unreachable --tags"
TIMEOUT = 60s
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; see more on http://git-scm.com/docs/git-fsck/1.7.5
ARGS =
@@ -307,13 +325,20 @@ SCHEDULE = @every 24h
[git]
MAX_GIT_DIFF_LINES = 10000
; Arguments for command 'git gc', e.g.: "--aggressive --auto"
; Arguments for command 'git gc', e.g. "--aggressive --auto"
; see more on http://git-scm.com/docs/git-gc/1.7.5
GC_ARGS =
; Operation timeout in seconds
[git.timeout]
MIGRATE = 600
MIRROR = 300
CLONE = 300
PULL = 300
[i18n]
LANGS = en-US,zh-CN,zh-HK,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT
NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano
LANGS = en-US,zh-CN,zh-HK,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI
NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen
; Used for datetimepicker
[i18n.datelang]
@@ -331,6 +356,11 @@ pt-BR = pt-BR
pl-PL = pl
bg-BG = bg
it-IT = it
fi-FI = fi
; Extension mapping to highlight class
; e.g. .toml=ini
[highlight.mapping]
[other]
SHOW_FOOTER_BRANDING = false

View File

@@ -1,39 +0,0 @@
Creative Commons CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.

View File

@@ -1,29 +1,54 @@
# This file lists all PUBLIC individuals having contributed content to the translation.
# Entries are in alphabetical order.
Adam Strzelecki <ono AT java DOT pl>
Adrian Verde <me AT adrianverde DOT com>
Akihiro YAGASAKI <yaggytter AT momiage DOT com>
Aleksejs Grocevs <aleksejs AT grocevs DOT pro>
Aleksey Tarakin <hukendo AT yandex DOT ru>
Alexander Steinhöfer <kontakt AT lx-s DOT de>
Alexandre Magno <alexandre DOT mbm AT gmail DOT com>
Andrey Nering <andrey AT nering DOT com DOT br>
Andrey Solomatin <toadron AT yandex DOT ru>
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>
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
Cysioland
Daniel Speichert <daniel AT speichert DOT pl>
David Yzaguirre <dvdyzag AT gmail DOT com>
Dmitriy Nogay <me AT catwhocode DOT ga>
Enrico Testori hypertesto AT gmail DOT com
Ezequiel Gonzalez Rial <gonrial AT gmail DOT com>
Gregor Santner <gdev AT live DOT de>
Hamid Feizabadi <hamidfzm AT gmail DOT com>
Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp>
ilko
ilko <kontact-mr.k AT outlook DOT com">
Ilya Makarov
Robin Hübner <profan AT prfn DOT se>
Jamie Mansfield <dev AT jamierocks DOT uk>
Jean THOMAS <contact AT tibounise DOT com>
Juraj Bubniak <contact AT jbub DOT eu>
Lafriks <lafriks AT gmail DOT com>
Lauri Ojansivu <x AT xet7 DOT org>
Luc Stepniewski <luc AT stepniewski DOT fr>
Luca Kröger <l DOT kroeger01 AT gmail DOT com>
Marc Schiller <marc AT schiller DOT im>
Marvin Menzerath <github AT marvin-menzerath DOT de>
Michael Härtl <haertl DOT mike AT gmail DOT com>
Miguel de la Cruz <miguel AT mcrx DOT me>
Mikhail Burdin <xdshot9000 AT gmail DOT com>
Morten Sørensen <klim8d AT gmail DOT com>
Muhammad Fawwaz Orabi <mfawwaz93 AT gmail DOT com>
Nakao Takamasa <at.mattenn AT gmail DOT com>
Natan Albuquerque <natanalbuquerque5 AT gmail DOT com>
Odilon Junior <odilon DOT junior93 AT gmail DOT com>
SeongJae Park <sj38 DOT park AT gmail DOT com>
Thomas Fanninger <gogs DOT thomas AT fanninger DOT at>
Tilmann Bach <tilmann AT outlook DOT com>
Toni Villena Jiménez <tonivj5 AT gmail DOT com>
Vladimir Jigulin mogaika AT yandex DOT ru
Vladimir Vissoultchev <wqweto AT gmail DOT com>
YJSoft <yjsoft AT yjsoft DOT pe DOT kr>
Łukasz Jan Niemier <lukasz AT niemier DOT pl>
Łukasz Jan Niemier <lukasz AT niemier DOT pl>

View File

@@ -2,12 +2,12 @@ app_desc=Безпроблемен собствен Git сървър
home=Начало
dashboard=Табло
explore=Преглед
explore=Каталог
help=Помощ
sign_in=Влизане
sign_out=Излизане
sign_in=Вход
sign_out=Изход
sign_up=Регистрирайте се
register=Регистриране
register=Регистрация
website=Уебсайт
version=Версия
page=Страница
@@ -28,6 +28,7 @@ organization=Организация
mirror=Огледало
new_repo=Ново хранилище
new_migrate=Нова миграция
new_mirror=Ново огледало
new_fork=Ново разклонено хранилище
new_org=Нова организация
manage_org=Управление на организации
@@ -37,9 +38,9 @@ settings=Настройки
your_profile=Вашият профил
your_settings=Вашите настройки
news_feed=Поток новини
pull_requests=Заявки сливане
issues=Проблеми
activities=Активности
pull_requests=Заявки за сливане
issues=Задачи
cancel=Отказ
@@ -47,7 +48,7 @@ cancel=Отказ
search=Търсене...
repository=Хранилище
user=Потребител
issue=Проблем
issue=Задача
code=Код
[install]
@@ -64,7 +65,7 @@ db_name=Име на база данни
db_helper=Моля, използвайте INNODB engine с utf8_general_ci кодиране на знаци за MySQL.
ssl_mode=Режим SSL
path=Път
sqlite_helper=Файл на SQLite3 или TiDB база данни.
sqlite_helper=Файл на SQLite3 или TiDB база данни.<br>Моля използвайте абсолютен път до файл когато стартирате Gogs като услуга.
err_empty_db_path=Пътят до SQLite3 или TiDB база данни не може да е празен.
err_invalid_tidb_name=TiDB не позволява "." и "-" в името на базата данни.
no_admin_and_disable_registration=Невъзможно изключване на регистрациите без предварително да е създаден поне един административен профил.
@@ -85,6 +86,8 @@ http_port=HTTP порт
http_port_helper=Порт, на който приложението ще слуша.
app_url=URL адрес на приложението
app_url_helper=Този настройка променя HTTP/HTTPS адреса за клониране, а понякога и адреса на ел. поща.
log_root_path=Път към журналите
log_root_path_helper=Директория в която се записват журналите.
optional_title=Опционални настройки
email_title=Настройки на пощенска услуга
@@ -121,6 +124,7 @@ run_user_not_match=Потребителският контекст на прил
save_config_failed=Неуспешно запазване на конфигурация: %v
invalid_admin_setting=Настройките на профил на администратора са невалидни: %v
install_success=Добре дошли! Радваме се, че избрахте Gogs, и Ви пожелаваме приятна работа и сърдечни поздрави!
invalid_log_root_path=Основният път към журналите е невалиден: %v
[home]
uname_holder=Име или ел. поща
@@ -202,7 +206,6 @@ repo_name_been_taken=Името на хранилището вече се пол
org_name_been_taken=Името на организацията вече се ползва.
team_name_been_taken=Името на екипа вече се ползва.
email_been_used=Този адрес на ел. поща вече се ползва.
illegal_team_name=Името на екипа съдържа недопустими знаци.
username_password_incorrect=Потребителското име или паролата не са верни.
enterred_invalid_repo_name=Моля уверете се, че въведеното име на хранилище е вярно.
enterred_invalid_owner_name=Моля уверете се, че въведеното име на притежател е вярно.
@@ -218,8 +221,6 @@ still_own_repo=Вашият профил притежава поне едно х
still_has_org=Вашият профил все още участва в поне една организация. Първо трябва да напуснете или изтриете Вашите участия в организациите.
org_still_own_repo=Тази организация все още притежава хранилище. Първо трябва да го изтриете или да го прехвърлите на друга организация.
still_own_user=Това удостоверяване се използва от поне един потребител. Моля премахнете потребителите към него и опитайте отново.
target_branch_not_exist=Целевият клон не съществува.
[user]
@@ -231,6 +232,8 @@ activity=Публична дейност
followers=Последователи
starred=Харесано
following=Следване
follow=Следване
unfollow=Не следвай
form.name_reserved=Потребителското име '%s' е запазено.
form.name_pattern_not_allowed=Потребителското име '%s' не е допустимо.
@@ -247,10 +250,11 @@ uid=UID
public_profile=Публичен профил
profile_desc=Вашият адрес на ел. поща е публичен и ще бъде използван за всички свързани с профила Ви уведомления и всички уеб базирани операции, направени чрез сайта.
password_username_disabled=Нелокални потребители не могат да променят името си от тук.
full_name=Пълно име
website=Уебсайт
location=Локация
update_profile=Обнови профила
update_profile=Запази профила
update_profile_success=Вашият профил е запазен успешно.
change_username=Потребителското име е променено
change_username_prompt=Този промяна ще засегне всички връзки сочещи към профила Ви.
@@ -258,11 +262,10 @@ continue=Продължи
cancel=Отказ
enable_custom_avatar=Разреши потребителски аватар
enable_custom_avatar_helper=Без зареждане от Gravatar
choose_new_avatar=Избор на нов аватар
update_avatar=Обнови настройките на аватара
update_avatar=Запази настройките на аватара
delete_current_avatar=Изтрий аватар
uploaded_avatar_not_a_image=Каченият файл не е изображение.
no_custom_avatar_available=Невъзможно използване на външен аватар, защото не е активирано.
update_avatar_success=Настройките на аватара са запазени успешно.
change_password=Промяна на собствената парола
@@ -271,6 +274,7 @@ new_password=Нова парола
retype_new_password=Повторно новата парола
password_incorrect=Въведената парола не е вярна.
change_password_success=Вашата парола е променена успешно. Вече може да влизате, използвайки тази нова парола.
password_change_disabled=Нелокални потребители не могат да променят паролата си от тук.
emails=Адреси на ел. поща
manage_emails=Управление на адреси на ел. поща
@@ -302,26 +306,26 @@ ssh_key_deletion_desc=При изтриване на този SSH ключ ще
ssh_key_deletion_success=SSH ключа беше изтрит успешно!
add_on=Добавен на
last_used=Последно използван на
no_activity=Няма скорошна активност
no_activity=Няма скорошна дейност
key_state_desc=Този ключ е използван през последните 7 дни
token_state_desc=Този токен е използван през последните 7 дни
token_state_desc=Този API ключ е използван през последните 7 дни
manage_social=Управление на свързани профили в социалните мрежи
social_desc=Това е списък на свързани профили в социалните мрежи. Премахнете всички, които не разпознавате.
unbind=Освобождаване
unbind_success=Социалния профил е освободен.
manage_access_token=Управление на индивидуални токени за достъп
generate_new_token=Генериране на нов токен
tokens_desc=Генерирани токени, които могат да се използват за достъп до API-то на Gogs.
new_token_desc=Всеки токен ще има пълен достъп до Вашия профил.
token_name=Име на токена
generate_token=Генериране на токен
generate_token_succees=Успешно е генериран токен за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново!
manage_access_token=Управление на индивидуални API ключове за достъп
generate_new_token=Генериране на нов API ключ
tokens_desc=Генерирани API ключове, които могат да се използват за достъп до API на Gogs.
new_token_desc=Всеки API ключ ще има пълен достъп до Вашия профил.
token_name=Име на API ключ
generate_token=Генериране на API ключ
generate_token_succees=Успешно е генериран API ключ за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново!
delete_token=Изтрий
access_token_deletion=Изтрий индивидуален токен за достъп
access_token_deletion_desc=При изтриване на този индивидуален токен за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите?
delete_token_success=Индивидуалния токен за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също.
access_token_deletion=Изтрий индивидуален API ключ за достъп
access_token_deletion_desc=При изтриване на този индивидуален API ключ за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите?
delete_token_success=Индивидуалният API ключ за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също.
delete_account=Изтриване на собствения профил
delete_prompt=Тази операция ще изтрие Вашия профил завинаги и тя <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие!
@@ -352,10 +356,13 @@ auto_init=Инициализиране на това хранилище с из
create_repo=Създай хранилище
default_branch=Клон по подразбиране
mirror_interval=Интервал на отразяване (часове)
mirror_address=Адрес на огледало
mirror_address_desc=Моля включете потребител и парола в адреса ако са нужни.
watchers=Наблюдаващи
stargazers=Харесващи
forks=Разклонения
form.reach_limit_of_creation=Притежателят е достигнал настроения лимит от %d брой хранилища.
form.name_reserved=Името на хранилището '%s' е запазено.
form.name_pattern_not_allowed=Име на хранилището от вида '%s' не е позволено.
@@ -369,17 +376,18 @@ migrate.permission_denied=Недостатъчни права за импорт
migrate.invalid_local_path=Невалиден път - не съществува или не е директория.
migrate.failed=Грешка при миграция: %v
mirror_from=огледало от
forked_from=разклонено от
fork_from_self=Не можете да разклоните хранилище което си е Ваше!
copy_link=Копирай
copy_link_success=Копирано!
copy_link_error=Натиснете ⌘-C или Ctrl-C за да копирате
copied=Успешно копиране
unwatch=Не следи
watch=Следи
unwatch=Не наблюдавам
watch=Наблюдаван
unstar=Не харесвам
star=Харесвам
fork=Разклонение
star=Харесван
fork=Разклонения
no_desc=Няма описание
quick_guide=Бърз справочник
@@ -388,20 +396,21 @@ create_new_repo_command=Създай ново хранилище чрез ком
push_exist_repo=Предай съществуващо хранилище през командния ред
repo_is_empty=Това хранилище е празно. Моля проверете по-късно пак!
code=Код
branch=Клон
tree=ИН на ревизия
filter_branch_and_tag=Филтър по маркер или клон
branches=Клонове
tags=Маркери
issues=Проблеми
pulls=Заявки сливане
issues=Задачи
pulls=Заявки за сливане
labels=Етикети
milestones=Етапи
commits=Ревизии
releases=Издания
file_raw=Изходен файл
releases=Версии
file_raw=Директен файл
file_history=История
file_view_raw=Виж изходен файл
file_view_raw=Виж директен файл
file_permalink=Постоянна връзка
commits.commits=Ревизии
@@ -413,7 +422,7 @@ commits.date=Дата
commits.older=По-стари
commits.newer=По-нови
issues.new=Нов проблем
issues.new=Нова задача
issues.new.labels=Етикети
issues.new.no_label=Няма етикет
issues.new.clear_labels=Изчисти етикети
@@ -425,7 +434,7 @@ issues.new.closed_milestone=Затворени етапи
issues.new.assignee=Изпълнител
issues.new.clear_assignee=Изчисти изпълнител
issues.new.no_assignee=Няма изпълнител
issues.create=Докладвай проблем
issues.create=Създай задача
issues.new_label=Нов етикет
issues.new_label_placeholder=Име на етикета...
issues.create_label=Създай етикет
@@ -438,7 +447,7 @@ issues.filter_milestone_no_select=Липсва избран етап
issues.filter_assignee=Изпълнител
issues.filter_assginee_no_select=Няма избран изпълнител
issues.filter_type=Тип
issues.filter_type.all_issues=Всички проблеми
issues.filter_type.all_issues=Всички задачи
issues.filter_type.assigned_to_you=Възложени на Вас
issues.filter_type.created_by_you=Създадени от Вас
issues.filter_type.mentioning_you=Споменават лично
@@ -465,9 +474,9 @@ issues.reopen_comment_issue=Kоментирай и oтвори отново
issues.create_comment=Коментирай
issues.closed_at=`затвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`повторно отвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`посочи този проблем от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`посочи тази задача от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Участник
issues.admin=Администратор
issues.collaborator=Сътрудник
issues.owner=Притежател
issues.sign_up_for_free=Регистрирай се безплатно
issues.sign_in_require_desc=за да се включите в този разговор. Вече имате профил? <a href="%s">Влезте, за да коментирате</a>
@@ -477,13 +486,14 @@ issues.save=Запис
issues.label_title=Име на етикета
issues.label_color=Цвят на етикет
issues.label_count=%d етикети
issues.label_open_issues=%d отворени проблема
issues.label_open_issues=%d отворени задачи
issues.label_edit=Редакция
issues.label_delete=Изтрий
issues.label_modify=Промяна на етикет
issues.label_deletion=Изтрий етикет
issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани проблеми. Желаете ли да продължите?
issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани задачи. Желаете ли да продължите?
issues.label_deletion_success=Етикетът е изтрит успешно!
issues.num_participants=%d участника
pulls.new=Нова заявка за сливане
pulls.compare_changes=Сравни промените
@@ -505,9 +515,9 @@ pulls.merged=Обединени
pulls.has_merged=Тази заявка за сливане е обединена успешно!
pulls.data_broken=Данните от тази заявка за сливане са невалидни поради изтрита информация за някое разклонение.
pulls.is_checking=Проверката за конфликт все още е в ход. Моля обновете страницата след малко.
pulls.can_auto_merge_desc=Можете да извършвате авто-обединяване на тази заявка за сливане.
pulls.cannot_auto_merge_desc=Не можете да извършите авто-обединяване, защото съществуват конфликти между ревизиите.
pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да отстраните проблема.
pulls.can_auto_merge_desc=Може да се извърши обединяване на тази заявка за сливане.
pulls.cannot_auto_merge_desc=Не може да се извърши обединяване, защото съществуват конфликти между ревизиите.
pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да разрешите конфликтите.
pulls.merge_pull_request=Обедини заявка за сливане
pulls.open_unmerged_pull_exists=`Невъзможно повторно отваряне, защото вече съществува заявка за сливане (#%d) от същото хранилище със същата информация за обединяване, която чака да бъде извършена`
@@ -518,7 +528,7 @@ milestones.closed=Затворен %s
milestones.no_due_date=Няма краен срок
milestones.open=Отвори
milestones.close=Затвори
milestones.new_subheader=Създайте етапи за да организирате проблемите.
milestones.new_subheader=Създайте етапи за да организирате задачите.
milestones.create=Създай етап
milestones.title=Заглавие
milestones.desc=Описание
@@ -532,32 +542,70 @@ milestones.cancel=Отказ
milestones.modify=Промяна на етап
milestones.edit_success=Промените в етап '%s' са запазени успешно!
milestones.deletion=Изтрий етап
milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани проблеми. Желаете ли да продължите?
milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани задачи. Желаете ли да продължите?
milestones.deletion_success=Етапът е изтрит успешно!
wiki=Уики
wiki.welcome=Добре дошли в Уики!
wiki.welcome_desc=Уики е място, където заедно можете да документирате проекта си, за да го направите по-добър.
wiki.create_first_page=Създай първата страница
wiki.page=Страница
wiki.filter_page=Филтър страница
wiki.new_page=Създай нова страница
wiki.default_commit_message=Напишете описание на тази модификация (опционално).
wiki.save_page=Запис на страница
wiki.last_commit_info=%s редактира тази страница %s
wiki.edit_page_button=Редакция
wiki.new_page_button=Нова страница
wiki.delete_page_button=Изтрий страница
wiki.delete_page_notice_1=Това ще изтрие страница <code>"%s"</code>. Моля, бъдете сигурни.
wiki.page_already_exists=Страница със същото име вече съществува.
wiki.pages=Страници
wiki.last_updated=Последна модификация на %s
settings=Настройки
settings.options=Опции
settings.collaboration=Сътрудничество
settings.hooks=Уеб-куки
settings.githooks=Git куки
settings.basic_settings=Основни настройки
settings.danger_zone=Опасна зона
settings.site=Официален сайт
settings.update_settings=Обнови настройките
settings.update_settings=Запази настройките
settings.change_reponame_prompt=Тази промяна ще засегне връзките, които се отнасят до това хранилището.
settings.advanced_settings=Разширени настройки
settings.wiki_desc=Включва уики за да може потребителите да създават документи
settings.use_external_wiki=Използвай външно уики
settings.external_wiki_url=URL адрес на външно уики
settings.external_wiki_url_desc=Посетителите ще бъдат пренасочени към този URL адрес от връзката за раздел уики.
settings.issues_desc=Включва вградена система за проследяване на задачи
settings.use_external_issue_tracker=Използвай външна система за проследяване на задачи
settings.tracker_url_format=Формат на URL адрес на външна система за проследяване на задачи
settings.tracker_url_format_desc=Можете да използвате текстови маркери <code>{user} {repo} {index}</code> за потребителско име, име на хранилище и индекс на задача съответно.
settings.pulls_desc=Включва заявки за сливане за да може да се приемат външни доработки
settings.danger_zone=Опасна зона
settings.new_owner_has_same_repo=Новият притежател вече има хранилище със същото име. Изберете друго име.
settings.convert=Промени към редовно хранилище
settings.convert_desc=Можете да промените това огледало към редовно хранилище. Конверсията не може да се отмени.
settings.convert_notices_1=- Тази операция ще конвертира огледалото към редовно хранилище и не може да бъде отменена в последствие.
settings.convert_confirm=Потвърдете конверсията
settings.convert_succeed=Конверсията към редовно хранилище е извършена успешно.
settings.transfer=Прехвърли притежание
settings.transfer_desc=Прехвърля това хранилище на друг потребител или към организация, в която имате права на администратор.
settings.new_owner_has_same_repo=Новият притежател вече има хранилище със същото име. Изберете друго име.
settings.delete=Изтрий това хранилище
settings.delete_desc=След като изтриете хранилището, няма връщане назад. Моля, бъдете сигурни.
settings.transfer_notices_1=- Вие ще загубите достъп, ако новият притежател е индивидуален потребител.
settings.transfer_notices_2=- Вие ще запазите достъпа си, ако новият притежател е организация и ако вие сте един от притежателите ѝ.
settings.transfer_form_title=Моля въведете следната информация за да потвърдите операцията:
settings.wiki_delete=Изтриване на данни на уики
settings.wiki_delete_desc=След като изтриете данни за уики, няма връщане назад. Моля, бъдете сигурни.
settings.wiki_delete_notices_1=- Това ще изтрие и ще деактивира уики за %s
settings.wiki_deletion_success=Данните за уики на това хранилище са изтрити успешно.
settings.delete=Изтрий това хранилище
settings.delete_desc=След като изтриете хранилището, няма връщане назад. Моля, бъдете сигурни.
settings.delete_notices_1=- Тази операция <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие.
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, проблеми, коментари и достъпа на сътрудници.
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, задачи, коментари и достъпа на сътрудници.
settings.delete_notices_fork_1=- Ако това хранилище е публично, всички негови разклонения ще останат независими след изтриването му.
settings.delete_notices_fork_2=- Ако това хранилище е частно, всички негови разклонения ще бъдат премахнати по време на изтриването.
settings.delete_notices_fork_3=- Ако желаете да запазите всички разклонения след изтриването му, първо направете хранилището публично.
settings.deletion_success=Хранилището е изтрито успешно!
settings.update_settings_success=Настройките на хранилището са запазени успешно.
settings.transfer_owner=Нов притежател
settings.make_transfer=Прехвърли
@@ -565,14 +613,21 @@ settings.transfer_succeed=Притежанието на хранилището
settings.confirm_delete=Потвърди изтриването
settings.add_collaborator=Добави нов сътрудник
settings.add_collaborator_success=Добавен е нов сътрудник.
settings.delete_collaborator=Премахни
settings.collaborator_deletion=Премахване на сътрудник
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=Изтрий уеб-кука
settings.webhook_deletion_desc=При изтриване на тази уеб-кука ще се премахне информацията за нея и цялата хронология на нейното изпращане. Желаете ли да продължите?
settings.webhook_deletion_success=Уеб-куката е изтрита успешно!
settings.webhook.test_delivery=Тестово изпращане
settings.webhook.test_delivery_desc=Симулира тестово изпращане за тест на настройките на уеб-куката
settings.webhook.test_delivery_success=Тестовата уеб-кука е добавена в опашката за изпращане. Може да отнеме няколко секунди преди да се появи в историята с доставени.
settings.webhook.request=Заявка
settings.webhook.response=Отговор
settings.webhook.headers=Заглавки
@@ -582,7 +637,7 @@ settings.githooks_desc=Git куките се изпълняват от Git. Ви
settings.githook_edit_desc=Ако куката е неактивна, ще бъде представено примерно съдържание. Ако оставите съдържанието празно, то тази кука ще бъде изключена.
settings.githook_name=Име на куката
settings.githook_content=Съдържание на куката
settings.update_githook=Обнови куката
settings.update_githook=Запази куката
settings.add_webhook_desc=Gogs ще изпрати <code>POST</code> заявка към указания URL адрес заедно с информация за събитието, което е настъпило. Също можете да укажете в какъв формат желаете да получите данните при задействане на куката (JSON, x-www-form-urlencoded, XML) и др. Допълнително описание можете да намерите в нашето <a target="_blank" href="%s">Ръководство за уеб-куки</a>.
settings.payload_url=URL адрес на изпращане
settings.content_type=Тип на съдържанието
@@ -601,17 +656,18 @@ settings.event_push_desc=Git предаване към хранилището
settings.active=Активна
settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени.
settings.add_hook_success=Новата уеб-кука е добавена успешно.
settings.update_webhook=Обнови уеб-куката
settings.update_webhook=Запази уеб-куката
settings.update_hook_success=Уеб-куката е запазена успешно.
settings.delete_webhook=Изтрий уеб-куката
settings.recent_deliveries=Последни изпращания
settings.hook_type=Тип на куката
settings.add_slack_hook_desc=Добавяне на интеграция със <a href="%s">Slack</a> във Вашето хранилище.
settings.slack_token=Токен
settings.slack_token=API ключ
settings.slack_domain=Домейн
settings.slack_channel=Канал
settings.deploy_keys=Ключове за внедряване
settings.add_deploy_key=Добави ключ за внедряване
settings.deploy_key_desc=Този ключ за внедряване има права само за четене. Това не е същото като SSH ключове на персонален потребител.
settings.no_deploy_keys=Все още няма настроен никакъв ключ за внедряване.
settings.title=Заглавие
settings.deploy_key_content=Съдържание
@@ -622,24 +678,26 @@ settings.deploy_key_deletion=Изтрий ключ за внедряване
settings.deploy_key_deletion_desc=При изтриването на този ключ за внедряване ще се премахнат свързаните права за достъп до това хранилище. Желаете ли да продължите?
settings.deploy_key_deletion_success=Ключът за внедряване е изтрит успешно!
diff.browse_source=Всички файлове в ревизията
diff.browse_source=Преглед на файлове
diff.parent=родител
diff.commit=ревизия
diff.data_not_available=Няма данни за разлики.
diff.show_diff_stats=Покажи статистика за разликите
diff.show_split_view=Разделен изглед
diff.show_unified_view=Обединен изглед
diff.stats_desc=променени са <strong>%d файла</strong>, в които са <strong>добавени %d</strong> реда и са <strong>изтрити %d</strong> реда
diff.bin=BIN
diff.view_file=Преглед на файла
diff.view_file=Целия файл
release.releases=Издания
release.new_release=Ново издание
release.releases=Версии
release.new_release=Нова версия
release.draft=Чернови
release.prerelease=Предварителни
release.stable=Стабилни
release.edit=редактиране
release.ahead=<strong>%d</strong> ревизии на %s след това издание
release.ahead=<strong>%d</strong> ревизии на %s след тази версия
release.source_code=Изходен код
release.new_subheader=Публикувайте издания на всяка нова итерация.
release.new_subheader=Публикувайте версия на всяка нова итерация.
release.edit_subheader=Подробният журнал на промените ще помогне на потребителите да разберат какви подобрения са направени.
release.tag_name=Име на маркера
release.target=Цел
@@ -649,17 +707,17 @@ release.content=Съдържание
release.write=Редактор
release.preview=Преглед
release.loading=Зареждане...
release.prerelease_desc=Това е предварително издание
release.prerelease_helper=Ние ще отбележим, че това издание не е завършено за употреба.
release.prerelease_desc=Това е предварителна версия
release.prerelease_helper=Ние ще отбележим, че тази версия не е готова за продукционна употреба.
release.cancel=Отказ
release.publish=Публикувай издание
release.publish=Публикувай версия
release.save_draft=Запис на чернова
release.edit_release=Редактирай издание
release.delete_release=Изтриване на това издание
release.deletion=Изтрий изданието
release.deletion_desc=При изтриване на това издание ще се премахне съответния Git маркер. Желаете ли да продължите?
release.deletion_success=Изданието беше изтрито успешно!
release.tag_name_already_exist=Издание с това име на маркер вече съществува.
release.edit_release=Редактирай версия
release.delete_release=Изтриване на тази версия
release.deletion=Изтрий версията
release.deletion_desc=При изтриване на тази версия ще се премахне и съответния Git маркер. Желаете ли да продължите?
release.deletion_success=Версията беше изтрита успешно!
release.tag_name_already_exist=Версия с това име на маркер вече съществува.
release.downloads=Изтегляния
[org]
@@ -689,7 +747,7 @@ settings.options=Опции
settings.full_name=Пълно име
settings.website=Уебсайт
settings.location=Локация
settings.update_settings=Обнови настройките
settings.update_settings=Запази настройките
settings.update_setting_success=Настройките на организацията са запазени успешно.
settings.change_orgname_prompt=Този промяна ще засегне всички връзки сочещи към организацията.
settings.update_avatar_success=Настройките на аватара на организацията са запазени успешно.
@@ -726,7 +784,7 @@ teams.no_desc=Този екип няма описание
teams.settings=Настройки
teams.owners_permission_desc=Притежателите имат пълен достъп до <strong>всички хранилища</strong> и имат <strong>права на администратори</strong> на организацията.
teams.members=Участници в екипа
teams.update_settings=Обнови настройките
teams.update_settings=Запази настройките
teams.delete_team=Изтриване на този екип
teams.add_team_member=Добави участник в екипа
teams.delete_team_title=Изтрий екипа
@@ -757,7 +815,7 @@ total=Общо: %d
dashboard.statistic=Статистика
dashboard.operations=Операции
dashboard.system_status=Наблюдение на системния статус
dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> проблеми, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> издания, <b>%d</b> източници за вписване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове.
dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> задачи, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> версии, <b>%d</b> начини на удостоверяване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове.
dashboard.operation_name=Име на операцията
dashboard.operation_switch=Превключи
dashboard.operation_run=Изпълни
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys=Презапис на ".ssh/authorized_keys" фай
dashboard.resync_all_sshkeys_success=Всички публични ключове са презаписани успешно.
dashboard.resync_all_update_hooks=Презапис на всички куки, закачени на актуализация на хранилищата (необходимо, когато се ползва собствен път за конфигурацията)
dashboard.resync_all_update_hooks_success=Всички куки, закачени на актуализация на хранилищата, са презаписани успешно.
dashboard.reinit_missing_repos=Реинициализира всички записи за хранилища
dashboard.reinit_missing_repos_success=Всички записи за хранилища със загубени Git файлове са реинициализирани успешно.
dashboard.server_uptime=Операционно време
dashboard.current_goroutine=Текущи Goroutines
@@ -816,17 +876,19 @@ users.created=Създаване
users.send_register_notify=Прати уведомление на потребителя при регистрация
users.new_success=Новият профил '%s' е добавен успешно.
users.edit=Редакция
users.auth_source=Източник за удостоверяване
users.auth_source=Начин на удостоверяване
users.local=Локално
users.auth_login_name=Потребителско име за удостоверяване
users.auth_login_name=Потребителско име за вход
users.password_helper=Оставете празна ако не се променя.
users.update_profile_success=Профилът е запазен успешно.
users.edit_account=Редактирай профил
users.max_repo_creation=Макс. брой хранилища
users.max_repo_creation_desc=(Задайте -1 за да се използва глобалния лимит)
users.is_activated=Този профил е активиран
users.is_admin=Този профил има административни права
users.allow_git_hook=Този профил има разрешение да създава Git куки
users.allow_import_local=Този профил има права за импорт на локални хранилища
users.update_profile=Обнови профила
users.update_profile=Запази профила
users.delete_account=Изтрий този профил
users.still_own_repo=Този профил притежава поне едно хранилище. Първо трябва да изтриете хранилището или да го прехвърлите на друг потребител.
users.still_has_org=Този профил участва в поне една организация. Първо трябва да напуснете или изтриете тези организации.
@@ -843,10 +905,10 @@ repos.name=Име
repos.private=Частно
repos.watches=Наблюдавания
repos.stars=Харесвания
repos.issues=Проблеми
repos.issues=Задачи
auths.auth_manage_panel=Управление на удостоверявания
auths.new=Добави нов източник за удостоверяване
auths.new=Добави нов начин на удостоверяване
auths.name=Име
auths.type=Тип
auths.enabled=Активно
@@ -861,9 +923,12 @@ auths.bind_password=Парола за свръзка
auths.bind_password_helper=Внимание: Тази парола се запазва некриптирана. Моля използвайте потребител, който няма административен достъп.
auths.user_base=Базов OU за търсене
auths.user_dn=Име (DN) на потребител
auths.attribute_username=Атрибут за име
auths.attribute_username_placeholder=Оставете празно за да използва потребителското име от форма за вписване.
auths.attribute_name=Атрибут за име
auths.attribute_surname=Атрибут за фамилия
auths.attribute_mail=Атрибут за ел. поща
auths.attributes_in_bind=Извличане на атрибути от контекста на име (DN) за свръзка
auths.filter=Филтър за потребител
auths.admin_filter=Филтър за администратор
auths.ms_ad_sa=Ms Ad SA
@@ -881,10 +946,11 @@ auths.edit=Редактирай настройки за удостоверява
auths.activated=Това удостоверяване е активно
auths.new_success=Новото удостоверяване '%s' е добавено успешно.
auths.update_success=Настройките за удостоверяване са запазени успешно.
auths.update=Обнови настройки за удостоверяване
auths.update=Запази настройки за удостоверяване
auths.delete=Изтриване на това удостоверяване
auths.delete_auth_title=Изтрий удостоверяването
auths.delete_auth_desc=Това удостоверяване ще бъде изтрито. Желаете ли да продължите?
auths.still_in_used=Това удостоверяване все още се използва от някои потребители. Моля изтрийте ги или ги конвертирайте до друг тип на влизане първо.
auths.deletion_success=Удостоверяването е изтрито успешно!
config.server_config=Сървърни настройки
@@ -901,6 +967,19 @@ config.static_file_root_path=Път към статични файлове
config.log_file_root_path=Път към журнал
config.script_type=Тип на скрипта
config.reverse_auth_user=Потребителско име при обратно удостоверяване
config.ssh_config=SSH конфигурация
config.ssh_enabled=Активен
config.ssh_start_builtin_server=Стартирай вграден сървър
config.ssh_domain=Домейн
config.ssh_port=Порт
config.ssh_listen_port=Порт за слушане
config.ssh_root_path=Основен път
config.ssh_key_test_path=Път до ключове
config.ssh_keygen_path=Път до генератор ('ssh-keygen')
config.ssh_minimum_key_size_check=Проверка за минимален размер на ключове
config.ssh_minimum_key_sizes=Минимален размер на ключове
config.db_config=Настройки на базата данни
config.db_type=Тип
config.db_host=Сървър
@@ -915,7 +994,6 @@ config.register_email_confirm=Изисквай потвърждение на а
config.disable_register=Изключи нови регистрации
config.show_registration_button=Покажи бутон за регистрация
config.require_sign_in_view=Изисквай вписване за преглед
config.enable_cache_avatar=Включи кеширане на аватари
config.mail_notify=Уведомяване по ел. поща
config.disable_key_size_check=Изключи проверка минимален размер на ключ
config.enable_captcha=Включи Captcha
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Изключи HELO
config.mailer_name=Име
config.mailer_host=Сървър
config.mailer_user=Потребител
config.send_test_mail=Изпрати тестово писмо
config.test_mail_failed=Невъзможно изпращане на тестово писмо до '%s': %v
config.test_mail_sent=Тестово писмо беше изпратено до '%s'.
config.oauth_config=OAuth конфигурация
config.oauth_enabled=Активна
config.cache_config=Конфигурация на кеша
@@ -964,23 +1045,34 @@ monitor.start=Начален час
monitor.execute_time=Време за изпълнение
notices.system_notice_list=Системни известия
notices.view_detail_header=Преглед на детайли на съобщение
notices.actions=Действия
notices.select_all=Избери всички
notices.deselect_all=Без избрани
notices.inverse_selection=Обърни избора
notices.delete_selected=Изтрий избраните
notices.delete_all=Изтрий всички съобщения
notices.type=Тип
notices.type_1=Хранилище
notices.desc=Описание
notices.op=Oп.
notices.delete_success=Системното съобщение е изтрито успешно.
notices.delete_success=Системните съобщения са изтрити успешно.
[action]
create_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>
create_issue=`отвори проблем <a href="%s/issues/%s">%s#%[2]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>`
create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментира проблем <a href="%s/issues/%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>
push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a>
compare_2_commits=Сравнение между тези 2 ревизии
compare_commits=Сравнение между тези %d ревизии
[tool]
ago=преди

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ user_profile_and_more = User profile and more
signed_in_as = Signed in as
username = Username
email = E-mail
email = Email
password = Password
re_type = Re-Type
captcha = Captcha
@@ -28,6 +28,7 @@ organization = Organization
mirror = Mirror
new_repo = New Repository
new_migrate = New Migration
new_mirror = New Mirror
new_fork = New Fork Repository
new_org = New Organization
manage_org = Manage Organizations
@@ -37,7 +38,7 @@ settings = Settings
your_profile = Your Profile
your_settings = Your Settings
news_feed = News Feed
activities = Activities
pull_requests = Pull Requests
issues = Issues
@@ -64,7 +65,7 @@ db_name = Database Name
db_helper = Please use INNODB engine with utf8_general_ci charset for MySQL.
ssl_mode = SSL Mode
path = Path
sqlite_helper = The file path of SQLite3 or TiDB database.
sqlite_helper = The file path of SQLite3 or TiDB database. <br>Please use absolute path when you start as service.
err_empty_db_path = SQLite3 or TiDB database path cannot be empty.
err_invalid_tidb_name = TiDB database name does not allow characters "." and "-".
no_admin_and_disable_registration = You cannot disable registration without creating an admin account.
@@ -84,14 +85,16 @@ ssh_port_helper = Port number which your SSH server is using, leave it empty to
http_port = HTTP Port
http_port_helper = Port number which application will listen on.
app_url = Application URL
app_url_helper = This affects HTTP/HTTPS clone URL and somewhere in e-mail.
app_url_helper = This affects HTTP/HTTPS clone URL and somewhere in email.
log_root_path = Log Path
log_root_path_helper = Directory to write log files to.
optional_title = Optional Settings
email_title = E-mail Service Settings
email_title = Email Service Settings
smtp_host = SMTP Host
smtp_from = From
smtp_from_helper = Mail from address, RFC 5322. It can be just an email address, or the "Name" <email@example.com> format.
mailer_user = Sender E-mail
mailer_user = Sender Email
mailer_password = Sender Password
register_confirm = Enable Register Confirmation
mail_notify = Enable Mail Notification
@@ -111,7 +114,7 @@ admin_title = Admin Account Settings
admin_name = Username
admin_password = Password
confirm_password = Confirm Password
admin_email = Admin E-mail
admin_email = Admin Email
install_gogs = Install Gogs
test_git_failed = Fail to test 'git' command: %v
sqlite3_not_available = Your release version does not support SQLite3, please download the official binary version from %s, NOT the gobuild version.
@@ -121,9 +124,10 @@ run_user_not_match = Run user isn't the current user: %s -> %s
save_config_failed = Fail to save configuration: %v
invalid_admin_setting = Admin account setting is invalid: %v
install_success = Welcome! We're glad that you chose Gogs, have fun and take care.
invalid_log_root_path = Log root path is invalid: %v
[home]
uname_holder = Username or E-mail
uname_holder = Username or email
password_holder = Password
switch_dashboard_context = Switch Dashboard Context
my_repos = My Repositories
@@ -147,13 +151,13 @@ remember_me = Remember Me
forgot_password= Forgot Password
forget_password = Forgot password?
sign_up_now = Need an account? Sign up now.
confirmation_mail_sent_prompt = A new confirmation e-mail has been sent to <b>%s</b>, please check your inbox within the next %d hours to complete the registration process.
confirmation_mail_sent_prompt = A new confirmation email has been sent to <b>%s</b>, please check your inbox within the next %d hours to complete the registration process.
active_your_account = Activate Your Account
resent_limit_prompt = Sorry, you already requested an activation email recently. Please wait 3 minutes then try again.
has_unconfirmed_mail = Hi %s, you have an unconfirmed e-mail address (<b>%s</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click on the button below.
resend_mail = Click here to resend your activation e-mail
email_not_associate = This e-mail address is not associated with any account.
send_reset_mail = Click here to (re)send your password reset e-mail
has_unconfirmed_mail = Hi %s, you have an unconfirmed email address (<b>%s</b>). If you haven't received a confirmation email or need to resend a new one, please click on the button below.
resend_mail = Click here to resend your activation email
email_not_associate = This email address is not associated with any account.
send_reset_mail = Click here to (re)send your password reset email
reset_password = Reset Your Password
invalid_code = Sorry, your confirmation code has expired or not valid.
reset_password_helper = Click here to reset your password
@@ -161,9 +165,9 @@ password_too_short = Password length cannot be less then 6.
[mail]
activate_account = Please activate your account
activate_email = Verify your e-mail address
activate_email = Verify your email address
reset_password = Reset your password
register_success = Register success, Welcome
register_success = Registration successful, welcome
register_notify = Welcome on board
[modal]
@@ -174,7 +178,7 @@ modify = Modify
[form]
UserName = Username
RepoName = Repository name
Email = E-mail address
Email = Email address
Password = Password
Retype = Re-type password
SSHTitle = SSH key name
@@ -182,7 +186,7 @@ HttpsUrl = HTTPS URL
PayloadUrl = Payload URL
TeamName = Team name
AuthName = Authorization name
AdminEmail = Admin E-mail
AdminEmail = Admin email
require_error = ` cannot be empty.`
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
@@ -190,19 +194,18 @@ alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot chara
size_error = ` must be size %s.`
min_size_error = ` must contain at least %s characters.`
max_size_error = ` must contain at most %s characters.`
email_error = ` is not a valid e-mail address.`
email_error = ` is not a valid email address.`
url_error = ` is not a valid URL.`
include_error = ` must contain substring '%s'.`
unknown_error = Unknown error:
captcha_incorrect = Captcha didn't match.
password_not_match = Password and confirm password are not same.
username_been_taken = Username has been already taken.
repo_name_been_taken = Repository name has been already taken.
org_name_been_taken = Organization name has been already taken.
team_name_been_taken = Team name has been already taken.
email_been_used = E-mail address has been already used.
illegal_team_name = Team name contains illegal characters.
username_been_taken = Username has already been taken.
repo_name_been_taken = Repository name has already been taken.
org_name_been_taken = Organization name has already been taken.
team_name_been_taken = Team name has already been taken.
email_been_used = Email address has already been used.
username_password_incorrect = Username or password is not correct.
enterred_invalid_repo_name = Please make sure that the repository name you entered is correct.
enterred_invalid_owner_name = Please make sure that the owner name you entered is correct.
@@ -216,9 +219,7 @@ auth_failed = Authentication failed: %v
still_own_repo = Your account still has ownership over at least one repository, you have to delete or transfer them first.
still_has_org = Your account still has membership in at least one organization, you have to leave or delete your memberships first.
org_still_own_repo = This organization still have ownership of repository, you have to delete or transfer them first.
still_own_user = This authentication still is in use by at least one user, please remove them from the authentication and try again.
org_still_own_repo = This organization still has ownership of repositories, you must delete or transfer them first.
target_branch_not_exist = Target branch does not exist.
@@ -229,8 +230,10 @@ join_on = Joined on
repositories = Repositories
activity = Public Activity
followers = Followers
starred = Starred
starred = Starred repositories
following = Following
follow = Follow
unfollow = Unfollow
form.name_reserved = Username '%s' is reserved.
form.name_pattern_not_allowed = Username pattern '%s' is not allowed.
@@ -246,7 +249,8 @@ delete = Delete Account
uid = Uid
public_profile = Public Profile
profile_desc = Your E-mail address is public and will be used for any account related notifications, and any web based operations made via the site.
profile_desc = Your email address is public and will be used for any account related notifications, and any web based operations made via the site.
password_username_disabled = Non-local type users are not allowed to change their username.
full_name = Full Name
website = Website
location = Location
@@ -258,11 +262,10 @@ continue = Continue
cancel = Cancel
enable_custom_avatar = Enable Custom Avatar
enable_custom_avatar_helper = Disable fetch from Gravatar
choose_new_avatar = Choose new avatar
update_avatar = Update Avatar Setting
delete_current_avatar = Delete Current Avatar
uploaded_avatar_not_a_image = Uploaded file is not a image.
no_custom_avatar_available = No custom avatar available, cannot enable it.
update_avatar_success = Your avatar setting has been updated successfully.
change_password = Change Password
@@ -271,28 +274,29 @@ new_password = New Password
retype_new_password = Retype New Password
password_incorrect = Current password is not correct.
change_password_success = Your password was successfully changed. You can now sign using this new password.
password_change_disabled = Non-local type users are not allowed to change their password.
emails = E-mail Addresses
manage_emails = Manage e-mail addresses
email_desc = Your primary e-mail address will be used for notifications and other operations.
emails = Email Addresses
manage_emails = Manage email addresses
email_desc = Your primary email address will be used for notifications and other operations.
primary = Primary
primary_email = Set as primary
delete_email = Delete
email_deletion = E-mail Deletion
email_deletion_desc = Delete this e-mail address will remove related information from your account. Do you want to continue?
email_deletion_success = E-mail has been deleted successfully!
add_new_email = Add new e-mail address
add_email = Add e-mail
add_email_confirmation_sent = A new confirmation e-mail has been sent to '%s', please check your inbox within the next %d hours to complete the confirmation process.
add_email_success = Your new E-mail address was successfully added.
email_deletion = Email Deletion
email_deletion_desc = Deleting this email address will remove related information from your account. Do you want to continue?
email_deletion_success = Email has been deleted successfully!
add_new_email = Add new email address
add_email = Add email
add_email_confirmation_sent = A new confirmation email has been sent to '%s', please check your inbox within the next %d hours to complete the confirmation process.
add_email_success = Your new email address was successfully added.
manage_ssh_keys = Manage SSH Keys
add_key = Add Key
ssh_desc = This is a list of SSH keys associated with your account. As these keys allow anyone using them to gain access to your repositories, it is highly important that you make sure you recognize them.
ssh_helper = <strong>Don't know how?</strong> Check out GitHub's guide to <a href="%s">create your own SSH keys</a> or solve <a href="%s">common problems</a> you might encounter using SSH.
add_new_key = Add SSH Key
ssh_key_been_used = Public key content has been used.
ssh_key_name_used = Public key with same name has already existed.
ssh_key_been_used = Public key content has been used.
ssh_key_name_used = Public key with same name has already existed.
key_name = Key Name
key_content = Content
add_key_success = New SSH key '%s' has been added successfully!
@@ -352,10 +356,13 @@ auto_init = Initialize this repository with selected files and template
create_repo = Create Repository
default_branch = Default Branch
mirror_interval = Mirror Interval (hour)
mirror_address = Mirror Address
mirror_address_desc = Please include necessary user credentials in the address.
watchers = Watchers
stargazers = Stargazers
forks = Forks
form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
form.name_reserved = Repository name '%s' is reserved.
form.name_pattern_not_allowed = Repository name pattern '%s' is not allowed.
@@ -369,8 +376,9 @@ migrate.permission_denied = You are not allowed to import local repositories.
migrate.invalid_local_path = Invalid local path, it does not exist or not a directory.
migrate.failed = Migration failed: %v
mirror_from = mirror of
forked_from = forked from
fork_from_self = You cannot fork repository you already owned!
fork_from_self = You cannot fork a repository you already own!
copy_link = Copy
copy_link_success = Copied!
copy_link_error = Press ⌘-C or Ctrl-C to copy
@@ -388,6 +396,7 @@ create_new_repo_command = Create a new repository on the command line
push_exist_repo = Push an existing repository from the command line
repo_is_empty = This repository is empty, please come back later!
code = Code
branch = Branch
tree = Tree
filter_branch_and_tag = Filter branch or tag
@@ -467,7 +476,7 @@ issues.closed_at = `closed <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at = `reopened <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at = `referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster = Poster
issues.admin = Admin
issues.collaborator = Collaborator
issues.owner = Owner
issues.sign_up_for_free = Sign up for free
issues.sign_in_require_desc = to join this conversation. Already have an account? <a href="%s">Sign in to comment</a>
@@ -482,8 +491,9 @@ issues.label_edit = Edit
issues.label_delete = Delete
issues.label_modify = Label Modification
issues.label_deletion = Label Deletion
issues.label_deletion_desc = Delete this label will remove its information in all related issues. Do you want to continue?
issues.label_deletion_desc = Deleting this label will remove its information in all related issues. Do you want to continue?
issues.label_deletion_success = Label has been deleted successfully!
issues.num_participants = %d Participants
pulls.new = New Pull Request
pulls.compare_changes = Compare Changes
@@ -505,9 +515,9 @@ pulls.merged = Merged
pulls.has_merged = This pull request has been merged successfully!
pulls.data_broken = Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking = The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc = You can perform auto-merge operation on this pull request.
pulls.cannot_auto_merge_desc = You can't perform auto-merge operation because there are conflicts between commits.
pulls.cannot_auto_merge_helper = Please use command line tool to solve it.
pulls.can_auto_merge_desc = This pull request can be merged automatically.
pulls.cannot_auto_merge_desc = This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper = Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request = Merge Pull Request
pulls.open_unmerged_pull_exists = `You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@@ -515,7 +525,7 @@ milestones.new = New Milestone
milestones.open_tab = %d Open
milestones.close_tab = %d Closed
milestones.closed = Closed %s
milestones.no_due_date = No due date
milestones.no_due_date = No due date
milestones.open = Open
milestones.close = Close
milestones.new_subheader = Create milestones to organize your issues.
@@ -527,37 +537,75 @@ milestones.clear = Clear
milestones.invalid_due_date_format = Due date format is invalid, must be 'yyyy-mm-dd'.
milestones.create_success = Milestone '%s' has been created successfully!
milestones.edit = Edit Milestone
milestones.edit_subheader = Use better description for milestones so people won't be confused.
milestones.edit_subheader = Use a better description for milestones so people won't be confused.
milestones.cancel = Cancel
milestones.modify = Modify Milestone
milestones.edit_success = Changes of milestone '%s' has been saved successfully!
milestones.deletion = Milestone Deletion
milestones.deletion_desc = Delete this milestone will remove its information in all related issues. Do you want to continue?
milestones.deletion_desc = Deleting this milestone will remove its information in all related issues. Do you want to continue?
milestones.deletion_success = Milestone has been deleted successfully!
wiki = Wiki
wiki.welcome = Welcome to Wiki!
wiki.welcome_desc = Wiki is the place where you would like to document your project together and make it better.
wiki.create_first_page = Create the first page
wiki.page = Page
wiki.filter_page = Filter page
wiki.new_page = Create New Page
wiki.default_commit_message = Write a note about this update (optional).
wiki.save_page = Save Page
wiki.last_commit_info = %s edited this page %s
wiki.edit_page_button = Edit
wiki.new_page_button = New Page
wiki.delete_page_button = Delete Page
wiki.delete_page_notice_1 = This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists = Wiki page with same name already exists.
wiki.pages = Pages
wiki.last_updated = Last updated %s
settings = Settings
settings.options = Options
settings.collaboration = Collaboration
settings.hooks = Webhooks
settings.githooks = Git Hooks
settings.basic_settings = Basic Settings
settings.danger_zone = Danger Zone
settings.site = Official Site
settings.update_settings = Update Settings
settings.change_reponame_prompt = This change will affect how links relate to the repository.
settings.advanced_settings = Advanced Settings
settings.wiki_desc = Enable wiki to allow people write documents
settings.use_external_wiki = Use external wiki
settings.external_wiki_url = External Wiki URL
settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab.
settings.issues_desc = Enable builtin lightweight issue tracker
settings.use_external_issue_tracker = Use external issue tracker
settings.tracker_url_format = External Issue Tracker URL Format
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.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.
settings.convert_notices_1 = - This operation will convert this repository mirror into a regular repository and cannot be undone.
settings.convert_confirm = Confirm Conversion
settings.convert_succeed = Repository has been converted to regular type successfully.
settings.transfer = Transfer Ownership
settings.transfer_desc = Transfer this repository to another user or to an organization in which you have admin rights.
settings.new_owner_has_same_repo = The new owner already has a repository with same name. Please choose another name.
settings.delete = Delete This Repository
settings.delete_desc = Once you delete a repository, there is no going back. Please be certain.
settings.transfer_notices_1 = - You will lose access if new owner is a individual user.
settings.transfer_notices_2 = - You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title = Please enter following information to confirm your operation:
settings.transfer_form_title = Please enter following information to confirm your operation:
settings.wiki_delete = Erase Wiki Data
settings.wiki_delete_desc = Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1 = - This will delete and disable the wiki for %s
settings.wiki_deletion_success = Repository wiki data have been erased successfully.
settings.delete = Delete This Repository
settings.delete_desc = Once you delete a repository, there is no going back. Please be certain.
settings.delete_notices_1 = - This operation <strong>CANNOT</strong> be undone.
settings.delete_notices_2 = - This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1 = - If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_1 = - If this repository is public, all forks will become independent after deletion.
settings.delete_notices_fork_2 = - If this repository is private, all forks will be removed at the same time.
settings.delete_notices_fork_3 = - If you want to keep all forks after deletion, please change visibility of this repository to public first.
settings.deletion_success = Repository has been deleted successfully!
settings.update_settings_success = Repository options has been updated successfully.
settings.transfer_owner = New Owner
settings.make_transfer = Make Transfer
@@ -565,14 +613,21 @@ settings.transfer_succeed = Repository ownership has been transferred successful
settings.confirm_delete = Confirm Deletion
settings.add_collaborator = Add New Collaborator
settings.add_collaborator_success = New collaborator has been added.
settings.delete_collaborator = Delete
settings.collaborator_deletion = Collaborator Deletion
settings.collaborator_deletion_desc = This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
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
settings.webhook_deletion_desc = Delete this webhook will remove its information and all delivery history. Do you want to continue?
settings.webhook_deletion_success = Webhook has been deleted successfully!
settings.webhook.test_delivery = Test Delivery
settings.webhook.test_delivery_desc = Send a fake push event delivery to test your webhook settings
settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
settings.webhook.request = Request
settings.webhook.response = Response
settings.webhook.headers = Headers
@@ -612,15 +667,15 @@ settings.slack_domain = Domain
settings.slack_channel = Channel
settings.deploy_keys = Deploy Keys
settings.add_deploy_key = Add Deploy Key
settings.deploy_key_desc = Deploy key only has read-only access. It is not same as personal account SSH keys.
settings.no_deploy_keys = You haven't added any deploy key.
settings.deploy_key_desc = Deploy keys have read-only access. They are not the same as personal account SSH keys.
settings.no_deploy_keys = You haven't added any deploy keys.
settings.title = Title
settings.deploy_key_content = Content
settings.key_been_used = Deploy key content has been used.
settings.key_name_used = Deploy key with same name has already existed.
settings.key_name_used = Deploy key with the same name already exists.
settings.add_key_success = New deploy key '%s' has been added successfully!
settings.deploy_key_deletion = Delete Deploy Key
settings.deploy_key_deletion_desc = Delete this deploy key will remove all related accesses for this repository. Do you want to continue?
settings.deploy_key_deletion_desc = Deleting this deploy key will remove all related accesses for this repository. Do you want to continue?
settings.deploy_key_deletion_success = Deploy key has been deleted successfully!
diff.browse_source = Browse Source
@@ -628,6 +683,8 @@ diff.parent = parent
diff.commit = commit
diff.data_not_available = Diff Data Not Available.
diff.show_diff_stats = Show Diff Stats
diff.show_split_view = Split View
diff.show_unified_view = Unified View
diff.stats_desc = <strong> %d changed files</strong> with <strong>%d additions</strong> and <strong>%d deletions</strong>
diff.bin = BIN
diff.view_file = View File
@@ -651,16 +708,16 @@ release.write = Write
release.preview = Preview
release.loading = Loading...
release.prerelease_desc = This is a pre-release
release.prerelease_helper = Well point out that this release is not production-ready.
release.prerelease_helper = We'll point out that this release is not production-ready.
release.cancel = Cancel
release.publish = Publish Release
release.save_draft = Save Draft
release.edit_release = Edit Release
release.delete_release = Delete This Release
release.deletion = Release Deletion
release.deletion_desc = Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_desc = Deleting this release will delete the corresponding Git tag. Do you want to continue?
release.deletion_success = Release has been deleted successfully!
release.tag_name_already_exist = Release with this tag name has already existed.
release.tag_name_already_exist = Release with this tag name already exists.
release.downloads = Downloads
[org]
@@ -776,6 +833,8 @@ dashboard.resync_all_sshkeys = Rewrite '.ssh/authorized_keys' file (caution: non
dashboard.resync_all_sshkeys_success = All public keys have been rewritten successfully.
dashboard.resync_all_update_hooks = Rewrite all update hook of repositories (needed when custom config path is changed)
dashboard.resync_all_update_hooks_success = All repositories' update hook have been rewritten successfully.
dashboard.reinit_missing_repos = Reinitialize all repository records that lost Git files
dashboard.reinit_missing_repos_success = All repository records that lost Git files have been reinitialized successfully.
dashboard.server_uptime = Server Uptime
dashboard.current_goroutine = Current Goroutines
@@ -798,7 +857,7 @@ dashboard.mspan_structures_obtained = MSpan Structures Obtained
dashboard.mcache_structures_usage = MCache Structures Usage
dashboard.mcache_structures_obtained = MCache Structures Obtained
dashboard.profiling_bucket_hash_table_obtained = Profiling Bucket Hash Table Obtained
dashboard.gc_metadata_obtained = GC Metadada Obtained
dashboard.gc_metadata_obtained = GC Metadata Obtained
dashboard.other_system_allocation_obtained = Other System Allocation Obtained
dashboard.next_gc_recycle = Next GC Recycle
dashboard.last_gc_time = Since Last GC Time
@@ -823,6 +882,8 @@ users.auth_login_name = Authentication Login Name
users.password_helper = Leave it empty to remain unchanged.
users.update_profile_success = Account profile has been updated successfully.
users.edit_account = Edit Account
users.max_repo_creation = Maximum Repository Creation Limit
users.max_repo_creation_desc = (Set -1 to use global default limit)
users.is_activated = This account is activated
users.is_admin = This account has administrator permissions
users.allow_git_hook = This account has permissions to create Git hooks
@@ -862,9 +923,12 @@ auths.bind_password = Bind Password
auths.bind_password_helper = Warning: This password is stored in plain text. Do not use a high privileged account.
auths.user_base = User Search Base
auths.user_dn = User DN
auths.attribute_username = Username attribute
auths.attribute_username_placeholder = Leave empty to use sign-in form field value for user name.
auths.attribute_name = First name attribute
auths.attribute_surname = Surname attribute
auths.attribute_mail = E-mail attribute
auths.attribute_mail = Email attribute
auths.attributes_in_bind = Fetch attributes in Bind DN context
auths.filter = User Filter
auths.admin_filter = Admin Filter
auths.ms_ad_sa = Ms Ad SA
@@ -886,6 +950,7 @@ auths.update = Update Authentication Setting
auths.delete = Delete This Authentication
auths.delete_auth_title = Authentication Deletion
auths.delete_auth_desc = This authentication is going to be deleted, do you want to continue?
auths.still_in_used = This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success = Authentication has been deleted successfully!
config.server_config = Server Configuration
@@ -902,6 +967,19 @@ config.static_file_root_path = Static File Root Path
config.log_file_root_path = Log File Root Path
config.script_type = Script Type
config.reverse_auth_user = Reverse Authentication User
config.ssh_config = SSH Configuration
config.ssh_enabled = Enabled
config.ssh_start_builtin_server = Start Builtin Server
config.ssh_domain = Domain
config.ssh_port = Port
config.ssh_listen_port = Listen Port
config.ssh_root_path = Root Path
config.ssh_key_test_path = Key Test Path
config.ssh_keygen_path = Keygen ('ssh-keygen') Path
config.ssh_minimum_key_size_check = Minimum Key Size Check
config.ssh_minimum_key_sizes = Minimum Key Sizes
config.db_config = Database Configuration
config.db_type = Type
config.db_host = Host
@@ -912,11 +990,10 @@ config.db_ssl_mode_helper = (for "postgres" only)
config.db_path = Path
config.db_path_helper = (for "sqlite3" and "tidb")
config.service_config = Service Configuration
config.register_email_confirm = Require E-mail Confirmation
config.register_email_confirm = Require Email Confirmation
config.disable_register = Disable Registration
config.show_registration_button = Show Register Button
config.require_sign_in_view = Require Sign In View
config.enable_cache_avatar = Enable Cache Avatar
config.mail_notify = Mail Notification
config.disable_key_size_check = Disable Minimum Key Size Check
config.enable_captcha = Enable Captcha
@@ -932,6 +1009,9 @@ config.mailer_disable_helo = Disable HELO
config.mailer_name = Name
config.mailer_host = Host
config.mailer_user = User
config.send_test_mail = Send Test Email
config.test_mail_failed = Fail to send test email to '%s': %v
config.test_mail_sent = Test email has been sent to '%s'.
config.oauth_config = OAuth Configuration
config.oauth_enabled = Enabled
config.cache_config = Cache Configuration
@@ -965,23 +1045,34 @@ monitor.start = Start Time
monitor.execute_time = Execution Time
notices.system_notice_list = System Notices
notices.view_detail_header = View Notice Detail
notices.actions = Actions
notices.select_all = Select All
notices.deselect_all = Deselect All
notices.inverse_selection = Inverse Selection
notices.delete_selected = Delete Selected
notices.delete_all = Delete All Notices
notices.type = Type
notices.type_1 = Repository
notices.desc = Description
notices.op = Op.
notices.delete_success = System notice has been deleted successfully.
notices.delete_success = System notices have been deleted successfully.
[action]
create_repo = created repository <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>
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>`
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>
push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_2_commits = View comparison for these 2 commits
compare_commits = View comparison for these %d commits
[tool]
ago = ago
@@ -1007,5 +1098,5 @@ raw_minutes = minutes
[dropzone]
default_message = Drop files here or click to upload.
invalid_input_type = You can't upload files of this type.
file_too_big = File size({{filesize}} MB) exceeds maximum size({{maxFilesize}} MB).
file_too_big = File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
remove_file = Remove file

View File

@@ -8,7 +8,7 @@ sign_in=Iniciar sesión
sign_out=Cerrar sesión
sign_up=Suscripción
register=Registro
website=Página Web
website=Página web
version=Versión
page=Página
template=Plantilla
@@ -27,8 +27,9 @@ repository=Repositorio
organization=Organización
mirror=Mirror
new_repo=Nuevo repositorio
new_migrate=Nueva Migración
new_fork=Nuevo Fork del Repositorio
new_migrate=Nueva migración
new_mirror=Nueva réplica
new_fork=Nuevo fork del repositorio
new_org=Nueva organización
manage_org=Administrar organizaciones
admin_panel=Panel de administración
@@ -37,7 +38,7 @@ settings=Configuraciones
your_profile=Tu perfil
your_settings=Tu configuración
news_feed=Feed de noticias
activities=Actividad
pull_requests=Pull Requests
issues=Incidencias
@@ -64,7 +65,7 @@ db_name=Nombre de la base de datos
db_helper=Por favor utilice el motor INNODB con la configuración de caracteres utf8_general_ci para MySQL.
ssl_mode=Modo SSL
path=Ruta
sqlite_helper=Ruta del archivo con la base de datos SQLite3 o TiDB.
sqlite_helper=Ruta al archivo de base de datos SQLite3 o TiDB. <br>Por favor, usa una ruta absoluta cuando inicies como servicio.
err_empty_db_path=La ruta a la base de datos SQLite3 o TiDB no puede estar vacía.
err_invalid_tidb_name=El nombre de la base de datos TiDB no puede contener los caracteres "." ni "-".
no_admin_and_disable_registration=No puede deshabilitar el registro sin crear una cuenta de administrador.
@@ -85,9 +86,11 @@ http_port=Puerto HTTP
http_port_helper=Puerto en el que escuchará la aplicación.
app_url=URL de la aplicación
app_url_helper=Esto afecta a las URLs para clonar por HTTP/HTTPS y a algunos correos electrónicos.
log_root_path=Ruta del registro
log_root_path_helper=Directorio donde almacenar los registros.
optional_title=Configuración Opcional
email_title=Configuración del Servicio de Correo
optional_title=Configuración opcional
email_title=Configuración del servicio de correo
smtp_host=SMTP Host
smtp_from=Desde
smtp_from_helper=Remitente del email, RFC 5322. Puede ser solamente una dirección de correo electrónico, o estar en el formato "Nombre" <email@example.com>.
@@ -95,10 +98,10 @@ mailer_user=Remitente del Correo Electrónico
mailer_password=Contraseña del Remitente
register_confirm=Habilitar la Confirmación en el Registro
mail_notify=Habilitar las Notificaciones de Correo
server_service_title=Configuración de Servidor y Otros Servicios
server_service_title=Configuración del servidor y otros servicios
offline_mode=Activar el modo Sin Conexión
offline_mode_popup=Desactivar el CDN incluso en el modo de producción, todos los recursos se servirán localmente.
disable_gravatar=Desactivar el Servicio Gravatar
disable_gravatar=Desactivar el servicio Gravatar
disable_gravatar_popup=Desactivar Gravatar y cualquier otra fuente personalizada. Todos los avatares deben ser cargados por los usuarios o en su defecto se mostrará el avatar predeterminado.
disable_registration=Desactivar Auto-Registro
disable_registration_popup=Desactivar auto-registro del usuario, solo el administrador podrá crear cuentas nuevas.
@@ -107,7 +110,7 @@ enable_captcha_popup=Requiere validar la captcha para el auto-registro de usuari
require_sign_in_view=Activar el Inicio de Sesión obligatorio para Ver Páginas
require_sign_in_view_popup=Solo los usuarios logados pueden ver páginas, los visitantes anónimos solo podrán ver las páginas de login/registro.
admin_setting_desc=No es necesario crear una cuenta de administrador ahora mismo, el usuario que tenga ID=1 obtendrá privilegios de administrador automáticamente.
admin_title=Configuración de la Cuenta de Administrador
admin_title=Configuración de la cuenta de administrador
admin_name=Nombre de usuario
admin_password=Contraseña
confirm_password=Confirmar Contraseña
@@ -121,15 +124,16 @@ run_user_not_match=El usuario que está ejecutando la aplicación no es el usuar
save_config_failed=Error al guardar la configuración: %v
invalid_admin_setting=La configuración de la cuenta de administración es inválida: %v
install_success=Bienvenido! Estamos encantados de que hayas escogido Gogs, diviértete y cuídate.
invalid_log_root_path=La ruta para los registros es inválida: %v
[home]
uname_holder=Nombre de usuario o correo electrónico
password_holder=Contraseña
switch_dashboard_context=Cambiar el contexto del Dashboard
my_repos=Mis Repositorios
collaborative_repos=Repositorios Colaborativos
my_orgs=Mis Organizaciones
my_mirrors=Mis Mirrors
my_repos=Mis repositorios
collaborative_repos=Repositorios colaborativos
my_orgs=Mis organizaciones
my_mirrors=Mis réplicas
view_home=Ver %s
issues.in_your_repos=En tus repositorios
@@ -192,7 +196,7 @@ min_size_error=` debe contener al menos %s caracteres.`
max_size_error=` debe contener como máximo %s caracteres.`
email_error=` no es una dirección de correo válida.`
url_error=` no es una URL válida.`
include_error='debe contener la subcadena '%s'.'
include_error=` debe contener la subcadena '%s'.`
unknown_error=Error desconocido:
captcha_incorrect=El captcha no es válido.
password_not_match=La contraseña de confirmación no coincide.
@@ -202,7 +206,6 @@ repo_name_been_taken=Ya existe un repositorio con este nombre.
org_name_been_taken=Ya existe una organización con este nombre.
team_name_been_taken=Ya existe un equipo con este nombre.
email_been_used=Esta dirección de correo electrónico ya está en uso.
illegal_team_name=El nombre del equipo contiene caracteres inválidos.
username_password_incorrect=Nombre de usuario o contraseña incorrectos.
enterred_invalid_repo_name=Por favor, asegúrate de que has introducido correctamente el nombre del repositorio.
enterred_invalid_owner_name=Por favor, asegúrate de que has introducido correctamente el nombre del propietario.
@@ -218,8 +221,6 @@ still_own_repo=Tu cuenta es la propietaria de uno o más repositorios, tienes qu
still_has_org=Tu cuenta es miembro de una o más organizaciones, tienes que abandonarlas o eliminarlas primero.
org_still_own_repo=Esta organización es dueña de uno o más repositorios, tienes que eliminarlos o transferirlos primero.
still_own_user=Esta autenticación está en uso por algunos usuarios, debes moverlos y antes de eliminarla.
target_branch_not_exist=La rama de destino no existe
[user]
@@ -231,6 +232,8 @@ activity=Actividad pública
followers=Seguidores
starred=Destacados
following=Siguiendo
follow=Seguir
unfollow=Dejar de seguir
form.name_reserved=El usuario '%s' está reservado.
form.name_pattern_not_allowed=El patrón de nombre de usuario '%s' no está permitido.
@@ -242,27 +245,27 @@ ssh_keys=Claves SSH
social=Redes Sociales
applications=Aplicaciones
orgs=Organizaciones
delete=Eliminar Cuenta
delete=Eliminar cuenta
uid=UUID
public_profile=Perfil Público
public_profile=Perfil público
profile_desc=Tu correo electrónico es público y será usado para todas las notificaciones relacionadas con cualquier cuenta y cualquier operación hecha a través de la web.
full_name=Nombre Completo
website=Página Web
password_username_disabled=Los usuarios que no son locales no tienen permitido cambiar su nombre de usuario.
full_name=Nombre completo
website=Página web
location=Localización
update_profile=Actualizar Perfil
update_profile=Actualizar perfil
update_profile_success=Tu perfil se ha actualizado correctamente.
change_username=Nombre de usuario modificado
change_username_prompt=Este cambio afectará a los enlaces que hacen referencia a su cuenta.
continue=Continuar
cancel=Cancelar
enable_custom_avatar=Activar Avatar Personalizado
enable_custom_avatar_helper=Activa esto para desactivar los avatares de Gravatar
enable_custom_avatar=Activar avatar personalizado
choose_new_avatar=Selecciona nuevo avatar
update_avatar=Actualizar Configuración del Avatar
update_avatar=Actualizar configuración del avatar
delete_current_avatar=Eliminar avatar
uploaded_avatar_not_a_image=El archivo enviado no es una imagen.
no_custom_avatar_available=No hay ningún avatar personalizado disponible, no se puede habilitar.
update_avatar_success=La configuración de tu avatar se ha actualizado correctamente.
change_password=Cambiar contraseña
@@ -271,6 +274,7 @@ new_password=Nueva contraseña
retype_new_password=Confirmar nueva contraseña
password_incorrect=Contraseña actual incorrecta.
change_password_success=La contraseña se ha modificado correctamente. Ya puedes iniciar sesión con tu nueva contraseña.
password_change_disabled=Los usuarios que no son locales no tienen permitido cambiar su contraseña.
emails=Direcciones de correo electrónico
manage_emails=Gestionar direcciones de correo electrónico
@@ -278,8 +282,8 @@ email_desc=Tu dirección de correo principal se utilizará para las notificacion
primary=Principal
primary_email=Marcar como principal
delete_email=Eliminar
email_deletion=Eliminación de Correo Electrónico
email_deletion_desc=Al eliminar esta dirección de correo electrónico se eliminará toda la información asociada a esta dirección de correo electrónico. ¿Deseas continuar?
email_deletion=Eliminar correo electrónico
email_deletion_desc=Al eliminar esta dirección de correo electrónico se eliminará toda la información asociada a esta. ¿Deseas continuar?
email_deletion_success=¡El correo electrónico ha sido eliminado correctamente!
add_new_email=Añadir nueva dirección de correo electrónico
add_email=Añadir correo electrónico
@@ -331,10 +335,10 @@ delete_account_desc=Esta cuenta se va a eliminar permanentemente, ¿quieres cont
[repo]
owner=Propietario
repo_name=Nombre del Repositorio
repo_name=Nombre del repositorio
repo_name_helper=Los grandes nombres de repositorios son cortos, memorables y <strong>únicos</strong>.
visibility=Visibilidad
visiblity_helper=Este repositorio es <span class="ui red text">Privado</span>
visiblity_helper=Este repositorio es <span class="ui red text">privado</span>
visiblity_helper_forced=El administrador web ha obligado a todos los repositorios nuevos a ser <span class="ui red text"> privados</span>
visiblity_fork_helper=(Este cambio afectará a todos los forks)
clone_helper=¿Necesitas ayuda con el clone? ¡Consulta la <a target="_blank" href="%s">Ayuda</a>!
@@ -342,37 +346,41 @@ fork_repo=Hacer Fork del repositorio
fork_from=Crear un Fork desde
fork_visiblity_helper=No es posible cambiar la visibilidad de un Fork
repo_desc=Descripción
repo_lang=Idioma
repo_lang=Lenguaje
repo_lang_helper=Seleccione archivo .gitignore
license=Licencia
license_helper=Selecciona un fichero de licencia
readme=Readme
readme_helper=Seleccione una plantilla de archivo readme
auto_init=Inicializar los archivos seleccionados y plantillas de este repositorio
create_repo=Crear Repositorio
create_repo=Crear repositorio
default_branch=Rama por defecto
mirror_interval=Intervalo de mirror(en horas)
mirror_interval=Intervalo de la réplica (en horas)
mirror_address=Dirección de la réplica
mirror_address_desc=Por favor, incluya las credenciales de usuario necesarias en la dirección.
watchers=Seguidores
stargazers=Fans
forks=Forks
form.reach_limit_of_creation=El propietario ha alcanzado el límite máximo de %d repositorios creados.
form.name_reserved=El nombre del repositorio '%s' está reservado.
form.name_pattern_not_allowed=El patrón del nombre del repositorio '%s' no está permitido.
need_auth=Requiere Autorización
migrate_type=Tipo de Migración
migrate_type_helper=Este repositorio será un <span class="text blue">mirror</span>
need_auth=Requiere autorización
migrate_type=Tipo de migración
migrate_type_helper=Este repositorio será una <span class="text blue">réplica</span>
migrate_repo=Migrar Repositorio
migrate.clone_address=Clonar Dirección
migrate.clone_address=Clonar dirección
migrate.clone_address_desc=Puede ser una URL HTTP/HTTPS/GIT o una ruta local del servidor.
migrate.permission_denied=No te está permitido importar repositorios locales.
migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio.
migrate.failed=Migración fallida: %v
mirror_from=espejo de
forked_from=forked de
fork_from_self=Eres el propietario del repositorio, ¡no puedes hacer fork!
copy_link=Copiar
copy_link_success=Copiado!
copy_link_success=¡Copiado!
copy_link_error=Presione ⌘ + C o Ctrl-C para copiar
copied=Copiado correctamente
unwatch=Dejar de vigilar
@@ -388,6 +396,7 @@ create_new_repo_command=Crear un nuevo repositorio desde línea de comandos
push_exist_repo=Hacer Push de un repositorio existente desde línea de comandos
repo_is_empty=Este repositorio está vacío, por favor, ¡vuelva más tarde!
code=Código
branch=Rama
tree=Árbol
filter_branch_and_tag=Filtrar por rama o etiqueta
@@ -413,7 +422,7 @@ commits.date=Fecha
commits.older=Anterior
commits.newer=Posterior
issues.new=Nueva Incidencia
issues.new=Nueva incidencia
issues.new.labels=Etiquetas
issues.new.no_label=Sin etiquetas
issues.new.clear_labels=Limpiar etiquetas
@@ -457,17 +466,17 @@ issues.open_title=Abierta
issues.closed_title=Cerrada
issues.num_comments=%d comentarios
issues.commented_at=`comentada <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.no_content=Aun no existe contenido.
issues.no_content=Aún no existe contenido.
issues.close_issue=Cerrar
issues.close_comment_issue=Comentar y cerrar
issues.reopen_issue=Reabrir
issues.reopen_comment_issue=Comentar y reabrir
issues.create_comment=Comentar
issues.closed_at=`cerrada <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`reabierta <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.closed_at=`cerró <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`reabrió <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`mencionada esta incidencia en un commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Autor
issues.admin=Administrador
issues.collaborator=Colaborador
issues.owner=Propietario
issues.sign_up_for_free=Registro gratuito
issues.sign_in_require_desc=para unirse a esta conversación. ¿Ya dispone de una cuenta? <a href="%s">Inicie sesión para comentar</a>
@@ -484,6 +493,7 @@ issues.label_modify=Edición de Etiqueta
issues.label_deletion=Borrado de Etiqueta
issues.label_deletion_desc=Al borrar la etiqueta su información será eliminada de todas las incidencias relacionadas. Desea continuar?
issues.label_deletion_success=Etiqueta borrada con éxito!
issues.num_participants=%d participantes
pulls.new=Nuevo Pull Request
pulls.compare_changes=Comparar Cambios
@@ -500,14 +510,14 @@ pulls.merged_title_desc=fusionados %[1]d commits de <code>%[2]s</code> en <code>
pulls.tab_conversation=Conversación
pulls.tab_commits=Commits
pulls.tab_files=Archivos modificados
pulls.reopen_to_merge=Por favor reabra este pull request para proceder con la operación de fusionado.
pulls.reopen_to_merge=Por favor reabra este Pull Request para proceder con la operación de fusionado.
pulls.merged=Fuisionado
pulls.has_merged=¡Este pull request se ha completado con éxito!
pulls.data_broken=Los datos de este pull request ya no están disponibles porque se ha eliminado la información del fork.
pulls.is_checking=Se está procediendo a la búsqueda de conflictos, por favor actualice la página en unos momentos.
pulls.can_auto_merge_desc=Puede realizar la operación auto-fusionado en este pull request.
pulls.cannot_auto_merge_desc=No puede realizar la operación de auto-fusionado porque existen conflictos entre los commits.
pulls.cannot_auto_merge_helper=Por favor use la línea de comandos para resolverlo.
pulls.can_auto_merge_desc=Este Pull Request puede ser fusionado automáticamente.
pulls.cannot_auto_merge_desc=Este Pull Request no puede ser fusionado automáticamente porque hay conflictos.
pulls.cannot_auto_merge_helper=Por favor, fusiona manualmente para resolver los conflictos.
pulls.merge_pull_request=Fusionar Pull Request
pulls.open_unmerged_pull_exists=`Usted no puede realizar la operación de reapertura porque en estos momentos existe una solicitud de pull request (#%d) para el mismo repositorio con la misma información que se encuentra a la espera de aprobación`
@@ -532,47 +542,92 @@ milestones.cancel=Cancelar
milestones.modify=Modificar Milestone
milestones.edit_success=¡Los cambios al milestone '%s' se han guardado con éxito!
milestones.deletion=Borrar milestone
milestones.deletion_desc=El borrado de este milestone eliminará su información y las incidencias asociadas. ¿Desea continuar?
milestones.deletion_desc=Eliminar este Milestone eliminará su información y las incidencias asociadas. ¿Desea continuar?
milestones.deletion_success=¡El milestone ha sido eliminado con éxito!
wiki=Wiki
wiki.welcome=¡Bienvenido a la Wiki!
wiki.welcome_desc=La Wiki es el lugar donde os gustaría documentar juntos vuestro proyecto y hacerlo mejor.
wiki.create_first_page=Crear la primera página
wiki.page=Página
wiki.filter_page=Filtrar página
wiki.new_page=Crear nueva página
wiki.default_commit_message=Escribe una nota sobre esta actualización (opcional).
wiki.save_page=Guardar página
wiki.last_commit_info=%s editó esta página %s
wiki.edit_page_button=Editar
wiki.new_page_button=Nueva página
wiki.delete_page_button=Eliminar página
wiki.delete_page_notice_1=Esto eliminará la página <code>"%s"</code>. Por favor, asegúrate de que es lo que quieres.
wiki.page_already_exists=Ya existe una página con el mismo nombre.
wiki.pages=Páginas
wiki.last_updated=Última actualización %s
settings=Configuración
settings.options=Opciones
settings.collaboration=Colaboración
settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Configuración Básica
settings.danger_zone=Zona de Peligro
settings.site=Sitio Oficial
settings.update_settings=Actualizar Configuración
settings.site=Sitio oficial
settings.update_settings=Actualizar configuración
settings.change_reponame_prompt=Este cambio afectará a los enlaces al repositorio.
settings.transfer=Transferir la Propiedad
settings.transfer_desc=Transferir este repositorio a otro usuario u organización donde tengas permisos de administración.
settings.advanced_settings=Ajustes avanzados
settings.wiki_desc=Habilitar la Wiki para que los colaboradores documenten
settings.use_external_wiki=Usar Wiki externa
settings.external_wiki_url=URL externa de la Wiki
settings.external_wiki_url_desc=Los visitantes serán redireccionados a la URL cuando hagan click en la barra.
settings.issues_desc=Habilitar tracker ligero de incidencias
settings.use_external_issue_tracker=Usar tracker externo de incidencias
settings.tracker_url_format=Formato URL del tracker de incidencias externo
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.new_owner_has_same_repo=El nuevo propietario tiene un repositorio con el mismo nombre.
settings.delete=Eliminar este Repositorio
settings.delete_desc=Una vez has eliminado un repositorio, no hay vuelta atrás. Por favor, asegúrate de que es lo que quieres.
settings.convert=Convertir en un repositorio normal
settings.convert_desc=Puedes convertir este repositorio en un repositorio normal. Este cambio no se puede deshacer.
settings.convert_notices_1=- Esta operación convertirá este repositorio espejo en un repositorio normal y no podrá deshacerse.
settings.convert_confirm=Confirmar conversión
settings.convert_succeed=El repositorio ha sido convertido en normal satisfactoriamente.
settings.transfer=Transferir la propiedad
settings.transfer_desc=Transferir este repositorio a otro usuario u organización donde tengas permisos de administración.
settings.transfer_notices_1=- Perderá el permiso de acceso si el nuevo propietario es otro usuario.
settings.transfer_notices_2=- Conservará el privilegio de acceso si el nuevo propietario es una organización y usted es uno de los propietarios de dicha organización.
settings.transfer_form_title=Por favor introduzca esta información para confirmar la operación:
settings.wiki_delete=Eliminar datos de la wiki
settings.wiki_delete_desc=Una vez borrados los datos de la wiki no habrá vuelta atrás. Por favor, asegúrate de que es lo que quieres.
settings.wiki_delete_notices_1=- Esto eliminará y deshabilitará la wiki para %s
settings.wiki_deletion_success=Los datos de la wiki del repositorio han sido borrados correctamente.
settings.delete=Eliminar este repositorio
settings.delete_desc=Una vez has eliminado un repositorio, no hay vuelta atrás. Por favor, asegúrate de que es lo que quieres.
settings.delete_notices_1=- Esta operación <strong>NO PUEDE</strong> revertirse.
settings.delete_notices_2=- Esta operación eliminará de manera permanente todo el contenido de este repositorio, incluyendo los datos de git, las incidencias, los comentarios y los permisos de acceso de los colaboradores.
settings.delete_notices_fork_1=- Si este repositorio es público, todos los forks se convertirán en repositorios independientes tras el borrado.
settings.delete_notices_fork_2=- Si este repositorio es privado, todos los forks serán eliminados simultáneamente.
settings.delete_notices_fork_3=- Si desea mantener los forks tras el borrado, por favor convierta este repositorio en público antes de proceder.
settings.deletion_success=¡El respositorio ha sido eliminado satisfactoriamente!
settings.update_settings_success=Las opciones del repositorio se han actualizado correctamente.
settings.transfer_owner=Nuevo Propietario
settings.make_transfer=Transferir
settings.transfer_succeed=La propiedad del repositorio ha sido transferida exitosamente.
settings.confirm_delete=Confirmar Eliminación
settings.add_collaborator=Añadir Nuevo Colaborador
settings.add_collaborator_success=Se ha añadido el nuevo colaborador.
settings.remove_collaborator_success=Se ha eliminado el colaborador.
settings.confirm_delete=Confirmar eliminación
settings.add_collaborator=Añadir nuevo colaborador
settings.add_collaborator_success=El nuevo colaborador ha sido añadido.
settings.delete_collaborator=Eliminar
settings.collaborator_deletion=Eliminar colaborador
settings.collaborator_deletion_desc=Este usuario no podrá colaborar en este repositorio tras eliminarlo. ¿Desea continuar?
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
settings.webhook_deletion_desc=Al borrar este webhook se eliminará su información y todo su historial. ¿Desea continuar?
settings.webhook_deletion_success=¡Webhook eliminado con éxito!
settings.webhook.test_delivery=Test de entrega
settings.webhook.test_delivery_desc=Enviar un falso evento Push de entrega para probar tus ajustes de webhook
settings.webhook.test_delivery_success=Probar que los webhook han sido añadidos a la cola de entrega. Esto puede tomar algunos segundos antes de aparecer en el historial de entregas.
settings.webhook.request=Petición
settings.webhook.response=Respuesta
settings.webhook.headers=Encabezado
@@ -585,7 +640,7 @@ settings.githook_content=Contenido del Hook
settings.update_githook=Actualizar Hook
settings.add_webhook_desc=Enviaremos una petición <code>POST</code> a la siguiente URL con los detalles de cualquier evento suscrito. También puedes especificar qué formato de datos te gustaría recibir (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). Puedes encontrar más información en la <a target="_blank" href="%s">Guía de Webhooks</a>.
settings.payload_url=URL de Payload
settings.content_type=Tipo de Contenido
settings.content_type=Tipo de contenido
settings.secret=Secreto
settings.slack_username=Nombre de usuario
settings.slack_icon_url=URL de icono
@@ -612,6 +667,7 @@ settings.slack_domain=Dominio
settings.slack_channel=Canal
settings.deploy_keys=Claves de Despliegue
settings.add_deploy_key=Añadir Clave de Despliegue
settings.deploy_key_desc=La clave de desarrollo tiene sólo acceso de lectura. No es igual que las claves SSH de las cuentas personales.
settings.no_deploy_keys=No has añadido ninguna clave de despliegue.
settings.title=Título
settings.deploy_key_content=Contenido
@@ -627,6 +683,8 @@ diff.parent=padre
diff.commit=commit
diff.data_not_available=Los datos del Diff no están disponibles.
diff.show_diff_stats=Mostrar Estadísticas de Diff
diff.show_split_view=Dividir vista
diff.show_unified_view=Unificar vista
diff.stats_desc=Se han <strong>modificado %d ficheros</strong> con <strong>%d adiciones</strong> y <strong>%d borrados</strong>
diff.bin=BIN
diff.view_file=Ver Fichero
@@ -653,18 +711,18 @@ release.prerelease_desc=Esta es una pre-release
release.prerelease_helper=Esta release está marcada como no apta para producción.
release.cancel=Cancelar
release.publish=Publicar Release
release.save_draft=Guardar Borrador
release.save_draft=Guardar borrador
release.edit_release=Editar Release
release.delete_release=Borrar este Release
release.deletion=Eliminación de Release
release.deletion_desc=Al eliminar este release se eliminará la etiqueta correspondiente. ¿Desea continuar?
release.deletion=Eliminar Release
release.deletion_desc=Eliminar este Release eliminará la etiqueta correspondiente. ¿Desea continuar?
release.deletion_success=¡El release ha sido eliminado correctamente!
release.tag_name_already_exist=Ya existe una Release con esta etiqueta.
release.downloads=Descargas
[org]
org_name_holder=Nombre de la Organización
org_full_name_holder=Nombre de la organización
org_name_holder=Nombre de la organización
org_full_name_holder=Nombre completo de la organización
org_name_helper=Los grandes nombres de organizaciones son cortos y memorables.
create_org=Crear Organización
repo_updated=Actualizado
@@ -673,9 +731,9 @@ invite_someone=Invitar a alguien
teams=Equipos
lower_members=miembros
lower_repositories=repositorios
create_new_team=Crear un Nuevo Equipo
create_new_team=Crear un nuevo equipo
org_desc=Descripción
team_name=Nombre del Equipo
team_name=Nombre del equipo
team_desc=Descripción
team_name_helper=Utiliza este nombre para mencionar a este equipo en las conversaciones.
team_desc_helper=¿En qué consiste este equipo?
@@ -686,18 +744,18 @@ form.name_pattern_not_allowed=El patrón de nombre de la organización '%s' no e
settings=Configuración
settings.options=Opciones
settings.full_name=Nombre Completo
settings.website=Página Web
settings.full_name=Nombre completo
settings.website=Página web
settings.location=Localización
settings.update_settings=Actualizar Configuración
settings.update_setting_success=La configuración de la Organización se ha actualizado correctamente.
settings.update_settings=Actualizar configuración
settings.update_setting_success=La configuración de la organización se ha actualizado correctamente.
settings.change_orgname_prompt=Este cambio afectará a los enlaces que hacen referencia a la organización.
settings.update_avatar_success=La configuración de avatar de la organización ha sido actualizada con éxito.
settings.delete=Eliminar Organización
settings.delete_account=Eliminar esta Organización
settings.delete=Eliminar organización
settings.delete_account=Eliminar esta organización
settings.delete_prompt=Esta operación eliminará esta organización de manera permanente, y ¡<strong>NO PUEDE</strong> deshacerse!
settings.confirm_delete_account=Confirmar Eliminación
settings.delete_org_title=Eliminación de la Organización
settings.confirm_delete_account=Confirmar eliminación
settings.delete_org_title=Eliminación de la organización
settings.delete_org_desc=Esta organización se va a eliminar permanentemente, ¿quieres continuar?
settings.hooks_desc=Añadir webhooks que serán ejecutados para <strong>todos los repositorios</strong> de esta organización.
@@ -720,24 +778,24 @@ teams.read_access=Acceso de Lectura
teams.read_access_helper=Este equipo podrá ver y clonar sus repositorios.
teams.write_access=Acceso de Escritura
teams.write_access_helper=Este equipo podrá leer sus repositorios, así como hacer push en ellos.
teams.admin_access=Acceso de Administrador
teams.admin_access=Acceso de administrador
teams.admin_access_helper=Este equipo podrá hacer push/pull en sus repositorios, así como añadir colaboradores a ellos.
teams.no_desc=Este equipo no tiene descripción
teams.settings=Configuración
teams.owners_permission_desc=Los propietarios tienen acceso completo a <strong>todos los repositorios</strong> y tienen <strong>derechos de administración</strong> en la organización.
teams.members=Miembros del Equipo
teams.update_settings=Actualizar Configuración
teams.delete_team=Borrar este Equipo
teams.add_team_member=Añadir Miembro al Equipo
teams.delete_team_title=Eliminar Equipo
teams.members=Miembros del equipo
teams.update_settings=Actualizar configuración
teams.delete_team=Eliminar este equipo
teams.add_team_member=Añadir miembro al equipo
teams.delete_team_title=Eliminar equipo
teams.delete_team_desc=Este equipo va a ser eliminado, ¿seguro que quieres continuar? Los miembros de este equipo pueden perder acceso a algunos repositorios.
teams.delete_team_success=El Equipo se ha eliminado correctamente.
teams.delete_team_success=El equipo ha sido eliminado correctamente.
teams.read_permission_desc=Este equipo tiene permisos de <strong>Lectura</strong>: sus miembros pueden ver y clonar los repositorios del equipo.
teams.write_permission_desc=Este equipo tiene permisos de <strong>Escritura</strong>: sus miembros pueden leer y hacer push a los repositorios del equipo.
teams.admin_permission_desc=Este equipo tiene permisos de <strong>Administración</strong>: sus miembros pueden leer, hacer push y añadir colaboradores a los repositorios del equipo.
teams.repositories=Repositorios del Equipo
teams.repositories=Repositorios del equipo
teams.search_repo_placeholder=Buscar repositorio...
teams.add_team_repository=Añadir Repositorio al Equipo
teams.add_team_repository=Añadir repositorio al equipo
teams.remove_repo=Eliminar
teams.add_nonexistent_repo=El repositorio que estás intentando añadir no existe, por favor, créalo primero.
@@ -748,7 +806,7 @@ organizations=Organizaciones
repositories=Repositorios
authentication=Autenticaciones
config=Configuración
notices=Avisos del Sistema
notices=Notificaciones del sistema
monitor=Monitorización
first_page=Primera
last_page=Última
@@ -758,7 +816,7 @@ dashboard.statistic=Estadísticas
dashboard.operations=Operaciones
dashboard.system_status=Estado del Monitor del Sistema
dashboard.statistic_info=La base de datos de Gogs contiene <b>%d</b> usuarios, <b>%d</b> organizaciones, <b>%d</b> claves públicas, <b>%d</b> repositorios, <b>%d</b> vigilados, <b>%d</b> destacados, <b>%d</b> acciones, <b>%d</b> accesos, <b>%d</b> incidencias, <b>%d</b> comentarios, <b>%d</b> cuentas de redes sociales, <b>%d</b> seguidores, <b>%d</b> mirrors, <b>%d</b> releases, <b>%d</b> fuentes de login, <b>%d</b> webhooks, <b>%d</b> milestones, <b>%d</b> etiquetas, <b>%d</b> hooks, <b>%d</b> equipos, <b>%d</b> tareas actualizadas, <b>%d</b> adjuntos.
dashboard.operation_name=Nombre de la Operación
dashboard.operation_name=Nombre de la operación
dashboard.operation_switch=Interruptor
dashboard.operation_run=Ejecutar
dashboard.clean_unbind_oauth=Limpiar solicitudes de OAuth sin confirmar
@@ -775,16 +833,18 @@ dashboard.resync_all_sshkeys=Reescribir el fichero '.ssh/authorized_keys'(atenci
dashboard.resync_all_sshkeys_success=Todas las claves públicas se han reescrito correctamente.
dashboard.resync_all_update_hooks=Reescribir todos los hooks de actualización de los repositorios (necesario cuando se modifica la ruta de configuración personalizada)
dashboard.resync_all_update_hooks_success=Todos los hooks de actualización de los repositorios se han reescrito correctamente.
dashboard.reinit_missing_repos=Reinicializar todos los registros del repositorio que tienen archivos Git eliminados
dashboard.reinit_missing_repos_success=Todos los registros del repositorio con archivos Git eliminados han sido reinicializados con éxito.
dashboard.server_uptime=Uptime del Servidor
dashboard.current_goroutine=Gorutinas Actuales
dashboard.current_memory_usage=Uso de Memoria Actual
dashboard.server_uptime=Tiempo de actividad del servidor
dashboard.current_goroutine=Gorutinas actuales
dashboard.current_memory_usage=Uso de memoria actual
dashboard.total_memory_allocated=Total de Memoria Reservada
dashboard.memory_obtained=Memoria Obtenida
dashboard.pointer_lookup_times=Tiempos de Búsqueda de Punteros
dashboard.pointer_lookup_times=Tiempos de búsqueda de punteros
dashboard.memory_allocate_times=Tiempos de Reserva de Memoria
dashboard.memory_free_times=Tiempos de Liberado de Memoria
dashboard.current_heap_usage=Uso de Heap Actual
dashboard.current_heap_usage=Uso de Heap actual
dashboard.heap_memory_obtained=Memoria de Heap Obtenida
dashboard.heap_memory_idle=Memoria de Heap Inactiva
dashboard.heap_memory_in_use=Memoria de Heap en Uso
@@ -818,10 +878,12 @@ users.new_success=La cuenta '%s' ha sido creada con éxito.
users.edit=Editar
users.auth_source=Fuente de Autenticación
users.local=Local
users.auth_login_name=Nombre de Inicio de Sesión de Autenticación
users.auth_login_name=Nombre de Inicio de sesión de autenticación
users.password_helper=Deje el campo vacío si no desea cambiar la contraseña.
users.update_profile_success=El perfil de la cuenta se ha actualizado correctamente.
users.edit_account=Editar Cuenta
users.max_repo_creation=Límite máximo de repositorios
users.max_repo_creation_desc=(Configura a -1 para usar el límite global por defecto)
users.is_activated=Esta cuenta está activada
users.is_admin=Esta cuenta tiene permisos de administrador
users.allow_git_hook=Esta cuenta tiene permisos para crear hooks de Git
@@ -845,34 +907,37 @@ repos.watches=Vigilantes
repos.stars=Estrellas
repos.issues=Incidencias
auths.auth_manage_panel=Panel de Administración de Autenticación
auths.new=Añadir Nuevo Origen
auths.auth_manage_panel=Panel de administración de autenticación
auths.new=Añadir nuevo origen
auths.name=Nombre
auths.type=Tipo
auths.enabled=Activo
auths.updated=Actualizado
auths.auth_type=Tipo de Autenticación
auths.auth_name=Nombre de Autenticación
auths.auth_type=Tipo de autenticación
auths.auth_name=Nombre de autenticación
auths.domain=Dominio
auths.host=Host
auths.port=Puerto
auths.bind_dn=Bind DN
auths.bind_password=Contraseña Bind
auths.bind_password_helper=Advertencia: La contraseña se almacena como texto plano. No utilice una cuenta con privilegios elevados.
auths.user_base=Base de Búsqueda de Usuarios
auths.user_base=Base de búsqueda de usuarios
auths.user_dn=DN de Usuario
auths.attribute_username=Atributo de nombre de usuario
auths.attribute_username_placeholder=Dejar vacío para usar el campo de inicio de sesión como nombre de usuario.
auths.attribute_name=Atributo nombre
auths.attribute_surname=Atributo apellido
auths.attribute_mail=Atributo correo electrónico
auths.filter=Filtro de Usuario
auths.admin_filter=Filtro de Aministrador
auths.attributes_in_bind=Buscar atributos en el contexto del Bind DN
auths.filter=Filtro de usuario
auths.admin_filter=Filtro de aministrador
auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Tipo de Autenticación SMTP
auths.smtp_auth=Tipo de autenticación SMTP
auths.smtphost=SMTP Host
auths.smtpport=Puerto SMTP
auths.allowed_domains=Dominios Permitidos
auths.allowed_domains_helper=Deje el campo vacío si no desea restringir ningún dominio. Para restringir más de uno, separe los dominios con una coma ','.
auths.enable_tls=Habilitar Cifrado TLS
auths.enable_tls=Habilitar cifrado TLS
auths.skip_tls_verify=Omitir la verificación TLS
auths.pam_service_name=Nombre del Servicio PAM
auths.enable_auto_register=Hablilitar Auto-Registro
@@ -881,13 +946,14 @@ auths.edit=Editar la Configuración de Autenticación
auths.activated=Esta autenticación ha sido activada
auths.new_success=¡La autenticación '%s' ha sido añadida con éxito!
auths.update_success=La configuración de autenticación ha sido actualizada con éxito.
auths.update=Actualizar la Configuración de Autenticación
auths.update=Actualizar la configuración de autenticación
auths.delete=Eliminar Autenticación
auths.delete_auth_title=Borrado de Autenticación
auths.delete_auth_title=Borrado de autenticación
auths.delete_auth_desc=Esta autenticación será eliminada. ¿Deseas continuar?
auths.still_in_used=Este método de autentificación aún es utilizado por algunos usuarios, por favor elimine o convierta estos usuarios a otro tipo de autentificación.
auths.deletion_success=¡La autenticación ha sido eliminada con éxito!
config.server_config=Configuración del Servidor
config.server_config=Configuración del servidor
config.app_name=Nombre de la Aplicación
config.app_ver=Versión de la Aplicación
config.app_url=URL de la Aplicación
@@ -895,27 +961,39 @@ config.domain=Dominio
config.offline_mode=Modo Sin Conexión
config.disable_router_log=Deshabilitar Log del Router
config.run_user=Ejecutada como Usuario
config.run_mode=Modo de Ejecución
config.run_mode=Modo de ejecución
config.repo_root_path=Ruta del Repositorio
config.static_file_root_path=Ruta de los Ficheros Estáticos
config.log_file_root_path=Ruta de los Ficheros de Log
config.script_type=Tipo de Script
config.reverse_auth_user=Autenticación Inversa de Usuario
config.ssh_config=Configuración SSH
config.ssh_enabled=Habilitado
config.ssh_start_builtin_server=Iniciar servidor integrado
config.ssh_domain=Dominio
config.ssh_port=Puerto
config.ssh_listen_port=Puerto de escucha
config.ssh_root_path=Ruta raíz
config.ssh_key_test_path=Ruta de la clave de prueba
config.ssh_keygen_path=Ruta del generador de claves ('ssh-keygen')
config.ssh_minimum_key_size_check=Tamaño mínimo de la clave de verificación
config.ssh_minimum_key_sizes=Tamaños de clave mínimos
config.db_config=Configuración de la Base de Datos
config.db_type=Tipo
config.db_host=Host
config.db_name=Nombre
config.db_user=Usuario
config.db_ssl_mode=Modo SSL
config.db_ssl_mode_helper=(solo para "postgres")
config.db_ssl_mode_helper=(sólo para "postgres")
config.db_path=Ruta
config.db_path_helper=(para "sqlite3" y "tidb")
config.service_config=Configuración del Servicio
config.service_config=Configuración del servicio
config.register_email_confirm=Solicitar Confirmación por Correo Electrónico
config.disable_register=Deshabilitar el Registro
config.show_registration_button=Mostrar Botón de Registro
config.require_sign_in_view=Solicitar la Vista de Inicio de Sesión
config.enable_cache_avatar=Activar la Caché de Avatar
config.mail_notify=Notificación por Correo Electrónico
config.disable_key_size_check=Deshabilitar la comprobación de Tamaño Mínimo de Clave
config.enable_captcha=Activar Captcha
@@ -925,12 +1003,15 @@ config.webhook_config=Configuración de Webhooks
config.queue_length=Tamaño de Cola de Envío
config.deliver_timeout=Timeout de Entrega
config.skip_tls_verify=Omitir la Verificación TLS
config.mailer_config=Configuración del Mailer
config.mailer_config=Configuración del servidor de correo
config.mailer_enabled=Activado
config.mailer_disable_helo=Desactivar HELO
config.mailer_name=Nombre
config.mailer_host=Host
config.mailer_user=Usuario
config.send_test_mail=Enviar email de prueba
config.test_mail_failed=Fallo al enviar el email de prueba a '%s': %v
config.test_mail_sent=El email de prueba ha sido enviado a '%s'.
config.oauth_config=Configuración OAuth
config.oauth_enabled=Activado
config.cache_config=Configuración de la Caché
@@ -955,32 +1036,43 @@ config.log_mode=Modo del Log
monitor.cron=Tareas de Cron
monitor.name=Nombre
monitor.schedule=Agenda
monitor.next=Próxima Vez
monitor.previous=Vez Anterior
monitor.next=Siguiente
monitor.previous=Anterior
monitor.execute_times=Ejecuciones
monitor.process=Procesos en Ejecución
monitor.process=Procesos en ejecución
monitor.desc=Descripción
monitor.start=Hora de Inicio
monitor.execute_time=Tiempo de ejecución
notices.system_notice_list=Notificaciones del Sistema
notices.view_detail_header=Ver detalles de la notificación
notices.actions=Acciones
notices.select_all=Sleccionar todo
notices.deselect_all=Deseleccionar todo
notices.inverse_selection=Selección inversa
notices.delete_selected=Eliminar seleccionado
notices.delete_all=Eliminar todas las notificaciones
notices.type=Tipo
notices.type_1=Repositorio
notices.desc=Descripción
notices.op=Op.
notices.delete_success=La notificación del sistema se ha eliminado correctamente.
notices.delete_success=Las notificaciones del sistema han sido eliminadas satisfactoriamente.
[action]
create_repo=repositorio creado <a href="%s">%s</a>
create_repo=creó el repositorio <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>
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>`
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>
push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_2_commits=Ver la comparación de estos 2 commits
compare_commits=Ver comparación de estos %d commits
[tool]
ago=hace
@@ -993,12 +1085,12 @@ now=ahora
1w=%s 1 semana
1mon=%s 1 mes
1y=%s 1 año
seconds=%[2]d %[1]s segundos
minutes=%s %d minutos
hours=%s %d horas
days=%s %d días
weeks=%s %d semanas
months=%s %d meses
seconds=%[2]s %[1]d segundos
minutes=%[2]s %[1]d minutos
hours=%[2]s %[1]d horas
days=%[2]s %[1]d días
weeks=%[2]s %[1]d semanas
months=%[2]s %[1]d meses
years=%s %d años
raw_seconds=segundos
raw_minutes=minutos

1103
conf/locale/locale_fi-FI.ini Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -6,9 +6,9 @@ explore=Explorer
help=Aide
sign_in=Connexion
sign_out=Déconnexion
sign_up=Créer un compte
register=Inscription
website=Site Web
sign_up=Inscription
register=S'inscrire
website=Site web
version=Version
page=Page
template=Modèle
@@ -26,20 +26,21 @@ captcha=Captcha
repository=Dépôt
organization=Organisation
mirror=Miroir
new_repo=Nouveau Dépôt
new_migrate=Nouvelle Migration
new_fork=Nouvel embranchement
new_org=Nouvelle Organisation
manage_org=Gérer les Organisations
new_repo=Nouveau dépôt
new_migrate=Nouvelle migration
new_mirror=Nouveau miroir
new_fork=Nouveau fork
new_org=Nouvelle organisation
manage_org=Gérer les organisations
admin_panel=Administration
account_settings=Paramètres du Compte
account_settings=Paramètres du compte
settings=Paramètres
your_profile=Votre profil
your_settings=Vos paramètres
news_feed=Flux d'actualités
activities=Activités
pull_requests=Pull Requests
issues=Problèmes
issues=Tickets
cancel=Annuler
@@ -47,7 +48,7 @@ cancel=Annuler
search=Rechercher...
repository=Dépôt
user=Utilisateur
issue=Problème
issue=Ticket
code=Code
[install]
@@ -56,49 +57,51 @@ title=Instructions pour la première exécution
docker_helper=Si vous exécutez Gogs grâce à Docker, merci de lire la <a target="_blank" href="%s">procédure</a> attentivement avant de modifier quoi que ce soit sur cette page !
requite_db_desc=Gogs requiert MySQL, PostgreSQL, SQLite3 ou TiDB.
db_title=Paramètres de la base de données
db_type=Type de Base de Données
db_type=Type de base de données
host=Hôte
user=Utilisateur
password=Mot De Passe
db_name=Nom de la Base de Données
password=Mot de passe
db_name=Nom de base de données
db_helper=Veuillez utiliser le moteur INNODB avec le jeu de caractères utf8_general_ci pour MySQL.
ssl_mode=Mode SSL
path=Chemin
sqlite_helper=Le chemin du fichier de la base de données SQLite3 ou TiDB.
sqlite_helper=Le chemin du fichier de base de données SQLite3 ou TiDB. <br>Utilisez un chemin absolu lorsque vous démarrez en tant que service.
err_empty_db_path=Le chemin de la base de données SQLite3 ou TiDB ne peut être vide.
err_invalid_tidb_name=Le nom de la base de données TiDB ne peut contenir les caractères "." ou "-".
no_admin_and_disable_registration=Vous ne pouvez pas désactiver l'enregistrement sans créer un compte administrateur.
err_empty_admin_password=Le mot de passe du compte administrateur ne peut être vide.
general_title=Paramètres Généraux de Gogs
app_name=Nom de l'Application
general_title=Paramètres généraux de Gogs
app_name=Nom de l'application
app_name_helper=Inscrivez fièrement le nom de votre organisation ici !
repo_path=Emplacement Racine du Dépôt
repo_path_helper=Tous les Dépôts Git distants seront sauvegardés ici.
run_user=Entrer un Utilisateur
run_user_helper=L'utilisateur doit avoir accès à la Racine du Référentiel et éxécuter Gogs.
repo_path=Emplacement racine des dépôts
repo_path_helper=Tous les dépôts Git distants seront sauvegardés ici.
run_user=Utilisateur système
run_user_helper=L'utilisateur doit avoir accès à la racine des dépôts et exécuter Gogs.
domain=Domaine
domain_helper=Cela affecte les doublons d'URL SSH.
ssh_port=Port SSH
ssh_port_helper=C'est le numéro de port qui est utilisé par votre serveur SSH, le laisser vide pour désactiver la fonctionnalité.
ssh_port_helper=Numéro de port utilisé par votre serveur SSH, le laisser vide pour désactiver la fonctionnalité.
http_port=Port HTTP
http_port_helper=Numéro de port que l'application écoutera.
app_url=URL de l'Application
app_url=URL de l'application
app_url_helper=Cela affecte les doublons d'URL HTTP/HTTPS et le contenu d'e-mail.
log_root_path=Chemin des fichiers log
log_root_path_helper=Répertoire d'écriture des fichiers de log.
optional_title=Paramètres facultatifs
email_title=Paramètres du Service de Messagerie
smtp_host=Hôte SMTP
smtp_from=Provenant de
smtp_from_helper=Adresse de l'expéditeur, RFC 5322. Soit une adresse courriel simple, soit au format "Nom" <email@example.com>.
mailer_user=E-mail de l'Expéditeur
mailer_password=Mot de Passe de l'Expéditeur
register_confirm=Activer la Confirmation d'Enregistrement
mail_notify=Activer la Notification des Mails reçus
mailer_user=E-mail de l'expéditeur
mailer_password=Mot de passe de l'expéditeur
register_confirm=Activer la confirmation de l'inscription
mail_notify=Activer la notification par e-mail
server_service_title=Paramètres du serveur et des autres services
offline_mode=Activer le Mode hors connexion
offline_mode=Activer le mode hors connexion
offline_mode_popup=Désactiver le CDN, même en production. Toutes les ressources seront distribuées en local.
disable_gravatar=Désactiver le Service Gravatar
disable_gravatar=Désactiver le service Gravatar
disable_gravatar_popup=Désactiver Gravatar et les sources personnalisées, tous les avatars sont téléchargés par les utilisateurs ou par défaut.
disable_registration=Désactiver le formulaire d'inscription
disable_registration_popup=Désactiver le formulaire d'inscription, seuls les administrateurs peuvent créer des comptes.
@@ -106,28 +109,29 @@ enable_captcha=Activez le Captcha
enable_captcha_popup=Demande la validation Captcha pour l'auto-enregistrement de l'utilisateur.
require_sign_in_view=Demander une connexion pour afficher des pages
require_sign_in_view_popup=Seules les personnes connectées peuvent voir les pages. Les visiteurs anonymes ne pourront voir que les pages de connexion/enregistrement.
admin_setting_desc=Vous n'avez pas besoin de créer un compte admin. L'utilisateur ayant l'ID = 1 se verra automatiquement attribuer l'accès administrateur.
admin_title=Paramètres du Compte Administrateur
admin_name=Nom d'Utilisateur
admin_password=Mot de Passe
confirm_password=Confirmez le Mot de Passe
admin_setting_desc=Vous n'avez pas besoin de créer un compte administrateur. L'utilisateur ayant l'ID = 1 aura automatiquement accès à l'administration.
admin_title=Paramètres du compte administrateur
admin_name=Nom d'utilisateur
admin_password=Mot de passe
confirm_password=Confirmez le mot de passe
admin_email=E-mail de l'administrateur
install_gogs=Installer Gogs
test_git_failed=Tentative de commande "git" échouée : %v
test_git_failed=Le test de la commande "git" a échoué : %v
sqlite3_not_available=Votre version publiée ne prend pas en charge SQLite3. Veuillez télécharger la version binaire officielle à cette adresse %s.
invalid_db_setting=Paramètres de base de données incorrects : %v
invalid_repo_path=Chemin vers le répertoire racine invalide : %v
invalid_repo_path=Chemin vers la racine du dépôt invalide : %v
run_user_not_match=L'utilisateur entré n'est pas l'utilisateur actuel : %s -> %s
save_config_failed=La sauvegarde de la configuration a échoué : %v
invalid_admin_setting=Paramètres du compte administrateur invalides : %v
install_success=Bienvenue ! Nous sommes heureux que vous ayez choisi Gogs, amusez-vous et prenez soin de vous.
invalid_log_root_path=Le chemin principal des fichiers logs est invalide: %v
[home]
uname_holder=Nom d'Utilisateur ou E-mail
password_holder=Mot de Passe
password_holder=Mot de passe
switch_dashboard_context=Basculer le Contexte du Tableau de Bord
my_repos=Mes Référentiels
collaborative_repos=Référentiels collaboratifs
my_repos=Mes dépôts
collaborative_repos=Dépôts collaboratifs
my_orgs=Mes Organisations
my_mirrors=Mes Miroirs
view_home=Voir %s
@@ -135,27 +139,27 @@ view_home=Voir %s
issues.in_your_repos=Dans vos dépôts
[explore]
repos=Référentiels
repos=Dépôts
[auth]
create_new_account=Créer un Nouveau Compte
create_new_account=Créer un nouveau compte
register_hepler_msg=Déjà enregistré ? Connectez-vous !
social_register_hepler_msg=Possesseur d'un compte ? Associez-le !
social_register_hepler_msg=Déjà enregistré ? Associez-le !
disable_register_prompt=Désolé, les enregistrements ont été désactivés. Veuillez contacter l'administrateur du site.
disable_register_mail=Désolé, la Confirmation par Mail des Enregistrements a été désactivée.
remember_me=Se souvenir de Moi
remember_me=Se souvenir de moi
forgot_password=Mot de Passe oublié
forget_password=Mot de Passe oublié ?
sign_up_now=Pas de compte ? Créer maintenant.
sign_up_now=Pas de compte ? Inscrivez-vous maintenant.
confirmation_mail_sent_prompt=Un nouveau mail de confirmation à été envoyé à <b>%s</b>. Veuillez vérifier votre boîte de réception dans un délai de %d heures pour compléter votre enregistrement.
active_your_account=Activer votre Compte
resent_limit_prompt=Désolé, vos tentatives d'activation sont trop fréquentes. Veuillez réessayer dans 3 minutes.
has_unconfirmed_mail=Bonjour %s, votre adresse courriel (<b>%s</b>) n'a pas été confirmée. Si vous n'avez reçu aucun courriel de confirmation ou souhaitez renouveler l'envoi, appuyez sur le bouton ci-dessous.
has_unconfirmed_mail=Bonjour %s, votre adresse e-mail (<b>%s</b>) n'a pas été confirmée. Si vous n'avez reçu aucun mail de confirmation ou souhaitez renouveler l'envoi, cliquez sur le bouton ci-dessous.
resend_mail=Cliquez ici pour renvoyer un mail de confirmation
email_not_associate=Cette adresse e-mail n'est associée à aucun compte.
send_reset_mail=Cliquez ici pour (r)envoyer le mail de réinitialisation du mot de passe
reset_password=Réinitialiser le Mot de Passe
invalid_code=Désolé, code de confirmation invalide ou expiré.
reset_password=Réinitialiser le mot de passe
invalid_code=Désolé, votre code de confirmation est invalide ou a expiré.
reset_password_helper=Cliquez ici pour réinitialiser votre mot de passe
password_too_short=Le mot de passe doit contenir 6 caractères minimum.
@@ -172,11 +176,11 @@ no=Non
modify=Modifier
[form]
UserName=Nom d'Utilisateur
UserName=Nom d'utilisateur
RepoName=Nom du dépôt
Email=Adresse E-mail
Password=Mot de Passe
Retype=Confirmez le Mot de Passe
Password=Mot de passe
Retype=Confirmez le mot de passe
SSHTitle=Nom de la clé SSH
HttpsUrl=URL HTTPS
PayloadUrl=URL des Données Utiles
@@ -202,7 +206,6 @@ repo_name_been_taken=Nom de dépôt déjà utilisé.
org_name_been_taken=Nom d'organisation déjà pris.
team_name_been_taken=Nom d'équipe déjà pris.
email_been_used=Adresse e-mail déjà utilisée.
illegal_team_name=Le nom de l'équipe contient des caractères interdits.
username_password_incorrect=Nom d'utilisateur ou mot de passe incorrect.
enterred_invalid_repo_name=Veuillez vérifier que le nom saisi du dépôt soit correct.
enterred_invalid_owner_name=Veuillez vérifier que le nom du propriétaire saisi soit correct.
@@ -218,19 +221,19 @@ still_own_repo=Votre compte comporte toujours des propriétés du dépôt. Vous
still_has_org=Votre compte contient toujours au moins une adhésion à une organisation, vous devez quitter ou supprimer votre adhésion.
org_still_own_repo=Cette organisation comporte toujours des propriétés du dépôt. Vous devez d'abord les supprimer ou les transférer.
still_own_user=Cette authentification a déjà servi à d'autres utilisateurs. Veuillez les déplacer puis supprimez à nouveau.
target_branch_not_exist=La branche cible n'existe pas.
[user]
change_avatar=Changez d'avatar via gravatar.com
change_custom_avatar=Changer votre avatar dans les paramètres
join_on=Adhéré le
repositories=Référentiels
activity=Activités publiques
followers=Abonnés
change_custom_avatar=Changez votre avatar dans les paramètres
join_on=Inscrit le
repositories=Dépôts
activity=Activité publique
followers=abonnés
starred=Votés
following=Abonnements
follow=Suivre
unfollow=Ne plus suivre
form.name_reserved=Le nom '%s' est réservé.
form.name_pattern_not_allowed=Motif '%s' interdit pour les noms d'utilisateur.
@@ -245,9 +248,10 @@ orgs=Organisations
delete=Supprimer le Compte
uid=ID d'Utilisateur
public_profile=Profil Public
public_profile=Profil public
profile_desc=Votre adresse e-mail est publique et sera utilisée pour les notifications relatives au compte, ainsi que pour toute opération Web effectuée via le site.
full_name=Nom Complet
password_username_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
full_name=Nom complet
website=Site Web
location=Localisation
update_profile=Valider les modifications
@@ -258,19 +262,19 @@ continue=Continuer
cancel=Annuler
enable_custom_avatar=Activer l'Avatar personnalisé
enable_custom_avatar_helper=Cette option désactive l'affichage via Gravatar
choose_new_avatar=Sélectionner un nouvel avatar
update_avatar=Mettre à jour l'avatar
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=Le fichier téléchargé n'est pas une image.
no_custom_avatar_available=Aucun avatar personnalisé disponible, activation impossible.
update_avatar_success=Votre avatar a été mis à jour avec succès.
change_password=Modifier le Mot de Passe
old_password=Mot de Passe actuel
change_password=Modifier le mot de passe
old_password=Mot de passe actuel
new_password=Nouveau Mot de Passe
retype_new_password=Retapez le nouveau mot de passe
password_incorrect=Mot de passe actuel incorrect.
change_password_success=Mot de passe modifié avec succès. Vous pouvez à présent vous connecter avec le nouveau mot de passe.
password_change_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur mot de passe.
emails=Adresses E-mail
manage_emails=Gérer les adresses e-mail
@@ -279,12 +283,12 @@ primary=Principale
primary_email=Définir comme principale
delete_email=Supprimer
email_deletion=Suppression de l'adresse mél
email_deletion_desc=Supprimer cette adresse l supprimera les informations associées à votre compte. Voulez-vous continuer ?
email_deletion_desc=Supprimer cette adresse e-mail supprimera les informations associées à votre compte. Voulez-vous continuer ?
email_deletion_success=L'adresse mél a été supprimée avec succès !
add_new_email=Ajouter une nouvelle adresse courriel
add_email=Ajouter un courriel
add_new_email=Ajouter une nouvelle adresse e-mail
add_email=Ajouter un e-mail
add_email_confirmation_sent=Une nouvelle confirmation d'adresse e-mail a été envoyé à '%s', veuillez vérifier votre boîte de réception dans un délai de %d heures pour terminer le processus de confirmation.
add_email_success=Votre courriel a été ajouté avec succès.
add_email_success=Votre nouvelle adresse e-mail a été ajoutée avec succès.
manage_ssh_keys=Gérer les clés SSH
add_key=Ajouter une Clé
@@ -304,7 +308,7 @@ add_on=Ajouté le
last_used=Dernière utilisation le
no_activity=Aucune activité récente
key_state_desc=Cette clé a été utilisée durant les 7 derniers jours
token_state_desc=Cette clé a été utilisée durant les 7 derniers jours
token_state_desc=Ce jeton a été utilisé durant les 7 derniers jours
manage_social=Gérer les réseaux sociaux associés
social_desc=Ceci est la liste des comptes de réseaux sociaux associés. Supprimez ceux que vous ne reconnaissez pas.
@@ -323,24 +327,24 @@ access_token_deletion=Suppression du jeton d'accès
access_token_deletion_desc=Supprimer ce jeton d'accès supprimera tous les accès de l'application. Voulez-vous continuer ?
delete_token_success=Le jeton d'accèsa été supprimé avec succès ! N'oubliez pas de mettre à jour vos applications.
delete_account=Supprimer le Compte
delete_prompt=Votre compte sera supprimé définitivement et cette opération est <strong>IRRÉVERSIBLE</strong> !
delete_account=Supprimer votre compte
delete_prompt=Votre compte sera définitivement supprimé et cette opération est <strong>irréversible</strong> !
confirm_delete_account=Confirmer la suppression
delete_account_title=Suppression de compte
delete_account_desc=Ce compte sera supprimé définitivement. Voulez-vous continuer ?
[repo]
owner=Propriétaire
repo_name=Nom du Référentiel
repo_name=Nom du Dépôt
repo_name_helper=Idéalement, le nom d'un dépot devrait être court, mémorable et <strong>unique</strong>.
visibility=Visibilité
visiblity_helper=Ce dépôt est <span class="ui red text"> privé</span>
visiblity_helper_forced=L'administrateur du site a forcé tous les nouveaux dépôts à être <span class="ui red text">privés</span>
visiblity_fork_helper=(Les changement de cette valeur affectera tous les forks)
visiblity_fork_helper=(Les changement de cette valeur affecteront tous les forks)
clone_helper=Besoin d'aide pour dupliquer ? Visitez <a target="_blank" href="%s">l'aide</a> !
fork_repo=Scinder le dépôt
fork_from=Embranchement de
fork_visiblity_helper=La visibilité d'un référentiel d'embranchement ne peut pas être modifiée.
fork_repo=Créer un fork du dépôt
fork_from=Fork de
fork_visiblity_helper=La visibilité d'un fork ne peut pas être modifiée.
repo_desc=Description
repo_lang=Langue
repo_lang_helper=Sélectionnez les fichiers .gitignore
@@ -352,25 +356,29 @@ auto_init=Initialiser ce dépôt avec le modèle et les fichiers sélectionnés
create_repo=Créer un dépôt
default_branch=Branche par défaut
mirror_interval=Intervalle du miroir (heure)
mirror_address=Adresse du miroir
mirror_address_desc=Veuillez inclure les informations d'identification nécessaires dans l'adresse.
watchers=Observateurs
stargazers=Stargazers
forks=Forks
form.reach_limit_of_creation=Le propriétaire a atteint le nombre maximal de %d dépôts créés.
form.name_reserved=Le nom de dépôt '%s' est réservé.
form.name_pattern_not_allowed=Motif '%s' interdit pour les noms de dépôt.
need_auth=Nécessite une Autorisation
migrate_type=Type de Migration
migrate_type=Type de migration
migrate_type_helper=Ce dépôt sera un <span class="text blue"> miroir</span>
migrate_repo=Migrer le dépôt
migrate.clone_address=Adresse du clone
migrate.clone_address_desc=Cela peut être une URL HTTP/HTTPS/GIT ou un chemin d'accès local.
migrate.permission_denied=Vous n'êtes pas autorisé à importer des dépôts locaux.
migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier.
migrate.failed=Migration failed: %v
migrate.failed=Echec de migration: %v
forked_from=embranché à partir de
fork_from_self=Vous nous ne pouvez pas scinder un dépôt que vous possédez déja !
mirror_from=miroir de
forked_from=scindé depuis
fork_from_self=Vous ne pouvez pas forker un dépôt que vous possédez déja !
copy_link=Copier
copy_link_success=Copié!
copy_link_error=Appuyez sur ⌘-C ou Ctrl-C pour copier
@@ -379,33 +387,34 @@ unwatch=Ne plus suivre
watch=Suivre
unstar=Retirer le vote
star=Voter
fork=Embranchement
fork=Fork
no_desc=Aucune description
quick_guide=Introduction rapide
clone_this_repo=Cloner ce dépôt
create_new_repo_command=Créer un nouveau dépôt en ligne de commande
push_exist_repo=Soumettre un référentiel existant via la ligne de commande
repo_is_empty=Ce référentiel est vide, veuillez revenir plus tard !
push_exist_repo=Soumettre un dépôt existant par ligne de commande
repo_is_empty=Ce dépôt est vide, veuillez revenir plus tard !
code=Code
branch=Branche
tree=Aborescence
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Filtrer une branche ou un tag
branches=Branches
tags=Tags
issues=Problèmes
issues=Tickets
pulls=Pull Requests
labels=Etiquettes
milestones=Étapes
commits=Commissions
commits=Commits
releases=Publications
file_raw=Raw
file_history=Historique
file_view_raw=Voir le Raw
file_permalink=Lien permanent
commits.commits=Commissions
commits.search=Rechercher des commissions
commits.commits=Commits
commits.search=Rechercher des commits
commits.find=Trouver
commits.author=Auteur
commits.message=Message
@@ -413,7 +422,7 @@ commits.date=Date
commits.older=Précédemment
commits.newer=Récemment
issues.new=Nouveau Problème
issues.new=Nouveau ticket
issues.new.labels=Etiquettes
issues.new.no_label=Pas d'étiquette
issues.new.clear_labels=Effacer les étiquettes
@@ -438,36 +447,36 @@ issues.filter_milestone_no_select=Aucun jalon sélectionné
issues.filter_assignee=Assigné
issues.filter_assginee_no_select=Pas d'assignataire selectionné
issues.filter_type=Type
issues.filter_type.all_issues=Tous les problèmes
issues.filter_type.all_issues=Tous les tickets
issues.filter_type.assigned_to_you=Qui vous sont assignés
issues.filter_type.created_by_you=Créé(es) par vous
issues.filter_type.created_by_you=Crées par vous
issues.filter_type.mentioning_you=Vous mentionnant
issues.filter_sort=Trier
issues.filter_sort.latest=Plus récent
issues.filter_sort.oldest=Plus ancien/ne
issues.filter_sort.recentupdate=Mis à jour récemment
issues.filter_sort.leastupdate=Moins récemment mis à jour
issues.filter_sort.mostcomment=Plus commentés
issues.filter_sort.leastcomment=Moins commenté
issues.opened_by=Ouvrir %[1]s by <a href="%[2]s">%[3]s</a>
issues.filter_sort.mostcomment=Les plus commentés
issues.filter_sort.leastcomment=Les moins commentés
issues.opened_by=Créé %[1]s par <a href="%[2]s">%[3]s</a>
issues.opened_by_fake=ouvert %[1]s par %[2]s
issues.previous=Page Précédente
issues.next=Page Suivante
issues.open_title=Ouvert
issues.closed_title=Fermé
issues.num_comments=%d commentaires
issues.commented_at='commenté à <a id="%[1]s" href="#%[1]s"> %[2]s'</a>
issues.commented_at=`commenté à <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
issues.no_content=Il n'existe pas encore de contenu.
issues.close_issue=Fermer
issues.close_comment_issue=Commenter et fermer
issues.reopen_issue=Réouvrir
issues.reopen_comment_issue=Commenter et réouvrir
issues.create_comment=Créer un commentaire
issues.closed_at="fermé à <a id="%[1]s"href="#%[1]s"> %[2]s"</a>
issues.reopened_at='réouvert à <a id="%[1]s" href="#%[1]s"> %[2]s'</a>
issues.closed_at=`fermé à <a id="%[1]s"href="#%[1]s"> %[2]s"</a>`
issues.reopened_at=`réouvert à <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
issues.commit_ref_at=`a référencé ce problème à partir d'un commit <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
issues.poster=Publier
issues.admin=Admin
issues.collaborator=Collaborator
issues.owner=Propriétaire
issues.sign_up_for_free=Inscrivez-vous gratuitement
issues.sign_in_require_desc=pour rejoindre cette conversation. Vous avez déjà un compte ? <a href="%s">Connectez-vous commenter</a>
@@ -477,15 +486,16 @@ issues.save=Enregistrer
issues.label_title=Nom du Label
issues.label_color=Couleur du Label
issues.label_count=%d labels
issues.label_open_issues=%d problèmes ouverts
issues.label_open_issues=%d tickets ouverts
issues.label_edit=Éditer
issues.label_delete=Supprimer
issues.label_modify=Modification du Label
issues.label_deletion=Suppression du Label
issues.label_deletion_desc=Cette opération supprimera également toutes les informations relatives aux problèmes. Voulez-vous continuer ?
issues.label_deletion_desc=Cette opération supprimera également toutes les informations relatives aux tickets. Voulez-vous continuer ?
issues.label_deletion_success=Label supprimé avec succès !
issues.num_participants=%d Participants
pulls.new=New Pull Request
pulls.new=Nouvelle Pull Request
pulls.compare_changes=Comparer les changements
pulls.compare_changes_desc=Comparer deux branches et faire une demande de récupération Pull pour les changements.
pulls.compare_base=Base
@@ -503,11 +513,11 @@ pulls.tab_files=Fichiers modifiés
pulls.reopen_to_merge=Veuillez rouvrir cette demande de Pull Request pour effectuer l'opération de fusion.
pulls.merged=Fusionné
pulls.has_merged=Cette Pull Request a été fusionnée avec succès !
pulls.data_broken=Les données de cette Pull Request a été rompues en raison de la suppression d'informations du Fork.
pulls.data_broken=Les données de cette pull request ont été compromises en raison de la suppression d'informations sur le fork.
pulls.is_checking=La recherche de conflits est toujours en cours, veuillez rafraichir la page dans quelques instants.
pulls.can_auto_merge_desc=Vous pouvez effectuer d'opération de fusion automatique sur cette demande de Pull Request.
pulls.cannot_auto_merge_desc=Vous ne pouvez effectuer des opération de fusion automatique car il y a des conflits entre les Commits.
pulls.cannot_auto_merge_helper=Veuillez utiliser l'outil en ligne de commande pour le résoudre.
pulls.can_auto_merge_desc=Cette pull request peut être fusionnée automatiquement.
pulls.cannot_auto_merge_desc=Cette pull request ne peut être fusionnée automatiquement à cause de conflits.
pulls.cannot_auto_merge_helper=Fusionner manuellement afin de résoudre les conflits.
pulls.merge_pull_request=Fusionner la Pull Request
pulls.open_unmerged_pull_exists=`Vous ne pouvez effectuer une réouverture car il y a déjà une pull-request ouverte (#%d) depuis le même dépôt avec les mêmes informations de fusion et est en attente de fusion.`
@@ -518,7 +528,7 @@ milestones.closed=%s fermé
milestones.no_due_date=Aucune date d'échéance
milestones.open=Ouvrir
milestones.close=Fermer
milestones.new_subheader=Créez des jalons pour organiser vos problèmes.
milestones.new_subheader=Créez des jalons pour organiser vos tickets.
milestones.create=Créer un Jalon
milestones.title=Titre
milestones.desc=Description
@@ -532,32 +542,70 @@ milestones.cancel=Annuler
milestones.modify=Modifier le Jalon
milestones.edit_success=Le Jalon '%s' a été modifié avec succès !
milestones.deletion=Supprimer le Jalon
milestones.deletion_desc=Supprimer ce Jalon effacera ses informations dans tous les problèmes relatifs. Voulez-vous continuer ?
milestones.deletion_desc=Supprimer ce jalon effacera ses informations dans tous les tickets relatifs. Voulez-vous continuer ?
milestones.deletion_success=Le Jalon a été supprimé avec succès !
wiki=Wiki
wiki.welcome=Bienvenue sur le Wiki !
wiki.welcome_desc=Le Wiki est l'endroit où vous pouvez documenter votre projet ensemble et l'améliorer.
wiki.create_first_page=Créer la première page
wiki.page=Page
wiki.filter_page=Filtrer la page
wiki.new_page=Créer une nouvelle page
wiki.default_commit_message=Écrire une note concernant cette mise à jour (optionnel).
wiki.save_page=Enregistrer la page
wiki.last_commit_info=%s a édité cette page %s
wiki.edit_page_button=Modifier
wiki.new_page_button=Nouvelle Page
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=Une page de wiki avec le même nom existe déjà.
wiki.pages=Pages
wiki.last_updated=Dernière mise à jour: %s
settings=Paramètres
settings.options=Options
settings.collaboration=Collaboration
settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Paramètres de base
settings.danger_zone=Zone de danger
settings.site=Site officiel
settings.update_settings=Valider
settings.change_reponame_prompt=Ce changement affectera comment les liens sont reliés avec le dépôt.
settings.transfer=Transférer les propriétés
settings.transfer_desc=Transfèrer ce dépôt à un autre utilisateur ou une organisation dont vous possédez des droits d'administrateur.
settings.advanced_settings=Paramètres avancés
settings.wiki_desc=Activer le wiki pour permettre l'écriture de documents
settings.use_external_wiki=Utiliser un wiki externe
settings.external_wiki_url=URL Wiki externe
settings.external_wiki_url_desc=Les visiteurs seront redirigés vers cette URL lorsqu'ils cliqueront sur l'onglet.
settings.issues_desc=Activer le bug-tracker léger intégré
settings.use_external_issue_tracker=Utiliser un bug-tracker externe
settings.tracker_url_format=Format d'URL du bug tracker
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.new_owner_has_same_repo=Le nouveau propriétaire a déjà un dépôt nommé ainsi.
settings.delete=Supprimer ce Référentiel
settings.delete_desc=Attention, action irréversible. Soyez sûr de vous.
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.
settings.convert_notices_1=- Cette opération va convertir ce dépôt miroir en un dépôt standard et ne peut être annulée.
settings.convert_confirm=Confirmer la conversion
settings.convert_succeed=Le dépôt a été converti avec succès en dépôt ordinaire.
settings.transfer=Changer de propriétaire
settings.transfer_desc=Transférer ce dépôt à un autre utilisateur ou une organisation dont vous possédez des droits d'administrateur.
settings.transfer_notices_1=-Vous perdrez l'accès si le nouveau propriétaire est un utilisateur individuel.
settings.transfer_notices_2=-Vous préserverez l'accès si le nouveau propriétaire est une organisation et si vous y appartenez.
settings.transfer_notices_2=- Vous conserverez l'accès si le nouveau propriétaire est une organisation et que vous y appartenez.
settings.transfer_form_title=Veuillez recopier le texte suivant afin de confirmer votre opération :
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=Supprimer ce dépôt
settings.delete_desc=Attention, cette action est action irréversible. Soyez sûr de vous.
settings.delete_notices_1=- Cette opération <strong>ne peut pas </strong> être annulée.
settings.delete_notices_2=-Cette opération supprimera définitivement le dépôt, y compris les données Git, problèmes, commentaires et accès des collaborateurs.
settings.delete_notices_fork_1=-Si ce dépôt est public, tous les Forks vont devenir indépendants après la suppression.
settings.delete_notices_fork_2=-Si ce dépôt est privé, tous les Forks seront supprimés en même temps.
settings.delete_notices_2=- Cette opération supprimera définitivement le dépôt, y compris les données Git, les tickets, les commentaires et les accès des collaborateurs.
settings.delete_notices_fork_1=- Si ce dépôt est public, tous les forks vont devenir indépendant après sa suppression.
settings.delete_notices_fork_2=-Si ce dépôt est privé, tous les forks seront supprimés en même temps.
settings.delete_notices_fork_3=-Si vous souhaitez conserver tous les forks après suppression, veuillez tout d'abord modifier la visibilité de ce dépôt en public.
settings.deletion_success=Le dépôt a été supprimé avec succès!
settings.update_settings_success=Options mises à jour avec succès.
settings.transfer_owner=Nouveau propriétaire
settings.make_transfer=Transférer
@@ -565,14 +613,21 @@ settings.transfer_succeed=Le contrôle du dépôt a été transféré avec succ
settings.confirm_delete=Confirmer la suppression
settings.add_collaborator=Ajouter un collaborateur
settings.add_collaborator_success=Nouveau collaborateur ajouté.
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
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
settings.webhook_deletion_desc=Supprimer ce webhook va supprimer ses informations et l'historique de livraison. Voulez-vous continuer ?
settings.webhook_deletion_success=Le webhook a été supprimé avec succès !
settings.webhook.test_delivery=Tester la version
settings.webhook.test_delivery_desc=Envoyer un faux push pour tester la configuration des webhooks
settings.webhook.test_delivery_success=Le webhook de test a été ajouté à la file d'attente de livraison. L'affichage dans l'historique de livraison peut prendre quelques secondes.
settings.webhook.request=Requête
settings.webhook.response=Réponse
settings.webhook.headers=Entêtes 
@@ -612,6 +667,7 @@ settings.slack_domain=Domaine
settings.slack_channel=Canal
settings.deploy_keys=Clés de déploiement
settings.add_deploy_key=Ajouter une Clé de Déploiement
settings.deploy_key_desc=Déployer une clé uniquement en lecture seule. Il ne s'agit pas des clés ssh de compte personnel.
settings.no_deploy_keys=Vous n'avez ajouté aucune clé de déploiement.
settings.title=Titre
settings.deploy_key_content=Contenu
@@ -624,9 +680,11 @@ settings.deploy_key_deletion_success=La clé de déploiement a été supprimée
diff.browse_source=Parcourir la Source
diff.parent=Parent
diff.commit=Commettre
diff.commit=commit
diff.data_not_available=Données Diff indisponibles.
diff.show_diff_stats=Afficher les stats Diff
diff.show_split_view=Vue séparée
diff.show_unified_view=Vue unifiée
diff.stats_desc=<strong> %d fichiers modifiés</strong> avec <strong>%d ajouts</strong> et <strong>%d suppressions</strong>
diff.bin=BIN
diff.view_file=Voir le fichier
@@ -637,10 +695,10 @@ release.draft=Brouillon
release.prerelease=Pré-publication
release.stable=Stable
release.edit=Éditer
release.ahead=<strong>%d</strong> commissions à %s depuis cette publication
release.source_code=Code Source
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.ahead=<strong>%d</strong> commits jusqu'à %s depuis cette publication
release.source_code=Code source
release.new_subheader=Publier une version pour itérer sur le produit.
release.edit_subheader=Un changelog détaillé peut aider les utilisateurs à comprendre ce qui a été amélioré.
release.tag_name=Nom du tag
release.target=Cible 
release.tag_helper=Choisissez un tag existant ou créez-en un nouveau à publier.
@@ -654,12 +712,12 @@ release.prerelease_helper=Nous soulignerons que cette version est considérée c
release.cancel=Annuler
release.publish=Publier
release.save_draft=Sauvegarder le Brouillon
release.edit_release=Éditer la publication
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.tag_name_already_exist=Une publication avec ce nom de tag existe déjà.
release.edit_release=Modifier la version
release.delete_release=Supprimer Cette Version
release.deletion=Suppression de la Version
release.deletion_desc=Supprimer cette version supprimera le tag Git correspondant. Voulez-vous continuer ?
release.deletion_success=La version à été supprimée avec succès !
release.tag_name_already_exist=Une version avec ce nom de tag existe déjà.
release.downloads=Téléchargements
[org]
@@ -672,7 +730,7 @@ people=Contacts
invite_someone=Inviter quelqu'un
teams=Équipes
lower_members=Membres
lower_repositories=Référentiels
lower_repositories=dépôts
create_new_team=Créer une Nouvelle Équipe
org_desc=Description
team_name=Nom d'Équipe
@@ -699,32 +757,32 @@ settings.delete_prompt=Cela supprimera cette organisation définitivement. Cette
settings.confirm_delete_account=Confirmez la suppression
settings.delete_org_title=Suppression d'organisation
settings.delete_org_desc=Cette organisation sera définitivement supprimée. Continuer ?
settings.hooks_desc=Ajoute des Webhooks qui seront activés pour <strong>tous les Référentiels</strong> de cette organisation.
settings.hooks_desc=Ajoute des vebhooks qui seront activés pour <strong>tous les dépôts</strong> de cette organisation.
members.membership_visibility=Membership Visibility:
members.membership_visibility=Visibilité des membres:
members.public=Public
members.public_helper=Rendre privé
members.private=Privé
members.private_helper=Rendre public
members.member_role=Member Role:
members.member_role=Rôle du membre :
members.owner=Propriétaire
members.member=Membre
members.remove=Exclure
members.leave=Quitter
members.invite_desc=Add a new member to %s:
members.invite_desc=Ajouter un nouveau membre à %s :
members.invite_now=Envoyer une invitation
teams.join=Rejoindre
teams.leave=Quitter
teams.read_access=Accès en Lecture
teams.read_access_helper=Cette équipe aura la possibilité de voir et dupliquer ses Référentiels.
teams.read_access_helper=Cette équipe aura la possibilité de voir et cloner ses dépôts.
teams.write_access=Accès en Écriture
teams.write_access_helper=Cette équipe possèdera aussi bien des droits de lecture que d'écriture sur ses Référentiels.
teams.write_access_helper=Cette équipe possèdera aussi bien des droits de lecture que d'écriture sur ses dépôts.
teams.admin_access=Accès Administrateur
teams.admin_access_helper=Cette équipe possèdera des droits de lecture, d'écriture, ainsi que le pouvoir d'ajouter des collaborateurs.
teams.no_desc=Aucune description
teams.settings=Paramètres
teams.owners_permission_desc=Les propriétaires possèdent <strong>les droits d'administrateur</strong> et disposent d'un accès complet à <strong>tous les Référentiels</strong> de l'organisation.
teams.owners_permission_desc=Les propriétaires possèdent <strong>les droits d'administrateur</strong> et disposent d'un accès complet à <strong>tous les dépôts</strong> de l'organisation.
teams.members=Membres de L'Équipe
teams.update_settings=Valider
teams.delete_team=Supprimer cette Équipe
@@ -732,11 +790,11 @@ teams.add_team_member=Ajouter un Membre
teams.delete_team_title=Suppression de l'équipe
teams.delete_team_desc=Cette équipe sera supprimée. Les membres pourraient perdre leurs accès à certains dépôts.
teams.delete_team_success=Équipe supprimée avec succès.
teams.read_permission_desc=Cette équipe permet l'accès en <strong>lecture</strong> : les membres peuvent voir et dupliquer ses Référentiels.
teams.write_permission_desc=Cette équipe permet l'accès en <strong>écriture</strong> : les membres peuvent participer à ses Référentiels.
teams.admin_permission_desc=Cette équipe permet l'accès en <strong>administrateur</strong> : les membres peuvent voir, participer et ajouter des collaborateurs à ses Référentiels.
teams.repositories=Référentiels de l'Équipe
teams.search_repo_placeholder=Search repository...
teams.read_permission_desc=Cette équipe permet l'accès en <strong>lecture</strong> : les membres peuvent voir et dupliquer ses dépôts.
teams.write_permission_desc=Cette équipe permet l'accès en <strong>écriture</strong> : les membres peuvent participer à ses dépôts.
teams.admin_permission_desc=Cette équipe permet l'accès en <strong>administrateur</strong> : les membres peuvent voir, participer et ajouter des collaborateurs à ses dépôts.
teams.repositories=Dépôts de l'Équipe
teams.search_repo_placeholder=Rechercher dans le dépôt...
teams.add_team_repository=Ajouter un Dépôt à l'Équipe
teams.remove_repo=Supprimer
teams.add_nonexistent_repo=Dépôt inexistant, veuillez d'abord le créer.
@@ -745,19 +803,19 @@ teams.add_nonexistent_repo=Dépôt inexistant, veuillez d'abord le créer.
dashboard=Tableau de bord
users=Utilisateurs
organizations=Organisations
repositories=Référentiels
repositories=Dépôts
authentication=Authentifications
config=Configuration
notices=Notes Systèmes
monitor=Supervision
monitor=Surveillance
first_page=Première
last_page=Dernière
total=Total : %d
dashboard.statistic=Statistiques
dashboard.operations=Opérations
dashboard.system_status=État du Moniteur Système
dashboard.statistic_info=La base de données Gogs contient <b>%d</b> utilisateurs, <b>%d</b> organisations, <b>%d</b> clés publiques, <b>%d</b> Référentiels, <b>%d</b> suivis, <b>%d</b> votes, <b>%d</b> actions, <b>%d</b> accès, <b>%d</b> problèmes, <b>%d</b> commentaires, <b>%d</b> comptes de réseaux sociaux, <b>%d</b> abonnements, <b>%d</b> miroirs, <b>%d</b> publications, <b>%d</b> connexions d'origine, <b>%d</b> webhooks, <b>%d</b> milestones, <b>%d</b> labels, <b>%d</b> tâches hook, <b>%d</b> équipes, <b>%d</b> tâches de mise à jour, <b>%d</b> fichiers.
dashboard.system_status=État du système
dashboard.statistic_info=La base de données Gogs contient <b>%d</b> utilisateurs, <b>%d</b> organisations, <b>%d</b> clés publiques, <b>%d</b> dépôts, <b>%d</b> surveillances de dépôts, <b>%d</b> votes, <b>%d</b> actions, <b>%d</b> accès, <b>%d</b> tickets, <b>%d</b> commentaires, <b>%d</b> comptes de réseaux sociaux, <b>%d</b> abonnements, <b>%d</b> miroirs, <b>%d</b> versions, <b>%d</b> connexions d'origine, <b>%d</b> webhooks, <b>%d</b> versions, <b>%d</b> labels, <b>%d</b> tâches hook, <b>%d</b> équipes, <b>%d</b> tâches de mise à jour, <b>%d</b> fichiers.
dashboard.operation_name=Nom de l'Opération
dashboard.operation_switch=Basculer
dashboard.operation_run=Exécuter
@@ -765,16 +823,18 @@ dashboard.clean_unbind_oauth=Nettoyer les associations OAuthes
dashboard.clean_unbind_oauth_success=Tous unbind OAuthes ont été supprimés avec succès.
dashboard.delete_inactivate_accounts=Supprimer tous les comptes inactifs
dashboard.delete_inactivate_accounts_success=Tous les comptes inactifs ont été supprimés avec succès.
dashboard.delete_repo_archives=Supprimer toutes les archives de référentiels
dashboard.delete_repo_archives_success=Toutes les archives des référentiels ont été supprimées avec succès.
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.git_gc_repos=Collecter les déchets des référentiels
dashboard.delete_repo_archives=Supprimer toutes les archives des dépôts
dashboard.delete_repo_archives_success=Toutes les archives des dépôts ont été supprimées avec succès.
dashboard.delete_missing_repos=Supprimer tous les dépôts ayant perdu leurs fichiers Git
dashboard.delete_missing_repos_success=Tous les dépôts ayant perdu leurs fichiers Git ont été supprimés avec succès.
dashboard.git_gc_repos=Collecter les déchets des dépôts
dashboard.git_gc_repos_success=Tous les dépôts ont effectué la collecte avec succès.
dashboard.resync_all_sshkeys=Ré-écrire le fichier '.ssh/authorized_keys' (attention : les clés hors-Gogs vont être perdues)
dashboard.resync_all_sshkeys_success=Toutes les clés publiques ont été ré-écrites avec succès.
dashboard.resync_all_update_hooks=Ré-écrire tous les hooks de mises à jour des dépôts (requis quand le chemin de la configuration personnalisé est modifié)
dashboard.resync_all_update_hooks_success=Les mises à jour de hook des référentiels ont toutes été réécrites avec succès.
dashboard.resync_all_update_hooks_success=Tous les hooks de mises à jour des dépôts ont été ré-écris avec succès.
dashboard.reinit_missing_repos=Réinitialiser tous les dépôts qui ont perdu des fichiers Git
dashboard.reinit_missing_repos_success=Tous les enregistrements de dépôts qui ont perdu des fichiers Git ont été réinitialisés avec succès.
dashboard.server_uptime=Durée de Marche Serveur
dashboard.current_goroutine=Goroutines actuelles
@@ -822,6 +882,8 @@ users.auth_login_name=Nom d'utilisateur d'authentification
users.password_helper=Laissez-le vide pour ne pas changer.
users.update_profile_success=Profil mis à jour avec succès.
users.edit_account=Modifier le Compte
users.max_repo_creation=Nombre maximum de dépôts créés
users.max_repo_creation_desc=(Mettre à -1 pour utiliser la limite globale par défaut)
users.is_activated=Ce compte est activé
users.is_admin=Ce compte possède un niveau d'accès administrateur
users.allow_git_hook=Ce compte dispose des autorisations pour créer des crochets de Git
@@ -829,7 +891,7 @@ users.allow_import_local=Ce compte dispose des permissions nécessaire à l'impo
users.update_profile=Mettre à jour le profil
users.delete_account=Supprimer ce Compte
users.still_own_repo=Ce compte possède toujours des dépôts. Vous devez d'abord les supprimer ou les transférer.
users.still_has_org=Ce compte a toujours membres de l'organisation, vous avez à gauche ou supprimez tout d'abord.
users.still_has_org=Ce compte est toujours membre d'une ou plusieurs organisations. Vous devez d'abord les supprimer ou en retirer ce compte.
users.deletion_success=Le compte a été supprimé avec succès !
orgs.org_manage_panel=Gestion des Organisations
@@ -843,7 +905,7 @@ repos.name=Nom
repos.private=Privé
repos.watches=Suivi par
repos.stars=Votes
repos.issues=Problèmes
repos.issues=Tickets
auths.auth_manage_panel=Panel d'administration des authentifications
auths.new=Ajouter une nouvelle source d'authentification
@@ -861,9 +923,12 @@ auths.bind_password=Bind mot de passe
auths.bind_password_helper=Avertissement : Ce mot de passe est stocké en clair. N'utilisez pas le mot de passe d'un compte doté de privilèges élevés.
auths.user_base=Utilisateur Search Base
auths.user_dn=Utilisateur DN
auths.attribute_username=Attribut nom d'utilisateur
auths.attribute_username_placeholder=Laisser vide pour utiliser la valeur du formulaire d'authentification comme nom d'utilisateur.
auths.attribute_name=Attribut du prénom
auths.attribute_surname=Attribut du nom de famille
auths.attribute_mail=Attribut de l'e-mail
auths.attributes_in_bind=Aller chercher les attributs dans le contexte de liaison DN
auths.filter=Filtre utilisateur
auths.admin_filter=Filtre administrateur
auths.ms_ad_sa=Ms Ad SA
@@ -885,22 +950,36 @@ auths.update=Mettre à jour les paramètres d'authentifications
auths.delete=Supprimer cette authentification
auths.delete_auth_title=Suppression de l'authentification
auths.delete_auth_desc=Cette authentification va être supprimée. voulez-vous continuer ?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=L'authentification a été supprimée avec succès !
config.server_config=Configuration du Serveur
config.app_name=Nom de l'Application
config.app_ver=Version de l'Application
config.app_url=URL de l'Application
config.app_name=Nom de l'application
config.app_ver=Version de l'application
config.app_url=URL de l'application
config.domain=Domaine
config.offline_mode=Mode hors-ligne
config.disable_router_log=Désactiver la Journalisation du Routeur
config.run_user=Entrer un Utilisateur
config.run_user=Utilisateur système
config.run_mode=Mode d'Éxécution
config.repo_root_path=Emplacement des Dépôts
config.static_file_root_path=Emplacement Racine du Fichier Statique
config.static_file_root_path=Chemin statique des fichiers racines
config.log_file_root_path=Emplacement Racine du Fichier Journal
config.script_type=Type de Script
config.reverse_auth_user=Annuler l'Authentification de l'Utilisateur
config.ssh_config=Configuration SSH
config.ssh_enabled=Activé
config.ssh_start_builtin_server=Démarrer le serveur intégré
config.ssh_domain=Domaine
config.ssh_port=Port
config.ssh_listen_port=Port d'écoute
config.ssh_root_path=Emplacement racine
config.ssh_key_test_path=Emplacement de test des clés
config.ssh_keygen_path=Chemin vers le générateur de clefs ("ssh-keygen")
config.ssh_minimum_key_size_check=Minimum Key Size Check
config.ssh_minimum_key_sizes=Tailles de clé minimales
config.db_config=Configuration de la Base de Données
config.db_type=Type
config.db_host=Hôte
@@ -911,12 +990,11 @@ config.db_ssl_mode_helper=("postgres" uniquement)
config.db_path=Emplacement
config.db_path_helper=(pour « sqlite3 » et « TIDB »)
config.service_config=Configuration du Service
config.register_email_confirm=Nécessite une confirmation par courriel
config.disable_register=Désactiver l'Enregistrement
config.register_email_confirm=Nécessite une confirmation par e-mail
config.disable_register=Désactiver les inscriptions
config.show_registration_button=Afficher le bouton d'enregistrement
config.require_sign_in_view=Connexion Obligatoire pour Visualiser
config.enable_cache_avatar=Activer le Cache d'Avatar
config.mail_notify=Mailer les Notifications
config.require_sign_in_view=Connexion obligatoire pour visualiser
config.mail_notify=Notifier par mail
config.disable_key_size_check=Désactiver la vérification de la taille de clé minimale
config.enable_captcha=Activez le Captcha
config.active_code_lives=Limites de Code Actif
@@ -925,32 +1003,35 @@ config.webhook_config=Configuration Webhook
config.queue_length=Longueur de la file d'attente
config.deliver_timeout=Expiration d'Envoi
config.skip_tls_verify=Ne pas vérifier TLS
config.mailer_config=Configuration du Maileur
config.mailer_config=Configuration du service de mail
config.mailer_enabled=Activé
config.mailer_disable_helo=Désactiver HELO
config.mailer_name=Nom
config.mailer_host=Hôte
config.mailer_user=Utilisateur
config.send_test_mail=Envoyer courriel de Test
config.test_mail_failed=Impossible d'envoyer un e-mail de test à '%s': %v
config.test_mail_sent=Un e-mail de test à été envoyé à '%s'.
config.oauth_config=Configuration OAuth
config.oauth_enabled=Activé
config.cache_config=Configuration du Cache
config.cache_adapter=Adaptateur du Cache
config.cache_interval=Intervales du Cache
config.cache_conn=Liaison du Cache
config.session_config=Configuration de Session
config.session_provider=Fournisseur de Session
config.provider_config=Configurer le Fournisseur
config.cookie_name=Nom du Cookie
config.enable_set_cookie=Activer les Cookies
config.session_config=Configuration de session
config.session_provider=Fournisseur de session
config.provider_config=Configuration du fournisseur
config.cookie_name=Nom du cookie
config.enable_set_cookie=Activer les cookies
config.gc_interval_time=Intervals GC
config.session_life_time=Durée de Session
config.session_life_time=Durée des sessions
config.https_only=HTTPS uniquement
config.cookie_life_time=Expiration du Cookie
config.cookie_life_time=Expiration du cookie
config.picture_config=Configuration d'Image
config.picture_service=Service d'Imagerie
config.disable_gravatar=Désactiver Gravatar
config.log_config=Configuration du Journal
config.log_mode=Mode du Journal
config.log_mode=Mode du journal
monitor.cron=Tâches Cron
monitor.name=Nom
@@ -958,29 +1039,40 @@ monitor.schedule=Planification
monitor.next=Suivant
monitor.previous=Précédent
monitor.execute_times=Nombre d'Éxécutions
monitor.process=Processus en cours d'Éxécution
monitor.process=Processus en cours d'éxécution
monitor.desc=Description
monitor.start=Heure de Démarrage
monitor.execute_time=Heure d'Éxécution
notices.system_notice_list=Notes Systèmes
notices.view_detail_header=Voir les détails de la notification
notices.actions=Actions
notices.select_all=Tout Sélectionner
notices.deselect_all=Tous déselectionner
notices.inverse_selection=Inverser la sélection
notices.delete_selected=Supprimé les éléments sélectionnés
notices.delete_all=Supprimer toutes les notifications
notices.type=Type
notices.type_1=Dépôt
notices.desc=Description
notices.op=Opération
notices.delete_success=Note système supprimée avec succès.
notices.delete_success=Notifications système supprimées avec succès.
[action]
create_repo=a crée le dépôt <a href="%s">%s</a>
create_repo=a créé le dépôt <a href="%s">%s</a>
rename_repo=rebaptisé le dépôt de <code>%[1]s</code> à <a href="%[2]s">%[3]s</a>
commit_repo=a soumis à <a href="%[1]s/src/%[2]s">%[3]s</a> chez <a href="%[1]s">%[4]s</a>
commit_repo=a soumis à <a href="%[1]s/src/%[2]s">%[3]s</a> sur <a href="%[1]s">%[4]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>`
create_pull_request=`pull request créée le <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 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>
push_tag=a soumis le tag <a href="%s/src/%s">%[2]s</a> à <a href="%[1]s">%[3]s</a>
compare_2_commits=Comparer ces 2 commissions
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
[tool]
ago=auparavant

View File

@@ -15,7 +15,7 @@ template=Template
language=Lingua
create_new=Crea...
user_profile_and_more=Profilo utente e altro
signed_in_as=Signed in as
signed_in_as=Accesso effettuato come
username=Nome utente
email=E-mail
@@ -28,17 +28,18 @@ organization=Organizzazione
mirror=Mirror
new_repo=Nuovo Repository
new_migrate=Nuova Migrazione
new_mirror=Nuovo Mirror
new_fork=Nuovo Fork Repository
new_org=Nuova organizzazione
manage_org=Gestisci le organizzazioni
admin_panel=Pannello di amministrazione
account_settings=Impostazioni dell'account
settings=Impostazioni
your_profile=Profilo
your_profile=Il tuo profilo
your_settings=Impostazioni
news_feed=Notizie
pull_requests=Pull Requests
activities=Attivitá
pull_requests=Pull Request
issues=Problemi
cancel=Annulla
@@ -64,9 +65,9 @@ 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 or TiDB database.
err_empty_db_path=SQLite3 or TiDB database path cannot be empty.
err_invalid_tidb_name=TiDB database name does not allow characters "." and "-".
sqlite_helper=The file path of SQLite3 or TiDB database. <br>Please use absolute path when you start as service.
err_empty_db_path=Il percorso file del database SQLite3 o TiDB non può essere vuoto.
err_invalid_tidb_name=Il nome del database TiDB non ammette caratteri "." e "-".
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.
@@ -80,11 +81,13 @@ run_user_helper=L'utente deve avere accesso al percorso root del repository e av
domain=Dominio
domain_helper=Questo modifica lo SSH clone URLs.
ssh_port=Porta SSH
ssh_port_helper=Port number which your SSH server is using, leave it empty to disable SSH feature.
ssh_port_helper=Numero di porta utilizzato dal server SSH, lasciare vuoto per disabilitare l'integrazione SSH.
http_port=Porta HTTP
http_port_helper=Porta di ascolto dell'applicazione.
app_url=URL Applicazione
app_url_helper=Questo influisce sugli URL per il clonaggio via HTTP/HTTPS e da qualche parte nella posta elettronica.
log_root_path=Percorso dei log
log_root_path_helper=Directory in cui scrivere i file di log.
optional_title=Impostazioni Facoltative
email_title=Impostazioni E-mail
@@ -98,12 +101,12 @@ mail_notify=Abilita Notifiche via Email
server_service_title=Impostazioni del Server e Altri Servizi
offline_mode=Abilita Modalità Offline
offline_mode_popup=Disabilita il CDN anche in modalità produttiva, tutte le risorse saranno servite localmente.
disable_gravatar=Disable Gravatar Service
disable_gravatar_popup=Disable Gravatar and custom sources, all avatars are uploaded by users or default.
disable_gravatar=Disattiva il servizio Gravatar
disable_gravatar_popup=Disabilita Gravatar e sorgenti customizzate, tutti gli avatar vengono caricati dagli utenti o come predefinito.
disable_registration=Disabilita Registrazione Manuale
disable_registration_popup=Disabilita la registrazione manuale degli utenti, solo gli amministratori possono creare account.
enable_captcha=Abilita Captcha
enable_captcha_popup=Require validate captcha for user self-registration.
enable_captcha_popup=Richiedi convalida captcha per i nuovi utenti.
require_sign_in_view=Abilita Richiesta di Accesso per Vedere le Pagine
require_sign_in_view_popup=Solo gli utenti loggati possono vedere le pagine, i visitatori potranno vedere solo le pagine di accesso e registrazione.
admin_setting_desc=Non devi per forza creare un account admin proprio adesso, ma comunque l'utente ID=1 otterrà l'accesso da amministratore automaticamente.
@@ -111,7 +114,7 @@ admin_title=Impostazioni Account Amministratore
admin_name=Nome utente
admin_password=Password
confirm_password=Conferma Password
admin_email=Admin E-mail
admin_email=E-mail dell'Admin
install_gogs=Installare Gogs
test_git_failed=Fallito il test del comando git: %v
sqlite3_not_available=Questa versione non supporta SQLite3, si prega di scaricare la versione binaria ufficiale da %s, NON la versione gobuild.
@@ -121,6 +124,7 @@ run_user_not_match=Run user non è l'utente corrente: %s -> %s
save_config_failed=Fallito il salvataggio della configurazione: %v
invalid_admin_setting=Impostazioni account Admin non valide: %v
install_success=Benvenuto! Siamo felici che tu abbia scelto Gogs, buon divertimento.
invalid_log_root_path=Log root path is invalid: %v
[home]
uname_holder=Nome Utente o E-mail
@@ -164,7 +168,7 @@ activate_account=Per favore attiva il tuo account
activate_email=Verifica il tuo indirizzo e-mail
reset_password=Reimposta la tua password
register_success=Registrazione completata con successo, Benvenuto
register_notify=Welcome on board
register_notify=Benvenuti a bordo
[modal]
yes=
@@ -202,7 +206,6 @@ repo_name_been_taken=Il nome del Repository è già utilizzato.
org_name_been_taken=Il nome dell'Organizzazione è già utlizzato.
team_name_been_taken=Il nome del Team è già utilizzato.
email_been_used=L'indirizzo E-mail è già utilizzato.
illegal_team_name=Il nome del Team contiene caratteri non validi.
username_password_incorrect=Nome utente o password incorretti.
enterred_invalid_repo_name=Si prega di assicurarsi che il nome del repository inserito sia corretto.
enterred_invalid_owner_name=Si prega di assicurarsi che il nome del proprietario inserito sia corretto.
@@ -218,8 +221,6 @@ still_own_repo=Il tuo account possiede ancora almeno un repository, dovete prima
still_has_org=Il tuo account è ancora associato ad almeno un'organizzazione, disassociarsi prima.
org_still_own_repo=Questa organizzazione ha ancora la proprietà del repository, dovete cancellarla o trasferirli prima.
still_own_user=Questa autenticazione è ancora in uso da almeno un utente, per favore rimuovili dall'autenticazione e riprova.
target_branch_not_exist=Il ramo (branch) di destinazione non esiste.
[user]
@@ -231,6 +232,8 @@ activity=Attività pubblica
followers=Seguaci
starred=Votate
following=Seguiti
follow=Segui
unfollow=Non seguire più
form.name_reserved=L'username '%s' è riservato.
form.name_pattern_not_allowed=La struttura del nome utente '%s' non è consentita.
@@ -247,22 +250,22 @@ uid=Uid
public_profile=Profilo pubblico
profile_desc=Il tuo indirizzo e-mail è pubblico e sarà usato per ogni notifica inerente al tuo account, e per qualsiasi operazione web effettuata attraverso il sito.
password_username_disabled=Gli utenti non locali non possono cambiare il proprio nome utente.
full_name=Nome Completo
website=Sito web
location=Posizione
update_profile=Aggiorna Profilo
update_profile_success=Il tuo profilo è stato aggiornato con successo.
change_username=Username Cambiato
change_username_prompt=This change will affect the way how links relate to your account.
change_username_prompt=Questa modifica influenzerà il modo in cui i link si riferiscono al tuo account.
continue=Continua
cancel=Annulla
enable_custom_avatar=Abilita avatar personalizzato
enable_custom_avatar_helper=Seleziona per disabilitare il fetch da Gravatar
choose_new_avatar=Scegli un nuovo avatar
update_avatar=Aggiorna le impostazioni avatar
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=Il file caricato non è un'immagine.
no_custom_avatar_available=Nessun avatar personalizzato disponibile, impossibile abilitarlo.
update_avatar_success=Le tue impostazioni avatar sono state aggiornate con successo.
change_password=Cambia Password
@@ -271,6 +274,7 @@ new_password=Nuova Password
retype_new_password=Re-inserisci la password
password_incorrect=La Password attuale non è corretta.
change_password_success=La tua password è stata cambiata con successo. Ora puoi accedere usando la nuova password.
password_change_disabled=Gli utenti non locali non possono cambiare la propria password.
emails=Indirizzi e-mail
manage_emails=Gestisci indirizzi email
@@ -278,9 +282,9 @@ email_desc=Il tuo indirizzo e-mail primario sarà usato per le notifiche e altre
primary=Primario
primary_email=Imposta come primario
delete_email=Elimina
email_deletion=E-mail Deletion
email_deletion_desc=Delete this e-mail address will remove related information from your account. Do you want to continue?
email_deletion_success=E-mail has been deleted successfully!
email_deletion=Eliminazione e-mail
email_deletion_desc=La procedura di rimozione indirizzo email eliminerà tutte le informazioni correlate dal tuo account. Si desidera continuare?
email_deletion_success=Indirizzo e-mail eliminato con successo!
add_new_email=Aggiungi un nuovo indirizzo E-mail
add_email=Aggiungi E-mail
add_email_confirmation_sent=Una nuova email di conferma è stata inviata a '%s', per favore controlla la tua posta in arrivo nelle prossime %d ore per completare il processo di registrazione.
@@ -291,14 +295,14 @@ add_key=Aggiungi Chiave
ssh_desc=Questa è una lista di chiavi SSH associate al tuo account. Poiché queste chiavi consentono a chiunque di ottenere accesso alle tue repository, è molto importante che tu le riconosca.
ssh_helper=<strong>Non sai come?</strong> Controlla la guida di GitHub sul <a href="%s">creare le tue chiavi SSH</a> o sul risolvere <a href="%s">problemi frequenti</a> che potresti incontrare usando SSH.
add_new_key=Aggiungi Chiave SSH
ssh_key_been_used=Public key content has been used.
ssh_key_name_used=Public key with same name has already existed.
ssh_key_been_used=È stato utilizzato il contenuto della chiave pubblica.
ssh_key_name_used=Chiave pubblica con lo stesso nome esiste già.
key_name=Nome della Chiave
key_content=Contenuto
add_key_success=New SSH key '%s' has been added successfully!
add_key_success=La nuova chiave SSH '%s' è stata aggiunta con successo!
delete_key=Elimina
ssh_key_deletion=SSH Key Deletion
ssh_key_deletion_desc=Delete this SSH key will remove all related accesses for your account. Do you want to continue?
ssh_key_deletion=Eliminazione chiave SSH
ssh_key_deletion_desc=Cancellare la chiave SSH rimuoverà tutti i relativi accessi per il tuo account. Vuoi continuare?
ssh_key_deletion_success=La chiave SSH e' stata cancellata con successo!
add_on=Aggiunto il
last_used=Ultimo accesso il
@@ -313,15 +317,15 @@ unbind_success=Account sociale disassociato.
manage_access_token=Gestisci i Token di Accesso Personale
generate_new_token=Genera Nuovo Token
tokens_desc=Tokens you have generated that can be used to access the Gogs APIs.
tokens_desc=I Token che hai generato e che possono essere utilizzati per accedere alle API Gogs.
new_token_desc=Da questo momento, ogni token avrà pieno accesso al tuo account.
token_name=Nome Token
generate_token=Genera Token
generate_token_succees=Nuovo token di accesso generato con successo! Assicurarsi di copiare il nuovo token di accesso personale ora: non sarà possibile visualizzarlo nuovamente!
delete_token=Elimina
access_token_deletion=Personal Access Token Deletion
access_token_deletion_desc=Delete this personal access token will remove all related accesses of application. Do you want to continue?
delete_token_success=Personal access token has been removed successfully! Don't forget to update your application as well.
access_token_deletion=Eliminazione Token di accesso personale
access_token_deletion_desc=Eliminare questo token di accesso personale rimuoverà tutti i relativi accessi di applicazione. Si desidera continuare?
delete_token_success=Il token di accesso personale è stato eliminato! Non dimenticare di aggiornare anche l'applicazione.
delete_account=Elimina Account
delete_prompt=L'operazione eliminerà permanentemente l'account e <strong>NON POTRÀ</strong> essere annullata!
@@ -334,9 +338,9 @@ owner=Proprietario
repo_name=Nome Repository
repo_name_helper=I migliori nomi dei repository sono brevi, facili da memorizzare e <strong>univoci</strong>.
visibility=Visibilità
visiblity_helper=This repository is <span class="ui red text">Private</span>
visiblity_helper_forced=Site admin has forced all new repositories to be <span class="ui red text">Private</span>
visiblity_fork_helper=(Change of this value will affect all forks)
visiblity_helper=Questo repository è <span class="ui red text"> privato</span>
visiblity_helper_forced=L'amministratore del sito ha deciso che tutti i nuovi repository devono essere <span class="ui red text">privati</span>
visiblity_fork_helper=(La modifica di questo valore avrà effetto su tutti i fork)
clone_helper=Hai bisogno di aiuto per la clonazione? Visita <a target="_blank" href="%s">Aiuto</a>!
fork_repo=Forka Repository
fork_from=Forka da
@@ -348,32 +352,36 @@ license=Licenza
license_helper=Selezionare un file di licenza
readme=Readme
readme_helper=Seleziona un template per il readme
auto_init=Initialize this repository with selected files and template
auto_init=Inizializzare questo repository con i file e il modello selezionati
create_repo=Crea Repository
default_branch=Ramo (Branch) predefinito
mirror_interval=Intervallo Mirror (in ore)
watchers=Watchers
stargazers=Stargazers
forks=Forks
mirror_address=Indirizzo del mirror
mirror_address_desc=Si prega di includere nell'indirizzo le credenziali utente necessarie.
watchers=Osservatori
stargazers=Fan
forks=Fork
form.reach_limit_of_creation=Il proprietario ha raggiunto il limite massimo di %d repository creati.
form.name_reserved=Il nome repository %s è riservato.
form.name_pattern_not_allowed=La struttura del nome del repository %s non è consentita.
need_auth=Richiesta di autorizzazione
migrate_type=Tipo di migrazione
migrate_type_helper=This repository will be a <span class="text blue">mirror</span>
migrate_type_helper=Questo repository sarà un <span class="text blue">mirror</span>
migrate_repo=Migra Repository
migrate.clone_address=Duplica Indirizzo
migrate.clone_address_desc=This can be a HTTP/HTTPS/GIT URL or local server path.
migrate.permission_denied=You are not allowed to import local repositories.
migrate.clone_address_desc=Può essere un URL HTTP/HTTPS/GIT o il percorso del server locale.
migrate.permission_denied=Non è consentito importare repository locali.
migrate.invalid_local_path=Percorso locale non valido, non esiste o non è una cartella.
migrate.failed=Migration failed: %v
migrate.failed=Migrazione non riuscita: %v
mirror_from=mirror da
forked_from=forkato da
fork_from_self=Non puoi forkare il tuo stesso repository!
copy_link=Copia
copy_link_success=Copiato!
copy_link_error=Press ⌘-C or Ctrl-C to copy
copy_link_error=Premere ⌘-C o Ctrl-C per copiare
copied=OK copiato
unwatch=Non seguire più
watch=Segui
@@ -386,11 +394,12 @@ quick_guide=Guida rapida
clone_this_repo=Clona questo repository
create_new_repo_command=Crea nuovo repository da riga di comando
push_exist_repo=Push un repo esistente dalla riga di comando
repo_is_empty=This repository is empty, please come back later!
repo_is_empty=Questo repository è vuoto, si prega di tornare più tardi!
code=Codice
branch=Ramo (Branch)
tree=Albero (Tree)
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Filtra per branch o tag
branches=Rami (Branch)
tags=Tag
issues=Problemi
@@ -418,62 +427,62 @@ issues.new.labels=Etichette
issues.new.no_label=Nessuna etichetta
issues.new.clear_labels=Pulisci le etichette
issues.new.milestone=Traguardo
issues.new.no_milestone=No Milestone
issues.new.clear_milestone=Clear milestone
issues.new.open_milestone=Open Milestones
issues.new.closed_milestone=Closed Milestones
issues.new.no_milestone=Nessuna milestone
issues.new.clear_milestone=Milestone pulita
issues.new.open_milestone=Apri Milestone
issues.new.closed_milestone=Milestone chiuse
issues.new.assignee=Assegnatario
issues.new.clear_assignee=Clear assignee
issues.new.no_assignee=No assignee
issues.create=Create Issue
issues.new.clear_assignee=Cancella l'assegnatario
issues.new.no_assignee=Nessun assegnatario
issues.create=Crea Problema
issues.new_label=Nuova etichetta
issues.new_label_placeholder=Nome dell'etichetta...
issues.create_label=Create Label
issues.create_label=Crea Etichetta
issues.open_tab=%d Aperti
issues.close_tab=%d Chiusi
issues.filter_label=Etichetta
issues.filter_label_no_select=Nessuna etichetta selezionata
issues.filter_milestone=Traguardo
issues.filter_milestone_no_select=No selected milestone
issues.filter_milestone_no_select=Nessuna Milestone selezionata
issues.filter_assignee=Assegnatario
issues.filter_assginee_no_select=No selected Assignee
issues.filter_assginee_no_select=Nessun Assegnatario selezionato
issues.filter_type=Tipo
issues.filter_type.all_issues=Tutti i problemi
issues.filter_type.assigned_to_you=Assegnati a te
issues.filter_type.created_by_you=Creati da te
issues.filter_type.mentioning_you=Che ti riguardano
issues.filter_sort=Ordina
issues.filter_sort.latest=Newest
issues.filter_sort.oldest=Oldest
issues.filter_sort.recentupdate=Recently updated
issues.filter_sort.leastupdate=Least recently updated
issues.filter_sort.mostcomment=Most commented
issues.filter_sort.leastcomment=Least commented
issues.opened_by=opened %[1]s by <a href="%[2]s">%[3]s</a>
issues.opened_by_fake=opened %[1]s by %[2]s
issues.filter_sort.latest=Più recenti
issues.filter_sort.oldest=Più vecchi
issues.filter_sort.recentupdate=Aggiornati di recente
issues.filter_sort.leastupdate=Aggiornati tempo fa
issues.filter_sort.mostcomment=I più commentati
issues.filter_sort.leastcomment=I meno commentati
issues.opened_by=aperto %[1]s da <a href="/%[2]s">%[3]s</a>
issues.opened_by_fake=aperto %[1]s da %[2]s
issues.previous=Pagina precedente
issues.next=Pagina successiva
issues.open_title=Open
issues.closed_title=Closed
issues.num_comments=%d comments
issues.open_title=Aperto
issues.closed_title=Chiuso
issues.num_comments=%d commenti
issues.commented_at=`commented <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.no_content=There is no content yet.
issues.close_issue=Chiudi
issues.close_comment_issue=Comment and close
issues.reopen_issue=Reopen
issues.reopen_comment_issue=Comment and reopen
issues.close_comment_issue=Commenta e chiudi
issues.reopen_issue=Riapri
issues.reopen_comment_issue=Commenta e riapri
issues.create_comment=Commento
issues.closed_at=`closed <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`reopened <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Poster
issues.admin=Amministratore
issues.poster=Autore
issues.collaborator=Collaborator
issues.owner=Proprietario
issues.sign_up_for_free=Registrati gratuitamente
issues.sign_in_require_desc=to join this conversation. Already have an account? <a href="%s">Sign in to comment</a>
issues.edit=Edit
issues.edit=Modifica
issues.cancel=Cancel
issues.save=Save
issues.save=Salva
issues.label_title=Nome etichetta
issues.label_color=Colore etichetta
issues.label_count=%d etichette
@@ -484,34 +493,35 @@ issues.label_modify=Modifica Etichetta
issues.label_deletion=Elimina Etichetta
issues.label_deletion_desc=Eliminare l'etichetta rimuovera le sue informazioni in tutti i problemi correlati. Vuoi continuare?
issues.label_deletion_success=Etichetta eliminata con successo!
issues.num_participants=%d Partecipanti
pulls.new=New Pull Request
pulls.compare_changes=Compare Changes
pulls.compare_changes_desc=Compare two branches and make a pull request for changes.
pulls.new=Nuova Pull Request
pulls.compare_changes=Confronta le modifiche
pulls.compare_changes_desc=Confronta due branch e fai una pull request per le modifiche.
pulls.compare_base=base
pulls.compare_compare=compare
pulls.compare_compare=confronta
pulls.filter_branch=Filter branch
pulls.no_results=No results found.
pulls.no_results=Nessun risultato trovato.
pulls.nothing_to_compare=There is nothing to compare because base and head branches are even.
pulls.has_pull_request=`There is already a pull request between these two targets: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Crea Pull Request
pulls.title_desc=wants to merge %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code>
pulls.merged_title_desc=merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
pulls.tab_conversation=Conversation
pulls.tab_commits=Commits
pulls.tab_files=Files changed
pulls.reopen_to_merge=Please reopen this pull request to perform merge operation.
pulls.tab_conversation=Conversazione
pulls.tab_commits=Commit
pulls.tab_files=File modificati
pulls.reopen_to_merge=Riapri questa pull request per effettuare il merge.
pulls.merged=Merged
pulls.has_merged=This pull request has been merged successfully!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
pulls.is_checking=Il controllo dei conflitti è ancora in corso, per favore aggiorna pagina tra qualche istante.
pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Effettua il merge manualmente per risolvere i conflitti.
pulls.merge_pull_request=Unisci Pull Request
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
milestones.new=New Milestone
milestones.new=Nuova Milestone
milestones.open_tab=%d Open
milestones.close_tab=%d Closed
milestones.closed=Closed %s
@@ -519,21 +529,39 @@ milestones.no_due_date=No due date
milestones.open=Open
milestones.close=Close
milestones.new_subheader=Create milestones to organize your issues.
milestones.create=Create Milestone
milestones.title=Title
milestones.desc=Description
milestones.due_date=Due Date (optional)
milestones.create=Crea Milestone
milestones.title=Titolo
milestones.desc=Descrizione
milestones.due_date=Data di scadenza (opzionale)
milestones.clear=Clear
milestones.invalid_due_date_format=Due date format is invalid, must be 'yyyy-mm-dd'.
milestones.create_success=Milestone '%s' has been created successfully!
milestones.edit=Edit Milestone
milestones.edit_subheader=Use better description for milestones so people won't be confused.
milestones.cancel=Cancel
milestones.modify=Modify Milestone
milestones.edit_success=Changes of milestone '%s' has been saved successfully!
milestones.deletion=Milestone Deletion
milestones.deletion_desc=Delete this milestone will remove its information in all related issues. Do you want to continue?
milestones.deletion_success=Milestone has been deleted successfully!
milestones.invalid_due_date_format=Il formato della data di scadenza non è valido, deve essere 'yyyy-mm-dd'.
milestones.create_success=La Milestone '%s' è stata creata con successo!
milestones.edit=Modifica Milestone
milestones.edit_subheader=Scrivi una descrizione della Milestone, così la gente non si confonderà.
milestones.cancel=Annulla
milestones.modify=Modifica Milestone
milestones.edit_success=Le modifiche alla milestone '%s' sono state salvate con successo!
milestones.deletion=Cancellazione Milestone
milestones.deletion_desc=L'eliminazione di questa Milestone rimuoverà le sue informazioni in tutti i problemi correlati. Si desidera continuare?
milestones.deletion_success=La milestone è stata cancellata con successo!
wiki=Wiki
wiki.welcome=Benvenuto nel Wiki!
wiki.welcome_desc=Wiki è il posto dove puoi documentare collaborativamente il tuo progetto così da renderlo migliore.
wiki.create_first_page=Crea la prima pagina
wiki.page=Pagina
wiki.filter_page=Filtra pagina
wiki.new_page=Crea nuova pagina
wiki.default_commit_message=Scrivere una nota su questo aggiornamento (opzionale).
wiki.save_page=Salva pagina
wiki.last_commit_info=%s ha modificato questa pagina %s
wiki.edit_page_button=Modifica
wiki.new_page_button=Nuova pagina
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=Esiste già una pagina Wiki con questo stesso nome.
wiki.pages=Pagine
wiki.last_updated=Ultimo aggiornamento: %s
settings=Impostazioni
settings.options=Opzioni
@@ -541,23 +569,43 @@ settings.collaboration=Collaborazione
settings.hooks=Webhooks
settings.githooks=Git Hooks
settings.basic_settings=Impostazioni di Base
settings.danger_zone=Zona Pericolosa
settings.site=Sito Ufficiale
settings.update_settings=Aggiorna Impostazioni
settings.change_reponame_prompt=This change will affect how links relate to the repository.
settings.change_reponame_prompt=Questa modifica influirà i link al repository.
settings.advanced_settings=Opzioni avanzate
settings.wiki_desc=Abilitare il wiki per consentire alle persone di scrivere documenti
settings.use_external_wiki=Usa Wiki esterno
settings.external_wiki_url=URL Wiki esterno
settings.external_wiki_url_desc=I visitatori verranno reindirizzati all'URL quando cliccano sulla scheda.
settings.issues_desc=Enable builtin lightweight issue tracker
settings.use_external_issue_tracker=Utilizza gestore di problemi esterno
settings.tracker_url_format=External Issue Tracker URL Format
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=Zona Pericolosa
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=Convert To Regular Repository
settings.convert_desc=You can convert this mirror to a regular repository. This cannot be reversed.
settings.convert_notices_1=- This operation will convert this repository mirror into a regular repository and cannot be undone.
settings.convert_confirm=Conferma la conversione
settings.convert_succeed=Repository has been converted to regular type successfully.
settings.transfer=Trasferisci proprietà
settings.transfer_desc=Trasferisci questa repository a un altro utente o a un'organizzazione nella quale hai diritti d'amministratore.
settings.new_owner_has_same_repo=Il nuovo proprietario ha già un repository con lo stesso nome. Per favore scegli un altro nome.
settings.delete=Elimina questo repository
settings.delete_desc=Una volta che hai cancellato il repository, non puoi tornare indietro. Si prega di fare attenzione.
settings.transfer_notices_1=- You will lose access if new owner is a individual user.
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title=Please enter following information to confirm your operation:
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
settings.transfer_form_title=Per favore inserisci le informazioni seguenti per confermare l'operazione:
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=Elimina questo repository
settings.delete_desc=Una volta che hai cancellato il repository, non puoi tornare indietro. Si prega di fare attenzione.
settings.delete_notices_1=-Questa operazione <strong>NON PUÒ</strong> essere annullata.
settings.delete_notices_2=-Questa operazione eliminerà definitivamente il tutto il contenuto del repository, inclusi i dati di Git, incidenti, commenti e accessi dei collaboratori.
settings.delete_notices_fork_1=-Se questo repository è pubblico, tutti i fork diventeranno indipendenti dopo la sua cancellazione.
settings.delete_notices_fork_2=-Se questo repository è privato, tutti fork verranno rimossi assieme ad esso.
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first.
settings.deletion_success=Il repository è stato eliminato con successo!
settings.update_settings_success=Le opzioni repository sono state aggiornate con successo.
settings.transfer_owner=Nuovo Proprietario
settings.make_transfer=Trasferisci
@@ -565,14 +613,21 @@ settings.transfer_succeed=Proprietà del repository trasferita con successo.
settings.confirm_delete=Conferma eliminazione
settings.add_collaborator=Aggiungi nuovo collaboratore
settings.add_collaborator_success=Il nuovo collaboratore è stato aggiunto.
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=Il collaboratore è stato rimosso.
settings.search_user_placeholder=Search user...
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=Delete Webhook
settings.webhook_deletion=Elimina Webhook
settings.webhook_deletion_desc=Delete this webhook will remove its information and all delivery history. Do you want to continue?
settings.webhook_deletion_success=Webhook has been deleted successfully!
settings.webhook.test_delivery=Test Delivery
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
settings.webhook.request=Request
settings.webhook.response=Response
settings.webhook.headers=Headers
@@ -588,13 +643,13 @@ settings.payload_url=Payload URL
settings.content_type=Content Type
settings.secret=Secret
settings.slack_username=Username
settings.slack_icon_url=Icon URL
settings.slack_color=Color
settings.slack_icon_url=URL icona
settings.slack_color=Colore
settings.event_desc=Quali eventi dovrebbero innescare questo webhook?
settings.event_push_only=Solo l'evento <code>push</code>.
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=Crea
settings.event_create_desc=Branch, or tag created
settings.event_push=Push
settings.event_push_desc=Git push to a repository
@@ -612,14 +667,15 @@ settings.slack_domain=Dominio
settings.slack_channel=Canale
settings.deploy_keys=Dispiega Chiavi
settings.add_deploy_key=Add Deploy Key
settings.no_deploy_keys=You haven't added any deploy key.
settings.deploy_key_desc=Deploy keys have read-only access. They are not the same as personal account SSH keys.
settings.no_deploy_keys=You haven't added any deploy keys.
settings.title=Title
settings.deploy_key_content=Content
settings.key_been_used=Deploy key content has been used.
settings.key_name_used=Deploy key with same name has already existed.
settings.key_name_used=Deploy key with the same name already exists.
settings.add_key_success=New deploy key '%s' has been added successfully!
settings.deploy_key_deletion=Delete Deploy Key
settings.deploy_key_deletion_desc=Delete this deploy key will remove all related accesses for this repository. Do you want to continue?
settings.deploy_key_deletion_desc=Deleting this deploy key will remove all related accesses for this repository. Do you want to continue?
settings.deploy_key_deletion_success=Deploy key has been deleted successfully!
diff.browse_source=Sfoglia il codice sorgente
@@ -627,6 +683,8 @@ diff.parent=parent
diff.commit=commit
diff.data_not_available=Diff Data non disponibile.
diff.show_diff_stats=Mostra Diff Stats
diff.show_split_view=Split View
diff.show_unified_view=Unified View
diff.stats_desc=<strong>%d ha cambiato i file</strong> con <strong>%d aggiunte</strong> e <strong>%d eliminazioni</strong>
diff.bin=BIN
diff.view_file=Vedi File
@@ -657,14 +715,14 @@ release.save_draft=Salva Bozza
release.edit_release=Modifica Rilascio
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_desc=Deleting this release will delete the corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.tag_name_already_exist=Un rilascio con questo tag esiste già.
release.downloads=Downloads
release.downloads=Download
[org]
org_name_holder=Nome dell'Organizzazione
org_full_name_holder=Organization Full Name
org_full_name_holder=Nome completo dell'organizzazione
org_name_helper=Le migliori organizzazioni hanno nomi brevi e memorabili.
create_org=Crea Organizzazione
repo_updated=Aggiornato
@@ -711,7 +769,7 @@ members.owner=Proprietario
members.member=Membro
members.remove=Rimuovere
members.leave=Abbandona
members.invite_desc=Add a new member to %s:
members.invite_desc=Aggiungi un nuovo membro a %s:
members.invite_now=Invita ora
teams.join=Iscriviti
@@ -750,9 +808,9 @@ authentication=Autenticazioni
config=Configurazione
notices=Avvisi di sistema
monitor=Monitoraggio
first_page=First
last_page=Last
total=Total: %d
first_page=Prima
last_page=Ultima
total=Totale: %d
dashboard.statistic=Statistiche
dashboard.operations=Operazioni
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys=Riscrivi il file '.ssh/authorized_keys' (attenzione
dashboard.resync_all_sshkeys_success=Tutte le chiavi pubbliche riscritte con successo.
dashboard.resync_all_update_hooks=Riscrivere tutti gli update hook dei repository (necessario quando il percorso di configurazione personalizzata viene modificato)
dashboard.resync_all_update_hooks_success=Tutti gli update hook dei repository riscritti con successo.
dashboard.reinit_missing_repos=Reinitialize all repository records that lost Git files
dashboard.reinit_missing_repos_success=All repository records that lost Git files have been reinitialized successfully.
dashboard.server_uptime=Tempo in Attività del Server
dashboard.current_goroutine=Goroutine Correnti
@@ -814,7 +874,7 @@ users.admin=Amministratore
users.repos=Repo
users.created=Creato
users.send_register_notify=Send Registration Notification To User
users.new_success=New account '%s' has been created successfully.
users.new_success=Il nuovo account '%s' è stato creato correttamente.
users.edit=Modifica
users.auth_source=Authentication Source
users.local=Locale
@@ -822,15 +882,17 @@ users.auth_login_name=Authentication Login Name
users.password_helper=Leave it empty to remain unchanged.
users.update_profile_success=Profilo dell'account aggiornato con successo.
users.edit_account=Modifica Account
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Questo account è attivato
users.is_admin=Questo account ha permessi di amministratore
users.allow_git_hook=Questo account ha il permesso di creare hooks di Git
users.allow_import_local=This account has permissions to import local repositories
users.allow_import_local=Questo account dispone delle autorizzazioni per importare repository locali
users.update_profile=Aggiornare Profilo Account
users.delete_account=Elimina Questo Account
users.still_own_repo=Questo account possiede ancora almeno un repository, devi prima cancellarli o trasferirli.
users.still_has_org=Questo account appartiene ancora ad almeno un'organizzazione, è necessario prima abbandonarle o eliminale.
users.deletion_success=Account has been deleted successfully!
users.deletion_success=Account eliminato correttamente!
orgs.org_manage_panel=Pannello Gestione Organizzazioni
orgs.name=Nome
@@ -861,19 +923,22 @@ auths.bind_password=Bind Password
auths.bind_password_helper=Warning: This password is stored in plain text. Do not use a high privileged account.
auths.user_base=User Search Base
auths.user_dn=User DN
auths.attribute_username=Username attribute
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
auths.attribute_name=Attributo Nome
auths.attribute_surname=Attributo Cognome
auths.attribute_mail=Attributo Email
auths.attributes_in_bind=Fetch attributes in Bind DN context
auths.filter=User Filter
auths.admin_filter=Admin Filter
auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP Authentication Type
auths.smtphost=Host SMTP
auths.smtpport=Porta SMTP
auths.allowed_domains=Allowed Domains
auths.allowed_domains=Domini consentiti
auths.allowed_domains_helper=Leave it empty to not restrict any domains. Multiple domains should be separated by comma ','.
auths.enable_tls=Abilitare Crittografia TLS
auths.skip_tls_verify=Skip TLS Verify
auths.skip_tls_verify=Salta verifica TLS
auths.pam_service_name=Nome del Servizio PAM
auths.enable_auto_register=Abilitare Registrazione Automatica
auths.tips=Consigli
@@ -885,6 +950,7 @@ auths.update=Update Authentication Setting
auths.delete=Delete This Authentication
auths.delete_auth_title=Authentication Deletion
auths.delete_auth_desc=This authentication is going to be deleted, do you want to continue?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=Authentication has been deleted successfully!
config.server_config=Configurazione Server
@@ -901,6 +967,19 @@ config.static_file_root_path=Percorso Root del File Statico
config.log_file_root_path=Percorso Root del File di Log
config.script_type=Tipo di Script
config.reverse_auth_user=Autenticazione Utente Inversa
config.ssh_config=Configurazione SSH
config.ssh_enabled=Enabled
config.ssh_start_builtin_server=Start Builtin Server
config.ssh_domain=Domain
config.ssh_port=Porta
config.ssh_listen_port=Porta in ascolto
config.ssh_root_path=Root Path
config.ssh_key_test_path=Key Test Path
config.ssh_keygen_path=Keygen ('ssh-keygen') Path
config.ssh_minimum_key_size_check=Minimum Key Size Check
config.ssh_minimum_key_sizes=Minimum Key Sizes
config.db_config=Configurazione Database
config.db_type=Tipo
config.db_host=Host
@@ -909,16 +988,15 @@ config.db_user=Utente
config.db_ssl_mode=Modalità SSL
config.db_ssl_mode_helper=(solo per "postgres")
config.db_path=Percorso
config.db_path_helper=(for "sqlite3" and "tidb")
config.db_path_helper=(per "sqlite3" e "tidb")
config.service_config=Configurazione Servizio
config.register_email_confirm=Richiedono Conferma dell'Email
config.disable_register=Disabilita Registrazione
config.show_registration_button=Mostra Pulsane Registrazione
config.require_sign_in_view=Richiesto Accesso per Vedere
config.enable_cache_avatar=Abilitare Cache dell'Avatar
config.mail_notify=Email di Notifica
config.disable_key_size_check=Disable Minimum Key Size Check
config.enable_captcha=Enable Captcha
config.enable_captcha=Abilita Captcha
config.active_code_lives=Attiva Vita del Codice
config.reset_password_code_lives=Reimpostare Password della Vita del Codice
config.webhook_config=Configurazione Webhook
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Disattiva HELO
config.mailer_name=Nome
config.mailer_host=Host
config.mailer_user=Utente
config.send_test_mail=Invia email di test
config.test_mail_failed=Fail to send test email to '%s': %v
config.test_mail_sent=Test email has been sent to '%s'.
config.oauth_config=Configurazione OAuth
config.oauth_enabled=Attivo
config.cache_config=Configurazione Cache
@@ -964,23 +1045,34 @@ monitor.start=Orario Avvio
monitor.execute_time=Tempo di Esecuzione
notices.system_notice_list=Avvisi di Sistema
notices.view_detail_header=View Notice Detail
notices.actions=Actions
notices.select_all=Seleziona tutto
notices.deselect_all=Deseleziona tutto
notices.inverse_selection=Inverti selezione
notices.delete_selected=Elimina selezionati
notices.delete_all=Delete All Notices
notices.type=Tipo
notices.type_1=Repository
notices.desc=Descrizione
notices.op=Op.
notices.delete_success=Avviso di sistema cancellato con successo.
notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=ha creato il repository <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]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>
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>`
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>
push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_2_commits=Vedi confronto per questi 2 commit
compare_commits=View comparison for these %d commits
[tool]
ago=fa
@@ -1006,6 +1098,6 @@ raw_minutes=minuti
[dropzone]
default_message=Drop files here or click to upload.
invalid_input_type=You can't upload files of this type.
file_too_big=File size({{filesize}} MB) exceeds maximum size({{maxFilesize}} MB).
file_too_big=File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
remove_file=Remove file

View File

@@ -28,6 +28,7 @@ organization=組織
mirror=ミラー
new_repo=新しいリポジトリ
new_migrate=新しい移行
new_mirror=新しいミラー
new_fork=新しいフォークのリポジトリ
new_org=新しい組織
manage_org=組織を管理
@@ -37,7 +38,7 @@ settings=設定
your_profile=あなたのプロファイル
your_settings=あなたの設定
news_feed=ニュースのフィード
activities=Activities
pull_requests=プルリクエスト
issues=課題
@@ -64,10 +65,10 @@ db_name=データベース名
db_helper=Mysql INNODB エンジン utf8_general_ci の文字セットを使用してください。
ssl_mode=SSL モード
path=パス
sqlite_helper=SQLite3 または TiDB のデータベースのファイル パス。
sqlite_helper=The file path of SQLite3 or TiDB database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 または TiDB データベースのパスを空にすることはできません。
err_invalid_tidb_name=TiDB データベース名は文字"."と"-"を許可しない。
no_admin_and_disable_registration=You cannot disable registration without creating an admin account.
no_admin_and_disable_registration=管理者アカウントを作成せずに登録を無効にすることはできません。
err_empty_admin_password=管理者パスワードは空白にできません。
general_title=Gogs の全般設定
@@ -85,6 +86,8 @@ http_port=HTTP ポート
http_port_helper=アプリケーションが待ち受けするポート番号。
app_url=アプリケーションの URL
app_url_helper=この設定は、HTTP / HTTPSのクローンURLおよび、一部のメールボックスへのリンクに影響を与えます。
log_root_path=Log Path
log_root_path_helper=Directory to write log files to.
optional_title=オプション設定
email_title=E-mailサービス設定
@@ -121,6 +124,7 @@ run_user_not_match=実行ユーザーは、現在のユーザーではない: %s
save_config_failed=構成の保存に失敗した: %v
invalid_admin_setting=管理者アカウントの設定が無効です: %v
install_success=ようこそ!我々はあなたが Gogs を選んでくれて嬉しいです!楽しみましょう!
invalid_log_root_path=Log root path is invalid: %v
[home]
uname_holder=ユーザー名またはEメール
@@ -202,7 +206,6 @@ repo_name_been_taken=リポジトリ名は既に使用されています。
org_name_been_taken=組織名は既に使用されています。
team_name_been_taken=チーム名は既に使用されています。
email_been_used=電子メール アドレスは既に使用されています。
illegal_team_name=チーム名に無効な文字が含まれています。
username_password_incorrect=ユーザー名またはパスワードが正しくありません。
enterred_invalid_repo_name=入力したリポジトリの名前が正しいかどうかを確認してください。
enterred_invalid_owner_name=入力された所有者名が正しいかどうかを確認してください。
@@ -218,8 +221,6 @@ still_own_repo=アカウント所有のリポジトリがあり、リポジト
still_has_org=アカウントはまだ組織のメンバーであり、組織から退出するか削除する必要があります。
org_still_own_repo=この組織はまだリポジトリの所有しています、リポジトリを削除または転送する必要があります。
still_own_user=この認証はまだ一部のユーザーによって使用されています。一部のユーザを移動させてから、もう一度削除してください。
target_branch_not_exist=ターゲットブランチが存在しない
[user]
@@ -231,6 +232,8 @@ activity=パブリック・アクティビティ
followers=フォロワー
starred=スター
following=フォロー
follow=フォロー
unfollow=フォロー解除
form.name_reserved=ユーザー名 '%s' は予約されています。
form.name_pattern_not_allowed=ユーザ名のパターン '%s' は許可されていません。
@@ -247,6 +250,7 @@ uid=Uid
public_profile=パブリック プロフィール
profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。
password_username_disabled=ローカルユーザ以外はユーザ名を変更できません。
full_name=フルネーム
website=WEBサイト
location=ロケーション
@@ -258,11 +262,10 @@ continue=続行
cancel=キャンセル
enable_custom_avatar=カスタムのアバターを有効にする
enable_custom_avatar_helper=Gravatarからのフェッチを無効にするのを、有効にします
choose_new_avatar=新しいアバターを選択
update_avatar=アバターの設定を更新
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=アップロードされたファイルは画像ではない。
no_custom_avatar_available=利用可能なカスタム アバターがないため、有効にできません。
update_avatar_success=あなたのアバターの設定が更新されました。
change_password=パスワードを変更
@@ -271,6 +274,7 @@ new_password=新しいパスワード
retype_new_password=新しいパスワードを再入力します。
password_incorrect=現在のパスワードが正しくありません。
change_password_success=パスワードが正常に変更されました。今すぐ新しいパスワード経由でサインインすることができます。
password_change_disabled=ローカルユーザ以外はパスワードを変更できません。
emails=E-mail アドレス
manage_emails=E-mail アドレスを管理
@@ -352,10 +356,13 @@ auto_init=選択されたファイルおよびテンプレートでリポジト
create_repo=リポジトリを作成
default_branch=デフォルトのブランチ
mirror_interval=ミラー 間隔(時)
watchers=Watchers
mirror_address=ミラー アドレス
mirror_address_desc=Please include necessary user credentials in the address.
watchers=ウォッチャー
stargazers=Stargazers
forks=Forks
forks=フォーク
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=リポジトリ名 '%s' は予約されています。
form.name_pattern_not_allowed=リポジトリ名のパターン '%s' は許可されていません。
@@ -365,10 +372,11 @@ migrate_type_helper=このリポジトリは、<span class="text blue"> ミラ
migrate_repo=リポジトリを移行
migrate.clone_address=クローンアドレス
migrate.clone_address_desc=これは、HTTP/HTTPS/GIT URL またはローカル サーバー パスを設定できます。
migrate.permission_denied=You are not allowed to import local repositories.
migrate.permission_denied=ローカル リポジトリをインポートすることはできません。
migrate.invalid_local_path=ローカルパスが無効です。存在しないかディレクトリではありません。
migrate.failed=Migration failed: %v
migrate.failed=移行に失敗しました: %v
mirror_from=mirror of
forked_from=フォーク元
fork_from_self=すでにあなたの所有しているリポジトリはフォークできません
copy_link=コピー
@@ -388,9 +396,10 @@ create_new_repo_command=コマンドラインで新しいリポジトリを作
push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ
repo_is_empty=このリポジトリは空です、後で戻って来て下さい!
code=コード
branch=ブランチ
tree=ツリー
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=ブランチまたはタグをフィルタリング
branches=ブランチ
tags=タグ
issues=課題
@@ -446,7 +455,7 @@ issues.filter_sort=並べ替え
issues.filter_sort.latest=最新
issues.filter_sort.oldest=最も古い
issues.filter_sort.recentupdate=最近更新された
issues.filter_sort.leastupdate=Least recently updated
issues.filter_sort.leastupdate=つい最近更新
issues.filter_sort.mostcomment=一番多いコメント
issues.filter_sort.leastcomment=一番少ないコメント
issues.opened_by=opened %[1]s by <a href="%[2]s">%[3]s</a>
@@ -456,7 +465,7 @@ issues.next=次ページ
issues.open_title=オープン
issues.closed_title=クローズ
issues.num_comments=%d コメント
issues.commented_at=`commented <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commented_at=`コメント <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.no_content=まだコンテンツがありません
issues.close_issue=閉じる
issues.close_comment_issue=コメントと閉じる
@@ -467,7 +476,7 @@ issues.closed_at=`closed <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`reopened <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=ポスター
issues.admin=アドミン
issues.collaborator=Collaborator
issues.owner=オーナー
issues.sign_up_for_free=無料でサインアップ
issues.sign_in_require_desc=to join this conversation. Already have an account? <a href="%s">Sign in to comment</a>
@@ -484,8 +493,9 @@ issues.label_modify=ラベルの変更
issues.label_deletion=ラベルの削除
issues.label_deletion_desc=ラベルを削除すると、関連するすべての問題の情報が削除されます。続行しますか。
issues.label_deletion_success=ラベルは正常に削除されました。
issues.num_participants=%d Participants
pulls.new=New Pull Request
pulls.new=新しいプルリクエスト
pulls.compare_changes=変更を比較
pulls.compare_changes_desc=2つのブランチを比較し、プルリクエストを作成します。
pulls.compare_base=ベース
@@ -505,9 +515,9 @@ pulls.merged=マージされた
pulls.has_merged=このプルプルリクエストは正常にマージされました!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
pulls.cannot_auto_merge_helper=それを解決するためにコマンド ライン ツールを使用してください
pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=競合を解決するためには、手動でマージする必要があります
pulls.merge_pull_request=プルリクエストをマージします。
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@@ -535,29 +545,67 @@ milestones.deletion=マイルス トーンの削除
milestones.deletion_desc=このマイルス トーンを削除すると、関連課題に該当情報が削除されます。続行しますか。
milestones.deletion_success=マイルス トーンは正常に削除されました。
wiki=Wiki
wiki.welcome=Wiki へようこそ!
wiki.welcome_desc=Wikiとは、あなたのプロジェクトを文書化し、複数人で一緒に編集する場所です。
wiki.create_first_page=最初のページを作成する。
wiki.page=ページ
wiki.filter_page=フィルターページ
wiki.new_page=新しいページを作成
wiki.default_commit_message=このアップデートについてメモを書く(オプション)
wiki.save_page=ページを保存
wiki.last_commit_info=%s このページを編集 %s
wiki.edit_page_button=編集
wiki.new_page_button=新規ページ
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=既に同じ名前のWiki ページが存在します。
wiki.pages=ページ
wiki.last_updated=最終更新 %s
settings=設定
settings.options=オプション
settings.collaboration=コラボレーション
settings.hooks=Webhooks
settings.githooks=Git のフック
settings.basic_settings=基本設定
settings.danger_zone=危険地帯
settings.site=公式サイト
settings.update_settings=設定の更新
settings.change_reponame_prompt=この変更はリンクがリポジトリに関連付ける方法に影響します。
settings.advanced_settings=拡張設定
settings.wiki_desc=Wikiでドキュメントの作成を許可
settings.use_external_wiki=外部 wiki を使用します。
settings.external_wiki_url=外部 Wiki の URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=組み込み簡易課題トラッカーを有効
settings.use_external_issue_tracker=外部課題トラッキングシステムを使用
settings.tracker_url_format=外部課題トラッキングツール URLのフォーマット
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.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.
settings.convert_notices_1=- This operation will convert this repository mirror into a regular repository and cannot be undone.
settings.convert_confirm=Confirm Conversion
settings.convert_succeed=Repository has been converted to regular type successfully.
settings.transfer=オーナー移転
settings.transfer_desc=リポジトリをあなたが管理者権限を持っている別のユーザーまた組織に移譲します。
settings.new_owner_has_same_repo=新しいオーナーは、既に同じ名前のリポジトリを持っています。
settings.delete=このリポジトリを削除
settings.delete_desc=リポジトリを削除すると元に戻せません。確実に確認してください。
settings.transfer_notices_1=-新しい所有者が個人ユーザーの場合、あなたがアクセスできなくなります。
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title=操作を確認するために、以下の情報を入力してください。
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=このリポジトリを削除
settings.delete_desc=リポジトリを削除すると元に戻せません。確実に確認してください。
settings.delete_notices_1=-この操作は<strong>元に戻せません</strong> 。
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
settings.delete_notices_fork_1=- If this repository is public, all forks will become independent after deletion.
settings.delete_notices_fork_2=もしプライペートリポジトリの場合、全てのフォークも同時に削除されます。
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first.
settings.deletion_success=Repository has been deleted successfully!
settings.update_settings_success=リポジトリ オプションが更新されました。
settings.transfer_owner=新しいオーナー
settings.make_transfer=転送
@@ -565,14 +613,21 @@ settings.transfer_succeed=リポジトリの所有権は正常に転送されま
settings.confirm_delete=削除の確認
settings.add_collaborator=新しい共同編集者を追加
settings.add_collaborator_success=新しい共同編集者が追加されました。
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=共同編集者が削除されました。
settings.search_user_placeholder=Search user...
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 を削除
settings.webhook_deletion_desc=このwebhookを削除すると、すべての情報と配信履歴が削除されます。続行しますか
settings.webhook_deletion_success=Webhook が正常に削除されました。
settings.webhook.test_delivery=テスト配信
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
settings.webhook.request=リクエスト
settings.webhook.response=レスポンス
settings.webhook.headers=ヘッダ
@@ -612,6 +667,7 @@ settings.slack_domain=ドメイン
settings.slack_channel=チャンネル
settings.deploy_keys=デプロイキー
settings.add_deploy_key=デプロイキーを追加
settings.deploy_key_desc=個人アカウントのSSHキーとは異なり、デプロイキーは読み取り専用アクセスとなります。
settings.no_deploy_keys=でプロキーは1つも追加されていません。
settings.title=タイトル
settings.deploy_key_content=コンテント
@@ -627,6 +683,8 @@ diff.parent=親
diff.commit=コミット
diff.data_not_available=差分データは利用できません。
diff.show_diff_stats=差分情報を表示
diff.show_split_view=分割表示
diff.show_unified_view=Unified View
diff.stats_desc=共有<strong>%d 個のファイルを変更した</strong>、<strong>%d 個の追加</strong> と <strong>%d 個の削除</strong>を含む
diff.bin=BIN
diff.view_file=ファイルの表示
@@ -640,25 +698,25 @@ release.edit=編集
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
release.source_code=ソース コード
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.edit_subheader=詳細な変更ログは、ユーザーに何が改善されたかの理解を助けることができます。
release.tag_name=タグ名
release.target=ターゲット
release.tag_helper=既存のタグを選択するか、新しいタグを作成し発行します。
release.title=Title
release.content=Content
release.title=タイトル
release.content=コンテント
release.write=書込み
release.preview=プレビュー
release.loading=読み込み中…
release.prerelease_desc=これはリリース前のものです
release.prerelease_helper=このリリースは非プロダクション利用として識別します。
release.cancel=Cancel
release.cancel=キャンセル
release.publish=リリースを発行
release.save_draft=下書きを保存
release.edit_release=リリースを編集
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.delete_release=このリリースを削除
release.deletion=リリースの削除
release.deletion_desc=このリリースを削除すると、対応するGitのタグも削除されます。よろしいですか
release.deletion_success=リリースが正常に削除されました。
release.tag_name_already_exist=このタグ名には既にリリースが存在します。
release.downloads=Downloads
@@ -692,7 +750,7 @@ settings.location=ロケーション
settings.update_settings=設定の更新
settings.update_setting_success=組織の設定が更新されました。
settings.change_orgname_prompt=This change will affect how links relate to the organization.
settings.update_avatar_success=Organization avatar setting has been updated successfully.
settings.update_avatar_success=組織のアバター画像が正常に更新されました。
settings.delete=組織を削除
settings.delete_account=この組織を削除
settings.delete_prompt=操作はこの組織を完全に削除し、復旧<strong>できない</strong>
@@ -706,12 +764,12 @@ members.public=パブリック
members.public_helper=プライベートにする
members.private=プライベート
members.private_helper=公開する
members.member_role=Member Role:
members.member_role=メンバーの役割:
members.owner=オーナー
members.member=メンバー
members.remove=削除
members.leave=退出
members.invite_desc=Add a new member to %s:
members.invite_desc=%s に新しいメンバーを追加
members.invite_now=今すぐ招待
teams.join=参加
@@ -736,7 +794,7 @@ teams.read_permission_desc=このチームは<strong>読み取り</strong>権限
teams.write_permission_desc=このチームは<strong>書き込み</strong>権限を持ち: メンバーはリポジトリの表示及リポジトリへのプッシュができます。
teams.admin_permission_desc=このチームは<strong>管理者</strong>の権限を持ち: メンバーはチームのリポジトリに対して、読み取り、プッシュや共同編集者の追加ができます。
teams.repositories=チームのリポジトリ
teams.search_repo_placeholder=Search repository...
teams.search_repo_placeholder=リポジトリを検索
teams.add_team_repository=チームのリポジトリを追加
teams.remove_repo=削除(Remove)
teams.add_nonexistent_repo=追加しようとしているリポジトリは存在しません。まずはじめに作成してください。
@@ -767,7 +825,7 @@ dashboard.delete_inactivate_accounts=非アクティブのアカウントをす
dashboard.delete_inactivate_accounts_success=すべての非アクティブアカウントは正常に削除されました。
dashboard.delete_repo_archives=リポジトリのすべてのアーカイブを削除
dashboard.delete_repo_archives_success=リポジトリのすべてのアーカイブが正常に削除されました。
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos=Gitファイルが失われたリポジトリのすべてのレコードを削除
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.git_gc_repos=リポジトリでのガベージコレクションを実行します。
dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys='.ssh/ authorized_keys' ファイルを再生成し
dashboard.resync_all_sshkeys_success=すべての公開鍵が正常に書き換えられました。
dashboard.resync_all_update_hooks=リポジトリの update フックをすべて再更新する(カスタムの設定パスが変更されたときに必要)
dashboard.resync_all_update_hooks_success=リポジトリの update フックがすべて正常に再更新されました。
dashboard.reinit_missing_repos=Reinitialize all repository records that lost Git files
dashboard.reinit_missing_repos_success=All repository records that lost Git files have been reinitialized successfully.
dashboard.server_uptime=サーバーの稼働時間
dashboard.current_goroutine=現在のGoroutine
@@ -814,7 +874,7 @@ users.admin=アドミン
users.repos=リポジトリ
users.created=作成されました
users.send_register_notify=登録通知をユーザーに送信
users.new_success=New account '%s' has been created successfully.
users.new_success=新規アカウント '%s' が正常に作成されました。
users.edit=編集
users.auth_source=認証ソース
users.local=ローカル
@@ -822,6 +882,8 @@ users.auth_login_name=認証ログイン名
users.password_helper=それをそのまま空のままにします。
users.update_profile_success=アカウントのプロファイルが更新されました。
users.edit_account=アカウントの編集
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=アカウントがアクティブされました
users.is_admin=このアカウントには管理者の権限を持つ
users.allow_git_hook=このアカウントには Git のフックを作成する権限を持つ
@@ -861,9 +923,12 @@ auths.bind_password=バインド パスワード
auths.bind_password_helper=警告: このパスワードは暗号化されずに格納されます。特権を持つアカウントに使用しないでください。
auths.user_base=ユーザ検索ベース
auths.user_dn=User DN
auths.attribute_username=Username attribute
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
auths.attribute_name=名前属性
auths.attribute_surname=名字属性
auths.attribute_mail=Eメール属性
auths.attributes_in_bind=Fetch attributes in Bind DN context
auths.filter=User フィルター
auths.admin_filter=Admin フィルター
auths.ms_ad_sa=Ms Ad SA
@@ -885,6 +950,7 @@ auths.update=認証設定を更新
auths.delete=この認証を削除
auths.delete_auth_title=認証削除
auths.delete_auth_desc=認証を削除します、継続しますか?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=認証が正常に削除されました。
config.server_config=サーバーの構成
@@ -901,6 +967,19 @@ config.static_file_root_path=静的ファイルのルートパス
config.log_file_root_path=ログ ファイルのルート パス
config.script_type=スクリプトの種類
config.reverse_auth_user=リバース認証ユーザ
config.ssh_config=SSH Configuration
config.ssh_enabled=Enabled
config.ssh_start_builtin_server=Start Builtin Server
config.ssh_domain=Domain
config.ssh_port=Port
config.ssh_listen_port=Listen Port
config.ssh_root_path=Root Path
config.ssh_key_test_path=Key Test Path
config.ssh_keygen_path=Keygen ('ssh-keygen') Path
config.ssh_minimum_key_size_check=Minimum Key Size Check
config.ssh_minimum_key_sizes=Minimum Key Sizes
config.db_config=データベースの構成
config.db_type=タイプ
config.db_host=ホスト
@@ -915,7 +994,6 @@ config.register_email_confirm=電子メールの確認を必要
config.disable_register=登録を無効にする
config.show_registration_button=登録ボタンを表示します。
config.require_sign_in_view=サインインを要求
config.enable_cache_avatar=アバターのキャッシュを有効にします。
config.mail_notify=メール通知
config.disable_key_size_check=最小キー サイズ チェックを無効にします
config.enable_captcha=Captchaを有効にする
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=HELOコマンド無効
config.mailer_name=名前
config.mailer_host=ホスト
config.mailer_user=ユーザ
config.send_test_mail=Send Test Email
config.test_mail_failed=Fail to send test email to '%s': %v
config.test_mail_sent=Test email has been sent to '%s'.
config.oauth_config=OAuth 構成
config.oauth_enabled=Enabled
config.cache_config=キャッシュの構成
@@ -964,6 +1045,13 @@ monitor.start=開始日時
monitor.execute_time=実行時間:
notices.system_notice_list=システム通知
notices.view_detail_header=お知らせの詳細を表示
notices.actions=アクション
notices.select_all=全て選択
notices.deselect_all=すべて選択解除
notices.inverse_selection=反転
notices.delete_selected=選択項目を削除
notices.delete_all=すべての通知を削除
notices.type=タイプ
notices.type_1=リポジトリ
notices.desc=説明
@@ -975,12 +1063,16 @@ create_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">%[4]s</a>を<a href="%[1]s/src/%[2]s">%[3]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>`
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> へ転送しました
push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
compare_2_commits=これら 2 のコミットの比較を閲覧する
compare_commits=これらの %d コミットの比較を表示
[tool]
ago=

View File

@@ -28,6 +28,7 @@ organization=Organizācija
mirror=Spogulis
new_repo=Jauns repozitorijs
new_migrate=Jauna migrācija
new_mirror=Jauns spogulis
new_fork=Jauns atdalītais repozitorijs
new_org=Jauna organizācija
manage_org=Pārvaldīt organizācijas
@@ -37,7 +38,7 @@ settings=Iestatījumi
your_profile=Tavs profils
your_settings=Tavi iestatījumi
news_feed=Jaunumu plūsma
activities=Aktivitāte
pull_requests=Izmaiņu pieprasījumi
issues=Problēmas
@@ -64,7 +65,7 @@ db_name=Datu bāzes nosaukums
db_helper=Nepieciešams izmantot MySQL INNODB dzini ar rakstzīmju kopu utf8_general_ci.
ssl_mode=SSL režīms
path=Ceļš
sqlite_helper=SQLite3 vai TiDB datu bāzes faila atrašanās vieta.
sqlite_helper=SQLite3 vai TiDB datu bāzēs faila ceļš.<br>Izmantojiet absolūto ceļu, startējot kā servisu.
err_empty_db_path=Nepieciešams norādīt SQLite3 vai TiDB datu bāzes atrašanās vietu.
err_invalid_tidb_name=TiDB datu bāzes nosaukums nevar saturēt simbolus "." un "-".
no_admin_and_disable_registration=Reģistrāciju nevar atslēgt, kamēr nav izveidots administratora konts.
@@ -85,6 +86,8 @@ http_port=HTTP ports
http_port_helper=Porta numurs pēc kura lietojumprogrammai būs iespējams pieslēgties.
app_url=Lietotnes URL
app_url_helper=Tas ietekmē HTTP/HTTPS klonēšanas URL un e-pasta saturā izsūtītās saites.
log_root_path=Žurnalizēšanas direktorija
log_root_path_helper=Direktorija, kurā tiks glabāti žurnāla faili.
optional_title=Neobligātie iestatījumi
email_title=E-pasta pakalpojuma iestatījumi
@@ -121,6 +124,7 @@ run_user_not_match=Izpildes lietotājs nav pašreizējais lietotājs: %s -> %s
save_config_failed=Neizdevās saglabāt konfigurāciju: %v
invalid_admin_setting=Nekorekts admin konta iestatījums: %v
install_success=Laipni lūdzam! Mēs priecājamies, ka Jūs izvēlaties Gogs, patīkamu lietošanu!
invalid_log_root_path=Norādītā žurnalizēšanas direktorija ir kļūdaina: %v
[home]
uname_holder=Lietotājvārds vai e-pasts
@@ -164,7 +168,7 @@ activate_account=Lūdzu, aktivizējiet savu kontu
activate_email=Apstipriniet savu e-pasta adresi
reset_password=Atiestatīt savu paroli
register_success=Reģistrācija notikusi veiksmīgi
register_notify=Welcome on board
register_notify=Laipni lūgti uz klāja
[modal]
yes=
@@ -202,7 +206,6 @@ repo_name_been_taken=Repozitorija vārds ir jau aizņemts.
org_name_been_taken=Organizācijas nosaukums ir jau aizņemts.
team_name_been_taken=Komandas nosaukums ir jau aizņemts.
email_been_used=E-pasta adrese jau tiek izmantota.
illegal_team_name=Grupas nosaukums satur neatļautas rakstzīmes.
username_password_incorrect=Lietotājvārds vai parole nav pareiza.
enterred_invalid_repo_name=Lūdzu, pārliecinieties, vai ievadītā repozitorija nosaukums ir pareizs.
enterred_invalid_owner_name=Lūdzu, pārliecinieties, vai ievadītā īpašnieka vārds ir pareizs.
@@ -218,8 +221,6 @@ still_own_repo=Jūsu esat vismaz viena repozitorija īpašnieks, tos sākumā ir
still_has_org=Jūsu esat vismaz vienas organizācijas biedrs, sākumā nepieciešams pamest vai izdzēst šo organizāciju.
org_still_own_repo=Šī organizācija ir vismaz viena repozitorija īpašnieks, tos sākumā ir nepieciešams izdzēst vai nomainīt to īpašnieku.
still_own_user=Šo autentifikāciju joprojām izmanto vismaz viens lietotājs, nepieciešams šiem lietotājiem nomainīt autentifikācijas veidu vai tos izdzēst.
target_branch_not_exist=Mērķa atzars neeksistē
[user]
@@ -231,6 +232,8 @@ activity=Publiskā aktivitāte
followers=Sekotāji
starred=Atzīmēti ar zvaigznīti
following=Seko
follow=Sekot
unfollow=Nesekot
form.name_reserved=Lietotāja vārds '%s' jau ir aizņemts.
form.name_pattern_not_allowed=Lietotāja vārds '%s' nav atļauts.
@@ -247,6 +250,7 @@ uid=Lietotāja ID
public_profile=Publiskais profils
profile_desc=Jūsu e-pasta adrese ir publiska un tiks izmantota, lai nosūtītju Jums paziņojumus, kas saistīti ar Jūsu kontu vai darbībām veiktām caur šo mājas lapu.
password_username_disabled=Ne-lokālie lietotāji nevar mainīt savus lietotājvārdus.
full_name=Pilns vārds
website=Mājas lapa
location=Atrašanās vieta
@@ -258,11 +262,10 @@ continue=Turpināt
cancel=Atcelt
enable_custom_avatar=Iespējot maināmu profila attēlu
enable_custom_avatar_helper=Iespējojiet šo, lai atslēgtu profilu attēlu ņemšanu no gravatar.com
choose_new_avatar=Izvēlēties jaunu profila attēlu
update_avatar=Saglabāt profila bildi
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=Augšupielādētais fails nav attēls.
no_custom_avatar_available=Nav iespējams mainīt profila bildi.
update_avatar_success=Jūsu profila bilde tika veiksmīgi saglabāta.
change_password=Mainīt paroli
@@ -271,6 +274,7 @@ new_password=Jauna parole
retype_new_password=Ievadīt paroli atkāroti
password_incorrect=Ievadīta nepareiza pašreizējā parole.
change_password_success=Parole tika veiksmīgi nomainīta. Tagad jūs varat pieraksītites, izmantojot jauno paroli.
password_change_disabled=Ne-lokālie lietotāji nevar mainīt savas paroles.
emails=E-pasta adreses
manage_emails=Pārvaldīt e-pasta adreses
@@ -352,10 +356,13 @@ auto_init=Inicializēt šo repozitoriju ar izvēlētajiem failiem un sagatavi
create_repo=Izveidot repozitoriju
default_branch=Noklusējuma atzars
mirror_interval=Spoguļošanas intervāls (stundās)
watchers=Watchers
stargazers=Stargazers
forks=Forks
mirror_address=Spoguļa adrese
mirror_address_desc=Lūdzu iekļaujiet adresē nepieciešamo lietotājvārdu/paroli.
watchers=Novērotāji
stargazers=Zvaigžņdevēji
forks=Atdalītie repozitoriji
form.reach_limit_of_creation=Īpašnieks sasniedza maksimālu pieļaujamo (%d) izveidoto repozitoriju skaitu.
form.name_reserved=Repozitorija nosaukums '%s' ir rezervēts.
form.name_pattern_not_allowed=Repozitorija nosaukums '%s' nav atļauts.
@@ -367,8 +374,9 @@ migrate.clone_address=Klonēšanas adrese
migrate.clone_address_desc=Tas var būt HTTP/HTTPS/GIT URL vai ceļš uz lokālā servera.
migrate.permission_denied=Jums nav tiesību importēt lokālu repozitoriju.
migrate.invalid_local_path=Nekorents lokālais ceļš, tas neeksistē vai nav direktorijs.
migrate.failed=Migration failed: %v
migrate.failed=Migrācija neizdevās: %v
mirror_from=spogulis no
forked_from=atdalīts no
fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks!
copy_link=Kopēt
@@ -388,9 +396,10 @@ create_new_repo_command=Izveidot jaunu repozitoriju komandrindā
push_exist_repo=Nosūtīt izmaiņas no komandrindas eksistējošam repozitorijam
repo_is_empty=Šis repozitorijs ir tukšs, apskatiet atkal vēlāk!
code=Kods
branch=Atzars
tree=Koks
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Filtrēt atzarus vai tagus
branches=Atzari
tags=Tagi
issues=Problēmas
@@ -467,7 +476,7 @@ issues.closed_at=`aizvērts <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`atvērts atkārtoti <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`pieminēja šo problēmu revīzijā <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Autors
issues.admin=Administrators
issues.collaborator=Collaborator
issues.owner=Īpašnieks
issues.sign_up_for_free=Pievienojieties
issues.sign_in_require_desc=, lai piedalītos diskusijā. Jau ir konts? <a href="%s">Pierakstieties, lai komentētu</a>
@@ -484,8 +493,9 @@ issues.label_modify=Etiķetes labošana
issues.label_deletion=Etiķetes dzēšana
issues.label_deletion_desc=Dzēšot šo etiķeti, tā tiks noņemta no visām saistītajām problēmām. Vai vēlaties turpināt?
issues.label_deletion_success=Etiķete tika veiksmīgi izdzēsta!
issues.num_participants=%d dalībnieki
pulls.new=New Pull Request
pulls.new=Jauns izmaiņu pieprasījums
pulls.compare_changes=Salīdzināt izmaiņas
pulls.compare_changes_desc=Salīdzināt divus atzarus un izveidot izmaiņu pieprasījumu.
pulls.compare_base=pamata
@@ -505,9 +515,9 @@ pulls.merged=Sapludināts
pulls.has_merged=Šo izmaiņu pieprasījums tika veiksmīgi sapludināts!
pulls.data_broken=Nepieejami izmaiņu pieprasījuma dati, jo dzēsta informācija no atdalītā repozitorija.
pulls.is_checking=Notiek konfliktu pārbaude, mirkli uzgaidiet un atjaunojiet lapu.
pulls.can_auto_merge_desc=Ir iespējams veikt automātisko sapludināšanas darbību šim izmaiņu pieprasījumam.
pulls.cannot_auto_merge_desc=Nav iespējams veikt automātisko sapludināšanas darbību, jo starp revīzijām ir konflikti.
pulls.cannot_auto_merge_helper=Lūdzu, izmantojiet komandrindas rīku, lai to atrisinātu.
pulls.can_auto_merge_desc=Šo izmaiņu pieprasījumu var automātiski saplūdināt.
pulls.cannot_auto_merge_desc=Šis izmaiņu pieprasījums nevar tikt automātiski saplūdināts konfliktu dēļ.
pulls.cannot_auto_merge_helper=Lūdzu sapludiniet manuāli, lai atrisinātu konfliktus.
pulls.merge_pull_request=Izmaiņu pieprasījuma sapludināšana
pulls.open_unmerged_pull_exists=`Jūs nevarat veikt atkārtotas atvēršanas darbību, jo jau eksistē izmaiņu pieprasījums (#%d) no šī repozitorija ar tādu pašu sapludināšanas informāciju un gaida sapludināšanu.`
@@ -535,29 +545,67 @@ milestones.deletion=Atskaites punkta dzēšana
milestones.deletion_desc=Dzēšot šo atskaites punktu tiks noņemta arī saistītā informācija no problēmu ziņojumiem. Vai vēlaties turpināt?
milestones.deletion_success=Atskaites punkts tika veiksmīgi izdzēsts!
wiki=Vikivietne
wiki.welcome=Laipni lūgti vikivietnē!
wiki.welcome_desc=Vikivietne ir vieta, kur Jūs varat dokumentēt savu projektu, lai padarīto to labāku.
wiki.create_first_page=Izveidot pirmo lapu
wiki.page=Lapa
wiki.filter_page=Meklēt lapu
wiki.new_page=Izveidot jaunu lapu
wiki.default_commit_message=Uzrakstiet piezīmes par šīm izmaiņām (neobligāti).
wiki.save_page=Saglabāt lapu
wiki.last_commit_info=%s laboja lapu %s
wiki.edit_page_button=Labot
wiki.new_page_button=Jauna lapa
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=Vikivietnes lapa ar šādu nosaukumu jau eksistē.
wiki.pages=Lapas
wiki.last_updated=Pēdējo reizi labota %s
settings=Iestatījumi
settings.options=Opcijas
settings.collaboration=Sadarbība
settings.hooks=Tīmekļa āķi
settings.githooks=Git āķi
settings.basic_settings=Pamatiestatījumi
settings.danger_zone=Bīstamā zona
settings.site=Oficiālā mājas lapa
settings.update_settings=Mainīt iestatījumus
settings.change_reponame_prompt=Šī izmaiņa ietekmēs saites, kas ir saistītas ar šo repozitoriju.
settings.advanced_settings=Papildu iestatījumi
settings.wiki_desc=Iespējot vikivietni, lai atļautu cilvēkiem rakstīt dokumentus
settings.use_external_wiki=Izmantot ārējo vikivietni
settings.external_wiki_url=Ārējās Vikivietnes adrese
settings.external_wiki_url_desc=Apmeklētāji tiks novirzīti uz adresi, kad viņi uzklikšķinās uz cilnes.
settings.issues_desc=Iespējot iebūvētu vieglu problēmu sekotāju
settings.use_external_issue_tracker=Izmantot ārējo problēmu sekotāju
settings.tracker_url_format=Ārējā problēmu sekotāja adreses formāts
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.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.
settings.convert_notices_1=- Šī darbība konvertēs šo repozitoriju par parastu repozitoriju un to nebūs iespējams atcelt.
settings.convert_confirm=Apstiprināt konvertēšanu
settings.convert_succeed=Repozitorijs tika veiksmīgi konvertēts uz parastu repozitoriju.
settings.transfer=Mainīt īpašnieku
settings.transfer_desc=Mainīt šī repozitorija īpašnieku uz citu lietotāju vai organizāciju, kurai Jums ir administratora tiesībs.
settings.new_owner_has_same_repo=Jaunajam īpašniekam jau ir repozitorijs ar šādu nosaukumu.
settings.delete=Dzēst šo repozitoriju
settings.delete_desc=Dzēšot repozitoriju, tā datus vairs nebūs iespējams atgūt. Pirms dzēšanas pārliecinieites vai patiešām vēlaties to darīt.
settings.transfer_notices_1=- Jūs pazaudēsiet piekļuvi, ja jaunais īpašnieks ir lietotājs.
settings.transfer_notices_2=- Jūs saglabāsiet piekļuvi, ja jaunais īpašnieks ir organizācija un Jūs esat viens no tās īpašniekiem.
settings.transfer_form_title=Lūdzu, ievadiet sekojošu informāciju, lai apstiprinātu šo darbību:
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=Dzēst šo repozitoriju
settings.delete_desc=Dzēšot repozitoriju, tā datus vairs nebūs iespējams atgūt. Pirms dzēšanas pārliecinieites vai patiešām vēlaties to darīt.
settings.delete_notices_1=- Šī darbība ir <strong>NEATGRIEZENISKA</strong>.
settings.delete_notices_2=- Šī darbība neatgriezeniski izdzēsīs visus šī repozitorija datus, tai skaitā Git datus, problēmu ziņojumus, komentārus un definētās piekļuves tiesības.
settings.delete_notices_fork_1=- Ja repozitorijs ir publisks, visi atdalītie repozitoriji kļūs neatkarīgi.
settings.delete_notices_fork_2=- Ja repozitorijs ir privāts, tiks dzēsti arī visi atdalītie repozitoriji.
settings.delete_notices_fork_3=- Ja vēlaties saglabāt atdalīts repozitorijus pēc dzēšanas, sākumā nomainiet repozitorija redzamību uz publisku.
settings.deletion_success=Repozitorijs tika veiksmīgi dzēsts!
settings.update_settings_success=Repozitorija opcijas ir veiksmīgi saglabātas.
settings.transfer_owner=Jaunais īpašnieks
settings.make_transfer=Mainīt
@@ -565,14 +613,21 @@ settings.transfer_succeed=Repozitorija īpašnieks ir veiksmīgi nomainīts.
settings.confirm_delete=Apstiprināt dzēšanu
settings.add_collaborator=Pievienot jaunu līdzstrādnieku
settings.add_collaborator_success=Jauns līdzstrādnieks ir pievienots.
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=Līdzstrādnieks tika noņemts.
settings.search_user_placeholder=Search user...
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
settings.webhook_deletion_desc=Dzēšot tīmekļa āķi tiks dzēsta visa ar to saistītā informācija un izpildes vēsture. Vai vēlaties turpināt?
settings.webhook_deletion_success=Tīmekļa āķis tika veiksmīgi izdzēsts!
settings.webhook.test_delivery=Testa piegāde
settings.webhook.test_delivery_desc=Veikt viltus push-notikuma piegādi lai notestētu Jūsu tīmekļa āķa iestatījumus
settings.webhook.test_delivery_success=Testa web-āķis ir pievienots piegādes rindai. Var paiet dažas sekundes, kamēr tas parādīsies piegāžu vēsturē.
settings.webhook.request=Pieprasījums
settings.webhook.response=Atbilde
settings.webhook.headers=Galvenes
@@ -612,6 +667,7 @@ settings.slack_domain=Domēns
settings.slack_channel=Kanāls
settings.deploy_keys=Izvietot atslēgas
settings.add_deploy_key=Pievienot izvietošanas atslēgu
settings.deploy_key_desc=Izvietošanas atslēgai ir tikai lasīšanas piekļuve. Tā nav tā pati kā Jūsu personīgā konta SSH atslēga.
settings.no_deploy_keys=Nav pievienota neviena izvietošanas atslēga.
settings.title=Virsraksts
settings.deploy_key_content=Saturs
@@ -627,6 +683,8 @@ diff.parent=vecāks
diff.commit=revīzija
diff.data_not_available=Salīdzināšanas dati nav pieejami.
diff.show_diff_stats=Rādīt salīdzināšanas statistiku
diff.show_split_view=Dalītais skats
diff.show_unified_view=Apvienotais skats
diff.stats_desc=<strong>%d mainītis faili</strong> ar <strong>%d papildinājumiem</strong> un <strong>%d dzēšanām</strong>
diff.bin=BIN
diff.view_file=Parādīt failu
@@ -639,28 +697,28 @@ release.stable=Stabila
release.edit=labot
release.ahead=<strong>%d</strong> revīzijas atzarā %s kopš šī laidiena
release.source_code=Izejas kods
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.new_subheader=Publicējiet laidienus, lai veiktu produkta iterācijas.
release.edit_subheader=Detalizēts žurnāls var palīdzēt lietotājiem saprast, kas tika uzlabots.
release.tag_name=Taga nosaukums
release.target=Mērķis
release.tag_helper=Publicējot, izvēlieties esošu vai izveidojiet jaunu tagu.
release.title=Title
release.content=Content
release.title=Virsraksts
release.content=Saturs
release.write=Rakstīt
release.preview=Priekšskatītījums
release.loading=Notiek ielāde...
release.prerelease_desc=Šī ir pirmslaidiena versija
release.prerelease_helper=Tiks norādīts, ka šis laidiens nav gatavs lietošanai produkcijas režīmā.
release.cancel=Cancel
release.cancel=Atcelt
release.publish=Publicēt laidienu
release.save_draft=Saglabāt melnrakstu
release.edit_release=Labot laidienu
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.delete_release=Dzēst šo laidienu
release.deletion=Laidiena dzēšana
release.deletion_desc=Dzēšot šo laidienu tiks dzēsts arī atbilstošs Git tags. Vai vēlaties turpināt?
release.deletion_success=Laidiens tika veiksmīgi dzēsts!
release.tag_name_already_exist=Laidiens ar šādu taga nosaukumu jau eksistē.
release.downloads=Downloads
release.downloads=Lejupielādes
[org]
org_name_holder=Organizācijas nosaukums
@@ -701,17 +759,17 @@ settings.delete_org_title=Organizācijas dzēšana
settings.delete_org_desc=Šī organizācija tiks pilnībā izdzēsta, vai vēlaties turpināt?
settings.hooks_desc=Pievienot tīmekļa āķus, kas nostrādās <strong>visiem repozitorijiem</strong> šajā organizācijā.
members.membership_visibility=Membership Visibility:
members.membership_visibility=Dalībnieka redzamība:
members.public=Publisks
members.public_helper=padarīt privātu
members.private=Privāts
members.private_helper=padarīt publisku
members.member_role=Member Role:
members.member_role=Dalībnieka loma:
members.owner=Īpašnieks
members.member=Biedri
members.remove=Noņemt
members.leave=Atstāt
members.invite_desc=Add a new member to %s:
members.invite_desc=Pievienot jaunu dalībnieku pie %s:
members.invite_now=Uzaicināt tagad
teams.join=Pievienoties
@@ -736,7 +794,7 @@ teams.read_permission_desc=Šai komandai ir <strong>lasīšanas</strong> tiesīb
teams.write_permission_desc=Šai komandai ir <strong>rakstīšanas</strong> tiesības: dalībnieki var lasīt un nosūtīt izmaiņas repozitorijiem.
teams.admin_permission_desc=Šai komandai ir <strong>administratora</strong> tiesības: dalībnieki var lasīt, rakstīt un pievienot citus dalībniekus komandas repozitorijiem.
teams.repositories=Komandas repozitoriji
teams.search_repo_placeholder=Search repository...
teams.search_repo_placeholder=Meklēt repozitorijā...
teams.add_team_repository=Pievienot komandas repozitoriju
teams.remove_repo=Noņemt
teams.add_nonexistent_repo=Repozitorijs, kuram Jūs mēģinat pievienot neeksistē, sākumā izveidojiet to.
@@ -767,14 +825,16 @@ dashboard.delete_inactivate_accounts=Dzēst visus neaktīvos kontus
dashboard.delete_inactivate_accounts_success=Visi neaktīvie kotni tika veiksmīgi izdzēsti.
dashboard.delete_repo_archives=Dzēst visu repozitoriju arhīvus
dashboard.delete_repo_archives_success=Visu repozitoriju arhīvi tika veiksmīgi izdzēsti.
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.delete_missing_repos=Dzēst visus repozitorija ierakstus, kas zaudēja Git failus
dashboard.delete_missing_repos_success=Visi repozitorija ieraksti, kas zaudēja Git failus tika veiksmīgi dzēsti.
dashboard.git_gc_repos=Veikt repozitoriju datu sakārtošānu (git gc)
dashboard.git_gc_repos_success=Datu sakārtošana visiem repozitorijiem veiksmīgi pabeigta.
dashboard.resync_all_sshkeys=Pārrakstīt '.ssh/authorized_keys' failu (brīdinājums: ne-Git atslēgas tiks pazaudētas)
dashboard.resync_all_sshkeys_success=Visas publiskās atslēgas tika veiksmīgi pārrakstītas.
dashboard.resync_all_update_hooks=Pārrakstīt visu repozitoriju izmaiņu āķus (nepieciešams, ja tiek mainīta konfigurācijas faila atrašanās vieta)
dashboard.resync_all_update_hooks_success=Visu repozitoriju izmaiņu āķi tika veiksmīgi pārrakstīti.
dashboard.reinit_missing_repos=Atkārtoti inicializēt visus repozitorija ierakstus, kam trūkst Git failu
dashboard.reinit_missing_repos_success=Visi repozitorija ieraksti, kam trūkst Git faili, tika atkārtoti inicializēti.
dashboard.server_uptime=Servera darbības laiks
dashboard.current_goroutine=Izmantotās Gorutīnas
@@ -822,6 +882,8 @@ users.auth_login_name=Autentifikācijas pieteikšanās vārds
users.password_helper=Atstājiet tukšu, ja nevēlaties mainīt.
users.update_profile_success=Konta profils tika veiksmīgi saglabāts.
users.edit_account=Labot kontu
users.max_repo_creation=Maksimāls repozitoriju veidošanas limits
users.max_repo_creation_desc=(Uzlikt -1 lai izmantotu globālu limitu pēc noklusējuma)
users.is_activated=Konts ir aktivizēts
users.is_admin=Šim kontam ir administratora piekļuves tiesības
users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus
@@ -861,9 +923,12 @@ auths.bind_password=Saistīšanas parole
auths.bind_password_helper=Brīdinājums: Šī parole tiks saglabāta nešifrētā veidā. Neizmantojiet kontu ar augstām privilēģijām.
auths.user_base=Lietotāja pamatnosacījumi
auths.user_dn=Lietotāja DN
auths.attribute_username=Lietotājvārda atribūts
auths.attribute_username_placeholder=Atstājiet tukšu, lai izmantotu lietotājvārdu ar kuru autorizējaties.
auths.attribute_name=Vārda atribūts
auths.attribute_surname=Uzvārda atribūts
auths.attribute_mail=E-pasta atribūts
auths.attributes_in_bind=Nolasīt atribūtus no saistīšanas DN konteksta
auths.filter=Lietotāju filts
auths.admin_filter=Administratoru filtrs
auths.ms_ad_sa=MS Ad SA
@@ -885,6 +950,7 @@ auths.update=Mainīt autentifikācijas iestatījumus
auths.delete=Dzēst šo autentifikāciju
auths.delete_auth_title=Autentifikācijas dzēšana
auths.delete_auth_desc=Šī autentifikācija tiks dzēsta, vai vēlaties turpināt?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=Autentifikācija tika veiksmīgi izdzēsta!
config.server_config=Servera konfigurācija
@@ -901,6 +967,19 @@ config.static_file_root_path=Statisko failu atrašanās vieta
config.log_file_root_path=Žurnalizēšanas failu glabāšanas vieta
config.script_type=Skripta veids
config.reverse_auth_user=Reversā lietotāja autentifikācija
config.ssh_config=SSH konfigurācija
config.ssh_enabled=Iespējots
config.ssh_start_builtin_server=Startēt iebūvēto serveri
config.ssh_domain=Domēns
config.ssh_port=Ports
config.ssh_listen_port=Klausīšanās ports
config.ssh_root_path=Saknes ceļš
config.ssh_key_test_path=Atslēgu pārbaudes ceļš
config.ssh_keygen_path=Keygen ('ssh-keygen') ceļš
config.ssh_minimum_key_size_check=Minimālā atslēgas lieluma pārbaude
config.ssh_minimum_key_sizes=Minimālais atslēgas lielums
config.db_config=Datu bāzes konfigurācija
config.db_type=Veids
config.db_host=Resursdators
@@ -915,7 +994,6 @@ config.register_email_confirm=Pieprasīt e-pasta apstiprināšanu
config.disable_register=Atspējot jaunu lietotāju reģistrāciju
config.show_registration_button=Rādīt reģistrēšanās pogu
config.require_sign_in_view=Nepieciešama autorizācija
config.enable_cache_avatar=Glabāt profila attēlus kešatmiņā
config.mail_notify=Pasta paziņojumi
config.disable_key_size_check=Atspējot atslēgas minimālā garuma pārbaudi
config.enable_captcha=Iespējot drošības kodu
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Atspējot HELO
config.mailer_name=Nosaukums
config.mailer_host=Resursdators
config.mailer_user=Lietotājs
config.send_test_mail=Nosūtīt pārbaudes e-pastu
config.test_mail_failed=Neizdevās nosūtīt pārbaudes e-pasta vēstuli uz '%s': %v
config.test_mail_sent=Pārbaudes e-pasta vēstule tika nosūtīta uz '%s'.
config.oauth_config=OAuth konfigurācija
config.oauth_enabled=Iespējota
config.cache_config=Kešatmiņas konfigurācija
@@ -964,23 +1045,34 @@ monitor.start=Sākuma laiks
monitor.execute_time=Izpildes laiks
notices.system_notice_list=Sistēmas paziņojumi
notices.view_detail_header=Skatīt paziņojuma detaļas
notices.actions=Darbības
notices.select_all=Iezīmēt visu
notices.deselect_all=Atcelt visa iezīmēšanu
notices.inverse_selection=Apgriezeniskā iezīmēšana
notices.delete_selected=Dzēst iezīmēto
notices.delete_all=Dzēst visus paziņojumus
notices.type=Veids
notices.type_1=Repozitorijs
notices.desc=Apraksts
notices.op=Op.
notices.delete_success=Sistēmas paziņojums tika veiksmīgi izdzēsts.
notices.delete_success=Sistēmas paziņojumi tika veiksmīgi izdzēstas.
[action]
create_repo=izveidoja repozitoriju <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>
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>`
create_pull_request=`izveidoja izmaiņu pieprasījumu <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=`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>
push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām
compare_commits=Salīdzināt šīs %d revīzijas
[tool]
ago=atpakaļ

View File

@@ -1,34 +1,35 @@
app_desc=Een eenvoudige zelfgehoste Git service geschreven in Go
home=Huis
home=Home
dashboard=Dashboard
explore=Verkennen
help=Help
sign_in=Inloggen
sign_out=Afmelden
sign_out=Uitloggen
sign_up=Aanmelden
register=Registreer
register=Registreren
website=Website
version=Versie
page=Pagina
template=Sjabloon
language=Taal
create_new=Create...
create_new=Creëren...
user_profile_and_more=Gebruikersprofiel en meer
signed_in_as=Aangemeld als
username=Gebruikersnaam
email=E-mail
password=Wachttwoord
password=Wachtwoord
re_type=Verificatie
captcha=CAPTCHA
repository=Repositorie
repository=Repository
organization=Organisatie
mirror=Spiegel
new_repo=Nieuwe repositorie
new_repo=Nieuwe repository
new_migrate=Nieuwe migratie
new_fork=Nieuwe vork Repository
new_mirror=Nieuwe Kopie
new_fork=Nieuwe Fork
new_org=Nieuwe organisatie
manage_org=Beheer organisaties
admin_panel=Adminpaneel
@@ -37,15 +38,15 @@ settings=Instellingen
your_profile=Uw profiel
your_settings=Uw instellingen
news_feed=Nieuwsfeed
pull_requests=Pull-aanvragen
activities=Activiteiten
pull_requests=Pull requests
issues=Kwesties
cancel=Annuleer
cancel=Annuleren
[search]
search=Zoeken...
repository=Opslagplaats
repository=Repository
user=Gebruiker
issue=Probleem
code=Code
@@ -53,9 +54,9 @@ code=Code
[install]
install=Installatie
title=Installatiestappen voor de eerste keer opstarten
docker_helper=If you're running Gogs inside Docker, please read <a target="_blank" href="%s">Guidelines</a> carefully before you change anything in this page!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB.
db_title=Database instellingen
docker_helper=Als u gebruik maakt Gogs binnen Docker, lees dan de <a target="_blank" href="%s">richtlijnen</a> voordat u iets veranderen op deze pagina!
requite_db_desc=Gogs vereist MySQL, PostgreSQL, SQite3 of TiDB.
db_title=Database-instellingen
db_type=Database-type
host=Host
user=Gebruikersnaam
@@ -64,11 +65,11 @@ db_name=Database naam
db_helper=Gebruik InnoDB engine met utf8_general_ci karakterset voor MySQL.
ssl_mode=SSL-modus
path=Pad
sqlite_helper=The file path of SQLite3 or TiDB database.
err_empty_db_path=SQLite3 or TiDB database path cannot be empty.
err_invalid_tidb_name=TiDB database name does not allow characters "." and "-".
no_admin_and_disable_registration=You cannot disable registration without creating an admin account.
err_empty_admin_password=Admin password cannot be empty.
sqlite_helper=Het pad van de SQLite3- of TiDB-database.<br>Als u Gogs start als een service, geef dan een absoluut pad op.
err_empty_db_path=SQLite3 of TiDB databankpad mag niet leeg.
err_invalid_tidb_name=TiDB databank naam niet tekens kunnen "." en "-".
no_admin_and_disable_registration=Je kunt niet de registratie uit te schakelen zonder een beheerders account.
err_empty_admin_password=Beheerder wachtwoord kan niet leeg zijn.
general_title=Toepassing algemene instellingen
app_name=Applicatienaam
@@ -85,6 +86,8 @@ http_port=HTTP-poort
http_port_helper=Poortnummer waar het programma naar luistert.
app_url=Applicatie URL
app_url_helper=Dit heeft invloed op de HTTP/HTTPS kloon urls en de urls die in de email worden gebruikt
log_root_path=Log-pad
log_root_path_helper=Directory waar logbestanden opgeslagen worden.
optional_title=Optionele instellingen
email_title=E-mail service instellingen
@@ -102,8 +105,8 @@ disable_gravatar=Gravatar Service uitschakelen
disable_gravatar_popup=Schakel Gravatar en andere bronnen uit, alle avatars worden door gebruikers geüpload of zijn standaard.
disable_registration=Schakel zelfregistratie uit
disable_registration_popup=Schakel zelfregistratie uit, alleen admins kunnen accounts maken.
enable_captcha=Enable Captcha
enable_captcha_popup=Require validate captcha for user self-registration.
enable_captcha=Inschakelen Captcha
enable_captcha_popup=Vereis captcha validatie voor zelf-registratie van gebruiker.
require_sign_in_view=Schakel vereiste aanmelding om pagina's te zien in
require_sign_in_view_popup=Alleen ingelogde gebruikers kunnen pagina's bekijken, bezoekers kunnen alleen de login/registratie pagina's zien.
admin_setting_desc=U hoeft niet meteen een administratie account te maken, de gebruiker met ID=1 krijgt automatisch administratierechten.
@@ -111,16 +114,17 @@ admin_title=Instellingen beheerdersaccount
admin_name=Gebruikersnaam
admin_password=Wachtwoord
confirm_password=Verifieer wachtwoord
admin_email=Admin E-mail
admin_email=Beheerder E-mail
install_gogs=Installeer Gogs
test_git_failed=Git test niet gelukt: 'git' commando %v
sqlite3_not_available=Uw versie biedt geen ondersteuning voor SQLite3, download de officiële binaire versie van %s, niet de gobuild versie.
invalid_db_setting=Uw database instellingen zijn niet correct: %v
invalid_repo_path=Repositorie basis pad is niet correct: %v
invalid_repo_path=Repositorie basis map is niet correct: %v
run_user_not_match=De uitvoerende gebruiker is niet de huidig gebruiker: %s -> %s
save_config_failed=Kan de configuratie niet opslaan: %v
invalid_admin_setting=Uw admin-instellingen zijn niet geldig: %v
install_success=Welkom! Wij zijn veheugd dat u voor Gogs heeft gekozen, veel plezier en tot ziens
invalid_log_root_path=Ongeldig log-pad: %v
[home]
uname_holder=Gebruikersnaam of e-mail
@@ -160,11 +164,11 @@ reset_password_helper=Klik hier om uw wachtwoord opnieuw in te stellen.
password_too_short=De lengte van uw wachtwoord moet minimaal zes karakters zijn.
[mail]
activate_account=Please activate your account
activate_email=Verify your e-mail address
reset_password=Reset your password
register_success=Register success, Welcome
register_notify=Welcome on board
activate_account=Activeer uw account
activate_email=Verifieer je e-mailadres
reset_password=Stel je wachtwoord opnieuw in
register_success=Registratie succesvol, welkom
register_notify=Welkom aan boord
[modal]
yes=Ja
@@ -173,7 +177,7 @@ modify=Aanpassen
[form]
UserName=Gebruikersnaam
RepoName=Repositorie naam
RepoName=Naam van repository
Email=e-mailadres
Password=Wachtwoord
Retype=Verifieer wachtwoord
@@ -192,17 +196,16 @@ min_size_error=moet minimaal %s karakters bevatten.
max_size_error=mag maximaal %s karakters bevatten.
email_error=is niet een valide e-mail adres.
url_error=is niet een valide URL.
include_error=` must contain substring '%s'.`
include_error=` moet substring '%s' bevatten.`
unknown_error=Onbekende fout:
captcha_incorrect=Captcha komt niet overeen.
password_not_match=Wachtwoord en verificatie wachtwoord komen niet overeen.
username_been_taken=Gebruikersnaam is al in gebruik.
repo_name_been_taken=Repositorie naam is al in gebruik.
repo_name_been_taken=Deze naam is al in gebruik.
org_name_been_taken=Organisatie naam is al in gebruik.
team_name_been_taken=Team naam is al in gebruik.
email_been_used=e-mailadres is al in gebruik.
illegal_team_name=Team naam bevat illegale karakters.
username_password_incorrect=Gebruikersnaam of wachtwoord is niet correct.
enterred_invalid_repo_name=U heeft een onjuiste repositorie naam ingevoerd.
enterred_invalid_owner_name=U heeft een onjuiste eigenaar ingevoerd.
@@ -218,8 +221,6 @@ still_own_repo=Uw account heeft nog een eigendom op een repositorie. U moet deze
still_has_org=Uw account nog steeds lidmaatschap van organisatie, u hebt naar links of hen eerst verwijderen.
org_still_own_repo=De organisatie heeft nog eigendomen op repositories. U moet deze eerst verwijderen of overdragen.
still_own_user=Deze authenticatie methode wordt nog gebruikt door sommige gebruikers. U moet hen eerst verplaatsen of verwijderen.
target_branch_not_exist=Doel branch bestaat niet
[user]
@@ -231,6 +232,8 @@ activity=Openbare activiteit
followers=Volgers
starred=Sterren
following=Volgt
follow=Volg
unfollow=Niet meer volgen
form.name_reserved=De gebruikersnaam '%s' is gereserveerd.
form.name_pattern_not_allowed=Het gebruikersnaam patroon '%s' is niet toegestaan.
@@ -247,30 +250,31 @@ uid=uid
public_profile=Openbaar profiel
profile_desc=Uw e-mailadres is openbaar en zal gebruikt worden voor alle account gerelateerde berichtgevingen en bewerkingingen die via de website worden gedaan.
password_username_disabled=Extern opgeslagen gebruikers zijn niet toegestaan om hun gebruikersnaam veranderen.
full_name=Volledige naam
website=Website
location=Locatie
update_profile=Profile bijwerken
update_profile_success=Uw profiel is succesvol bijgewerkt.
change_username=Username veranderd
change_username_prompt=This change will affect the way how links relate to your account.
change_username_prompt=Deze verandering zal de weg links hebben betrekking op uw account beïnvloeden.
continue=Doorgaan
cancel=Annuleren
enable_custom_avatar=Aangepaste avatar inschakelen
enable_custom_avatar_helper=Avatar niet ophalen van Gravatar
choose_new_avatar=Kies een nieuwe avatar
update_avatar=Avatar instelling bijwerken
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=Geüpload bestand is geen afbeelding.
no_custom_avatar_available=Geen aangepaste avatar beschikbaar, kan niet worden ingeschakeld.
update_avatar_success=Instellingen voor avatar succesvol bijgewerkt.
change_password=Verander wachtwoord
old_password=Huidige wachtwoord
new_password=Nieuw wachtwoord
retype_new_password=Retype New Password
retype_new_password=Herhaal Nieuw Wachtwoord
password_incorrect=Huidig wachtwoord is niet correct.
change_password_success=Wachtwoord is succesvol gewijzigd. U kunt nu met uw nieuwe wachtwoord inloggen.
password_change_disabled=Extern opgeslagen gebruikers zijn niet toegestaan om hun wachtwoord te wijzigen.
emails=E-mailadressen
manage_emails=E-mailadressen beheren
@@ -278,9 +282,9 @@ email_desc=Uw primaire e-mailadres zal worden gebruikt voor meldingen en andere
primary=Primair
primary_email=Instellen als primair
delete_email=Verwijder
email_deletion=E-mail Deletion
email_deletion_desc=Delete this e-mail address will remove related information from your account. Do you want to continue?
email_deletion_success=E-mail has been deleted successfully!
email_deletion=E-mail Verwijderen
email_deletion_desc=Dit e-mailadres verwijdert, worden gerelateerde informatie van uw account te verwijderen. Wil je verdergaan?
email_deletion_success=E-mail is succesvol verwijderd!
add_new_email=Nieuw e-mailadres toevoegen
add_email=E-mailadres toevoegen
add_email_confirmation_sent=Een nieuwe bevestiging e-mail werd verstuurd naar '%s', gelieve uw inbox in de komende %d uren te controleren om het bevestigingsproces te voltooien.
@@ -331,16 +335,16 @@ delete_account_desc=Dit account zal permanent worden verwijderd. Wilt u doorgaan
[repo]
owner=Eigenaar
repo_name=Repositorie naam
repo_name_helper=Een goede repositorie naam is kort, memorabel en <strong>uniek</strong>.
repo_name=Naam van repository
repo_name_helper=Een goede repository-naam is kort, makkelijk te onthouden en <strong>uniek</strong>.
visibility=Zichtbaarheid
visiblity_helper=Deze repositorie is <span class="ui red text">privaat</span>
visiblity_helper_forced=Site admin has forced all new repositories to be <span class="ui red text">Private</span>
visiblity_helper_forced=Sitebeheerder heeft alle nieuwe repositories gedwongen <span class="ui red text">privé</span> te zijn
visiblity_fork_helper=(Verandering van deze waarde zal van invloed zijn op alle forks)
clone_helper=De behoeftehulp van klonen? Bezoek <a target="_blank" href="%s"> helpen</a>!
fork_repo=Vork Repository
fork_repo=Repository forken
fork_from=Afsplitsing van
fork_visiblity_helper=Gevorkte repository wijzigen zijn bereik potentiële kopers niet
fork_visiblity_helper=U kunt de zichtbaarheid van een geforkte repository niet aanpassen.
repo_desc=Omschrijving
repo_lang=Taal
repo_lang_helper=Selecteer .gitignore bestanden
@@ -349,13 +353,16 @@ license_helper=Selecteer een licentie bestand
readme=Leesmij-bestand
readme_helper=Selecteer een sjabloon voor het Leesmij-bestand
auto_init=Initialiseer deze repositorie met de geselecteerde bestanden en sjabloon
create_repo=Nieuwe Repositorie
create_repo=Nieuwe repository
default_branch=Standaard branch
mirror_interval=Mirror interval(uur)
watchers=Watchers
mirror_address=Kopie-adres
mirror_address_desc=Gelieve noodzakelijke gebruikersgegevens in de adresbalk.
watchers=Volgers
stargazers=Stargazers
forks=Forks
form.reach_limit_of_creation=De eigenaar heeft maximale creatie limiet van %d repositories bereikt.
form.name_reserved=Repositorienaam '%s' is gereserveerd.
form.name_pattern_not_allowed=Repositorie naampatroon '%s' is niet toegestaan.
@@ -365,15 +372,16 @@ migrate_type_helper=Deze repositorie zal een <span class="text blue">mirror</spa
migrate_repo=Migreer repositorie
migrate.clone_address=Clone adres
migrate.clone_address_desc=Dit kan een HTTP/HTTPS/GIT URL zijn of een lokaal pad.
migrate.permission_denied=You are not allowed to import local repositories.
migrate.permission_denied=U bent niet toegestaan om deze lokale repositories te importeren.
migrate.invalid_local_path=Ongeldig lokaal pad, het pad bestaat niet of het is geen map.
migrate.failed=Migration failed: %v
migrate.failed=Migratie is mislukt: %v
mirror_from=spiegel van
forked_from=geforked van
fork_from_self=U kunt geen repository forken die u al beheert!
copy_link=Kopieer
copy_link_success=Copied!
copy_link_error=Press ⌘-C or Ctrl-C to copy
copy_link_success=Gekopieerd!
copy_link_error=Druk op ⌘-C of Ctrl-C om te kopiëren
copied=Gekopieerd
unwatch=Negeren
watch=Volgen
@@ -386,11 +394,12 @@ quick_guide=Snelstart gids
clone_this_repo=Kloon deze repositorie
create_new_repo_command=Maak een nieuwe repositorie aan vanaf de console
push_exist_repo=Push een bestaande repositorie vanaf de console
repo_is_empty=This repository is empty, please come back later!
repo_is_empty=Deze repositories is leeg is, probeer het later opnieuw!
code=Code
branch=Aftakking
tree=Boom
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Filter branch of tag
branches=Aftakkingen
tags=Labels
issues=Kwesties
@@ -422,7 +431,7 @@ issues.new.no_milestone=Geen mijlpaal
issues.new.clear_milestone=Verwijder mijlpaal
issues.new.open_milestone=Open mijlpalen
issues.new.closed_milestone=Gesloten mijlpalen
issues.new.assignee=Verantwoordelijke
issues.new.assignee=Toegewezen aan
issues.new.clear_assignee=Verwijder verantwoordelijke
issues.new.no_assignee=Geen verantwoordelijke
issues.create=Maak probleem
@@ -467,7 +476,7 @@ issues.closed_at=`gesloten om <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`heropend om <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at='verwees naar dit probleem vanuit een commit <a id="%[1]s" href="#%[1]s"> %[2]s'</a>
issues.poster=Poster
issues.admin=Admin
issues.collaborator=Collaborator
issues.owner=Eigenaar
issues.sign_up_for_free=Gratis aanmelden
issues.sign_in_require_desc=om deel te nemen in deze conversatie. Heeft u al een account? <a href="%s">Meld u aan om te reageren</a>
@@ -484,8 +493,9 @@ issues.label_modify=Wijzig label
issues.label_deletion=Verwijder label
issues.label_deletion_desc=Het verwijderen van dit label zal alle informatie in de gerelateerde problemen verwijderen. Wilt u doorgaan?
issues.label_deletion_success=Label werd met succes verwijderd!
issues.num_participants=%d deelnemers
pulls.new=New Pull Request
pulls.new=Nieuwe Pull aanvraag
pulls.compare_changes=Vergelijk veranderingen
pulls.compare_changes_desc=Vergelijk twee vertakkingen en maak een pull verzoek voor wijzigingen.
pulls.compare_base=base
@@ -496,18 +506,18 @@ pulls.nothing_to_compare=Er is niets te vergelijken omdat base en head branches
pulls.has_pull_request=' Er is al een pull-aanvraag tussen deze twee targets: <a href="%[1]s/pulls/%[3]d"> %[2]s #% [3]d</a>'
pulls.create=Pull verzoek aanmaken
pulls.title_desc=wil %[1]d commits van <code>%[2]s</code> samenvoegen met <code>%[3]s</code>
pulls.merged_title_desc=merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
pulls.merged_title_desc=%[1] commits samengevoegd van <code>%[2]s</code> naar <code>%[3]s</code> %[4]s
pulls.tab_conversation=Discussie
pulls.tab_commits=Commits
pulls.tab_files=Bestanden gewijzigd
pulls.reopen_to_merge=Please reopen this pull request to perform merge operation.
pulls.merged=Merged
pulls.has_merged=This pull request has been merged successfully!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
pulls.reopen_to_merge=Heropen deze pull request aub om een een merge actie uit te voeren.
pulls.merged=Samengevoegd
pulls.has_merged=Dit pull-request is samengevoegd!
pulls.data_broken=Omdat informatie over de fork is verwijderd, zijn de gegevens van dit pull-request niet beschikbaar.
pulls.is_checking=Controle van conflicten is nog bezig, ververs deze pagina in enkele ogenblikken.
pulls.can_auto_merge_desc=Dit pull-request kan automatisch samengevoegd worden.
pulls.cannot_auto_merge_desc=Dit pull-request kan niet worden gemerged omdat er conflicten zijn.
pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Samenvoegen van pull verzoek
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@@ -535,29 +545,67 @@ milestones.deletion=Mijlpaal verwijderen
milestones.deletion_desc=Het verwijderen van dit label zal alle informatie in de gerelateerde problemen verwijderen. Wilt u doorgaan?
milestones.deletion_success=Mijlpaal is met succes verwijderd!
wiki=Wiki
wiki.welcome=Welkom op de Wiki!
wiki.welcome_desc=In een wiki kunnen gebruikers samen een project documenteren en bediscussiëren.
wiki.create_first_page=Maak de eerste pagina
wiki.page=Pagina
wiki.filter_page=Filter pagina
wiki.new_page=Maak nieuwe pagina
wiki.default_commit_message=Schrijf een notitie over deze aanpassing (optioneel).
wiki.save_page=Pagina opslaan
wiki.last_commit_info=%s heeft deze pagina aangepast %s
wiki.edit_page_button=Bewerken
wiki.new_page_button=Nieuwe pagina
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=Er bestaat al een wiki-pagina met deze naam.
wiki.pages=Paginas
wiki.last_updated=Laatst bijgewerkt: %s
settings=Instellingen
settings.options=Opties
settings.collaboration=Samenwerking
settings.hooks=Webhooks
settings.githooks=Git haken
settings.githooks=Git-hooks
settings.basic_settings=Basis instellingen
settings.danger_zone=Gevaren zone
settings.site=Officiële site
settings.update_settings=Instellingen bewerken
settings.change_reponame_prompt=This change will affect how links relate to the repository.
settings.advanced_settings=Geavanceerde opties
settings.wiki_desc=Enable wiki to allow people write documents
settings.use_external_wiki=Externe wiki gebruiken
settings.external_wiki_url=Externe wiki-URL
settings.external_wiki_url_desc=Bezoekers worden doorgestuurd naar de URL als ze op het tabblad klikken.
settings.issues_desc=Ingebouwde compacte issuetracker inschakelen
settings.use_external_issue_tracker=Externe issuetracker gebruiken
settings.tracker_url_format=URL-formaat externe issuetracker
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=Gevaren zone
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.
settings.convert_notices_1=- This operation will convert this repository mirror into a regular repository and cannot be undone.
settings.convert_confirm=Conversie bevestigen
settings.convert_succeed=Deze repository is geconverteerd naar een normale repository.
settings.transfer=Eigendom overdragen
settings.transfer_desc=Draag deze repo over aan een andere gebruiker of een organisatie waar u beheerders rechten heeft.
settings.new_owner_has_same_repo=De nieuwe eigenaar heeft al een repositorie met deze naam
settings.delete=Verwijder deze repositorie
settings.delete_desc=Als u eenmaal een repositorie verwijderd is er geen weg terug. Gelieve zeker te zijn van uw acties.
settings.transfer_notices_1=- You will lose access if new owner is a individual user.
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title=Please enter following information to confirm your operation:
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=Verwijder deze repositorie
settings.delete_desc=Als u eenmaal een repositorie verwijderd is er geen weg terug. Gelieve zeker te zijn van uw acties.
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_1=- If this repository is public, all forks will become independent after deletion.
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first.
settings.deletion_success=Repository is succesvol verwijderd!
settings.update_settings_success=Repositorie instellingen zijn succesvol bijgewerkt.
settings.transfer_owner=Nieuwe eigenaar
settings.make_transfer=Maak overdracht
@@ -565,14 +613,21 @@ settings.transfer_succeed=Eigendom repositorie succesvol overgedragen
settings.confirm_delete=Bevestig verwijdering
settings.add_collaborator=Nieuwe medewerker toevoegen
settings.add_collaborator_success=medewerker is toegevoegd.
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=medewerker is verwijderd.
settings.search_user_placeholder=Search user...
settings.search_user_placeholder=Zoek gebruiker...
settings.org_not_allowed_to_be_collaborator=Organization is not allowed to be added as a collaborator.
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
settings.webhook_deletion_desc=Delete this webhook will remove its information and all delivery history. Do you want to continue?
settings.webhook_deletion_success=Webhook has been deleted successfully!
settings.webhook_deletion_success=Webhook is succesvol verwijderd!
settings.webhook.test_delivery=Test-bezorging
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
settings.webhook.request=Verzoek
settings.webhook.response=Antwoord
settings.webhook.headers=Headers
@@ -612,6 +667,7 @@ settings.slack_domain=Slack domein
settings.slack_channel=Slack kanaal
settings.deploy_keys=Installeer sleutels
settings.add_deploy_key=Toevoegen deploy sleutel
settings.deploy_key_desc=Deploy keys have read-only access. They are not the same as personal account SSH keys.
settings.no_deploy_keys=U hebt nog geen deploy sleutels toegevoegd.
settings.title=Titel
settings.deploy_key_content=Inhoud
@@ -627,6 +683,8 @@ diff.parent=bovenliggende
diff.commit=commit
diff.data_not_available=Diff gegevens niet beschikbaar.
diff.show_diff_stats=Toon Diff Stats
diff.show_split_view=Split View
diff.show_unified_view=Unified View
diff.stats_desc=<strong>%d gewijzigde bestanden</strong> met <strong>toevoegingen van %d</strong> en <strong>%d verwijderingen</strong>
diff.bin=BIN
diff.view_file=Bestand weergeven
@@ -640,31 +698,31 @@ release.edit=bewerken
release.ahead=<strong>%d</strong> aanpassingen aan %s sinds deze versie
release.source_code=Broncode
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.edit_subheader=Een gedetailleerd changelog helpt gebruikers te begrijpen wat er is verbeterd in deze release.
release.tag_name=Tagnaam
release.target=Doel
release.tag_helper=Kies een bestaande tag, of creëer een nieuwe tag bij publiceren.
release.title=Title
release.content=Content
release.title=Titel
release.content=Inhoud
release.write=Schrijf
release.preview=Voorbeeld
release.loading=Laden...
release.prerelease_desc=Dit is een beta-versie
release.prerelease_helper=Wij wijzen u erop dat deze release is niet geschikt voor productie doeleinden.
release.cancel=Cancel
release.cancel=Annuleren
release.publish=Release publiceren
release.save_draft=Concept opslaan
release.edit_release=Release bewerken
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.delete_release=Deze release verwijderen
release.deletion=Release verwijderen
release.deletion_desc=Deleting this release will delete the corresponding Git tag. Do you want to continue?
release.deletion_success=Release is verwijderd!
release.tag_name_already_exist=Versie met deze naam bestaat al.
release.downloads=Downloads
[org]
org_name_holder=Organisatienaam
org_full_name_holder=Organization Full Name
org_full_name_holder=Volledige naam organisatie
org_name_helper=Een goede organisatienaam is kort en memorabel.
create_org=Nieuwe organisatie aanmaken
repo_updated=Geupdate
@@ -706,7 +764,7 @@ members.public=Openbaar
members.public_helper=maak prive
members.private=Prive
members.private_helper=maak openbaar
members.member_role=Member Role:
members.member_role=Rol van lid:
members.owner=Eigenaar
members.member=Lid
members.remove=Verwijderen
@@ -736,10 +794,10 @@ teams.read_permission_desc=Dit team heeft <strong>Lees</strong> rechten : leden
teams.write_permission_desc=Dit team heeft <strong>Schrijf</strong> rechten : leden kunnen repositories lezen en push aanvragen verwerken.
teams.admin_permission_desc=Dit team heeft <strong>Beheerders</strong> rechten : leden kunnen repositories lezen en push aanvragen verwerken en medewerkers toevoegen.
teams.repositories=Teamrepositories
teams.search_repo_placeholder=Search repository...
teams.search_repo_placeholder=Repository zoeken...
teams.add_team_repository=Nieuwe teamrepositorie aanmaken
teams.remove_repo=Verwijder
teams.add_nonexistent_repo=De opslagplaats die u probeert toe te voegen niet bestaat, kunt u het eerst aanmaken.
teams.add_nonexistent_repo=De opslagplaats die u probeert toe te voegen bestaat niet: maak deze eerst aan.
[admin]
dashboard=Dashboard
@@ -750,9 +808,9 @@ authentication=Autenticaties
config=Configuratie
notices=Systeem aankondigingen
monitor=Bijhouden
first_page=First
last_page=Last
total=Total: %d
first_page=Eerste
last_page=Laatste
total=Totaal: %d
dashboard.statistic=Statistieken
dashboard.operations=Bewerkingen
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys=Herschrijf '.ssh/authorized_keys' (Let op: alle sle
dashboard.resync_all_sshkeys_success=Alle publieke sleutels zijn herschreven.
dashboard.resync_all_update_hooks=Herschrijf alle repositorie-hooks (nodig als de configuratie bestandslocatie is gewijzigd)
dashboard.resync_all_update_hooks_success=Alle repositorie-hooks zijn herschreven.
dashboard.reinit_missing_repos=Reinitialize all repository records that lost Git files
dashboard.reinit_missing_repos_success=All repository records that lost Git files have been reinitialized successfully.
dashboard.server_uptime=Uptime server
dashboard.current_goroutine=Huidige Goroutines
@@ -813,24 +873,26 @@ users.activated=Geactiveerd
users.admin=Admin
users.repos=Repos
users.created=Aangemaakt
users.send_register_notify=Send Registration Notification To User
users.new_success=New account '%s' has been created successfully.
users.send_register_notify=Stuur notificatie voor registratie naar gebruiker
users.new_success=Nieuw account '%s' is aangemaakt.
users.edit=Bewerken
users.auth_source=Authentication Source
users.auth_source=Authenticatiebron
users.local=Lokaal
users.auth_login_name=Authentication Login Name
users.auth_login_name=Authenticatie-loginnaam
users.password_helper=Leave it empty to remain unchanged.
users.update_profile_success=Profiel is succesvol bijgewerkt.
users.edit_account=Bewerk account
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Dit account is geactiveerd
users.is_admin=Dit account heeft beheerdersrechten
users.allow_git_hook=Deze account beschikt over machtigingen voor het maken van Git haken
users.allow_import_local=This account has permissions to import local repositories
users.allow_import_local=Dit account mag lokale repositories importeren
users.update_profile=Account profiel bijwerken
users.delete_account=Dit account verwijderen
users.still_own_repo=Dit account is nog steeds eigendom van een repositorie. U moet deze repositorie eerst verwijderen of overdragen.
users.still_has_org=Deze account nog steeds lidmaatschap van organisatie, u hebt naar links of hen eerst verwijderen.
users.deletion_success=Account has been deleted successfully!
users.deletion_success=Het account is verwijderd!
orgs.org_manage_panel=Organisaties beheren
orgs.name=Naam
@@ -846,13 +908,13 @@ repos.stars=Sterren
repos.issues=Kwesties
auths.auth_manage_panel=Authentication Manage Panel
auths.new=Add New Source
auths.new=Nieuwe bron toevoegen
auths.name=Naam
auths.type=Type
auths.enabled=Ingeschakeld
auths.updated=Bijgewerkt
auths.auth_type=Authentication Type
auths.auth_name=Authentication Name
auths.auth_type=Authenticatietype
auths.auth_name=Authenticatienaam
auths.domain=Domein
auths.host=Host
auths.port=Poort
@@ -861,19 +923,22 @@ auths.bind_password=Bind Password
auths.bind_password_helper=Warning: This password is stored in plain text. Do not use a high privileged account.
auths.user_base=User Search Base
auths.user_dn=User DN
auths.attribute_username=Username attribute
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
auths.attribute_name=Voornaam attribuut
auths.attribute_surname=Achternaam attribuut
auths.attribute_mail=E-mail attribuut
auths.filter=User Filter
auths.admin_filter=Admin Filter
auths.attributes_in_bind=Fetch attributes in Bind DN context
auths.filter=Gebruikersfilter
auths.admin_filter=Beheerdersfilter
auths.ms_ad_sa=MS Ad SA
auths.smtp_auth=SMTP Authentication Type
auths.smtp_auth=SMTP-authenticatietype
auths.smtphost=SMTP host
auths.smtpport=SMTP poort
auths.allowed_domains=Allowed Domains
auths.allowed_domains=Toegelaten domeinen
auths.allowed_domains_helper=Leave it empty to not restrict any domains. Multiple domains should be separated by comma ','.
auths.enable_tls=Activeer TLS-encryptie
auths.skip_tls_verify=Skip TLS Verify
auths.skip_tls_verify=TLS-verificatie overslaan
auths.pam_service_name=PAM servicenaam
auths.enable_auto_register=Activeer automatische registratie
auths.tips=Tips
@@ -881,10 +946,11 @@ auths.edit=Edit Authentication Setting
auths.activated=Deze autorisatiemethode is geactiveerd
auths.new_success=New authentication '%s' has been added successfully.
auths.update_success=Authentication setting has been updated successfully.
auths.update=Update Authentication Setting
auths.delete=Delete This Authentication
auths.update=Authenticatie-instellingen bijwerken
auths.delete=Deze authenticatiewijze verwijderen
auths.delete_auth_title=Authentication Deletion
auths.delete_auth_desc=This authentication is going to be deleted, do you want to continue?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=Authentication has been deleted successfully!
config.server_config=Serverconfiguratie
@@ -901,6 +967,19 @@ config.static_file_root_path=Statische bestanden basis pad
config.log_file_root_path=Log bestand basis pad
config.script_type=Script type
config.reverse_auth_user=Omgekeerde verificatie gebruiker
config.ssh_config=SSH-configuratie
config.ssh_enabled=Ingeschakeld
config.ssh_start_builtin_server=Ingebouwde server starten
config.ssh_domain=Domein
config.ssh_port=Poort
config.ssh_listen_port=Luister op poort
config.ssh_root_path=Root-pad
config.ssh_key_test_path=Pad voor key-tests
config.ssh_keygen_path=Pad van keygen ('ssh-keygen')
config.ssh_minimum_key_size_check=Controleer minimale key-lengte
config.ssh_minimum_key_sizes=Minimale key-lengtes
config.db_config=Databaseconfiguratie
config.db_type=Type
config.db_host=Host
@@ -909,16 +988,15 @@ config.db_user=Gebruiker
config.db_ssl_mode=SSL modus
config.db_ssl_mode_helper=(alleen voor "postgres")
config.db_path=Pad
config.db_path_helper=(for "sqlite3" and "tidb")
config.db_path_helper=(voor "sqlite3" en "tidb")
config.service_config=Serviceconfiguratie
config.register_email_confirm=E-mailbevestiging registreren
config.disable_register=Registratie uitgeschakeld
config.show_registration_button=Registeren knop weergeven
config.require_sign_in_view=Inloggen vereist om te kunnen inzien
config.enable_cache_avatar=Avatar Cache inschakelen
config.mail_notify=E-mailnotificaties
config.disable_key_size_check=Disable Minimum Key Size Check
config.enable_captcha=Enable Captcha
config.disable_key_size_check=Controle op key-lengte uitschakelen
config.enable_captcha=CAPTCHA inschakelen
config.active_code_lives=Actieve Code leven
config.reset_password_code_lives=Reset wachtwoord Code leven
config.webhook_config=Webhook configuratie
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Schakel HELO uit
config.mailer_name=Naam
config.mailer_host=Host
config.mailer_user=Gebruiker
config.send_test_mail=Testbericht verzenden
config.test_mail_failed=Verzending van een testmail naar '%s' is mislukt: %v
config.test_mail_sent=Test-email is verstuurd naar '%s'.
config.oauth_config=OAuth-configuratie
config.oauth_enabled=Ingeschakeld
config.cache_config=Cache-configuratie
@@ -964,23 +1045,34 @@ monitor.start=Starttijd
monitor.execute_time=Uitvoertijd
notices.system_notice_list=Systeem aankondigingen
notices.view_detail_header=View Notice Detail
notices.actions=Acties
notices.select_all=Alles selecteren
notices.deselect_all=Alles deselecteren
notices.inverse_selection=Selectie omkeren
notices.delete_selected=Selectie verwijderen
notices.delete_all=Delete All Notices
notices.type=Type
notices.type_1=Opslagplaats
notices.desc=Beschrijving
notices.op=Op.
notices.delete_success=Systeem bericht is met succes verwijderd.
notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=repositorie aangemaakt in <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <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>
create_issue=`opende issue in <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>`
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=`reactie op 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=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
compare_2_commits=Weergave vergelijking voor deze 2 commits
compare_commits=Toon vergelijking voor deze %d commits
[tool]
ago=geleden

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
app_desc=Um serviço de Git auto-hospedado e amigável escrito em Go
home=Página Inicial
dashboard=Painel de controle
dashboard=Página Inicial
explore=Explorar
help=Ajuda
sign_in=Entrar
@@ -20,7 +20,7 @@ signed_in_as=Você é
username=Usuário
email=E-mail
password=Senha
re_type=Redigite
re_type=Digite novamente
captcha=Captcha
repository=Repositório
@@ -28,6 +28,7 @@ organization=Organização
mirror=Espelho
new_repo=Novo Repositório
new_migrate=Nova Migração
new_mirror=Novo espelho
new_fork=Novo Fork de Repositório
new_org=Nova Organização
manage_org=Gerenciar Organizações
@@ -37,8 +38,8 @@ settings=Configurações
your_profile=Seu perfil
your_settings=Suas configurações
news_feed=Feed de Notícias
pull_requests=Solicitações de Pull
activities=Atividades
pull_requests=Pull Requests
issues=Problemas
cancel=Cancelar
@@ -52,7 +53,7 @@ code=Código
[install]
install=Instalação
title=Etapas de instalação para Primeira Execução
title=Etapas de instalação para primeira execução
docker_helper=Se você está rodando o Gogs dentro do Docker, por favor leia os <a target="_blank" href="%s">Guias</a> cuidadosamente antes de mudar qualquer coisa nesta página!
requite_db_desc=Gogs requer MySQL, PostgreSQL, SQLite3 ou TiDB.
db_title=Configurações de Banco de Dados
@@ -60,22 +61,22 @@ db_type=Tipo do Banco de Dados
host=Host
user=Usuário
password=Senha
db_name=Nome do Banco de Dados
db_name=Nome do banco de dados
db_helper=Por favor, use o mecanismo INNODB com o conjunto de caracteres utf8_general_ci para MySQL.
ssl_mode=Modo SSL
path=Caminho
sqlite_helper=O caminho do arquivo do banco de dados SQLite3 ou TiDB.
sqlite_helper=O caminho do arquivo de banco de dados SQLite3 ou TiDB. <br>Por favor use o caminho absoluto quando você iniciar como serviço.
err_empty_db_path=O Caminho do banco de dados SQLite3 ou TiDB não pode ser vazio.
err_invalid_tidb_name=Nome do banco de dados TiDB não permite os caracteres "." e "-".
no_admin_and_disable_registration=Você não pode desabilitar o registro sem criar uma conta de administrador.
err_empty_admin_password=A senha de administrador não pode ser vazia.
general_title=Configurações Gerais do Gogs
app_name=Nome do Aplicativo
general_title=Configurações gerais do Gogs
app_name=Nome do aplicativo
app_name_helper=Coloque o nome da sua organização aqui!
repo_path=Caminho da Raiz do Repositório
repo_path=Caminho da raíz do repositório
repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório.
run_user=Executar Usuário
run_user=Usuário da execução
run_user_helper=O usuário deve ter acesso ao caminho raiz do repositório e executar o Gogs
domain=Domínio
domain_helper=Isto afeta URLs para clonagem via SSH.
@@ -83,35 +84,37 @@ ssh_port=Porta SSH
ssh_port_helper=Número da porta que seu servidor SSH está usando, deixe vazio para desativar o recurso SSH.
http_port=Porta HTTP
http_port_helper=Número da porta em que a aplicação irá executar.
app_url=URL do Aplicativo
app_url=URL do aplicativo
app_url_helper=Isto afeta a URL de clonagem via HTTP/HTTPs e também o email.
log_root_path=Caminho do log
log_root_path_helper=Pasta dos arquivos de log.
optional_title=Configurações Opcionais
email_title=Configurações do Serviço de E-mail
optional_title=Configurações opcionais
email_title=Configurações do serviço de e-mail
smtp_host=Host SMTP
smtp_from=De
smtp_from=De
smtp_from_helper=O endereço de email deve atender a especificação RFC 5322. O formato deve ser um email ou "Nome" <email@example.com>.
mailer_user=E-mail do Remetente
mailer_password=Senha do Remetente
register_confirm=Habilitar Confirmação de Registro
mail_notify=Habilitar Notificação de Correio
server_service_title=Configurações de Servidor e Outros Serviços
offline_mode=Ativar Modo Offline
mailer_user=E-mail do remetente
mailer_password=Senha do remetente
register_confirm=Habilitar confirmação de registro
mail_notify=Habilitar notificação de e-mail
server_service_title=Configurações de servidor e outros serviços
offline_mode=Ativar modo off-line
offline_mode_popup=Desative o CDN mesmo em modo de produção, todos os recursos serão disponibilizados localmente.
disable_gravatar=Desativar Serviço Gravatar
disable_gravatar=Desativar serviço Gravatar
disable_gravatar_popup=Desabilitar o Gravatar e fontes personalizadas, todos os avatares são enviados por usuários ou padrão.
disable_registration=Desativar auto-registro
disable_registration_popup=Desativar o auto-registro de usuário, para que somente o administrador possa criar contas.
enable_captcha=Habilitar Captcha
enable_captcha=Habilitar captcha
enable_captcha_popup=Obrigar validação por captcha para auto-registro de usuários.
require_sign_in_view=Requerer login para a visualização de páginas
require_sign_in_view=Obrigar login para a visualização de páginas
require_sign_in_view_popup=Somente usuários autenticados podem ver todas as páginas, visitantes somente podem entrar ou se cadastrar.
admin_setting_desc=Você não precisa criar uma conta de administrador agora, no entanto o primeiro usuário (ID=1) automaticamente terá acesso de administrador.
admin_title=Configurações da Conta de Administrador
admin_name=Nome de Usuário
admin_title=Configurações da conta de administrador
admin_name=Nome de usuário
admin_password=Senha
confirm_password=Confirmar Senha
admin_email=E-mail do Administrador
confirm_password=Confirmar senha
admin_email=E-mail do administrador
install_gogs=Instalar Gogs
test_git_failed=Falha ao testar o comando 'git': %v
sqlite3_not_available=Sua versão não suporta SQLite3, por favor faça o download da versão binária oficial em %s, NÃO da versão gobuild.
@@ -121,6 +124,7 @@ run_user_not_match=O usuário da execução não é o usuário atual: %s -> %s
save_config_failed=Falha ao salvar a configuração: %v
invalid_admin_setting=Configuração da conta de administrador está inválida: %v
install_success=Bem-vindo! Estamos contentes que você escolheu o Gogs, divirta-se e tenha cuidado.
invalid_log_root_path=Pasta raíz do log é inválida: %v
[home]
uname_holder=Nome de Usuário ou E-mail
@@ -164,7 +168,7 @@ activate_account=Por favor, ative sua conta
activate_email=Verifique seu endereço de e-mail
reset_password=Resetar sua senha
register_success=Registrado com sucesso. Bem vindo
register_notify=Welcome on board
register_notify=Bem-vindo a bordo
[modal]
yes=Sim
@@ -187,7 +191,7 @@ AdminEmail=E-mail do Administrador
require_error=` não pode estar vazio.`
alpha_dash_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
alpha_dash_dot_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
size_error='deve ser o tamanho %s.'
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.`
email_error=` não é um endereço de e-mail válido.`
@@ -202,7 +206,6 @@ repo_name_been_taken=Nome do repositório já foi tomado.
org_name_been_taken=Nome da organização já foi tomado.
team_name_been_taken=Nome da equipe já foi tomado.
email_been_used=Endereço de e-mail já foi usado.
illegal_team_name=O nome da equipe contém caracteres não permitidos.
username_password_incorrect=Usuário ou senha incorretos.
enterred_invalid_repo_name=Por favor certifique-se que informou o nome do repositório corretamente.
enterred_invalid_owner_name=Por favor, verifique se o nome do proprietário está correto.
@@ -218,8 +221,6 @@ still_own_repo=Sua conta ainda tem propriedade do repositório, você tem que ex
still_has_org=Sua conta ainda faz parte da organização, você deve sair ou excluí-la primeiro.
org_still_own_repo=Esta organização ainda tem a propriedade do repositório, você deve excluir ou transferí-la primeiro.
still_own_user=Esta autenticação ainda é usada por alguns usuários, você deve movê-los e depois apagar novamente.
target_branch_not_exist=O branch de destino não existe.
[user]
@@ -231,6 +232,8 @@ activity=Atividade Pública
followers=Seguidores
starred=Favorito
following=Seguindo
follow=Seguir
unfollow=Deixar de seguir
form.name_reserved=O nome de usuário '%s' não pode ser usado.
form.name_pattern_not_allowed=Não é permitido usar o padrão '%s' para o nome de usuário.
@@ -247,6 +250,7 @@ uid=Uid
public_profile=Perfil Público
profile_desc=Seu endereço de E-mail é publico e será usado para qualquer notificação relacionada à conta, e qualquer operação na web feita através do site.
password_username_disabled=Usuários do tipo não-local não são permitidos de mudarem seu nome de usuário.
full_name=Nome Completo
website=Site
location=Localização
@@ -258,11 +262,10 @@ continue=Continuar
cancel=Cancelar
enable_custom_avatar=Habilitar Avatar Customizado
enable_custom_avatar_helper=Habilite para desativar a busca no Gravatar
choose_new_avatar=Escolha um novo avatar
update_avatar=Atualizar configuração de Avatar
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem.
no_custom_avatar_available=Nenhum avatar personalizado disponível, não pode habilitá-lo.
update_avatar_success=Sua configuração de avatar foi atualizada com sucesso.
change_password=Mudança de senha
@@ -271,6 +274,7 @@ new_password=Nova Senha
retype_new_password=Digite novamente a nova senha
password_incorrect=A senha atual não está correta.
change_password_success=A senha está alterada com sucesso. Você pode agora entrar com a senha nova.
password_change_disabled=Usuários do tipo não-local não são permitidos de mudarem sua senha.
emails=Endereços de E-mail
manage_emails=Gerenciar endereços de e-mail
@@ -352,10 +356,13 @@ auto_init=Inicializar este repositório com os arquivos selecionados e modelo
create_repo=Criar Repositório
default_branch=Branch padrão
mirror_interval=Intervalo de Espelho (hora)
watchers=Watchers
stargazers=Stargazers
mirror_address=Endereço do espelho
mirror_address_desc=Por favor, inclua as credenciais do usuário necessários no endereço.
watchers=Observadores
stargazers=Usuários que estrelaram
forks=Forks
form.reach_limit_of_creation=O proprietário atingiu o limite máximo de criação de repositórios de %d.
form.name_reserved=O nome de repositório '%s' não pode ser usado.
form.name_pattern_not_allowed=Não é permitido usar o padrão '%s' para o nome de repositório.
@@ -367,8 +374,9 @@ migrate.clone_address=Endereço de Clone
migrate.clone_address_desc=Isto pode ser uma URL de HTTP/HTTPS/GIT ou um caminho de diretório local.
migrate.permission_denied=Você não pode importar repositórios locais.
migrate.invalid_local_path=Caminho local inválido, não existe ou não é um diretório.
migrate.failed=Migration failed: %v
migrate.failed=Migração falhou: %v
mirror_from=espelho de
forked_from=forkado de
fork_from_self=Você não pode criar fork de um repositório que já é seu!
copy_link=Copiar
@@ -388,9 +396,10 @@ create_new_repo_command=Criar um novo repositório na linha de comando
push_exist_repo=Push um repositório existente na linha de comando
repo_is_empty=Este repositório está vazio, por favor volte mais tarde!
code=Código
branch=Branch
tree=Árvore
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Filtrar branch ou tag
branches=Branches
tags=Tags
issues=Problemas
@@ -467,7 +476,7 @@ issues.closed_at=`fechado em <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`reaberto em <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`citou este problema em um commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Autor
issues.admin=Administrador
issues.collaborator=Collaborator
issues.owner=Proprietário
issues.sign_up_for_free=Cadastre-se gratuitamente
issues.sign_in_require_desc=para participar nesta conversa. Já tem uma conta? <a href="%s">Faça login para comentar</a>
@@ -484,8 +493,9 @@ issues.label_modify=Alteração de etiqueta
issues.label_deletion=Exclusão de etiqueta
issues.label_deletion_desc=Excluir uma etiqueta a retirará de todos os problemas que ela estiver marcando. Quer mesmo continuar?
issues.label_deletion_success=A etiqueta foi excluída com sucesso!
issues.num_participants=%d participantes
pulls.new=New Pull Request
pulls.new=Novo Pull Request
pulls.compare_changes=Comparar mudanças
pulls.compare_changes_desc=Comparar os dois branches e criar pull request com as mudanças.
pulls.compare_base=base
@@ -505,11 +515,11 @@ pulls.merged=Merge realizado
pulls.has_merged=Este pull request foi mesclado com sucesso!
pulls.data_broken=Dados deste pull request foram quebrados devido à deleção de informação do fork.
pulls.is_checking=A verificação do conflito ainda está em progresso, por favor recarregue a página em instantes.
pulls.can_auto_merge_desc=Você pode realizar uma auto-mescla neste pull request.
pulls.cannot_auto_merge_desc=Você não pode realizar uma auto-mescla porque há conflitos entre os commits.
pulls.cannot_auto_merge_helper=Por favor, utilize linha de comando para solucionar isto.
pulls.can_auto_merge_desc=Este pull request pode ser mesclado automaticamente.
pulls.cannot_auto_merge_desc=Este pull request não pode ser mesclado automaticamente pois há conflitos.
pulls.cannot_auto_merge_helper=Por favor, mescle manualmente para resolver os conflitos.
pulls.merge_pull_request=Merge Pull Request
pulls.open_unmerged_pull_exists=' Você não pode executar a operação de reabrir porque já existe uma solicitação de pull aberta (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.'
pulls.open_unmerged_pull_exists=`Você não pode executar a operação de reabrir porque já existe uma solicitação de pull aberta (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.`
milestones.new=Novo marco
milestones.open_tab=%d abertos
@@ -535,29 +545,67 @@ milestones.deletion=Exclusão de marco
milestones.deletion_desc=Excluir este marco removerá a informação dele em todos os problemas aos quais estiver associado. Você quer mesmo continuar?
milestones.deletion_success=Marco excluído com sucesso!
wiki=Wiki
wiki.welcome=Bem-vindo ao wiki!
wiki.welcome_desc=Wiki é o lugar onde você gostaria de documentar o seu projeto em conjunto e torná-lo melhor.
wiki.create_first_page=Criar a primeira página
wiki.page=Página
wiki.filter_page=Filtrar página
wiki.new_page=Criar nova página
wiki.default_commit_message=Escrever um comentário sobre esta atualização (opcional).
wiki.save_page=Salvar página
wiki.last_commit_info=%s editou esta página %s
wiki.edit_page_button=Editar
wiki.new_page_button=Nova página
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=já existe uma página de wiki com o mesmo nome.
wiki.pages=Páginas
wiki.last_updated=Última atualização %s
settings=Configurações
settings.options=Opções
settings.collaboration=Colaboração
settings.hooks=Webhooks
settings.githooks=Hooks do Git
settings.basic_settings=Configurações Básicas
settings.danger_zone=Zona de Perigo
settings.site=Site Oficial
settings.update_settings=Configurações de Atualização
settings.change_reponame_prompt=Este mudanças vai afetar os links para este repositório.
settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar o wiki para permitir que as pessoas escrevam documentos
settings.use_external_wiki=Usar wiki externa
settings.external_wiki_url=URL externa da wiki
settings.external_wiki_url_desc=Os visitantes serão redirecionados para a URL quando clicarem na aba.
settings.issues_desc=Habilitar gerenciamento de "problemas" nativo
settings.use_external_issue_tracker=Usar issue tracker externo
settings.tracker_url_format=Formato de URL do issue tracker externo
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.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.
settings.convert_notices_1=- Esta operação vai converter este repositório espelho em um repositório tradicional. Esta ação não pode ser desfeita.
settings.convert_confirm=Confirmar conversão
settings.convert_succeed=Repositório espelho convertido para tradicional com sucesso.
settings.transfer=Transferir Propriedade
settings.transfer_desc=Transferir este repositório para outro usuário ou para uma organização onde você tem direitos de administrador.
settings.new_owner_has_same_repo=O novo dono já tem um repositório com o mesmo nome. Por favor, escolha outro nome.
settings.delete=Deletar Este Repositório
settings.delete_desc=Uma vez que você deleta um repositório, não tem volta. Por favor, tenha certeza.
settings.transfer_notices_1=- Você vai perder acesso se o novo dono for um usuário individual.
settings.transfer_notices_2=- Você vai continuar tendo acesso se o novo dono é uma organização e você é um dos membros.
settings.transfer_form_title=Informe a seguinte informação para confirmar a sua operação:
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=Deletar Este Repositório
settings.delete_desc=Uma vez que você deleta um repositório, não tem volta. Por favor, tenha certeza.
settings.delete_notices_1=-Esta operação <strong>NÃO PODERÁ</strong> ser desfeita.
settings.delete_notices_2=- Esta operação irá apagar permanentemente o tudo deste repositório, incluindo os dados do Git, problemas, comentários e acessos dos colaboradores.
settings.delete_notices_fork_1=- Se este repositório é público, todos os forks se tornarão independentes após a deleção.
settings.delete_notices_fork_2=- Se este repositório é privado, todos os forks serão removidos imediatamente.
settings.delete_notices_fork_3=- Se você deseja manter todos os forks, por favor muda a visibilidade do repositório para pública primeiro.
settings.deletion_success=Repositório excluído com sucesso!
settings.update_settings_success=As opções do repositório foram atualizadas com sucesso.
settings.transfer_owner=Novo Dono
settings.make_transfer=Fazer Transferência
@@ -565,14 +613,21 @@ settings.transfer_succeed=A posse do repositório foi transferido com sucesso.
settings.confirm_delete=Confirmar Deleção
settings.add_collaborator=Adicionar um Novo Colaborador
settings.add_collaborator_success=O novo colaborador foi adicionado.
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=O colaborador foi removido.
settings.search_user_placeholder=Search user...
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
settings.webhook_deletion_desc=Deletar este Webhook vai remover sua informação e todo o histórico de entrega. Deseja continuar?
settings.webhook_deletion_success=Webhook deletado com sucesso!
settings.webhook.test_delivery=Entrega de teste
settings.webhook.test_delivery_desc=Enviar uma entrega de evento de push falso para testar suas configurações de webhook
settings.webhook.test_delivery_success=O teste webhook foi adicionado para a fila de entrega. Pode demorar alguns segundos antes de ser exibido no histórico de entrega.
settings.webhook.request=Solicitação
settings.webhook.response=Resposta
settings.webhook.headers=Cabeçalhos
@@ -612,6 +667,7 @@ settings.slack_domain=Domínio
settings.slack_channel=Canal
settings.deploy_keys=Chaves de Deploy
settings.add_deploy_key=Nova chave
settings.deploy_key_desc=Chave de deploy só tem acesso somente leitura. Não é igual as chaves SSH de conta pessoal.
settings.no_deploy_keys=Você ainda não adicionou chaves para implantação de software.
settings.title=Título
settings.deploy_key_content=Conteúdo da chave
@@ -627,6 +683,8 @@ diff.parent=pai
diff.commit=commit
diff.data_not_available=Dados de Diff não disponíveis.
diff.show_diff_stats=Mostrar estatísticas do Diff
diff.show_split_view=Visão dividida
diff.show_unified_view=Visão unificada
diff.stats_desc=<strong> %d arquivos alterados</strong> com <strong>%d adições</strong> e <strong>%d exclusões</strong>
diff.bin=BIN
diff.view_file=Ver Arquivo
@@ -639,26 +697,26 @@ 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
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.new_subheader=Publicar versões para iterar o produto.
release.edit_subheader=Um changelog detalhado ajuda os usuários a entenderem o que foi melhorado.
release.tag_name=Nome da tag
release.target=Destino
release.tag_helper=Escolha uma tag existente, ou crie uma nova tag em publicar.
release.title=Title
release.content=Content
release.title=Título
release.content=Conteúdo
release.write=Escrever
release.preview=Visualizar
release.loading=Carregando...
release.prerelease_desc=Esta é uma versão prévia
release.prerelease_helper=Vou salientar que esta versão é identificada como não pronta para produção.
release.cancel=Cancel
release.cancel=Cancelar
release.publish=Publicar Versão
release.save_draft=Salvar Rascunho
release.edit_release=Editar Versão
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.delete_release=Deletar esta versão
release.deletion=Deleção de versão
release.deletion_desc=Deletar esta versão vai deletar a tag do git correspondente. Você deseja continuar?
release.deletion_success=A versão foi deletada com sucesso!
release.tag_name_already_exist=Já existiu versão com esse nome de tag.
release.downloads=Downloads
@@ -701,17 +759,17 @@ settings.delete_org_title=Deleção da Organização
settings.delete_org_desc=Esta organização será deletada permanentemente, você quer continuar?
settings.hooks_desc=Adicionar Webhooks que serão acionados para <strong>todos os repositórios</strong> dessa organização.
members.membership_visibility=Membership Visibility:
members.membership_visibility=Visibilidade da associação:
members.public=Público
members.public_helper=tornar privado
members.private=Privado
members.private_helper=torar público
members.member_role=Member Role:
members.member_role=Categoria de membro:
members.owner=Dono
members.member=Membro
members.remove=Remover
members.leave=Sair
members.invite_desc=Add a new member to %s:
members.invite_desc=Adicionar novo membro em %s:
members.invite_now=Convidar Agora
teams.join=Juntar-se
@@ -736,7 +794,7 @@ teams.read_permission_desc=Essa equipe concede acesso para <strong>Leitura</stro
teams.write_permission_desc=Esta equipe concede acesso para <strong>escrita</strong>: Membros podem ler e fazer push para os repositórios da equipe.
teams.admin_permission_desc=Esta equipe concede acesso de <strong>Administrador</strong>: Membros podem ler, fazer push e adicionar outros colaboradores para os repositórios da equipe.
teams.repositories=Repositórios da Equipe
teams.search_repo_placeholder=Search repository...
teams.search_repo_placeholder=Pesquisar repositório...
teams.add_team_repository=Adicionar Repositório da Equipe
teams.remove_repo=Remover
teams.add_nonexistent_repo=O repositório que você está tentando adicionar não existe, por favor, crie-o primeiro.
@@ -767,14 +825,16 @@ dashboard.delete_inactivate_accounts=Excluir todas as contas inativas
dashboard.delete_inactivate_accounts_success=Todas as contas inativas foram excluídas com sucesso.
dashboard.delete_repo_archives=Excluir todos os arquivos dos repositórios
dashboard.delete_repo_archives_success=Todos os arquivos dos repositórios foram excluídos com sucesso.
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.delete_missing_repos=Deletar todos os repositórios que perderam arquivos do git
dashboard.delete_missing_repos_success=Todos os registros de repositórios que perderam arquivos do git foram deletados com sucesso.
dashboard.git_gc_repos=Fazer coleta de lixo nos repositórios
dashboard.git_gc_repos_success=Em todos repositórios, a coleta de lixo foi realizada com sucesso.
dashboard.resync_all_sshkeys=Reescrever o arquivo '.ssh/authorized_keys' (atenção: chaves que não sejam do Gogs serão perdidas)
dashboard.resync_all_sshkeys_success=Todas as chaves públicas foram reescritas com sucesso.
dashboard.resync_all_update_hooks=Reescrever todos os hooks de atualização dos repositórios (necessário quando o caminho de configuração customizado é alterado)
dashboard.resync_all_update_hooks_success=Os hooks de atualização de todos os repositórios foram reescritos com sucesso.
dashboard.reinit_missing_repos=Reinicializar todos os registros de repositório que perderam os arquivos do Git
dashboard.reinit_missing_repos_success=Todos os repositórios que perderam arquivos do Git foram reinicializados com sucesso.
dashboard.server_uptime=Servidor Ligado
dashboard.current_goroutine=Goroutines Atuais
@@ -822,6 +882,8 @@ users.auth_login_name=Nome de login da autenticação
users.password_helper=Deixe em branco para não mudar.
users.update_profile_success=O perfil da conta foi atualizado com sucesso.
users.edit_account=Editar Conta
users.max_repo_creation=Limite máximo de criação de repositórios
users.max_repo_creation_desc=(Use "-1" para utilizar o limite padrão)
users.is_activated=Esta conta está ativada
users.is_admin=Esta conta tem permissões de administrador
users.allow_git_hook=Esta conta tem permissões para criar hooks do Git
@@ -861,9 +923,12 @@ auths.bind_password=Vincular senha
auths.bind_password_helper=Atenção: Esta senha é armazenada em texto plano. Não use uma conta com muitos privilégios.
auths.user_base=Base de pesquisa do usuário
auths.user_dn=Usuário do DN
auths.attribute_username=Atributo nome de usuário
auths.attribute_username_placeholder=Deixe vazio para usar o valor do campo de formulário de entrada de nome de usuário.
auths.attribute_name=Atributo primeiro nome
auths.attribute_surname=Atributo sobrenome
auths.attribute_mail=Atributo e-mail
auths.attributes_in_bind=Buscar os atributos no contexto de Bind DN
auths.filter=Filtro de usuário
auths.admin_filter=Filtro de administrador
auths.ms_ad_sa=Ms Ad SA
@@ -885,6 +950,7 @@ auths.update=Atualizar a configuração da autenticação
auths.delete=Excluir esta autenticação
auths.delete_auth_title=Exclusão da autenticação
auths.delete_auth_desc=Esta autenticação esta prestes a ser deletada, deseja continuar?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=Autenticação deletada com sucesso!
config.server_config=Configuração do Servidor
@@ -901,6 +967,19 @@ config.static_file_root_path=Caminho Raiz para Arquivo Estático
config.log_file_root_path=Caminho Raiz para Arquivo de Log
config.script_type=Tipo de Script
config.reverse_auth_user=Usuário de Autenticação Reversa
config.ssh_config=Configuração de SSH
config.ssh_enabled=Habilitado
config.ssh_start_builtin_server=Iniciar servidor embutido
config.ssh_domain=Domínio
config.ssh_port=Porta
config.ssh_listen_port=Porta de escuta
config.ssh_root_path=Caminho da raiz
config.ssh_key_test_path=Caminho da chave de teste
config.ssh_keygen_path=Caminho do keygen ('ssh-keygen')
config.ssh_minimum_key_size_check=Verificar tamanho mínimo da chave
config.ssh_minimum_key_sizes=Tamanhos mínimos da chave
config.db_config=Configuração do Banco de Dados
config.db_type=Tipo
config.db_host=Host
@@ -915,7 +994,6 @@ config.register_email_confirm=Requerer Confirmação de E-mail
config.disable_register=Desabilitar Registro
config.show_registration_button=Mostrar Botão de Registo
config.require_sign_in_view=Requerer Entrar no Gogs para Ver
config.enable_cache_avatar=Habilitar Cache de Avatar
config.mail_notify=Notificação de Correio
config.disable_key_size_check=Desativar verificação de tamanho mínimo da chave
config.enable_captcha=Habilitar o Captcha
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Desabilitar HELO
config.mailer_name=Nome
config.mailer_host=Host
config.mailer_user=Usuário
config.send_test_mail=Enviar email de teste
config.test_mail_failed=Falha ao enviar o email de teste para '%s': %v
config.test_mail_sent=O email de teste foi enviado para '%s'.
config.oauth_config=Configuração do OAuth
config.oauth_enabled=Habilitado
config.cache_config=Configuração de Cache
@@ -964,23 +1045,34 @@ monitor.start=Hora de Início
monitor.execute_time=Tempo de Execução
notices.system_notice_list=Sistema de Notificações
notices.view_detail_header=Ver detalhe do anúncio
notices.actions=Ações
notices.select_all=Selecionar tudo
notices.deselect_all=Desmarcar tudo
notices.inverse_selection=Seleção inversa
notices.delete_selected=Apagar seleção
notices.delete_all=Excluir todos os avisos
notices.type=Tipo
notices.type_1=Repositório
notices.desc=Descrição
notices.op=Op.
notices.delete_success=Aviso do sistema foi deletado com sucesso.
notices.delete_success=Avisos do sistema foram excluídos com sucesso.
[action]
create_repo=repositório criado <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>
create_issue='questão aberta <a href="%s/issues/%s">%s#%[2]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>`
create_pull_request=`criou 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>'
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=`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>
push_tag=Foi feito push na tag <a href="%s/src/%s">%[2]s</a> para <a href="%[1]s">%[3]s</a>
compare_2_commits=Ver comparação desses 2 commits
compare_commits=Ver comparação entre esses %d commits
[tool]
ago=atrás

View File

@@ -1,13 +1,13 @@
app_desc=Удобная служба для собственного Git-репозитория, написанная на языке Go
home=Главная
dashboard=Панель мониторинга
dashboard=Панель управления
explore=Обзор
help=Помощь
sign_in=Войти
sign_out=Выход
sign_up=Регистрация
register=Зарегистрироваться
register=Регистрация
website=Веб-сайт
version=Версия
page=Страница
@@ -20,26 +20,27 @@ signed_in_as=Вы вошли как
username=Имя пользователя
email=Эл. почта
password=Пароль
re_type=Повтор
captcha=Captcha
re_type=Введите повторно
captcha=Капча
repository=Репозиторий
organization=Организация
mirror=Зеркало
new_repo=Новый репозиторий
new_migrate=Новая Миграция
new_fork=Новый проект из репозитория
new_org=Новая Организация
manage_org=Управление Организацией
new_mirror=Новое зеркало
new_fork=Новое ответвление репозитория
new_org=Новая организация
manage_org=Управление организациями
admin_panel=Панель администратора
account_settings=Настройки аккаунта
settings=Настройки
your_profile=Ваш профиль
your_settings=Ваши настройки
news_feed=Лента новостей
pull_requests=Pull Requests
issues=Вопросы
activities=Активность
pull_requests=Запросы на слияние
issues=Задачи
cancel=Отмена
@@ -47,13 +48,13 @@ cancel=Отмена
search=Поиск...
repository=Репозиторий
user=Пользователь
issue=Проблема
issue=Задача
code=Код
[install]
install=Установка
title=Установочные шаги для первого запуска
docker_helper=Если вы используете Gogs в Docker-контейнере, пожалуйста прочтите <a target="_blank" href="%s">эти советы</a>, перед тем как что-либо изменить!
docker_helper=Если вы запускаете Gogs внутри Docker, пожалуйста прочтите <a target="_blank" href="%s">эти советы</a> внимательно перед тем как что-либо изменить на этой странице!
requite_db_desc=Gogs требует MySQL, PostgreSQL, SQLite3 или TiDB.
db_title=Настройки базы данных
db_type=Тип базы данных
@@ -64,17 +65,17 @@ db_name=Имя базы данных
db_helper=Для MySQL используйте тип таблиц InnoDB с кодировкой utf8_general_ci.
ssl_mode=Режим SSL
path=Путь
sqlite_helper=Путь до базы данных SQLite или TiDB.
sqlite_helper=Путь к файлу базы данных SQLite3 или TiDB. <br>Укажите абсолютный путь при запуске в качестве службы.
err_empty_db_path=Путь к базе данных SQLite3 или TiDB не может быть пустым.
err_invalid_tidb_name=Название базы данных TiDB не может содержать символы "." и "-".
no_admin_and_disable_registration=Вы не можете отключить регистрацию, не создав аккаунт администратора.
err_invalid_tidb_name=Имя базы данных TiDB не может содержать символы "." и "-".
no_admin_and_disable_registration=Вы не можете отключить регистрацию до создания учетной записи администратора.
err_empty_admin_password=Пароль администратора не может быть пустым.
general_title=Общие параметры Gogs
app_name=Имя приложения
app_name_helper=Укажите здесь название вашей потрясающей организации!
repo_path=Путь корня репозитория
repo_path_helper=Все удаленные репозитории Git будут сохранены в этой директории.
repo_path_helper=Все сетевые репозитории Git будут сохранены в этой директории.
run_user=Пользователь
run_user_helper=У пользователя должен быть доступ к пути к корню репозитория и к запуску Gogs.
domain=Домен
@@ -85,6 +86,8 @@ http_port=Порт HTTP
http_port_helper=Номер порта, который приложение будет слушать.
app_url=URL приложения
app_url_helper=Этот параметр влияет на URL для клонирования по HTTP/HTTPS и на адреса в электронной почте.
log_root_path=Путь к журналу
log_root_path_helper=Каталог для записи файлов журнала.
optional_title=Расширенные настройки
email_title=Настройки службы электронной почты
@@ -121,6 +124,7 @@ run_user_not_match=Текущий пользователь не является
save_config_failed=Не удалось сохранить конфигурацию: %v
invalid_admin_setting=Указан недопустимый параметр учетной записи администратора: %v
install_success=Добро пожаловать! Мы рады, что вы выбрали Gogs. Веселитесь и берегите себя.
invalid_log_root_path=Недопустимый путь для логов: %v
[home]
uname_holder=Имя пользователь или E-mail
@@ -128,11 +132,11 @@ password_holder=Пароль
switch_dashboard_context=Переключить контекст панели управления
my_repos=Мои репозитории
collaborative_repos=Совместные репозитории
my_orgs=Моя Организация
my_orgs=Мои организации
my_mirrors=Мои зеркала
view_home=Показать %s
issues.in_your_repos=В вашем репозитории
issues.in_your_repos=В ваших репозиториях
[explore]
repos=Репозитории
@@ -149,7 +153,7 @@ forget_password=Забыли пароль?
sign_up_now=Нужен аккаунт? Зарегистрируйтесь.
confirmation_mail_sent_prompt=Новое письмо для подтверждения было направлено на <b>%s</b>, пожалуйста, проверьте ваш почтовый ящик в течение %d часов для завершения регистрации.
active_your_account=Активируйте свой аккаунт
resent_limit_prompt=Вы слишком часто отправляете письмо с активацией. Подождите 3 минуты, пожалуйста.
resent_limit_prompt=Извините, вы уже запросили активацию по электронной почте недавно. Пожалуйста, подождите 3 минуты, а затем повторите попытку.
has_unconfirmed_mail=Здравствуйте, %s! У вас есть неподтвержденный адрес электронной почты (<b>%s</b>). Если вам не приходило письмо с подтверждением или нужно выслать новое письмо, нажмите на кнопку ниже.
resend_mail=Нажмите здесь, чтобы переотправить активационное письмо
email_not_associate=Этот адрес электронной почты не связан ни с одной учетной записью.
@@ -191,24 +195,23 @@ size_error=` должен быть размер %s.`
min_size_error=«должен содержать по крайней мере %s символов.»
max_size_error=` должен содержать максимум %s символов.`
email_error=«не является адресом электронной почты.»
url_error=«не является допустимым URL-адресом.»
include_error=` должен содержать '%s'`
url_error=` не является допустимым URL-адресом.`
include_error=` должен содержать '%s'.`
unknown_error=Неизвестная ошибка:
captcha_incorrect=CAPTCHA не совпадает.
password_not_match=Пароль и подтверждение пароля не совпадают.
captcha_incorrect=Капча не пройдена.
password_not_match=Пароли не совпадают.
username_been_taken=Имя пользователя уже принято.
repo_name_been_taken=Имя репозитория уже принято.
org_name_been_taken=Название организации было уже принято.
team_name_been_taken=Название команды было уже принято.
username_been_taken=Имя пользователя занято.
repo_name_been_taken=Имя репозитория занято.
org_name_been_taken=Название организации занято.
team_name_been_taken=Название команды занято.
email_been_used=Адрес электронной почты уже используется.
illegal_team_name=Имя группы содержит недопустимые знаки.
username_password_incorrect=Имя пользователя или пароль не правильный.
enterred_invalid_repo_name=Пожалуйста, убедитесь, что введенно правильное имя хранилища.
enterred_invalid_repo_name=Пожалуйста, убедитесь, что введено правильное имя репозитория.
enterred_invalid_owner_name=Убедитесь, что введенное имя владельца верное.
enterred_invalid_password=Убедитесь, что введенный пароль верен.
user_not_exist=Данный пользователь не существует.
last_org_owner=Удаляемый пользователь является последним в команде владельцев. Должен быть хотя бы один владелец.
last_org_owner=Удаление последнего пользователя из команды владельцев невозможно, поскольку всегда должен быть хотя бы один владелец в любой организации.
invalid_ssh_key=К сожалению, мы не смогли проверить ваш SSH-ключ: %s
unable_verify_ssh_key=Gogs не может проверить ваш SSH-ключ, но мы допускаем, что он действителен. Пожалуйста, удостоверьтесь самостоятельно, что ключ действителен.
@@ -218,19 +221,19 @@ still_own_repo=На вашем аккаунте все еще остается
still_has_org=Вы находитесь в организации, сперва Вам необходимо покинуть ее или удалить.
org_still_own_repo=Данная организация все еще является владельцем репозиториев, необходимо удалить или переместить их в начале.
still_own_user=Эта проверка подлинности по-прежнему используется некоторыми пользователями, вы должны переместить их и затем снова удалить.
target_branch_not_exist=Целевая ветка не существует
[user]
change_avatar=Измените ваш аватар на gravatar.com
change_custom_avatar=Измените ваш аватар в настройках
join_on=Присоединилась к
join_on=Присоединился
repositories=Репозитории
activity=Активность
followers=Подписчики
starred=Избранное
following=Подписан
follow=Подписаться
unfollow=Отписаться
form.name_reserved=Имя пользователя '%s' зарезервировано.
form.name_pattern_not_allowed=Имя пользователя «%s» не допускается.
@@ -247,6 +250,7 @@ uid=UID
public_profile=Открытый профиль
profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт.
password_username_disabled=Нелокальные пользователи не могут изменить своё имя.
full_name=ФИО
website=Веб-сайт
location=Местоположение
@@ -258,11 +262,10 @@ continue=Далее
cancel=Отмена
enable_custom_avatar=Включить собственный аватар
enable_custom_avatar_helper=Включите эту опцию, чтоб отключить загрузку с Gravatar
choose_new_avatar=Выбрать новый аватар
update_avatar=Обновить настройку аватара
delete_current_avatar=Удалить текущий аватар
uploaded_avatar_not_a_image=Загружаемый файл не является изображением.
no_custom_avatar_available=Собственный аватар недоступен, включить его невозможно.
update_avatar_success=Настройка вашего аватара обновлена успешно.
change_password=Сменить пароль
@@ -271,6 +274,7 @@ new_password=Новый пароль
retype_new_password=Подтверждение нового пароля
password_incorrect=Текущий пароль не правильный.
change_password_success=Пароль сменен успешно. Теперь вы можете войти с новым паролем.
password_change_disabled=Нелокальные пользователи не могут изменить свой пароль.
emails=Адреса электронной почты
manage_emails=Управление адресами электронной почты
@@ -319,7 +323,7 @@ token_name=Имя маркера
generate_token=Генерировать маркер
generate_token_succees=Успешно создан новый токен доступа! Пожалуйста сделайте копию вашего нового токена персонального доступа. Вы не сможете увидеть его снова!
delete_token=Удалить
access_token_deletion=Удаление персонального токена доступа
access_token_deletion=Удаление личного токена доступа
access_token_deletion_desc=Удаление этого персонального токена доступа приведет к удалению всех связанных прав доступа к приложению. Вы хотите продолжить?
delete_token_success=Персональный токен доступа успешно удален! Не забудьте изменить настройки вашего приложения.
@@ -336,7 +340,7 @@ repo_name_helper=Лучшие названия репозиториев коро
visibility=Видимость
visiblity_helper=<span class="ui red text">Личный</span> репозиторий
visiblity_helper_forced=Все новые репозитории являются <span class="ui red text">Личными</span> по желанию администратора сайта
visiblity_fork_helper=(Изменение этого значения затронет все форки)
visiblity_fork_helper=(Изменение этого значения затронет все ответвления)
clone_helper=Нужна помощь в клонировании? Посетите страницу <a target="_blank" href="%s">помощи</a>!
fork_repo=Ответвить репозиторий
fork_from=Ответвление от
@@ -352,10 +356,13 @@ auto_init=Инициализировать этот репозиторий вы
create_repo=Создать репозиторий
default_branch=Ветка по умолчанию
mirror_interval=Интервал зеркалирования (час)
mirror_address=Адрес зеркала
mirror_address_desc=Укажите необходимые учетные данные в адрес.
watchers=Наблюдатели
stargazers=Stargazers
forks=Форки
stargazers=Звездочеты
forks=Ответвления
form.reach_limit_of_creation=У владельца достигнут максимальный предел в %d создаваемых репозиториев.
form.name_reserved=Имя репозитория '%s' зарезервировано.
form.name_pattern_not_allowed=Шаблон имени репозитория '%s' не допускается.
@@ -367,10 +374,11 @@ migrate.clone_address=Скопировать адрес
migrate.clone_address_desc=Это может быть HTTP/HTTPS/GIT адрес или локальный путь на сервере.
migrate.permission_denied=У вас нет прав на импорт локальных репозиториев.
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
migrate.failed=Migration failed: %v
migrate.failed=Миграция не удалась: %v
forked_from=форк от
fork_from_self=Вы не можете форкнуть репозитарий, так как Вы уже его владелец!
mirror_from=зеркало из
forked_from=ответвлено от
fork_from_self=Вы не можете ответвить репозиторий, так как Вы уже его владелец!
copy_link=Скопировать
copy_link_success=Скопировано!
copy_link_error=Нажмите ⌘-C или Ctrl-C для копирования
@@ -388,13 +396,14 @@ create_new_repo_command=Создать новый репозиторий из к
push_exist_repo=Отправить существующий репозиторий из командной строки
repo_is_empty=Этот репозиторий пуст, пожалуйста, возвращайтесь позже!
code=Код
branch=Ветка
tree=Дерево
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=Фильтр по ветке или тегу
branches=Ветки
tags=Метки
issues=Обсуждения
pulls=Пулл реквесты
pulls=Запросы на слияние
labels=Метки
milestones=Этапы
commits=Коммиты
@@ -415,7 +424,7 @@ commits.newer=Новее
issues.new=Новая задача
issues.new.labels=Метки
issues.new.no_label=Не метка
issues.new.no_label=Нет меток
issues.new.clear_labels=Отчистить метки
issues.new.milestone=Этап
issues.new.no_milestone=Нет этапа
@@ -429,8 +438,8 @@ issues.create=Добавить задачу
issues.new_label=Новая метка
issues.new_label_placeholder=Имя метки...
issues.create_label=Добавить метку
issues.open_tab=%d Открыть
issues.close_tab=%d Закрыть
issues.open_tab=%d открыто(ы)
issues.close_tab=%d закрыто(ы)
issues.filter_label=Метка
issues.filter_label_no_select=Нет выбранной метки
issues.filter_milestone=Этап
@@ -439,7 +448,7 @@ issues.filter_assignee=Назначено
issues.filter_assginee_no_select=Ответственный не выбран
issues.filter_type=Тип
issues.filter_type.all_issues=Все задачи
issues.filter_type.assigned_to_you=Назначено Вам
issues.filter_type.assigned_to_you=Назначено вам
issues.filter_type.created_by_you=Созданные вами
issues.filter_type.mentioning_you=Вы упомянуты
issues.filter_sort=Сортировать
@@ -449,25 +458,25 @@ issues.filter_sort.recentupdate=Недавно обновленные
issues.filter_sort.leastupdate=Давно обновленные
issues.filter_sort.mostcomment=Большего комментариев
issues.filter_sort.leastcomment=Меньше комментариев
issues.opened_by=%[1] открыта <a href="%[2]s">%[3]s</a>
issues.opened_by=%[1]s открыта <a href="%[2]s">%[3]s</a>
issues.opened_by_fake=%[1]s открыта %[2]s
issues.previous=Предыдущая страница
issues.next=Следующая страница
issues.open_title=Открыта
issues.closed_title=Закрыта
issues.open_title=Открыто
issues.closed_title=Закрыто
issues.num_comments=комментариев: %d
issues.commented_at=` прокомментировал <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.no_content=Пока нет содержимого.
issues.close_issue=Закрыть
issues.close_comment_issue=Прокомментировать и закрыть
issues.reopen_issue=Открыть снова
issues.reopen_comment_issue=Прокомментировать и открыть
issues.reopen_comment_issue=Прокомментировать и открыть снова
issues.create_comment=Комментировать
issues.closed_at=`закрыл <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`открыл снова <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`упомянул эту задачу в коммите <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Автор
issues.admin=Администратор
issues.collaborator=Соавтор
issues.owner=Владелец
issues.sign_up_for_free=Зарегистрируйтесь бесплатно
issues.sign_in_require_desc=чтобы присоединиться к обсуждению. Уже есть аккаунт? <a href="%s">Войдите чтобы прокомментировать</a>
@@ -484,41 +493,42 @@ issues.label_modify=Изменение метки
issues.label_deletion=Удаление метки
issues.label_deletion_desc=Удаление ярлыка затронет все связанные задачи. Продолжить?
issues.label_deletion_success=Метка была удалена успешно!
issues.num_participants=%d участников
pulls.new=Новый пул реквест
pulls.new=Новый запрос на слияние
pulls.compare_changes=Сравнить изменения
pulls.compare_changes_desc=Сравнить две ветки и создать пулл реквест для изменений.
pulls.compare_changes_desc=Сравнить две ветки и создать запрос на слияние для изменений.
pulls.compare_base=родительская ветка
pulls.compare_compare=сравнить
pulls.filter_branch=Фильтр по ветке
pulls.no_results=Результатов не найдено.
pulls.nothing_to_compare=Нечего сравнивать, родительская и текущая ветка одинаковые.
pulls.has_pull_request=`Уже существует пулл-реквест между двумя целями <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Создать пулл-реквест
pulls.has_pull_request=`Уже существует запрос на слияние между двумя целями: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Создать запрос на слияние
pulls.title_desc=хочет смерджить %[1]d коммит(ов) из <code>%[2]s</code> в <code>%[3]s</code>
pulls.merged_title_desc=слито %[1]d коммит(ов) из <code>%[2]s</code> в <code>%[3]s</code> %[4]s
pulls.tab_conversation=Обсуждение
pulls.tab_commits=Коммиты
pulls.tab_files=Измененные файлы
pulls.reopen_to_merge=Пожалуйста пересоздайте пулл-реквест для слияния.
pulls.reopen_to_merge=Пожалуйста снова откройте этот запрос для слияния.
pulls.merged=Слито
pulls.has_merged=Слияние этого пулл-реквеста успешно завершено!
pulls.data_broken=Содержимое этого пулл-реквеста было нарушено, вследствии удаления или клонирования информации.
pulls.has_merged=Слияние этого запроса успешно завершено!
pulls.data_broken=Содержимое этого запроса было нарушено вследствие удаления информации ответвления.
pulls.is_checking=Продолжается проверка конфликтов, пожалуйста обновите страницу несколько позже.
pulls.can_auto_merge_desc=Вы можете провести операцию автоматического слияния для этого пулл-реквеста.
pulls.cannot_auto_merge_desc=Вы не можете произвести операцию автоматического слияния, потому как существуют конфликты между коммитами.
pulls.cannot_auto_merge_helper=Используйте командную строку для решения этого.
pulls.can_auto_merge_desc=Этот запрос на слияние может быть объединён автоматически.
pulls.cannot_auto_merge_desc=Этот запрос на слияние не может быть объединён автоматически.
pulls.cannot_auto_merge_helper=Пожалуйста, совершите слияние вручную для урегулирования конфликтов.
pulls.merge_pull_request=Слить пулл-реквест
pulls.open_unmerged_pull_exists=`Вы не можете произвести операцию переоткрытия, потому что уже существует пулл-реквест (#%d) из этого же репозитория, с такими же параметрами слияния, который ожидает слияния.`
pulls.open_unmerged_pull_exists=`Вы не можете снова открыть, поскольку уже существует запрос на слияние (#%d) из того же репозитория с той же информацией о слиянии и ожидающий слияния. `
milestones.new=Новая контрольная точка
milestones.open_tab=%d открыты
milestones.close_tab=%d Закрыт
milestones.close_tab=%d закрыты
milestones.closed=Закрыт %s
milestones.no_due_date=Срок не указан
milestones.open=Открыть
milestones.close=Закрыть
milestones.new_subheader=Создавайте контрольные точки для трекинга ваших вопросов.
milestones.new_subheader=Создавайте этапы для организации ваших задач.
milestones.create=Создать контрольную точку
milestones.title=Заголовок
milestones.desc=Описание
@@ -532,32 +542,70 @@ milestones.cancel=Отмена
milestones.modify=Изменить контрольную точку
milestones.edit_success=Изменения контрольной точки '%s' успешно сохранены!
milestones.deletion=Удаление контрольной точки
milestones.deletion_desc=Удаление этой контрольной точки приведет с удалению всей информации, во всех вопросах (Issues). Вы действительно хотите продолжить?
milestones.deletion_desc=Удаление этого этапа приведет к удалению связанной информации во всех связанных задачах. Вы хотите продолжить?
milestones.deletion_success=Контрольная точка успешно удалена!
wiki=Вики
wiki.welcome=Добро пожаловать в Вики!
wiki.welcome_desc=Вики это место, где вы можете документировать проект вместе и сделать его лучше.
wiki.create_first_page=Создать первую страницу
wiki.page=Страница
wiki.filter_page=Фильтр страницы
wiki.new_page=Создать новую страницу
wiki.default_commit_message=Написать заметку о данном обновлении (опционально).
wiki.save_page=Сохранить страницу
wiki.last_commit_info=%s редактировал эту страницу %s
wiki.edit_page_button=Редактировать
wiki.new_page_button=Новая страница
wiki.delete_page_button=Удалить страницу
wiki.delete_page_notice_1=Будьте внимательны! Это приведет к удалению страницы <code>«%s»</code>.
wiki.page_already_exists=Вики-страница с таким именем уже существует.
wiki.pages=Страницы
wiki.last_updated=Последнее обновление %s
settings=Настройки
settings.options=Опции
settings.collaboration=Сотрудничество
settings.hooks=Автоматическое обновление
settings.githooks=Git хуки
settings.basic_settings=Основные параметры
settings.danger_zone=Опасная зона
settings.site=Официальный сайт
settings.update_settings=Обновить настройки
settings.change_reponame_prompt=Это изменение повлияет на отношения ссылок к этому репозиторию.
settings.advanced_settings=Расширенные настройки
settings.wiki_desc=Включить Вики, чтобы позволить людям писать документы
settings.use_external_wiki=Использовать внешнюю Wiki
settings.external_wiki_url=URL-адрес внешней Вики
settings.external_wiki_url_desc=Посетители будут перенаправлены на URL-адрес, когда они кликнут по вкладке.
settings.issues_desc=Включить встроенную, легковесную систему отслеживания ошибок
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера задачи.
settings.pulls_desc=Включить публичные запросы на слияние
settings.danger_zone=Опасная зона
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
settings.convert=Преобразовать в обычный репозиторий
settings.convert_desc=Это зеркало можно преобразовать в обычный репозиторий. Это не может быть отменено.
settings.convert_notices_1=- Эта операция преобразует это зеркало в обычный репозиторий, и она не может быть отменена.
settings.convert_confirm=Подтвердите преобразование
settings.convert_succeed=Репозиторий был успешно преобразован в обычный.
settings.transfer=Передать права собственности
settings.transfer_desc=Передать репозиторий другому пользователю или организации где у вас есть права администратора.
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
settings.delete=Удалить этот репозиторий
settings.delete_desc=Как только вы удалите репозиторий — пути назад не будет. Удостоверьтесь, что вам это точно нужно.
settings.transfer_notices_1=- Вы можете потерять доступ, если новый владелец является отдельным пользователем.
settings.transfer_notices_2=- Вы сохраните доступ, если новым владельцем станет организация, владельцем которой вы являетесь.
settings.transfer_form_title=Введите сопутствующую информацию для подтверждения операции:
settings.wiki_delete=Стереть данные Вики
settings.wiki_delete_desc=Будьте внимательны! Как только вы удалите Вики — пути назад не будет.
settings.wiki_delete_notices_1=-Это будет удалено и отключит Вики для %s
settings.wiki_deletion_success=Данные Вики успешно стерты.
settings.delete=Удалить этот репозиторий
settings.delete_desc=Будьте внимательны! Как только вы удалите репозиторий — пути назад не будет.
settings.delete_notices_1=- Эта операция <strong>НЕ МОЖЕТ</strong> быть отменена.
settings.delete_notices_2=- Эта операция перманентно удалит всё из этого репозитория, включая данные Git, связанные с ним вопросы, комментарии и права доступа для сотрудников.
settings.delete_notices_2=- Эта операция навсегда удалит всё из этого репозитория, включая данные Git, связанные с ним задачи, комментарии и права доступа для сотрудников.
settings.delete_notices_fork_1=- Если данный репозиторий является публичным, все склонированные репозитории останутся независимыми, после его удаления.
settings.delete_notices_fork_2=- Если данный репозиторий является приватным, все его форки будут удалены вместе с ним.
settings.delete_notices_fork_3=- Если вы хотите сохранить все форки после удаления репозитория, то сначала сделайте его публичным.
settings.delete_notices_fork_2=- Если данный репозиторий является приватным, все его ответвления будут удалены вместе с ним.
settings.delete_notices_fork_3=- Если вы хотите сохранить все ответвления после удаления репозитория, то сначала сделайте его публичным.
settings.deletion_success=Репозиторий был успешно удалён!
settings.update_settings_success=Настройка репозитория обновлена успешно.
settings.transfer_owner=Новый владелец
settings.make_transfer=Выполнить передачу
@@ -565,14 +613,21 @@ settings.transfer_succeed=Владение репозиторием было у
settings.confirm_delete=Подтвердить удаление
settings.add_collaborator=Добавить нового соавтора
settings.add_collaborator_success=Был добавлен новый соавтор.
settings.delete_collaborator=Удалить
settings.collaborator_deletion=Удаление соавтора
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=Удалить веб-хук
settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей, связанной с ним, информации, включая историю. Хотите продолжить?
settings.webhook_deletion_success=Веб-хук успешно удален!
settings.webhook.test_delivery=Проверить доставку
settings.webhook.test_delivery_desc=Отправить push для тестирования настройки веб-хуков
settings.webhook.test_delivery_success=Тест веб-хука была добавлен в очередь доставки. Это может занять несколько секунд, прежде чем он отобразится в истории доставки.
settings.webhook.request=Запрос
settings.webhook.response=Ответ
settings.webhook.headers=Заголовки
@@ -612,6 +667,7 @@ settings.slack_domain=Домен
settings.slack_channel=Канал
settings.deploy_keys=Ключи развертывания
settings.add_deploy_key=Добавить ключ развертывания
settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта.
settings.no_deploy_keys=Вы не добавляли ключи развертывания.
settings.title=Заголовок
settings.deploy_key_content=Содержимое
@@ -627,6 +683,8 @@ diff.parent=Родитель
diff.commit=Сommit
diff.data_not_available=Данные Diff не доступны.
diff.show_diff_stats=Показать статистику Diff
diff.show_split_view=Разделённый вид
diff.show_unified_view=Единый вид
diff.stats_desc=<strong> %d измененных файлов</strong> с <strong>%d добавлено</strong> и <strong>%d удалено</strong>
diff.bin=BIN
diff.view_file=Просмотреть файл
@@ -634,18 +692,18 @@ diff.view_file=Просмотреть файл
release.releases=Релизы
release.new_release=Новый релиз
release.draft=Черновик
release.prerelease=Предрелиз
release.prerelease=Пре-релиз
release.stable=Стабильный
release.edit=Редактировать
release.ahead=<strong>%d</strong> коммитов %s начиная с этого релиза
release.source_code=Исходный код
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.new_subheader=Публикуйте релизы для итерации продукта.
release.edit_subheader=Подробный журнал изменений может помочь пользователям понять, что было улучшено.
release.tag_name=Имя тега
release.target=Цель
release.tag_helper=Выберите существующий тег, или создайте новый.
release.title=Title
release.content=Content
release.title=Заголовок
release.content=Содержимое
release.write=Запись
release.preview=Предварительный просмотр
release.loading=Загрузка...
@@ -655,11 +713,11 @@ release.cancel=Отменить
release.publish=Опубликовать релиз
release.save_draft=Сохранить черновик
release.edit_release=Редактировать релиз
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.tag_name_already_exist=Релиз с этим именем тега уже существует.
release.delete_release=Удалить этот релиз
release.deletion=Удаление релиза
release.deletion_desc=Удаление этого релиза удалит соответствующую Git метку. Вы хотите продолжить?
release.deletion_success=Релиз был успешно удален!
release.tag_name_already_exist=Релиз с этим именем метки уже существует.
release.downloads=Загрузки
[org]
@@ -757,7 +815,7 @@ total=Всего: %d
dashboard.statistic=Статистика
dashboard.operations=Операции
dashboard.system_status=Статус системного монитора
dashboard.statistic_info=В базе данных Gogs записано <b>%d</b> пользователей, <b>%d</b> организаций, <b>%d</b> публичных ключей, <b>%d</b> репозиторий, <b>%d</b> подписок на репозитории, <b>%d</b> добавлений в избранное, <b>%d</b> действий, <b>%d</b> доступов, <b>%d</b> обсуждений, <b>%d</b> комментариев, <b>%d</b> социальных учетных записей, <b>%d</b> подписок на пользователей, <b>%d</b> зеркал, <b>%d</b> релизов, <b>%d</b> источников входа, <b>%d</b> веб-хуков, <b>%d</b> вех, <b>%d</b> меток, <b>%d</b> задач хуков, <b>%d</b> команд, <b>%d</b> задач по обновлению, <b>%d</b> присоединенных файлов.
dashboard.statistic_info=В базе данных Gogs записано <b>%d</b> пользователей, <b>%d</b> организаций, <b>%d</b> публичных ключей, <b>%d</b> репозиториев, <b>%d</b> подписок на репозитории, <b>%d</b> добавлений в избранное, <b>%d</b> действий, <b>%d</b> доступов, <b>%d</b> задач, <b>%d</b> комментариев, <b>%d</b> социальных учетных записей, <b>%d</b> подписок на пользователей, <b>%d</b> зеркал, <b>%d</b> релизов, <b>%d</b> источников входа, <b>%d</b> веб-хуков, <b>%d</b> этапов, <b>%d</b> меток, <b>%d</b> задач хуков, <b>%d</b> команд, <b>%d</b> задач по обновлению, <b>%d</b> присоединенных файлов.
dashboard.operation_name=Наименование Операции
dashboard.operation_switch=Переключить
dashboard.operation_run=Запуск
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys=Переписать файл «.ssh/authorized_key
dashboard.resync_all_sshkeys_success=Были успешно переписаны все открытые ключи.
dashboard.resync_all_update_hooks=Перезаписать все апдейт-хуки этого репозитория (необходимо, когда изменен путь до папки конфигураций)
dashboard.resync_all_update_hooks_success=Апдейт-хуки всех репозиториев успешно перезаписаны.
dashboard.reinit_missing_repos=Реинициализировать все репозитории с утерянными Git файлами
dashboard.reinit_missing_repos_success=Все репозитории с утерянными Git файлами успешно реинициализированы.
dashboard.server_uptime=Время непрерывной работы сервера
dashboard.current_goroutine=Текущий Goroutines
@@ -822,6 +882,8 @@ users.auth_login_name=Логин для авторизации
users.password_helper=Оставьте пустым, чтобы оставить без изменений.
users.update_profile_success=Профиль учетной записи обновлен успешно.
users.edit_account=Изменение учетной записи
users.max_repo_creation=Ограничение максимального количества создаваемых репозиториев
users.max_repo_creation_desc=(Установить -1 для использования стандартного глобального значения предела)
users.is_activated=Эта учетная запись активирована
users.is_admin=У этой учетной записи есть права администратора
users.allow_git_hook=Пользователь имеет право создать Git перехватчик
@@ -843,7 +905,7 @@ repos.name=Имя
repos.private=Приватный
repos.watches=Следят
repos.stars=В избранном
repos.issues=Вопросы
repos.issues=Задачи
auths.auth_manage_panel=Панель управления аутнентификациями
auths.new=Добавить новый источник
@@ -861,9 +923,12 @@ auths.bind_password=Привязать пароль
auths.bind_password_helper=Внимание: Этот пароль сохранен в небезопасном виде. Не используйте высоко-привилегированную учетную запись.
auths.user_base=База для поиска пользователя
auths.user_dn=DN пользователя
auths.attribute_username=Атрибут username
auths.attribute_username_placeholder=Оставьте пустым, чтобы использовать имя пользователя для регистрации.
auths.attribute_name=Имя аттрибута
auths.attribute_surname=Фамилия аттрибута
auths.attribute_mail=Электронная почта аттрибута
auths.attributes_in_bind=Извлечение атрибутов в виде Bind DN
auths.filter=Фильтр пользователя
auths.admin_filter=Фильтр администратора
auths.ms_ad_sa=Ms Ad SA
@@ -885,6 +950,7 @@ auths.update=Обновить параметры аутентификации
auths.delete=Удалить этот канал аутентификации
auths.delete_auth_title=Удаление канала аутентификации
auths.delete_auth_desc=Этот канал аутентификации будет удален. Вы уверены что хотите продолжить?
auths.still_in_used=Эта проверка подлинности до сих пор используется некоторыми пользователями, удалите или преобразуйте этих пользователей в другой тип входа в систему.
auths.deletion_success=Канал аутентификации успешно удален!
config.server_config=Конфигурация сервера
@@ -901,6 +967,19 @@ config.static_file_root_path=Статичный путь до файла
config.log_file_root_path=Путь до папки с логами
config.script_type=Тип сценария
config.reverse_auth_user=Заголовок с именем пользователя для авторизации на reverse proxy
config.ssh_config=Конфигурация SSH
config.ssh_enabled=Включено
config.ssh_start_builtin_server=Запустить встроенный сервер
config.ssh_domain=Домен
config.ssh_port=Порт
config.ssh_listen_port=Прослушиваемый порт
config.ssh_root_path=Корневой путь
config.ssh_key_test_path=Путь к тестовому ключу
config.ssh_keygen_path=Путь к генератору ключей ('ssh-keygen')
config.ssh_minimum_key_size_check=Минимальный размер ключа проверки
config.ssh_minimum_key_sizes=Минимальные размеры ключа
config.db_config=Конфигурация базы данных
config.db_type=Тип
config.db_host=Хост
@@ -915,7 +994,6 @@ config.register_email_confirm=Требуется подтверждение по
config.disable_register=Отключить регистрацию
config.show_registration_button=Показать кнопку регистрации
config.require_sign_in_view=Для просмотра необходима авторизация
config.enable_cache_avatar=Кешировать аватар
config.mail_notify=Почтовые уведомления
config.disable_key_size_check=Отключить проверку на минимальный размер ключа
config.enable_captcha=Включить капчу
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=Отключить HELO
config.mailer_name=Имя
config.mailer_host=Сервер
config.mailer_user=Пользователь
config.send_test_mail=Отправить тестовое письмо
config.test_mail_failed=Не удалось отправить тестовое письмо «%s»: %v
config.test_mail_sent=Тестовое письмо было отправлено «%s».
config.oauth_config=Конфигурация OAuth
config.oauth_enabled=Включено
config.cache_config=Настройки кеша
@@ -964,6 +1045,13 @@ monitor.start=Момент начала
monitor.execute_time=Время выполнения
notices.system_notice_list=Система уведомлений
notices.view_detail_header=Подробности уведомления
notices.actions=Действия
notices.select_all=Выбрать всё
notices.deselect_all=Убрать выделение со всего
notices.inverse_selection=Инверсия выделения
notices.delete_selected=Удалить выбранные
notices.delete_all=Удалить все уведомления
notices.type=Тип
notices.type_1=Репозиторий
notices.desc=Описание
@@ -971,16 +1059,20 @@ notices.op=Op.
notices.delete_success=Системное уведомление успешно удалено.
[action]
create_repo=создан репозиторий <a href="%s"> %s</a>
create_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>
create_issue=`открытый вопрос <a href="%s/issues/%s">%s#%[2]</a>`
create_pull_request=`созданный пулл-реквест <a href="%s/pulls/%s">%s#%[2]s</a>`
commit_repo=запушил(а) <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]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>`
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>
push_tag=запушил тэг <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
compare_2_commits=Просмотреть сравнение двух коммитов
push_tag=запушил(а) метку <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
compare_commits=Просмотр сравнение для этих %d коммитов
[tool]
ago=назад
@@ -993,13 +1085,13 @@ now=сейчас
1w=1 неделя %s
1mon=1 месяц %s
1y=1 год %s
seconds=%d секунд %s
minutes=%d минут %s
seconds=секунд %[2]s: %[1]d
minutes=минут %[2]s: %[1]d
hours=%d часов %s
days=%d дней %s
weeks=недель %s: %d
months=месяцев %s: %d
years=лет %s: %d
days=дней %[2]s: %[1]d
weeks=недель %[2]s: %[1]d
months=месяцев %[2]s: %[1]d
years=лет %[2]s: %[1]d
raw_seconds=секунд
raw_minutes=минут

View File

@@ -28,6 +28,7 @@ organization=组织
mirror=镜像
new_repo=创建新的仓库
new_migrate=迁移外部仓库
new_mirror=创建新的镜像
new_fork=创建新的派生仓库
new_org=创建新的组织
manage_org=管理我的组织
@@ -37,7 +38,7 @@ settings=帐户设置
your_profile=个人信息
your_settings=用户设置
news_feed=活动
activities=活动
pull_requests=合并请求
issues=工单管理
@@ -64,7 +65,7 @@ db_name=数据库名称
db_helper=如果您使用 MySQL请使用 INNODB 引擎以及 utf8_general_ci 字符集。
ssl_mode=SSL 模式
path=数据库文件路径
sqlite_helper=SQLite3 或 TiDB 数据库路径。
sqlite_helper=SQLite3 或 TiDB 数据库文件路径。<br>作为服务启动时,请使用绝对路径。
err_empty_db_path=SQLite3 或 TiDB 的数据库路径不能为空。
err_invalid_tidb_name=TiDB 数据库名称不允许包含字符 "." 或 "-" 。
no_admin_and_disable_registration=您不能够在未创建管理员用户的情况下禁止注册。
@@ -85,6 +86,8 @@ http_port=HTTP 端口号
http_port_helper=应用监听的端口号
app_url=应用 URL
app_url_helper=该设置影响 HTTP/HTTPS 克隆地址和一些邮箱中的链接。
log_root_path=日志路径
log_root_path_helper=存放日志文件的目录
optional_title=可选设置
email_title=邮件服务设置
@@ -121,6 +124,7 @@ run_user_not_match=运行系统用户非当前用户:%s -> %s
save_config_failed=应用配置保存失败:%v
invalid_admin_setting=管理员帐户设置不正确:%v
install_success=您好!我们很高兴您选择使用 Gogs祝您使用愉快代码从此无 BUG
invalid_log_root_path=无效的日志路径:%v
[home]
uname_holder=用户名或邮箱
@@ -202,7 +206,6 @@ repo_name_been_taken=仓库名称已经被占用。
org_name_been_taken=组织名称已经被占用。
team_name_been_taken=团队名称已经被占用。
email_been_used=邮箱地址已经被使用。
illegal_team_name=团队名称包含非法字符。
username_password_incorrect=用户名或密码不正确。
enterred_invalid_repo_name=请检查您输入的仓库名称是正确。
enterred_invalid_owner_name=请检查您输入的新所有者用户名是否正确。
@@ -218,8 +221,6 @@ still_own_repo=您的帐户仍然是某些仓库的拥有者,您必须先转
still_has_org=您的帐户仍旧是某些组织的成员,您必须先离开或删除组织。
org_still_own_repo=该组织仍然是某些仓库的拥有者,您必须先转移或删除它们才能执行删除组织操作!
still_own_user=该授权认证依旧被部分用户使用,请先删除该部分用户后再试!
target_branch_not_exist=目标分支不存在。
[user]
@@ -231,6 +232,8 @@ activity=公开活动
followers=关注者
starred=已点赞
following=关注中
follow=关注
unfollow=取消关注
form.name_reserved=用户名 '%s' 是被保留的。
form.name_pattern_not_allowed=用户名不允许 '%s' 的格式。
@@ -247,6 +250,7 @@ uid=用户 ID
public_profile=公开信息
profile_desc=您的邮箱地址将会被公开,并被用于接收帐户的所有提醒和通知。
password_username_disabled=非本地类型的用户被禁止修改用户名。
full_name=自定义名称
website=个人网站
location=所在地区
@@ -258,11 +262,10 @@ continue=继续操作
cancel=取消操作
enable_custom_avatar=启动自定义头像
enable_custom_avatar_helper=激活该选项来禁止从 Gravatar 获取头像
choose_new_avatar=选择新的头像
update_avatar=更新头像设置
delete_current_avatar=删除当前头像
uploaded_avatar_not_a_image=上传的文件不是一张图片!
no_custom_avatar_available=未上传过自定义头像,无法激活该选项。
update_avatar_success=您的头像设置更新成功!
change_password=修改密码
@@ -271,6 +274,7 @@ new_password=新的密码
retype_new_password=重新输入新的密码
password_incorrect=当前密码不正确!
change_password_success=密码修改成功!您现在可以使用新的密码登录。
password_change_disabled=非本地类型的用户被禁止修改密码。
emails=邮箱地址
manage_emails=管理邮箱地址
@@ -352,10 +356,13 @@ auto_init=使用选定的文件和模板初始化仓库
create_repo=创建仓库
default_branch=默认分支
mirror_interval=镜像同步周期(小时)
mirror_address=镜像地址
mirror_address_desc=请在镜像地址中写入必要的用户凭据信息。
watchers=关注者
stargazers=称赞者
forks=派生仓库
form.reach_limit_of_creation=该用户已经达到允许创建 %d 个仓库的最大上限。
form.name_reserved=仓库名称 '%s' 是被保留的。
form.name_pattern_not_allowed=仓库名称不允许 '%s' 的格式。
@@ -369,6 +376,7 @@ migrate.permission_denied=您没有获得导入本地仓库的权限。
migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录!
migrate.failed=迁移失败:%v
mirror_from=镜像自地址
forked_from=派生自
fork_from_self=无法派生已经拥有的仓库!
copy_link=复制链接
@@ -388,6 +396,7 @@ create_new_repo_command=从命令行创建一个新的仓库
push_exist_repo=从命令行推送已经创建的仓库
repo_is_empty=该仓库不包含任何内容,请稍后再进行访问!
code=代码
branch=分支
tree=目录树
filter_branch_and_tag=过滤分支或标签
@@ -467,7 +476,7 @@ issues.closed_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 关闭`
issues.reopened_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 重新开启`
issues.commit_ref_at=`在代码提交 <a id="%[1]s" href="#%[1]s">%[2]s</a> 中引用了该工单`
issues.poster=发布者
issues.admin=管理员
issues.collaborator=协作者
issues.owner=所有者
issues.sign_up_for_free=免费注册
issues.sign_in_require_desc=并加入到对话中来。如果您已经注册,可以直接 <a href="%s">登录并评论</a>
@@ -484,6 +493,7 @@ issues.label_modify=修改标签
issues.label_deletion=删除标签操作
issues.label_deletion_desc=删除该标签将会移除所有工单中相关的信息。是否继续?
issues.label_deletion_success=标签删除成功!
issues.num_participants=%d 名参与者
pulls.new=创建合并请求
pulls.compare_changes=对比文件变化
@@ -505,9 +515,9 @@ pulls.merged=已合并
pulls.has_merged=该合并请求已经成功合并!
pulls.data_broken=该合并请求的数据由于派生仓库的相关信息被删除而被破坏。
pulls.is_checking=该合并请求正在进行冲突检查,请稍后再刷新页面。
pulls.can_auto_merge_desc=您可以实现该合并请求自动合并操作。
pulls.cannot_auto_merge_desc=因为代码提交存在冲突,无法对该合并请求执行自动合并操作。
pulls.cannot_auto_merge_helper=使用命令行工具来解决冲突。
pulls.can_auto_merge_desc=该合并请求可以进行自动合并操作。
pulls.cannot_auto_merge_desc=该合并请求存在冲突,无法行自动合并操作。
pulls.cannot_auto_merge_helper=手动拉取代码变更以解决冲突。
pulls.merge_pull_request=合并请求
pulls.open_unmerged_pull_exists=`由于已经存在来自相同仓库和合并信息的未合并请求(#%d您无法执行重新开启操作。`
@@ -535,29 +545,67 @@ milestones.deletion=删除里程碑操作
milestones.deletion_desc=删除该里程碑将会移除所有工单中相关的信息。是否继续?
milestones.deletion_success=里程碑删除成功!
wiki=Wiki
wiki.welcome=欢迎使用 Wiki
wiki.welcome_desc=Wiki 是用于共同协作文档的地方,清晰的文档可以帮助其他人深入了解您的项目。
wiki.create_first_page=创建第一个页面
wiki.page=页面
wiki.filter_page=过滤页面
wiki.new_page=创建新的页面
wiki.default_commit_message=关于此次修改的说明(可选)。
wiki.save_page=保存页面
wiki.last_commit_info=%s 于 %s 修改了此页面
wiki.edit_page_button=修改
wiki.new_page_button=新的页面
wiki.delete_page_button=删除页面
wiki.delete_page_notice_1=此操作将删除页面 <code>"%s"</code>,请三思而后行。
wiki.page_already_exists=相同名称的 Wiki 页面已经存在。
wiki.pages=所有页面
wiki.last_updated=最后更新于 %s
settings=仓库设置
settings.options=基本设置
settings.collaboration=管理协作者
settings.hooks=管理 Web 钩子
settings.githooks=管理 Git 钩子
settings.basic_settings=基本设置
settings.danger_zone=危险操作区
settings.site=官方网站
settings.update_settings=更新仓库设置
settings.change_reponame_prompt=该操作将会影响到所有与该仓库有关的链接
settings.advanced_settings=高级设置
settings.wiki_desc=启用 Wiki 以允许用户协作文档
settings.use_external_wiki=使用外部 Wiki
settings.external_wiki_url=外部 Wiki 链接
settings.external_wiki_url_desc=当访问者单击分页标签时,将会被重定向到该链接。
settings.issues_desc=启用内置的轻量级工单管理系统
settings.use_external_issue_tracker=使用外部的工单管理系统
settings.tracker_url_format=外部工单管理系统的 URL 格式
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分别作为用户名、仓库名和工单索引的占位符。
settings.pulls_desc=启用合并请求以接受社区贡献
settings.danger_zone=危险操作区
settings.new_owner_has_same_repo=新的仓库拥有者已经存在同名仓库!
settings.convert=转换为普通仓库
settings.convert_desc=您可以将该镜像仓库转换为普通仓库,且此操作不可逆。
settings.convert_notices_1=- 该操作会将该镜像仓库转换为普通仓库,且操作不可逆。
settings.convert_confirm=确认转换
settings.convert_succeed=转换为普通仓库类型成功!
settings.transfer=转移仓库所有权
settings.transfer_desc=您可以将仓库转移至您拥有管理员权限的帐户或组织。
settings.new_owner_has_same_repo=新的仓库拥有者已经存在同名仓库!
settings.delete=删除本仓库
settings.delete_desc=删除仓库操作不可逆转,请三思而后行。
settings.transfer_notices_1=- 如果您将仓库转移给个人用户,您将会丢失操作权限。
settings.transfer_notices_2=- 如果您将仓库转移给您是所有者的组织,您的操作权限将被保留。
settings.transfer_form_title=请输入以下信息以确认您的操作:
settings.wiki_delete=清除 Wiki 数据
settings.wiki_delete_desc=清除 Wiki 数据操作不可逆转,请三思而后行。
settings.wiki_delete_notices_1=- 此操作将会清除并禁用仓库 %s 的 Wiki
settings.wiki_deletion_success=仓库 Wiki 数据清除成功!
settings.delete=删除本仓库
settings.delete_desc=删除仓库操作不可逆转,请三思而后行。
settings.delete_notices_1=- 此操作 <strong>不可以</strong> 被回滚。
settings.delete_notices_2=- 此操作将永久删除该仓库,包括 Git 数据、 工单、 评论和协作者的操作权限。
settings.delete_notices_fork_1=- 如果该仓库为公开的,则在删除仓库后所有的派生仓库都将转换成独立的仓库。
settings.delete_notices_fork_2=- 如果该仓库为私有,则会同时删除所有的派生仓库。
settings.delete_notices_fork_3=- 如果您想要保留派生仓库,请先将可见性修改为公开的后再进行删除操作。
settings.deletion_success=仓库删除成功!
settings.update_settings_success=仓库设置更新成功!
settings.transfer_owner=新拥有者
settings.make_transfer=确认转移仓库
@@ -565,14 +613,21 @@ settings.transfer_succeed=仓库所有权转移成功!
settings.confirm_delete=确认删除仓库
settings.add_collaborator=增加新的协作者
settings.add_collaborator_success=成功添加新的协作者!
settings.delete_collaborator=删除
settings.collaborator_deletion=删除协作者
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 钩子
settings.webhook_deletion_desc=删除该 Web 钩子将会删除与其有关的信息和推送历史。是否继续?
settings.webhook_deletion_success=Web 钩子删除成功!
settings.webhook.test_delivery=测试推送
settings.webhook.test_delivery_desc=生成并推送一个模拟的 Push 事件
settings.webhook.test_delivery_success=测试推送已经加入到队列,请耐心等待数秒再刷新推送记录。
settings.webhook.request=请求内容
settings.webhook.response=响应内容
settings.webhook.headers=头信息
@@ -612,6 +667,7 @@ settings.slack_domain=域名
settings.slack_channel=频道
settings.deploy_keys=管理部署密钥
settings.add_deploy_key=添加部署密钥
settings.deploy_key_desc=部署密钥仅具有只读权限,它在功能上和个人用户的公开密钥有本质区别。
settings.no_deploy_keys=您还没有添加任何部署密钥。
settings.title=标题
settings.deploy_key_content=密钥文本
@@ -627,6 +683,8 @@ diff.parent=父节点
diff.commit=当前提交
diff.data_not_available=暂无可用数据
diff.show_diff_stats=显示文件统计
diff.show_split_view=分列视图
diff.show_unified_view=合并视图
diff.stats_desc=共有 <strong> %d 个文件被更改</strong>,包括 <strong>%d 次插入</strong> 和 <strong>%d 次删除</strong>
diff.bin=二进制
diff.view_file=查看文件
@@ -775,6 +833,8 @@ dashboard.resync_all_sshkeys=重新生成 '.ssh/authorized_keys' 文件(警告
dashboard.resync_all_sshkeys_success=所有公钥重新生成成功!
dashboard.resync_all_update_hooks=重新生成所有仓库的 Update 钩子(用于自定义配置文件被修改)
dashboard.resync_all_update_hooks_success=所有仓库的 Update 钩子重新生成成功!
dashboard.reinit_missing_repos=重新初始化所有丢失 Git 文件的仓库
dashboard.reinit_missing_repos_success=所有丢失 Git 文件的仓库重新初始化成功!
dashboard.server_uptime=服务运行时间
dashboard.current_goroutine=当前 Goroutines 数量
@@ -822,6 +882,8 @@ users.auth_login_name=认证登录名称
users.password_helper=将值留空使其保持不变。
users.update_profile_success=该用户信息更新成功!
users.edit_account=编辑用户信息
users.max_repo_creation=最大允许创建仓库数量
users.max_repo_creation_desc=(设置为 -1 表示使用全局默认值)
users.is_activated=该用户已被激活
users.is_admin=该用户具有管理员权限
users.allow_git_hook=该用户具有创建 Git 钩子的权限
@@ -861,9 +923,12 @@ auths.bind_password=绑定密码
auths.bind_password_helper=警告:该密码将会以明文的形式保存在数据库中。请不要使用拥有高权限的帐户!
auths.user_base=用户搜索基准
auths.user_dn=User DN
auths.attribute_username=用户名属性
auths.attribute_username_placeholder=留空表示使用用户登录时所使用的用户名
auths.attribute_name=名字属性
auths.attribute_surname=姓氏属性
auths.attribute_mail=邮箱属性
auths.attributes_in_bind=从 Bind DN 中拉取属性信息
auths.filter=用户过滤规则
auths.admin_filter=管理员过滤规则
auths.ms_ad_sa=Ms Ad SA
@@ -885,6 +950,7 @@ auths.update=更新认证设置
auths.delete=删除该认证
auths.delete_auth_title=删除认证操作
auths.delete_auth_desc=该认证将被删除。是否继续?
auths.still_in_used=此认证仍旧与一些用户有关联,请先删除或者将这些用户转换为其它登录类型。
auths.deletion_success=授权源删除成功!
config.server_config=服务器配置
@@ -901,6 +967,19 @@ config.static_file_root_path=静态文件根目录
config.log_file_root_path=日志文件根目录
config.script_type=脚本类型
config.reverse_auth_user=反向代理认证
config.ssh_config=SSH 配置
config.ssh_enabled=启用服务
config.ssh_start_builtin_server=启用内置服务
config.ssh_domain=域名
config.ssh_port=端口
config.ssh_listen_port=监听端口
config.ssh_root_path=根目录
config.ssh_key_test_path=密钥测试路径
config.ssh_keygen_path=密钥生成器('ssh-keygen')路径
config.ssh_minimum_key_size_check=密钥最小长度检查
config.ssh_minimum_key_sizes=密钥最小长度限制
config.db_config=数据库配置
config.db_type=数据库类型
config.db_host=主机地址
@@ -915,7 +994,6 @@ config.register_email_confirm=注册邮件确认
config.disable_register=关闭注册功能
config.show_registration_button=显示注册按钮
config.require_sign_in_view=强制登录浏览
config.enable_cache_avatar=开启缓存头像
config.mail_notify=邮件通知提醒
config.disable_key_size_check=禁用密钥最小长度检查
config.enable_captcha=启用验证码服务
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=禁用 HELO 操作
config.mailer_name=发送者名称
config.mailer_host=邮件主机地址
config.mailer_user=发送者帐号
config.send_test_mail=发送测试邮件
config.test_mail_failed=发送测试邮件至 '%s' 时失败:%v
config.test_mail_sent=测试邮件已经发送至 '%s'。
config.oauth_config=社交帐号配置
config.oauth_enabled=启用服务
config.cache_config=Cache 配置
@@ -964,6 +1045,13 @@ monitor.start=开始时间
monitor.execute_time=已执行时间
notices.system_notice_list=系统提示管理
notices.view_detail_header=查看提示详情
notices.actions=操作
notices.select_all=选中全部
notices.deselect_all=取消所有选中
notices.inverse_selection=反向选中
notices.delete_selected=删除选中项
notices.delete_all=删除所有提示
notices.type=提示类型
notices.type_1=仓库
notices.desc=描述
@@ -975,12 +1063,16 @@ create_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>
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>`
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>
push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_2_commits=查看 2 次提交的内容对比
compare_commits=对比 %d 次代码提交
[tool]
ago=之前

View File

@@ -3,43 +3,44 @@ app_desc=基於 Go 語言的自助 Git 服務
home=首頁
dashboard=控制面版
explore=探索
help=幫助
sign_in=
sign_out=退
help=說明
sign_in=
sign_out=
sign_up=註冊
register=註冊
website=官方網站
version=當前版本
website=網站
version=版本
page=頁面
template=模版
language=語言選項
template=樣板
language=語言
create_new=創建...
user_profile_and_more=用戶信息及更多
signed_in_as=已登錄用戶
username=用戶名
email=郵箱
username=用戶名
email=電子郵件
password=密碼
re_type=確認密碼
captcha=驗證碼
repository=
repository=儲存
organization=組織
mirror=鏡像
new_repo=創建新的倉
new_repo=新增儲存
new_migrate=遷移外部倉庫
new_fork=的派生倉庫
new_org=創建新的組織
manage_org=管理我的組織
admin_panel=管理面版
account_settings=帳戶設置
settings=戶設置
your_profile=個人信息
your_settings=用戶設置
new_mirror=鏡像
new_fork=新增程式庫分支
new_org=新增組織
manage_org=管理組織
admin_panel=管理面板
account_settings=號設定
settings=設定
your_profile=個人資料
your_settings=用戶設定
news_feed=最新活動
activities=Activities
pull_requests=合併請求
issues=問題管理
issues=問題
cancel=取消
@@ -52,46 +53,48 @@ code=程式碼
[install]
install=安裝頁面
title=首次執行安裝程序
docker_helper=If you're running Gogs inside Docker, please read <a target="_blank" href="%s">Guidelines</a> carefully before you change anything in this page!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB.
title=首次安裝步驟
docker_helper=如果您正在使用 Docker 容器運行 Gogs請務必先仔細閱讀 <a target="_blank" href="%s">官方文檔</a> 後再對本頁面進行填寫。
requite_db_desc=Gogs 要求安裝 MySQLPostgreSQLSQLite3 TiDB
db_title=數據庫設置
db_type=數據庫類型
host=數據庫主機
user=數據庫用戶
password=數據庫用戶密碼
db_name=數據庫名稱
db_type=資料庫類型
host=主機
user=帳號
password=密碼
db_name=資料庫名稱
db_helper=如果您使用 MySQL請使用 INNODB 引擎以及 utf8_general_ci 字符集。
ssl_mode=SSL 模式
path=數據庫文件路徑
sqlite_helper=The file path of SQLite3 or TiDB database.
err_empty_db_path=SQLite3 or TiDB database path cannot be empty.
err_invalid_tidb_name=TiDB database name does not allow characters "." and "-".
no_admin_and_disable_registration=You cannot disable registration without creating an admin account.
err_empty_admin_password=Admin password cannot be empty.
sqlite_helper=The file path of SQLite3 or TiDB database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 TiDB 的數據庫路徑不能為空。
err_invalid_tidb_name=TiDB 數據庫名稱不允許包含字符 "." "-"
no_admin_and_disable_registration=您不能夠在未創建管理員用戶的情況下禁止註冊。
err_empty_admin_password=管理員密碼不能為空。
general_title=應用基本設置
app_name=應用名稱
app_name_helper=為您的組織取個響亮而又偉大的名稱
repo_path=倉庫根目錄
repo_path_helper=所有 Git 遠程倉庫都將被存放於該目錄
run_user=執行系統用戶
run_user_helper=該用戶必須具有對庫根目錄和執行 Gogs 的操作權限。
repo_path=儲存庫的根目錄
repo_path_helper=所有Git遠端儲存庫將會儲存在這個目錄之下
run_user=執行使用者
run_user_helper=該用戶必須具有對儲存庫根目錄和執行 Gogs 的操作權限。
domain=域名
domain_helper=該設置影響 SSH 複製地址。
ssh_port=SSH 埠
ssh_port_helper=您的 SSH 服務正在使用此埠號若要禁用SSH 功能請保持欄位空白。
http_port=HTTP 端口號
http_port_helper=應用監聽的端口號
app_url=應用 URL
app_url=應用程式網址
app_url_helper=該設置影響 HTTP/HTTPS 複製地址和一些郵箱中的連結。
log_root_path=Log Path
log_root_path_helper=Directory to write log files to.
optional_title=可選設置
email_title=電子郵件服務設定
smtp_host=SMTP 主機
smtp_from=郵件來自
smtp_from=寄件者
smtp_from_helper=郵件來自地址,遵循 RFC 5322 標准。可以是一個單純的郵箱地址或使用 "name" <email@example.com> 的格式。
mailer_user=發送郵箱
mailer_user=寄件者 E-mail
mailer_password=發送郵箱密碼
register_confirm=啟用註冊郵箱確認
mail_notify=啟用郵件通知提醒
@@ -102,8 +105,8 @@ disable_gravatar=禁用 Gravatar 服務
disable_gravatar_popup=禁用 Gravatar 和自定義源,僅使用由用戶上傳或默認的頭像。
disable_registration=禁止用戶自主註冊
disable_registration_popup=禁止用戶自主註冊功能,只有管理員可以添加帳號。
enable_captcha=Enable Captcha
enable_captcha_popup=Require validate captcha for user self-registration.
enable_captcha=啟用驗證碼服務
enable_captcha_popup=要求在用戶註冊時輸入驗證碼
require_sign_in_view=啓用登錄訪問限制
require_sign_in_view_popup=只有已登錄的用戶才能夠訪問頁面,否則將只能看到登錄或註冊頁面。
admin_setting_desc=創建管理員帳號並不是必須的,因為 ID=1 的用戶將自動獲得管理員權限。
@@ -111,7 +114,7 @@ admin_title=管理員帳號設置
admin_name=管理員用戶名
admin_password=管理員密碼
confirm_password=確認密碼
admin_email=Admin E-mail
admin_email=管理員郵箱
install_gogs=立即安裝
test_git_failed=無法識別 'git' 命令:%v
sqlite3_not_available=您所使用的發行版本不支持 SQLite3請從 %s 下載官方構建版,而不是 gobuild 版本。
@@ -121,6 +124,7 @@ run_user_not_match=執行系統用戶非當前用戶:%s -> %s
save_config_failed=應用配置保存失敗:%v
invalid_admin_setting=管理員帳戶設置不正確:%v
install_success=您好!我們很高興您選擇使用 Gogs祝您使用愉快代碼從此無 BUG
invalid_log_root_path=Log root path is invalid: %v
[home]
uname_holder=用戶名或郵箱
@@ -160,11 +164,11 @@ reset_password_helper=單擊此處重置密碼
password_too_short=密碼長度不能少於 6 位!
[mail]
activate_account=Please activate your account
activate_email=Verify your e-mail address
reset_password=Reset your password
register_success=Register success, Welcome
register_notify=Welcome on board
activate_account=請激活您的帳戶
activate_email=請驗證您的郵箱地址
reset_password=重置密碼
register_success=註冊成功,歡迎使用
register_notify=歡迎使用
[modal]
yes=確認操作
@@ -173,7 +177,7 @@ modify=確認修改
[form]
UserName=用戶名
RepoName=庫名稱
RepoName=儲存庫名稱
Email=郵箱地址
Password=密碼
Retype=確認密碼
@@ -192,7 +196,7 @@ min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。
email_error=不是一個有效的郵箱地址。
url_error=不是一個有效的 URL。
include_error=` must contain substring '%s'.`
include_error=必須包含子字符串 '%s'
unknown_error=未知錯誤:
captcha_incorrect=驗證碼未匹配。
password_not_match=密碼與確認密碼未匹配。
@@ -202,7 +206,6 @@ repo_name_been_taken=倉庫名稱已經被佔用。
org_name_been_taken=組織名稱已經被佔用。
team_name_been_taken=團隊名稱已經被佔用。
email_been_used=郵箱地址已經被使用。
illegal_team_name=團隊名稱包含不合法字符。
username_password_incorrect=用戶名或密碼不正確。
enterred_invalid_repo_name=請檢查您輸入的倉庫名稱是正確。
enterred_invalid_owner_name=請檢查您輸入的新所有者用戶名是否正確。
@@ -218,8 +221,6 @@ still_own_repo=您的帳戶仍然是某些倉庫的擁有者,您必須先轉
still_has_org=您的帳戶仍舊是某些組織的成員,您必須先離開或刪除組織。
org_still_own_repo=該組織仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除組織操作!
still_own_user=該授權認證依舊被部分用戶使用,請先刪除該部分用戶後再試!
target_branch_not_exist=目標分支不存在
[user]
@@ -231,6 +232,8 @@ activity=公開活動
followers=關註者
starred=已讚好
following=關註中
follow=關注
unfollow=取消關注
form.name_reserved=用戶名 '%s' 是被保留的。
form.name_pattern_not_allowed=用戶名不允許 '%s' 的格式。
@@ -247,30 +250,31 @@ uid=用戶 ID
public_profile=公開信息
profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。
password_username_disabled=不允許非本地類型使用者更改他們的使用者名。
full_name=自定義名稱
website=個人網站
location=所在地區
update_profile=更新信息
update_profile_success=您的個人信息更新成功!
change_username=用戶名將被修改
change_username_prompt=This change will affect the way how links relate to your account.
change_username_prompt=該操作將會影響到所有與您帳戶有關的鏈接
continue=繼續操作
cancel=取消操作
enable_custom_avatar=啟動自定義頭像
enable_custom_avatar_helper=激活該選項來禁止從 Gravatar 獲取頭像
choose_new_avatar=選擇新的頭像
update_avatar=更新頭像設置
delete_current_avatar=Delete Current Avatar
uploaded_avatar_not_a_image=上傳的文件不是一張圖片!
no_custom_avatar_available=沒有任何自定義頭像,無法激活該選項。
update_avatar_success=您的頭像設置更新成功!
change_password=修改密碼
old_password=當前密碼
new_password=新的密碼
retype_new_password=Retype New Password
retype_new_password=重新輸入新的密碼
password_incorrect=當前密碼不正確!
change_password_success=密碼修改成功!您現在可以使用新的密碼登錄。
password_change_disabled=不允許非本地類型使用者,更改其密碼。
emails=電子郵件地址
manage_emails=管理電子郵件地址
@@ -278,9 +282,9 @@ email_desc=您的主要邮箱地址将被用于通知提醒和其它操作。
primary=主要
primary_email=设为主要
delete_email=刪除
email_deletion=E-mail Deletion
email_deletion_desc=Delete this e-mail address will remove related information from your account. Do you want to continue?
email_deletion_success=E-mail has been deleted successfully!
email_deletion=刪除郵箱
email_deletion_desc=刪除該郵箱地址將會移除所有相關的信息。是否繼續?
email_deletion_success=成功刪除郵箱!
add_new_email=添加新的電子郵件地址
add_email=添加電子郵件
add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。
@@ -335,7 +339,7 @@ repo_name=倉庫名稱
repo_name_helper=偉大的倉庫名稱一般都較短、令人深刻並且 <strong>獨一無二</strong> 的。
visibility=可見度
visiblity_helper=該倉庫為 <span class="ui red text">私有的</span>
visiblity_helper_forced=Site admin has forced all new repositories to be <span class="ui red text">Private</span>
visiblity_helper_forced=網站管理員已強制要求所有新建倉庫必須為 <span class="ui red text">私有的</span>
visiblity_fork_helper=(修改該值將會影響到所有派生倉庫)
clone_helper=不知道如何操作?訪問 <a target="_blank"href="%s"> 帮助説明</a>
fork_repo=派生倉庫
@@ -343,19 +347,22 @@ fork_from=派生自
fork_visiblity_helper=派生倉庫無法修改可見性。
repo_desc=倉庫描述
repo_lang=倉庫語言
repo_lang_helper=Select .gitignore files
repo_lang_helper=請選擇 .gitignore 文件
license=授權許可
license_helper=請選擇授權許可文件
readme=Readme
readme_helper=Select a readme template
auto_init=Initialize this repository with selected files and template
readme_helper=請選擇readme模板
auto_init=使用選定的文件和模板初始化倉庫
create_repo=創建倉庫
default_branch=默認分支
mirror_interval=鏡像同步周期(小時)
watchers=Watchers
stargazers=Stargazers
forks=Forks
mirror_address=鏡像地址
mirror_address_desc=請在位址中包括必要的使用者憑據。
watchers=關注者
stargazers=稱讚者
forks=派生倉庫
form.reach_limit_of_creation=擁有者已達到儲存庫最大的新增上限 %d。
form.name_reserved=倉庫名稱 '%s' 是被保留的。
form.name_pattern_not_allowed=倉庫名稱不允許 '%s' 的格式。
@@ -365,17 +372,18 @@ migrate_type_helper=該倉庫將是一個 <span class="text blue">鏡像</span>
migrate_repo=遷移倉庫
migrate.clone_address=複製地址
migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。
migrate.permission_denied=You are not allowed to import local repositories.
migrate.permission_denied=您並沒有導入本地倉庫的權限。
migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄!
migrate.failed=Migration failed: %v
migrate.failed=遷移失敗:%v
mirror_from=镜像来自
forked_from=派生自
fork_from_self=無法派生已經擁有的倉庫!
copy_link=複製連結
copy_link_success=Copied!
copy_link_error=Press ⌘-C or Ctrl-C to copy
copy_link_success=複製成功!
copy_link_error=請按下 ⌘-C Ctrl-C 複製
copied=複製成功
unwatch=取消關
unwatch=取消關
watch=關註
unstar=取消讚好
star=讚好
@@ -386,15 +394,16 @@ quick_guide=快速幫助
clone_this_repo=複製當前倉庫
create_new_repo_command=從命令行創建一個新的倉庫
push_exist_repo=從命令行推送已經創建的倉庫
repo_is_empty=This repository is empty, please come back later!
repo_is_empty=這倉庫不包含任何內容,請稍後再訪問!
code=代碼
branch=分支
tree=目錄樹
filter_branch_and_tag=Filter branch or tag
filter_branch_and_tag=過濾分支或標籤
branches=分支列表
tags=標籤列表
issues=問題管理
pulls=Pull Requests
pulls=合併請求
labels=標籤
milestones=里程碑
commits=提交歷史
@@ -449,7 +458,7 @@ issues.filter_sort.recentupdate=最近更新
issues.filter_sort.leastupdate=最少更新
issues.filter_sort.mostcomment=最多評論
issues.filter_sort.leastcomment=最少評論
issues.opened_by=opened %[1]s by <a href="%[2]s">%[3]s</a>
issues.opened_by= <a href="%[2]s">%[3]s</a> 與 %[1]s創建
issues.opened_by_fake=由 %[2]s 於 %[1]s創建
issues.previous=上一頁
issues.next=下一頁
@@ -465,9 +474,9 @@ issues.reopen_comment_issue=重新開啟及評論
issues.create_comment=評論
issues.closed_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 關閉`
issues.reopened_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 重新開啟`
issues.commit_ref_at=`referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`在代碼提交 <a id="%[1]s" href="#%[1]s">%[2]s</a> 中引用了該問題`
issues.poster=發佈者
issues.admin=管理員
issues.collaborator=Collaborator
issues.owner=所有者
issues.sign_up_for_free=免費註冊
issues.sign_in_require_desc=及加入到對話當中。如果您已經註冊,可以直接 <a href="%s">登錄及評論</a>
@@ -484,32 +493,33 @@ issues.label_modify=修改標籤
issues.label_deletion=刪除標籤
issues.label_deletion_desc=刪除該標籤將會移除所有問題中相關的訊息。是否繼續?
issues.label_deletion_success=標籤刪除成功!
issues.num_participants=%d Participants
pulls.new=New Pull Request
pulls.new=創建合併請求
pulls.compare_changes=對比文件變化
pulls.compare_changes_desc=對比兩個分支間的文件變化及發起一個合併請求。
pulls.compare_base=base
pulls.compare_compare=compare
pulls.filter_branch=Filter branch
pulls.compare_base=基準分支
pulls.compare_compare=對比文件變化
pulls.filter_branch=過濾分支
pulls.no_results=未找到結果
pulls.nothing_to_compare=There is nothing to compare because base and head branches are even.
pulls.has_pull_request=`There is already a pull request between these two targets: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Create Pull Request
pulls.title_desc=wants to merge %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code>
pulls.merged_title_desc=merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
pulls.tab_conversation=Conversation
pulls.tab_commits=Commits
pulls.tab_files=Files changed
pulls.reopen_to_merge=Please reopen this pull request to perform merge operation.
pulls.merged=Merged
pulls.has_merged=This pull request has been merged successfully!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
pulls.merge_pull_request=Merge Pull Request
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
pulls.nothing_to_compare=基準和對比分支代碼已經同步,無需進行對比。
pulls.has_pull_request=`已經存在目標分支的合併請求:<a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=創建合併請求
pulls.title_desc=請求將 %[1]d 次代碼提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code>
pulls.merged_title_desc=於 %[4]s 將 %[1]d 次代碼提交從 <code>%[2]s</code>合併至 <code>%[3]s</code>
pulls.tab_conversation=對話內容
pulls.tab_commits=代碼提交
pulls.tab_files=文件變動
pulls.reopen_to_merge=請重新開啟合併請求來完成合併操作。
pulls.merged=已合併
pulls.has_merged=該合併請求已經成功合併!
pulls.data_broken=該合併請求的數據由於派生倉庫的相關信息被刪除而被破壞。
pulls.is_checking=該合併請求正在進行衝突檢查,請稍後再刷新頁面。
pulls.can_auto_merge_desc=這個拉請求可以自動合併。
pulls.cannot_auto_merge_desc=由於存在衝突,不能自動合併這推送請求。
pulls.cannot_auto_merge_helper=請手動合併來解決衝突。
pulls.merge_pull_request=合併請求
pulls.open_unmerged_pull_exists=`由於已經存在來自相同倉庫和合併信息的未合併請求(#%d您無法執行重新開啟操作。`
milestones.new=新的里程碑
milestones.open_tab=%d 開啟中
@@ -535,29 +545,67 @@ milestones.deletion=刪除里程碑
milestones.deletion_desc=刪除該里程碑將會移除所有問題中相關信息。是否繼續?
milestones.deletion_success=里程碑刪除成功!
wiki=Wiki
wiki.welcome=歡迎使用 Wiki
wiki.welcome_desc=Wiki 是用於共同協作文檔的地方,清晰的文檔可以幫助其他人深入了解您的項目。
wiki.create_first_page=創建第一個頁面
wiki.page=頁面
wiki.filter_page=過濾頁面
wiki.new_page=創建新的頁面
wiki.default_commit_message=關於此次修改的說明(可選)。
wiki.save_page=保存頁面
wiki.last_commit_info=%s 於 %s 修改了此頁面
wiki.edit_page_button=修改
wiki.new_page_button=新的頁面
wiki.delete_page_button=Delete Page
wiki.delete_page_notice_1=This will delete the page <code>"%s"</code>. Please be certain.
wiki.page_already_exists=相同名稱的 Wiki 頁面已經存在。
wiki.pages=所有頁面
wiki.last_updated=最後更新於 %s
settings=倉庫設置
settings.options=基本設置
settings.collaboration=管理協作者
settings.hooks=管理 Web 鉤子
settings.githooks=管理 Git 鉤子
settings.basic_settings=基本設置
settings.danger_zone=危險操作區
settings.site=官方網站
settings.update_settings=更新倉庫設置
settings.change_reponame_prompt=This change will affect how links relate to the repository.
settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關的鏈接
settings.advanced_settings=高級設置
settings.wiki_desc=啟用 Wiki 以允許用戶協作文檔
settings.use_external_wiki=使用外部 wiki
settings.external_wiki_url=外部 Wiki 連結
settings.external_wiki_url_desc=當分頁上按一下,訪客將會重新導到 URL。
settings.issues_desc=啟用內置的輕量級問題管理系統
settings.use_external_issue_tracker=使用外部的問題管理系統
settings.tracker_url_format=外部問題管理系統的 URL 格式
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
settings.pulls_desc=啟用合併請求以接受社區貢獻
settings.danger_zone=危險操作區
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.
settings.convert_notices_1=- This operation will convert this repository mirror into a regular repository and cannot be undone.
settings.convert_confirm=Confirm Conversion
settings.convert_succeed=Repository has been converted to regular type successfully.
settings.transfer=轉移倉庫所有權
settings.transfer_desc=您可以將倉庫轉移至您擁有管理員權限的帳戶或組織。
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
settings.transfer_notices_1=- 如果您將倉庫轉移給個人用戶,您將會丟失操作權限。
settings.transfer_notices_2=- 如果您將倉庫轉移給您是所有者的組織,您的操作權限將被保留。
settings.transfer_form_title=請輸入以下信息以確認您的操作:
settings.wiki_delete=Erase Wiki Data
settings.wiki_delete_desc=Once you erase wiki data there is no going back. Please be certain.
settings.wiki_delete_notices_1=- This will delete and disable the wiki for %s
settings.wiki_deletion_success=Repository wiki data have been erased successfully.
settings.delete=刪除本倉庫
settings.delete_desc=刪除倉庫操作不可逆轉,請三思而後行。
settings.transfer_notices_1=- You will lose access if new owner is a individual user.
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title=Please enter following information to confirm your operation:
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first.
settings.delete_notices_1=- 此操作 <strong>不可以</strong> 被回滾。
settings.delete_notices_2=- 此操作將永久刪除該倉庫,包括 Git 數據、 問題、 評論和協作者的操作權限。
settings.delete_notices_fork_1=- 如果該倉庫為公開的,則在刪除倉庫後所有的派生倉庫都將轉換成獨立的倉庫。
settings.delete_notices_fork_2=- 如果該倉庫為私有,則會同時刪除所有的派生倉庫。
settings.delete_notices_fork_3=- 如果您想要保留派生倉庫,請先將可見性修改為公開的後再進行刪除操作。
settings.deletion_success=倉庫刪除成功!
settings.update_settings_success=倉庫設置更新成功!
settings.transfer_owner=新擁有者
settings.make_transfer=確認轉移倉庫
@@ -565,19 +613,26 @@ settings.transfer_succeed=倉庫所有權轉移成功!
settings.confirm_delete=確認刪除倉庫
settings.add_collaborator=增加新的協作者
settings.add_collaborator_success=成功添加新的協作者!
settings.delete_collaborator=Delete
settings.collaborator_deletion=Collaborator Deletion
settings.collaborator_deletion_desc=This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success=被操作的協作者已經被收回權限!
settings.search_user_placeholder=Search user...
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=Delete Webhook
settings.webhook_deletion_desc=Delete this webhook will remove its information and all delivery history. Do you want to continue?
settings.webhook_deletion_success=Webhook has been deleted successfully!
settings.webhook.request=Request
settings.webhook.response=Response
settings.webhook.headers=Headers
settings.webhook.payload=Payload
settings.webhook.body=Body
settings.webhook_deletion=刪除 Web 鉤子
settings.webhook_deletion_desc=刪除該 Web 鉤子將會刪除與其有關的信息和推送歷史。是否繼續?
settings.webhook_deletion_success=Web 鉤子刪除成功!
settings.webhook.test_delivery=測試推送
settings.webhook.test_delivery_desc=生成並推送一個模擬的 Push 事件
settings.webhook.test_delivery_success=測試推送已經加入到隊列,請耐心等待數秒再刷新推送記錄。
settings.webhook.request=請求內容
settings.webhook.response=響應內容
settings.webhook.headers=標題
settings.webhook.payload=推送內容
settings.webhook.body=響應內容
settings.githooks_desc=Git 鉤子是由 Git 本身提供的功能,以下為 Gogs 所支持的鉤子列表。
settings.githook_edit_desc=如果鉤子未啟動,則會顯示樣例文件中的內容。如果想要刪除某個鉤子,則提交空白文本即可。
settings.githook_name=鉤子名稱
@@ -587,17 +642,17 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
settings.payload_url=推送地址
settings.content_type=數據格式
settings.secret=密鑰文本
settings.slack_username=Username
settings.slack_icon_url=Icon URL
settings.slack_color=Color
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=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_push=Push
settings.event_push_desc=Git push to a repository
settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=讓我選擇我的需要
settings.event_create=創建
settings.event_create_desc=創建分支或標籤
settings.event_push=推送
settings.event_push_desc=Git 倉庫推送
settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功!
@@ -612,6 +667,7 @@ settings.slack_domain=域名
settings.slack_channel=頻道
settings.deploy_keys=管理部署密鑰
settings.add_deploy_key=添加部署密鑰
settings.deploy_key_desc=部署密鑰僅具有隻讀權限,它在功能上和個人用戶的公開密鑰有本質區別。
settings.no_deploy_keys=您還沒有添加任何部署密鑰。
settings.title=標題
settings.deploy_key_content=密鑰文本
@@ -627,6 +683,8 @@ diff.parent=父節點
diff.commit=當前提交
diff.data_not_available=暫無可用數據
diff.show_diff_stats=顯示文件統計
diff.show_split_view=分割檢視
diff.show_unified_view=統一視圖
diff.stats_desc=共有 <strong> %d 個文件被更改</strong>,包括 <strong>%d 次插入</strong> 和 <strong>%d 次删除</strong>
diff.bin=二進制
diff.view_file=查看文件
@@ -639,32 +697,32 @@ release.stable=穩定
release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼
release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved.
release.new_subheader=發布版本對產品進行迭代。
release.edit_subheader=詳細的變更日誌可以幫助用戶更好地了解產品做了哪些改進。
release.tag_name=標籤名稱
release.target=目標分支
release.tag_helper=選擇或創建一個已存在的標籤
release.title=Title
release.content=Content
release.title=標題
release.content=內容
release.write=內容編輯
release.preview=效果預覽
release.loading=正在加載...
release.prerelease_desc=這是一個預發佈版本
release.prerelease_helper=我們會告知用戶不建議將本發佈投入生產環境使用。
release.cancel=Cancel
release.cancel=取消
release.publish=發佈版本
release.save_draft=保在草稿
release.save_draft=儲存草稿
release.edit_release=編輯發佈信息
release.delete_release=Delete This Release
release.deletion=Release Deletion
release.deletion_desc=Delete this release will delete corresponding Git tag. Do you want to continue?
release.deletion_success=Release has been deleted successfully!
release.delete_release=刪除此次發布
release.deletion=刪除版本發布操作
release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
release.deletion_success=版本發布刪除成功!
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
release.downloads=Downloads
release.downloads=下載附件
[org]
org_name_holder=組織名稱
org_full_name_holder=Organization Full Name
org_full_name_holder=組織全名
org_name_helper=偉大的組織都有一個簡短而寓意深刻的名字。
create_org=創建組織
repo_updated=最後更新於
@@ -691,8 +749,8 @@ settings.website=官方網站
settings.location=所在地區
settings.update_settings=更新組織設置
settings.update_setting_success=組織設置更新成功!
settings.change_orgname_prompt=This change will affect how links relate to the organization.
settings.update_avatar_success=Organization avatar setting has been updated successfully.
settings.change_orgname_prompt=該操作將會影響到所有與該組織有關的鏈接
settings.update_avatar_success=組織頭像更新成功!
settings.delete=刪除組織
settings.delete_account=刪除當前組織
settings.delete_prompt=刪除操作會永久清除該組織的信息,並且 <strong>不可恢復</strong>
@@ -701,17 +759,17 @@ settings.delete_org_title=組織刪除操作
settings.delete_org_desc=該組織將被永久性刪除,您確定要繼續操作嗎?
settings.hooks_desc=在此處添加的 Web 鉤子將會應用到該組織下的 <strong>所有倉庫</strong>。
members.membership_visibility=Membership Visibility:
members.membership_visibility=成員可見性:
members.public=公開成員
members.public_helper=設為私有
members.private=私有成員
members.private_helper=設為公開
members.member_role=Member Role:
members.member_role=成員角色:
members.owner=管理員
members.member=普通成員
members.remove=移除成員
members.leave=離開組織
members.invite_desc=Add a new member to %s:
members.invite_desc=邀請新的用戶加入 %s
members.invite_now=立即邀請
teams.join=加入團隊
@@ -736,7 +794,7 @@ teams.read_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</str
teams.write_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</strong> 和 <strong>寫入</strong> 的權限。
teams.admin_permission_desc=該團隊擁有一定的 <strong>管理</strong> 權限,團隊成員可以讀取、複製、推送以及添加其它倉庫協作者。
teams.repositories=團隊倉庫
teams.search_repo_placeholder=Search repository...
teams.search_repo_placeholder=搜索倉庫...
teams.add_team_repository=添加團隊倉庫
teams.remove_repo=移除倉庫
teams.add_nonexistent_repo=您嘗試添加到團隊的倉庫不存在,請先創建倉庫!
@@ -750,9 +808,9 @@ authentication=授權認證管理
config=應用配置管理
notices=系統提示管理
monitor=應用監控面版
first_page=First
last_page=Last
total=Total: %d
first_page=首頁
last_page=末頁
total=總計:%d
dashboard.statistic=應用統計數據
dashboard.operations=管理員操作
@@ -767,14 +825,16 @@ dashboard.delete_inactivate_accounts=刪除所有未激活帳戶
dashboard.delete_inactivate_accounts_success=所有未激活帳號清除成功!
dashboard.delete_repo_archives=刪除所有倉庫存檔
dashboard.delete_repo_archives_success=所有倉庫存檔清除成功!
dashboard.delete_missing_repos=Delete all repository records that lost Git files
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.delete_missing_repos=刪除所有丟失 Git 文件的倉庫記錄
dashboard.delete_missing_repos_success=成功刪除所有丟失 Git 文件的倉庫記錄!
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_update_hooks=重新生成所有倉庫的 Update 鈎子(用於被修改的自定義配置文件)
dashboard.resync_all_update_hooks_success=已成功重新生成所有倉庫的 Update 鈎子!
dashboard.reinit_missing_repos=Reinitialize all repository records that lost Git files
dashboard.reinit_missing_repos_success=All repository records that lost Git files have been reinitialized successfully.
dashboard.server_uptime=服務執行時間
dashboard.current_goroutine=當前 Goroutines 數量
@@ -813,24 +873,26 @@ users.activated=已激活
users.admin=管理員
users.repos=倉庫數
users.created=創建時間
users.send_register_notify=Send Registration Notification To User
users.new_success=New account '%s' has been created successfully.
users.send_register_notify=向用戶發送註冊通知郵件
users.new_success=新用戶 '%s' 創建成功!
users.edit=編輯
users.auth_source=Authentication Source
users.auth_source=認證源
users.local=本地
users.auth_login_name=Authentication Login Name
users.password_helper=Leave it empty to remain unchanged.
users.auth_login_name=認證登錄名稱
users.password_helper=留空使其保持不變。
users.update_profile_success=該用戶信息更新成功!
users.edit_account=編輯用戶信息
users.max_repo_creation=最大儲存庫新增限制
users.max_repo_creation_desc=(設定 -1 使用全域預設限制)
users.is_activated=該用戶已被激活
users.is_admin=該用戶具有管理員權限
users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限
users.allow_import_local=This account has permissions to import local repositories
users.allow_import_local=該用戶具有導入本地倉庫的權限
users.update_profile=更新用戶信息
users.delete_account=刪除該用戶
users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作!
users.still_has_org=該帳戶仍舊是某些組織的成員,您必須先使其離開或刪除組織。
users.deletion_success=Account has been deleted successfully!
users.deletion_success=用戶刪除成功!
orgs.org_manage_panel=組織管理面版
orgs.name=組織名稱
@@ -845,47 +907,51 @@ repos.watches=關註數
repos.stars=讚好數
repos.issues=問題數
auths.auth_manage_panel=Authentication Manage Panel
auths.new=Add New Source
auths.auth_manage_panel=認證管理面板
auths.new=添加新認證源
auths.name=認證名稱
auths.type=認證類型
auths.enabled=已啟用
auths.updated=最後更新時間
auths.auth_type=Authentication Type
auths.auth_name=Authentication Name
auths.auth_type=認證類型
auths.auth_name=認證名稱
auths.domain=域名
auths.host=主機地址
auths.port=主機端口
auths.bind_dn=綁定DN
auths.bind_password=綁定密碼
auths.bind_password_helper=Warning: This password is stored in plain text. Do not use a high privileged account.
auths.user_base=User Search Base
auths.bind_password_helper=警告:該密碼將會以明文的形式保存在數據庫中。請不要使用擁有高權限的帳戶!
auths.user_base=用戶搜索基準
auths.user_dn=User DN
auths.attribute_username=用戶名屬性
auths.attribute_username_placeholder=留空表示使用用戶登錄時所使用的用戶名
auths.attribute_name=名子屬性
auths.attribute_surname=姓氏屬性
auths.attribute_mail=電子郵箱屬性
auths.attributes_in_bind=Fetch attributes in Bind DN context
auths.filter=使用者篩選器
auths.admin_filter=管理者篩選器
auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP Authentication Type
auths.smtp_auth=SMTP 驗證類型
auths.smtphost=SMTP 主機地址
auths.smtpport=SMTP 主機端口
auths.allowed_domains=Allowed Domains
auths.allowed_domains_helper=Leave it empty to not restrict any domains. Multiple domains should be separated by comma ','.
auths.allowed_domains=域名白名單
auths.allowed_domains_helper=留空表示不對域名做任何限制。多個域名之間需要使用逗號 ',' 分隔。
auths.enable_tls=啟用 TLS 加密
auths.skip_tls_verify=Skip TLS Verify
auths.skip_tls_verify=忽略 TLS 驗證
auths.pam_service_name=PAM 服務名稱
auths.enable_auto_register=允許授權用戶自動註冊
auths.tips=幫助提示
auths.edit=Edit Authentication Setting
auths.edit=編輯認證設置
auths.activated=該授權認證已經啟用
auths.new_success=New authentication '%s' has been added successfully.
auths.update_success=Authentication setting has been updated successfully.
auths.update=Update Authentication Setting
auths.delete=Delete This Authentication
auths.delete_auth_title=Authentication Deletion
auths.delete_auth_desc=This authentication is going to be deleted, do you want to continue?
auths.deletion_success=Authentication has been deleted successfully!
auths.new_success=新的認證源 "%s" 添加成功!
auths.update_success=認證設置更新成功!
auths.update=更新認證設置
auths.delete=刪除該認證
auths.delete_auth_title=刪除認證操作
auths.delete_auth_desc=該認證將被刪除。是否繼續?
auths.still_in_used=This authentication is still used by some users, please delete or convert these users to another login type first.
auths.deletion_success=認證源刪除成功!
config.server_config=服務器配置
config.app_name=應用名稱
@@ -901,6 +967,19 @@ config.static_file_root_path=靜態文件根目錄
config.log_file_root_path=日志文件根目錄
config.script_type=腳本類型
config.reverse_auth_user=反向代理認證
config.ssh_config=SSH Configuration
config.ssh_enabled=Enabled
config.ssh_start_builtin_server=Start Builtin Server
config.ssh_domain=Domain
config.ssh_port=Port
config.ssh_listen_port=Listen Port
config.ssh_root_path=Root Path
config.ssh_key_test_path=Key Test Path
config.ssh_keygen_path=Keygen ('ssh-keygen') Path
config.ssh_minimum_key_size_check=Minimum Key Size Check
config.ssh_minimum_key_sizes=Minimum Key Sizes
config.db_config=數據庫配置
config.db_type=數據庫類型
config.db_host=主機地址
@@ -909,16 +988,15 @@ config.db_user=數據庫用戶
config.db_ssl_mode=SSL 模式
config.db_ssl_mode_helper=(僅限 "postgres" 使用)
config.db_path=數據庫路徑
config.db_path_helper=(for "sqlite3" and "tidb")
config.db_path_helper=(用於 "sqlite3" "tidb"
config.service_config=服務配置
config.register_email_confirm=註冊電子郵件確認
config.disable_register=關閉註冊功能
config.show_registration_button=顯示註冊按鈕
config.require_sign_in_view=強制登錄瀏覽
config.enable_cache_avatar=開啟緩存頭像
config.mail_notify=郵件通知提醒
config.disable_key_size_check=Disable Minimum Key Size Check
config.enable_captcha=Enable Captcha
config.disable_key_size_check=禁用密鑰最小長度檢查
config.enable_captcha=啟用驗證碼服務
config.active_code_lives=激活用戶連結有效期
config.reset_password_code_lives=重置密碼連結有效期
config.webhook_config=Web 鉤子配置
@@ -931,6 +1009,9 @@ config.mailer_disable_helo=禁用 HELO 操作
config.mailer_name=發送者名稱
config.mailer_host=郵件主機地址
config.mailer_user=發送者帳號
config.send_test_mail=Send Test Email
config.test_mail_failed=Fail to send test email to '%s': %v
config.test_mail_sent=Test email has been sent to '%s'.
config.oauth_config=社交帳號配置
config.oauth_enabled=啟用服務
config.cache_config=Cache 配置
@@ -964,6 +1045,13 @@ monitor.start=開始時間
monitor.execute_time=已執行時間
notices.system_notice_list=系統提示管理
notices.view_detail_header=查看提示詳情
notices.actions=操作
notices.select_all=選取全部
notices.deselect_all=取消所有選取
notices.inverse_selection=反向選取
notices.delete_selected=刪除選取項
notices.delete_all=刪除所有提示
notices.type=提示類型
notices.type_1=倉庫
notices.desc=描述
@@ -971,16 +1059,20 @@ notices.op=操作
notices.delete_success=系統提示刪除成功!
[action]
create_repo=創建了庫 <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
create_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>
create_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_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>`
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=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_2_commits=查看 2 次提交的內容
compare_commits=查看 %d 次提交的內容比
[tool]
ago=之前

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) see all available tags.
## Usage
To keep your data out of Docker container, we do a volume(`/var/gogs` -> `/data`) here, and you can change it based on your situation.
To keep your data out of Docker container, we do a volume (`/var/gogs` -> `/data`) here, and you can change it based on your situation.
```
# Pull image from Docker Hub.
@@ -20,6 +20,8 @@ $ docker run --name=gogs -p 10022:22 -p 10080:3000 -v /var/gogs:/data gogs/gogs
$ docker start gogs
```
Note: It is important to map the Gogs ssh service from the container to the host and set the appropriate SSH Port and URI settings when setting up Gogs for the first time. To access and clone Gogs Git repositories with the above configuration you would use: `git clone ssh://git@hostname:10022/username/myrepo.git` for example.
Files will be store in local path `/var/gogs` in my case.
Directory `/var/gogs` keeps Git repositories and Gogs data:
@@ -33,7 +35,6 @@ Directory `/var/gogs` keeps Git repositories and Gogs data:
|-- conf
|-- data
|-- log
|-- templates
### Volume with data container
@@ -45,19 +46,34 @@ docker run --name=gogs-data --entrypoint /bin/true gogs/gogs
# Use `docker run` for the first time.
docker run --name=gogs --volumes-from gogs-data -p 10022:22 -p 10080:3000 gogs/gogs
```
#### Using Docker 1.9 Volume command
```
# Create docker volume.
$ docker volume create --name gogs-data
# Use `docker run` for the first time.
$ docker run --name=gogs -p 10022:22 -p 10080:3000 -v gogs-data:/data gogs/gogs
```
## Settings
### Application
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`.
- **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.
- **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.
- **Application URL**: Use combination of **Domain** and **exposed HTTP Port** values(e.g. `http://192.168.99.100:10080/`).
- **Application URL**: Use combination of **Domain** and **exposed HTTP Port** values (e.g. `http://192.168.99.100:10080/`).
Full documentation of settings can be found [here](http://gogs.io/docs/advanced/configuration_cheat_sheet.html).
Full documentation of application settings can be found [here](http://gogs.io/docs/advanced/configuration_cheat_sheet.html).
### Crond
Please set environment variable `RUN_CROND` to be `true` or `1` in order to start `crond` inside the container.
## Upgrade
@@ -72,4 +88,4 @@ Steps to upgrade Gogs with Docker:
## Known Issues
- `.dockerignore` seems to be ignored during Docker Hub Automated build
- The docker container can not currently be build on Raspberry 1 (armv6l) as our base image `alpine` does not have a `go` package available for this platform.

View File

@@ -7,20 +7,20 @@ export GOPATH=/tmp/go
export PATH=${PATH}:${GOPATH}/bin
# Install build deps
apk -U --no-progress add linux-pam-dev go@community gcc musl-dev
apk --no-cache --no-progress add --virtual build-deps linux-pam-dev go gcc musl-dev
# Init go environment to build Gogs
mkdir -p ${GOPATH}/src/github.com/gogits/
ln -s /app/gogs/ ${GOPATH}/src/github.com/gogits/gogs
cd ${GOPATH}/src/github.com/gogits/gogs
go get -v -tags "sqlite redis memcache cert pam"
go build -tags "sqlite redis memcache cert pam"
go get -v -tags "sqlite cert pam"
go build -tags "sqlite cert pam"
# Cleanup GOPATH
rm -r $GOPATH
# Remove build deps
apk --no-progress del linux-pam-dev go gcc musl-dev
apk --no-progress del build-deps
# Create git user for Gogs
adduser -H -D -g 'Gogs Git User' git -h /data/git -s /bin/bash && passwd -u git

16
docker/nsswitch.conf Normal file
View File

@@ -0,0 +1,16 @@
# /etc/nsswitch.conf
passwd: compat
group: compat
shadow: compat
hosts: files dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis

0
docker/s6/crond/down Normal file
View File

9
docker/s6/crond/run Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
# Crontabs are located by default in /var/spool/cron/crontabs/
# The default configuration is also calling all the scripts in /etc/periodic/${period}
if test -f ./setup; then
source ./setup
fi
exec gosu root /usr/sbin/crond -fS

View File

@@ -1,10 +1,6 @@
#!/bin/sh
# Check if host keys are present, else create them
if ! test -f /data/ssh/ssh_host_key; then
ssh-keygen -q -f /data/ssh/ssh_host_key -N '' -t rsa1
fi
if ! test -f /data/ssh/ssh_host_rsa_key; then
ssh-keygen -q -f /data/ssh/ssh_host_rsa_key -N '' -t rsa
fi

View File

@@ -4,7 +4,6 @@ ListenAddress 0.0.0.0
ListenAddress ::
Protocol 2
LogLevel INFO
HostKey /data/ssh/ssh_host_key
HostKey /data/ssh/ssh_host_rsa_key
HostKey /data/ssh/ssh_host_dsa_key
HostKey /data/ssh/ssh_host_ecdsa_key

View File

@@ -48,6 +48,15 @@ else
create_socat_links
fi
CROND=$(echo "$RUN_CROND" | tr '[:upper:]' '[:lower:]')
if [ "$CROND" = "true" -o "$CROND" = "1" ]; then
echo "init:crond | Cron Daemon (crond) will be run as requested by s6" 1>&2
rm -f /app/gogs/docker/s6/crond/down
else
# Tell s6 not to run the crond service
touch /app/gogs/docker/s6/crond/down
fi
# Exec CMD or S6 by default if nothing present
if [ $# -gt 0 ];then
exec "$@"

View File

@@ -1,4 +1,4 @@
// +build go1.3
// +build go1.4
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
const APP_VER = "0.7.22.1125 Beta"
const APP_VER = "0.9.0.0306"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())

View File

@@ -13,11 +13,11 @@ import (
type AccessMode int
const (
ACCESS_MODE_NONE AccessMode = iota
ACCESS_MODE_READ
ACCESS_MODE_WRITE
ACCESS_MODE_ADMIN
ACCESS_MODE_OWNER
ACCESS_MODE_NONE AccessMode = iota // 0
ACCESS_MODE_READ // 1
ACCESS_MODE_WRITE // 2
ACCESS_MODE_ADMIN // 3
ACCESS_MODE_OWNER // 4
)
// Access represents the highest access level of a user to the repository. The only access type
@@ -151,15 +151,14 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode
return nil
}
// FIXME: should be able to have read-only access.
// Give all collaborators write access.
// refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]AccessMode) error {
collaborators, err := repo.getCollaborators(e)
collaborations, err := repo.getCollaborations(e)
if err != nil {
return fmt.Errorf("getCollaborators: %v", err)
return fmt.Errorf("getCollaborations: %v", err)
}
for _, c := range collaborators {
accessMap[c.Id] = ACCESS_MODE_WRITE
for _, c := range collaborations {
accessMap[c.UserID] = c.Mode
}
return nil
}

View File

@@ -17,10 +17,10 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
@@ -28,17 +28,21 @@ import (
type ActionType int
const (
CREATE_REPO ActionType = iota + 1 // 1
RENAME_REPO // 2
STAR_REPO // 3
FOLLOW_REPO // 4
COMMIT_REPO // 5
CREATE_ISSUE // 6
CREATE_PULL_REQUEST // 7
TRANSFER_REPO // 8
PUSH_TAG // 9
COMMENT_ISSUE // 10
MERGE_PULL_REQUEST // 11
ACTION_CREATE_REPO ActionType = iota + 1 // 1
ACTION_RENAME_REPO // 2
ACTION_STAR_REPO // 3
ACTION_WATCH_REPO // 4
ACTION_COMMIT_REPO // 5
ACTION_CREATE_ISSUE // 6
ACTION_CREATE_PULL_REQUEST // 7
ACTION_TRANSFER_REPO // 8
ACTION_PUSH_TAG // 9
ACTION_COMMENT_ISSUE // 10
ACTION_MERGE_PULL_REQUEST // 11
ACTION_CLOSE_ISSUE // 12
ACTION_REOPEN_ISSUE // 13
ACTION_CLOSE_PULL_REQUEST // 14
ACTION_REOPEN_PULL_REQUEST // 15
)
var (
@@ -90,54 +94,70 @@ func (a *Action) AfterSet(colName string, _ xorm.Cell) {
}
}
func (a Action) GetOpType() int {
func (a *Action) GetOpType() int {
return int(a.OpType)
}
func (a Action) GetActUserName() string {
func (a *Action) GetActUserName() string {
return a.ActUserName
}
func (a Action) GetActEmail() string {
func (a *Action) ShortActUserName() string {
return base.EllipsisString(a.ActUserName, 20)
}
func (a *Action) GetActEmail() string {
return a.ActEmail
}
func (a Action) GetRepoUserName() string {
func (a *Action) GetRepoUserName() string {
return a.RepoUserName
}
func (a Action) GetRepoName() string {
func (a *Action) ShortRepoUserName() string {
return base.EllipsisString(a.RepoUserName, 20)
}
func (a *Action) GetRepoName() string {
return a.RepoName
}
func (a Action) GetRepoPath() string {
func (a *Action) ShortRepoName() string {
return base.EllipsisString(a.RepoName, 33)
}
func (a *Action) GetRepoPath() string {
return path.Join(a.RepoUserName, a.RepoName)
}
func (a Action) GetRepoLink() string {
func (a *Action) ShortRepoPath() string {
return path.Join(a.ShortRepoUserName(), a.ShortRepoName())
}
func (a *Action) GetRepoLink() string {
if len(setting.AppSubUrl) > 0 {
return path.Join(setting.AppSubUrl, a.GetRepoPath())
}
return "/" + a.GetRepoPath()
}
func (a Action) GetBranch() string {
func (a *Action) GetBranch() string {
return a.RefName
}
func (a Action) GetContent() string {
func (a *Action) GetContent() string {
return a.Content
}
func (a Action) GetCreate() time.Time {
func (a *Action) GetCreate() time.Time {
return a.Created
}
func (a Action) GetIssueInfos() []string {
func (a *Action) GetIssueInfos() []string {
return strings.SplitN(a.Content, "|", 2)
}
func (a Action) GetIssueTitle() string {
func (a *Action) GetIssueTitle() string {
index := com.StrTo(a.GetIssueInfos()[0]).MustInt64()
issue, err := GetIssueByIndex(a.RepoID, index)
if err != nil {
@@ -147,7 +167,7 @@ func (a Action) GetIssueTitle() string {
return issue.Name
}
func (a Action) GetIssueContent() string {
func (a *Action) GetIssueContent() string {
index := com.StrTo(a.GetIssueInfos()[0]).MustInt64()
issue, err := GetIssueByIndex(a.RepoID, index)
if err != nil {
@@ -162,7 +182,7 @@ func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
ActUserID: u.Id,
ActUserName: u.Name,
ActEmail: u.Email,
OpType: CREATE_REPO,
OpType: ACTION_CREATE_REPO,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
@@ -185,7 +205,7 @@ func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Reposit
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
OpType: RENAME_REPO,
OpType: ACTION_RENAME_REPO,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
@@ -229,6 +249,28 @@ func NewPushCommits() *PushCommits {
}
}
func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit {
commits := make([]*api.PayloadCommit, len(pc.Commits))
for i, cmt := range pc.Commits {
author_username := ""
author, err := GetUserByEmail(cmt.AuthorEmail)
if err == nil {
author_username = author.Name
}
commits[i] = &api.PayloadCommit{
ID: cmt.Sha1,
Message: cmt.Message,
URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
Author: &api.PayloadAuthor{
Name: cmt.AuthorName,
Email: cmt.AuthorEmail,
UserName: author_username,
},
}
}
return commits
}
// AvatarLink tries to match user in database with e-mail
// in order to show custom avatar, and falls back to general avatar link.
func (push *PushCommits) AvatarLink(email string) string {
@@ -328,7 +370,7 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
continue
}
if err = issue.ChangeStatus(u, true); err != nil {
if err = issue.ChangeStatus(u, repo, true); err != nil {
return err
}
}
@@ -368,7 +410,7 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
continue
}
if err = issue.ChangeStatus(u, false); err != nil {
if err = issue.ChangeStatus(u, repo, false); err != nil {
return err
}
}
@@ -405,23 +447,19 @@ func CommitRepoAction(
}
isNewBranch := false
opType := COMMIT_REPO
opType := ACTION_COMMIT_REPO
// Check it's tag push or branch.
if strings.HasPrefix(refFullName, "refs/tags/") {
opType = PUSH_TAG
opType = ACTION_PUSH_TAG
commit = &PushCommits{}
} else {
// if not the first commit, set the compareUrl
if !strings.HasPrefix(oldCommitID, "0000000") {
commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
commit.CompareUrl = repo.ComposeCompareURL(oldCommitID, newCommitID)
} else {
isNewBranch = true
}
// NOTE: limit to detect latest 100 commits.
if len(commit.Commits) > 100 {
commit.Commits = commit.Commits[len(commit.Commits)-100:]
}
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
log.Error(4, "updateIssuesCommit: %v", err)
}
@@ -451,24 +489,9 @@ func CommitRepoAction(
IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("NotifyWatchers: %v", err)
}
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
payloadRepo := &api.PayloadRepo{
ID: repo.ID,
Name: repo.LowerName,
URL: repoLink,
Description: repo.Description,
Website: repo.Website,
Watchers: repo.NumWatches,
Owner: &api.PayloadAuthor{
Name: repo.Owner.DisplayName(),
Email: repo.Owner.Email,
UserName: repo.Owner.Name,
},
Private: repo.IsPrivate,
}
payloadRepo := repo.ComposePayload()
pusher_email, pusher_name := "", ""
pusher, err := GetUserByName(userName)
@@ -479,35 +502,17 @@ func CommitRepoAction(
payloadSender := &api.PayloadUser{
UserName: pusher.Name,
ID: pusher.Id,
AvatarUrl: setting.AppUrl + pusher.RelAvatarLink(),
AvatarUrl: pusher.AvatarLink(),
}
switch opType {
case COMMIT_REPO: // Push
commits := make([]*api.PayloadCommit, len(commit.Commits))
for i, cmt := range commit.Commits {
author_username := ""
author, err := GetUserByEmail(cmt.AuthorEmail)
if err == nil {
author_username = author.Name
}
commits[i] = &api.PayloadCommit{
ID: cmt.Sha1,
Message: cmt.Message,
URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
Author: &api.PayloadAuthor{
Name: cmt.AuthorName,
Email: cmt.AuthorEmail,
UserName: author_username,
},
}
}
case ACTION_COMMIT_REPO: // Push
p := &api.PushPayload{
Ref: refFullName,
Before: oldCommitID,
After: newCommitID,
CompareUrl: setting.AppUrl + commit.CompareUrl,
Commits: commits,
Commits: commit.ToApiPayloadCommits(repo.FullRepoLink()),
Repo: payloadRepo,
Pusher: &api.PayloadAuthor{
Name: pusher_name,
@@ -529,7 +534,7 @@ func CommitRepoAction(
})
}
case PUSH_TAG: // Create
case ACTION_PUSH_TAG: // Create
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
@@ -546,7 +551,7 @@ func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repos
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
OpType: TRANSFER_REPO,
OpType: ACTION_TRANSFER_REPO,
RepoID: repo.ID,
RepoUserName: newOwner.Name,
RepoName: repo.Name,
@@ -577,7 +582,7 @@ func mergePullRequestAction(e Engine, actUser *User, repo *Repository, pull *Iss
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
OpType: MERGE_PULL_REQUEST,
OpType: ACTION_MERGE_PULL_REQUEST,
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
@@ -592,12 +597,29 @@ func MergePullRequestAction(actUser *User, repo *Repository, pull *Issue) error
}
// GetFeeds returns action list of given user in given context.
func GetFeeds(uid, offset int64, isProfile bool) ([]*Action, error) {
// userID is the user who's requesting, ctxUserID is the user/org that is requested.
// userID can be -1, if isProfile is true or in order to skip the permission check.
func GetFeeds(ctxUserID, userID, offset int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, 20)
sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", uid)
sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", ctxUserID)
if isProfile {
sess.And("is_private=?", false).And("act_user_id=?", uid)
sess.And("is_private=?", false).And("act_user_id=?", ctxUserID)
} else if ctxUserID != -1 {
ctxUser := &User{Id: ctxUserID}
if err := ctxUser.GetUserRepositories(userID); err != nil {
return nil, err
}
var repoIDs []int64
for _, repo := range ctxUser.Repos {
repoIDs = append(repoIDs, repo.ID)
}
if len(repoIDs) > 0 {
sess.In("repo_id", repoIDs)
}
}
err := sess.Find(&actions)
return actions, err
}

View File

@@ -5,9 +5,17 @@
package models
import (
"fmt"
"os"
"os/exec"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
type NoticeType int
@@ -18,7 +26,7 @@ const (
// Notice represents a system notice for admin.
type Notice struct {
Id int64
ID int64 `xorm:"pk autoincr"`
Type NoticeType
Description string `xorm:"TEXT"`
Created time.Time `xorm:"CREATED"`
@@ -44,6 +52,25 @@ func CreateRepositoryNotice(desc string) error {
return CreateNotice(NOTICE_REPOSITORY, desc)
}
// RemoveAllWithNotice removes all directories in given path and
// creates a system notice when error occurs.
func RemoveAllWithNotice(title, path string) {
var err error
if setting.IsWindows {
err = exec.Command("cmd", "/C", "rmdir", "/S", "/Q", path).Run()
} else {
err = os.RemoveAll(path)
}
if err != nil {
desc := fmt.Sprintf("%s [%s]: %v", title, path, err)
log.Warn(desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
}
}
}
// CountNotices returns number of notices.
func CountNotices() int64 {
count, _ := x.Count(new(Notice))
@@ -61,3 +88,22 @@ func DeleteNotice(id int64) error {
_, err := x.Id(id).Delete(new(Notice))
return err
}
// DeleteNotices deletes all notices with ID from start to end (inclusive).
func DeleteNotices(start, end int64) error {
sess := x.Where("id >= ?", start)
if end > 0 {
sess.And("id <= ?", end)
}
_, err := sess.Delete(new(Notice))
return err
}
// DeleteNoticesByIDs deletes notices by given IDs.
func DeleteNoticesByIDs(ids []int64) error {
if len(ids) == 0 {
return nil
}
_, err := x.Where("id IN (" + strings.Join(base.Int64sToStrings(ids), ",") + ")").Delete(new(Notice))
return err
}

View File

@@ -1,59 +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 cron
import (
"time"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/cron"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
var c = cron.New()
func NewContext() {
var (
entry *cron.Entry
err error
)
if setting.Cron.UpdateMirror.Enabled {
entry, err = c.AddFunc("Update mirrors", setting.Cron.UpdateMirror.Schedule, models.MirrorUpdate)
if err != nil {
log.Fatal(4, "Cron[Update mirrors]: %v", err)
}
if setting.Cron.UpdateMirror.RunAtStart {
entry.Prev = time.Now()
go models.MirrorUpdate()
}
}
if setting.Cron.RepoHealthCheck.Enabled {
entry, err = c.AddFunc("Repository health check", setting.Cron.RepoHealthCheck.Schedule, models.GitFsck)
if err != nil {
log.Fatal(4, "Cron[Repository health check]: %v", err)
}
if setting.Cron.RepoHealthCheck.RunAtStart {
entry.Prev = time.Now()
go models.GitFsck()
}
}
if setting.Cron.CheckRepoStats.Enabled {
entry, err = c.AddFunc("Check repository statistics", setting.Cron.CheckRepoStats.Schedule, models.CheckRepoStats)
if err != nil {
log.Fatal(4, "Cron[Check repository statistics]: %v", err)
}
if setting.Cron.CheckRepoStats.RunAtStart {
entry.Prev = time.Now()
go models.CheckRepoStats()
}
}
c.Start()
}
// ListTasks returns all running cron tasks.
func ListTasks() []*cron.Entry {
return c.Entries()
}

View File

@@ -107,6 +107,39 @@ func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
type ErrReachLimitOfRepo struct {
Limit int
}
func IsErrReachLimitOfRepo(err error) bool {
_, ok := err.(ErrReachLimitOfRepo)
return ok
}
func (err ErrReachLimitOfRepo) Error() string {
return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
}
// __ __.__ __ .__
// / \ / \__| | _|__|
// \ \/\/ / | |/ / |
// \ /| | <| |
// \__/\ / |__|__|_ \__|
// \/ \/
type ErrWikiAlreadyExist struct {
Title string
}
func IsErrWikiAlreadyExist(err error) bool {
_, ok := err.(ErrWikiAlreadyExist)
return ok
}
func (err ErrWikiAlreadyExist) Error() string {
return fmt.Sprintf("wiki page already exists [title: %s]", err.Title)
}
// __________ ___. .__ .__ ____ __.
// \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__.
// | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | |
@@ -168,6 +201,22 @@ func (err ErrKeyNameAlreadyUsed) Error() string {
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
}
type ErrKeyAccessDenied struct {
UserID int64
KeyID int64
Note string
}
func IsErrKeyAccessDenied(err error) bool {
_, ok := err.(ErrKeyAccessDenied)
return ok
}
func (err ErrKeyAccessDenied) Error() string {
return fmt.Sprintf("user does not have access to the key [user_id: %d, key_id: %d, note: %s]",
err.UserID, err.KeyID, err.Note)
}
type ErrDeployKeyNotExist struct {
ID int64
KeyID int64
@@ -343,6 +392,26 @@ func (err ErrReleaseNotExist) Error() string {
return fmt.Sprintf("Release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
}
// __________ .__
// \______ \____________ ____ ____ | |__
// | | _/\_ __ \__ \ / \_/ ___\| | \
// | | \ | | \// __ \| | \ \___| Y \
// |______ / |__| (____ /___| /\___ >___| /
// \/ \/ \/ \/ \/
type ErrBranchNotExist struct {
Name string
}
func IsErrBranchNotExist(err error) bool {
_, ok := err.(ErrBranchNotExist)
return ok
}
func (err ErrBranchNotExist) Error() string {
return fmt.Sprintf("Branch does not exist [name: %s]", err.Name)
}
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
@@ -492,3 +561,44 @@ func IsErrAttachmentNotExist(err error) bool {
func (err ErrAttachmentNotExist) Error() string {
return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
}
// _____ __ .__ __ .__ __ .__
// / _ \ __ ___/ |_| |__ ____ _____/ |_|__| ____ _____ _/ |_|__| ____ ____
// / /_\ \| | \ __\ | \_/ __ \ / \ __\ |/ ___\\__ \\ __\ |/ _ \ / \
// / | \ | /| | | Y \ ___/| | \ | | \ \___ / __ \| | | ( <_> ) | \
// \____|__ /____/ |__| |___| /\___ >___| /__| |__|\___ >____ /__| |__|\____/|___| /
// \/ \/ \/ \/ \/ \/ \/
type ErrAuthenticationNotExist struct {
ID int64
}
func IsErrAuthenticationNotExist(err error) bool {
_, ok := err.(ErrAuthenticationNotExist)
return ok
}
func (err ErrAuthenticationNotExist) Error() string {
return fmt.Sprintf("authentication does not exist [id: %d]", err.ID)
}
// ___________
// \__ ___/___ _____ _____
// | |_/ __ \\__ \ / \
// | |\ ___/ / __ \| Y Y \
// |____| \___ >____ /__|_| /
// \/ \/ \/
type ErrTeamAlreadyExist struct {
OrgID int64
Name string
}
func IsErrTeamAlreadyExist(err error) bool {
_, ok := err.(ErrTeamAlreadyExist)
return ok
}
func (err ErrTeamAlreadyExist) Error() string {
return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
}

View File

@@ -8,47 +8,54 @@ import (
"bufio"
"bytes"
"fmt"
"html"
"html/template"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/sergi/go-diff/diffmatchpatch"
"golang.org/x/net/html/charset"
"golang.org/x/text/transform"
"github.com/Unknwon/com"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/template/highlight"
)
// Diff line types.
type DiffLineType uint8
const (
DIFF_LINE_PLAIN = iota + 1
DIFF_LINE_PLAIN DiffLineType = iota + 1
DIFF_LINE_ADD
DIFF_LINE_DEL
DIFF_LINE_SECTION
)
type DiffFileType uint8
const (
DIFF_FILE_ADD = iota + 1
DIFF_FILE_ADD DiffFileType = iota + 1
DIFF_FILE_CHANGE
DIFF_FILE_DEL
DIFF_FILE_RENAME
)
type DiffLine struct {
LeftIdx int
RightIdx int
Type int
Content string
LeftIdx int
RightIdx int
Type DiffLineType
Content string
}
func (d DiffLine) GetType() int {
return d.Type
func (d *DiffLine) GetType() int {
return int(d.Type)
}
type DiffSection struct {
@@ -56,12 +63,99 @@ type DiffSection struct {
Lines []*DiffLine
}
var (
addedCodePrefix = []byte("<span class=\"added-code\">")
removedCodePrefix = []byte("<span class=\"removed-code\">")
codeTagSuffix = []byte("</span>")
)
func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
var buf bytes.Buffer
for i := range diffs {
if diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DIFF_LINE_ADD {
buf.Write(addedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
} else if diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DIFF_LINE_DEL {
buf.Write(removedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
} else if diffs[i].Type == diffmatchpatch.DiffEqual {
buf.WriteString(html.EscapeString(diffs[i].Text))
}
}
return template.HTML(buf.Bytes())
}
// get an specific line by type (add or del) and file line number
func (diffSection *DiffSection) GetLine(lineType DiffLineType, idx int) *DiffLine {
difference := 0
for _, diffLine := range diffSection.Lines {
if diffLine.Type == DIFF_LINE_PLAIN {
// get the difference of line numbers between ADD and DEL versions
difference = diffLine.RightIdx - diffLine.LeftIdx
continue
}
if lineType == DIFF_LINE_DEL {
if diffLine.RightIdx == 0 && diffLine.LeftIdx == idx-difference {
return diffLine
}
} else if lineType == DIFF_LINE_ADD {
if diffLine.LeftIdx == 0 && diffLine.RightIdx == idx+difference {
return diffLine
}
}
}
return nil
}
// computes inline diff for the given line
func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML {
var compareDiffLine *DiffLine
var diff1, diff2 string
getDefaultReturn := func() template.HTML {
return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
// just compute diff for adds and removes
if diffLine.Type != DIFF_LINE_ADD && diffLine.Type != DIFF_LINE_DEL {
return getDefaultReturn()
}
// try to find equivalent diff line. ignore, otherwise
if diffLine.Type == DIFF_LINE_ADD {
compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
if compareDiffLine == nil {
return getDefaultReturn()
}
diff1 = compareDiffLine.Content
diff2 = diffLine.Content
} else {
compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
if compareDiffLine == nil {
return getDefaultReturn()
}
diff1 = diffLine.Content
diff2 = compareDiffLine.Content
}
dmp := diffmatchpatch.New()
diffRecord := dmp.DiffMain(diff1[1:], diff2[1:], true)
diffRecord = dmp.DiffCleanupSemantic(diffRecord)
return diffToHTML(diffRecord, diffLine.Type)
}
type DiffFile struct {
Name string
OldName string
Index int
Addition, Deletion int
Type int
Type DiffFileType
IsCreated bool
IsDeleted bool
IsBin bool
@@ -69,6 +163,14 @@ type DiffFile struct {
Sections []*DiffSection
}
func (diffFile *DiffFile) GetType() int {
return int(diffFile.Type)
}
func (diffFile *DiffFile) GetHighlightClass() string {
return highlight.FileNameToHighlightClass(diffFile.Name)
}
type Diff struct {
TotalAddition, TotalDeletion int
Files []*DiffFile
@@ -80,37 +182,52 @@ func (diff *Diff) NumFiles() int {
const DIFF_HEAD = "diff --git "
func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff, error) {
scanner := bufio.NewScanner(reader)
func ParsePatch(maxlines int, reader io.Reader) (*Diff, error) {
var (
diff = &Diff{Files: make([]*DiffFile, 0)}
curFile *DiffFile
curSection = &DiffSection{
Lines: make([]*DiffLine, 0, 10),
}
leftLine, rightLine int
// FIXME: Should use cache in the future.
buf bytes.Buffer
lineCount int
)
diff := &Diff{Files: make([]*DiffFile, 0)}
var i int
for scanner.Scan() {
line := scanner.Text()
input := bufio.NewReader(reader)
isEOF := false
for {
if isEOF {
break
}
line, err := input.ReadString('\n')
if err != nil {
if err == io.EOF {
isEOF = true
} else {
return nil, fmt.Errorf("ReadString: %v", err)
}
}
if len(line) > 0 && line[len(line)-1] == '\n' {
// Remove line break.
line = line[:len(line)-1]
}
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") {
continue
}
if line == "" {
} else if len(line) == 0 {
continue
}
i = i + 1
lineCount++
// Diff data too large, we only show the first about maxlines lines
if i >= maxlines {
if lineCount >= maxlines {
log.Warn("Diff data too large")
io.Copy(ioutil.Discard, reader)
diff.Files = nil
return diff, nil
}
@@ -189,17 +306,26 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
diff.Files = append(diff.Files, curFile)
// Check file diff type.
for scanner.Scan() {
for {
line, err := input.ReadString('\n')
if err != nil {
if err == io.EOF {
isEOF = true
} else {
return nil, fmt.Errorf("ReadString: %v", err)
}
}
switch {
case strings.HasPrefix(scanner.Text(), "new file"):
case strings.HasPrefix(line, "new file"):
curFile.Type = DIFF_FILE_ADD
curFile.IsCreated = true
case strings.HasPrefix(scanner.Text(), "deleted"):
case strings.HasPrefix(line, "deleted"):
curFile.Type = DIFF_FILE_DEL
curFile.IsDeleted = true
case strings.HasPrefix(scanner.Text(), "index"):
case strings.HasPrefix(line, "index"):
curFile.Type = DIFF_FILE_CHANGE
case strings.HasPrefix(scanner.Text(), "similarity index 100%"):
case strings.HasPrefix(line, "similarity index 100%"):
curFile.Type = DIFF_FILE_RENAME
curFile.IsRenamed = true
curFile.OldName = curFile.Name
@@ -212,6 +338,8 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
}
}
// FIXME: detect encoding while parsing.
var buf bytes.Buffer
for _, f := range diff.Files {
buf.Reset()
for _, sec := range f.Sections {
@@ -238,61 +366,55 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
return diff, nil
}
func GetDiffRange(repoPath, beforeCommitId string, afterCommitId string, maxlines int) (*Diff, error) {
func GetDiffRange(repoPath, beforeCommitID string, afterCommitID string, maxlines int) (*Diff, error) {
repo, err := git.OpenRepository(repoPath)
if err != nil {
return nil, err
}
commit, err := repo.GetCommit(afterCommitId)
commit, err := repo.GetCommit(afterCommitID)
if err != nil {
return nil, err
}
rd, wr := io.Pipe()
var cmd *exec.Cmd
// if "after" commit given
if beforeCommitId == "" {
if len(beforeCommitID) == 0 {
// First commit of repository.
if commit.ParentCount() == 0 {
cmd = exec.Command("git", "show", afterCommitId)
cmd = exec.Command("git", "show", afterCommitID)
} else {
c, _ := commit.Parent(0)
cmd = exec.Command("git", "diff", "-M", c.ID.String(), afterCommitId)
cmd = exec.Command("git", "diff", "-M", c.ID.String(), afterCommitID)
}
} else {
cmd = exec.Command("git", "diff", "-M", beforeCommitId, afterCommitId)
cmd = exec.Command("git", "diff", "-M", beforeCommitID, afterCommitID)
}
cmd.Dir = repoPath
cmd.Stdout = wr
cmd.Stdin = os.Stdin
cmd.Stderr = os.Stderr
done := make(chan error)
go func() {
cmd.Start()
done <- cmd.Wait()
wr.Close()
}()
defer rd.Close()
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("StdoutPipe: %v", err)
}
desc := fmt.Sprintf("GetDiffRange(%s)", repoPath)
pid := process.Add(desc, cmd)
go func() {
// In case process became zombie.
select {
case <-time.After(5 * time.Minute):
if errKill := process.Kill(pid); errKill != nil {
log.Error(4, "git_diff.ParsePatch(Kill): %v", err)
}
<-done
// return "", ErrExecTimeout.Error(), ErrExecTimeout
case err = <-done:
process.Remove(pid)
}
}()
if err = cmd.Start(); err != nil {
return nil, fmt.Errorf("Start: %v", err)
}
return ParsePatch(pid, maxlines, cmd, rd)
pid := process.Add(fmt.Sprintf("GetDiffRange (%s)", repoPath), cmd)
defer process.Remove(pid)
diff, err := ParsePatch(maxlines, stdout)
if err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err)
}
if err = cmd.Wait(); err != nil {
return nil, fmt.Errorf("Wait: %v", err)
}
return diff, nil
}
func GetDiffCommit(repoPath, commitId string, maxlines int) (*Diff, error) {

70
models/git_diff_test.go Normal file
View File

@@ -0,0 +1,70 @@
package models
import (
dmp "github.com/sergi/go-diff/diffmatchpatch"
"html/template"
"testing"
)
func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
if s1 != string(s2) {
t.Errorf("%s should be equal %s", s2, s1)
}
}
func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) {
if d1 != d2 {
t.Errorf("%v should be equal %v", d1, d2)
}
}
func TestDiffToHTML(t *testing.T) {
assertEqual(t, "foo <span class=\"added-code\">bar</span> biz", diffToHTML([]dmp.Diff{
dmp.Diff{dmp.DiffEqual, "foo "},
dmp.Diff{dmp.DiffInsert, "bar"},
dmp.Diff{dmp.DiffDelete, " baz"},
dmp.Diff{dmp.DiffEqual, " biz"},
}, DIFF_LINE_ADD))
assertEqual(t, "foo <span class=\"removed-code\">bar</span> biz", diffToHTML([]dmp.Diff{
dmp.Diff{dmp.DiffEqual, "foo "},
dmp.Diff{dmp.DiffDelete, "bar"},
dmp.Diff{dmp.DiffInsert, " baz"},
dmp.Diff{dmp.DiffEqual, " biz"},
}, DIFF_LINE_DEL))
}
// test if GetLine is return the correct lines
func TestGetLine(t *testing.T) {
ds := DiffSection{Lines: []*DiffLine{
&DiffLine{LeftIdx: 28, RightIdx: 28, Type: DIFF_LINE_PLAIN},
&DiffLine{LeftIdx: 29, RightIdx: 29, Type: DIFF_LINE_PLAIN},
&DiffLine{LeftIdx: 30, RightIdx: 30, Type: DIFF_LINE_PLAIN},
&DiffLine{LeftIdx: 31, RightIdx: 0, Type: DIFF_LINE_DEL},
&DiffLine{LeftIdx: 0, RightIdx: 31, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 0, RightIdx: 32, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 32, RightIdx: 33, Type: DIFF_LINE_PLAIN},
&DiffLine{LeftIdx: 33, RightIdx: 0, Type: DIFF_LINE_DEL},
&DiffLine{LeftIdx: 34, RightIdx: 0, Type: DIFF_LINE_DEL},
&DiffLine{LeftIdx: 35, RightIdx: 0, Type: DIFF_LINE_DEL},
&DiffLine{LeftIdx: 36, RightIdx: 0, Type: DIFF_LINE_DEL},
&DiffLine{LeftIdx: 0, RightIdx: 34, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 0, RightIdx: 35, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 0, RightIdx: 36, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 0, RightIdx: 37, Type: DIFF_LINE_ADD},
&DiffLine{LeftIdx: 37, RightIdx: 38, Type: DIFF_LINE_PLAIN},
&DiffLine{LeftIdx: 38, RightIdx: 39, Type: DIFF_LINE_PLAIN},
}}
assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 31), ds.Lines[4])
assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 31), ds.Lines[3])
assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 33), ds.Lines[11])
assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 34), ds.Lines[12])
assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 35), ds.Lines[13])
assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 36), ds.Lines[14])
assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 34), ds.Lines[7])
assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 35), ds.Lines[8])
assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 36), ds.Lines[9])
assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 37), ds.Lines[10])
}

View File

@@ -17,11 +17,11 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
gouuid "github.com/satori/go.uuid"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
gouuid "github.com/gogits/gogs/modules/uuid"
)
var (
@@ -218,7 +218,8 @@ func (i *Issue) ReadBy(uid int64) error {
return UpdateIssueUserByRead(uid, i.ID)
}
func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err error) {
func (i *Issue) changeStatus(e *xorm.Session, doer *User, repo *Repository, isClosed bool) (err error) {
// Nothing should be performed if current status is same as target status
if i.IsClosed == isClosed {
return nil
}
@@ -230,7 +231,7 @@ func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err er
return err
}
// Update labels.
// Update issue count of labels
if err = i.getLabels(e); err != nil {
return err
}
@@ -245,28 +246,28 @@ func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err er
}
}
// Update milestone.
// Update issue count of milestone
if err = changeMilestoneIssueStats(e, i); err != nil {
return err
}
// New action comment.
if _, err = createStatusComment(e, doer, i.Repo, i); err != nil {
// New action comment
if _, err = createStatusComment(e, doer, repo, i); err != nil {
return err
}
return nil
}
// ChangeStatus changes issue status to open/closed.
func (i *Issue) ChangeStatus(doer *User, isClosed bool) (err error) {
// ChangeStatus changes issue status to open or closed.
func (i *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = i.changeStatus(sess, doer, isClosed); err != nil {
if err = i.changeStatus(sess, doer, repo, isClosed); err != nil {
return err
}
@@ -297,20 +298,19 @@ func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64,
return err
}
var label *Label
for _, id := range labelIDs {
if id == 0 {
continue
if len(labelIDs) > 0 {
// During the session, SQLite3 dirver cannot handle retrieve objects after update something.
// So we have to get all needed labels first.
labels := make([]*Label, 0, len(labelIDs))
if err = e.In("id", labelIDs).Find(&labels); err != nil {
return fmt.Errorf("find all labels: %v", err)
}
label, err = getLabelByID(e, id)
if err != nil {
return err
for _, label := range labels {
if err = issue.addLabel(e, label); err != nil {
return fmt.Errorf("addLabel: %v", err)
}
}
if err = issue.addLabel(e, label); err != nil {
return fmt.Errorf("addLabel: %v", err)
}
}
if issue.MilestoneID > 0 {
@@ -364,7 +364,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
ActUserID: issue.Poster.Id,
ActUserName: issue.Poster.Name,
ActEmail: issue.Poster.Email,
OpType: CREATE_ISSUE,
OpType: ACTION_CREATE_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
@@ -665,6 +665,47 @@ func GetIssueUserPairsByMode(uid, rid int64, isClosed bool, page, filterMode int
return ius, err
}
func UpdateMentions(userNames []string, issueId int64) error {
for i := range userNames {
userNames[i] = strings.ToLower(userNames[i])
}
users := make([]*User, 0, len(userNames))
if err := x.Where("lower_name IN (?)", strings.Join(userNames, "\",\"")).OrderBy("lower_name ASC").Find(&users); err != nil {
return err
}
ids := make([]int64, 0, len(userNames))
for _, user := range users {
ids = append(ids, user.Id)
if !user.IsOrganization() {
continue
}
if user.NumMembers == 0 {
continue
}
tempIds := make([]int64, 0, user.NumMembers)
orgUsers, err := GetOrgUsersByOrgId(user.Id)
if err != nil {
return err
}
for _, orgUser := range orgUsers {
tempIds = append(tempIds, orgUser.ID)
}
ids = append(ids, tempIds...)
}
if err := UpdateIssueUsersByMentions(ids, issueId); err != nil {
return err
}
return nil
}
// IssueStats represents issue statistic information.
type IssueStats struct {
OpenCount, ClosedCount int64
@@ -819,7 +860,7 @@ func UpdateIssue(issue *Issue) error {
return updateIssue(x, issue)
}
// updateIssueCols updates specific fields of given issue.
// updateIssueCols only updates values of specific columns for given issue.
func updateIssueCols(e Engine, issue *Issue, cols ...string) error {
_, err := e.Id(issue.ID).Cols(cols...).Update(issue)
return err
@@ -893,213 +934,6 @@ func UpdateIssueUsersByMentions(uids []int64, iid int64) error {
return nil
}
// .____ ___. .__
// | | _____ \_ |__ ____ | |
// | | \__ \ | __ \_/ __ \| |
// | |___ / __ \| \_\ \ ___/| |__
// |_______ (____ /___ /\___ >____/
// \/ \/ \/ \/
// Label represents a label of repository for issues.
type Label struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
Name string
Color string `xorm:"VARCHAR(7)"`
NumIssues int
NumClosedIssues int
NumOpenIssues int `xorm:"-"`
IsChecked bool `xorm:"-"`
}
// CalOpenIssues calculates the open issues of label.
func (m *Label) CalOpenIssues() {
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
}
// NewLabel creates new label of repository.
func NewLabel(l *Label) error {
_, err := x.Insert(l)
return err
}
func getLabelByID(e Engine, id int64) (*Label, error) {
if id <= 0 {
return nil, ErrLabelNotExist{id}
}
l := &Label{ID: id}
has, err := x.Get(l)
if err != nil {
return nil, err
} else if !has {
return nil, ErrLabelNotExist{l.ID}
}
return l, nil
}
// GetLabelByID returns a label by given ID.
func GetLabelByID(id int64) (*Label, error) {
return getLabelByID(x, id)
}
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
func GetLabelsByRepoID(repoID int64) ([]*Label, error) {
labels := make([]*Label, 0, 10)
return labels, x.Where("repo_id=?", repoID).Find(&labels)
}
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
issueLabels, err := getIssueLabels(e, issueID)
if err != nil {
return nil, fmt.Errorf("getIssueLabels: %v", err)
}
var label *Label
labels := make([]*Label, 0, len(issueLabels))
for idx := range issueLabels {
label, err = getLabelByID(e, issueLabels[idx].LabelID)
if err != nil && !IsErrLabelNotExist(err) {
return nil, fmt.Errorf("getLabelByID: %v", err)
}
labels = append(labels, label)
}
return labels, nil
}
// GetLabelsByIssueID returns all labels that belong to given issue by ID.
func GetLabelsByIssueID(issueID int64) ([]*Label, error) {
return getLabelsByIssueID(x, issueID)
}
func updateLabel(e Engine, l *Label) error {
_, err := e.Id(l.ID).AllCols().Update(l)
return err
}
// UpdateLabel updates label information.
func UpdateLabel(l *Label) error {
return updateLabel(x, l)
}
// DeleteLabel delete a label of given repository.
func DeleteLabel(repoID, labelID int64) error {
l, err := GetLabelByID(labelID)
if err != nil {
if IsErrLabelNotExist(err) {
return nil
}
return err
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if _, err = x.Where("label_id=?", labelID).Delete(new(IssueLabel)); err != nil {
return err
} else if _, err = sess.Delete(l); err != nil {
return err
}
return sess.Commit()
}
// .___ .____ ___. .__
// | | ______ ________ __ ____ | | _____ \_ |__ ____ | |
// | |/ ___// ___/ | \_/ __ \| | \__ \ | __ \_/ __ \| |
// | |\___ \ \___ \| | /\ ___/| |___ / __ \| \_\ \ ___/| |__
// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/
// \/ \/ \/ \/ \/ \/ \/
// IssueLabel represetns an issue-lable relation.
type IssueLabel struct {
ID int64 `xorm:"pk autoincr"`
IssueID int64 `xorm:"UNIQUE(s)"`
LabelID int64 `xorm:"UNIQUE(s)"`
}
func hasIssueLabel(e Engine, issueID, labelID int64) bool {
has, _ := e.Where("issue_id=? AND label_id=?", issueID, labelID).Get(new(IssueLabel))
return has
}
// HasIssueLabel returns true if issue has been labeled.
func HasIssueLabel(issueID, labelID int64) bool {
return hasIssueLabel(x, issueID, labelID)
}
func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if _, err = e.Insert(&IssueLabel{
IssueID: issue.ID,
LabelID: label.ID,
}); err != nil {
return err
}
label.NumIssues++
if issue.IsClosed {
label.NumClosedIssues++
}
return updateLabel(e, label)
}
// NewIssueLabel creates a new issue-label relation.
func NewIssueLabel(issue *Issue, label *Label) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = newIssueLabel(sess, issue, label); err != nil {
return err
}
return sess.Commit()
}
func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) {
issueLabels := make([]*IssueLabel, 0, 10)
return issueLabels, e.Where("issue_id=?", issueID).Asc("label_id").Find(&issueLabels)
}
// GetIssueLabels returns all issue-label relations of given issue by ID.
func GetIssueLabels(issueID int64) ([]*IssueLabel, error) {
return getIssueLabels(x, issueID)
}
func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if _, err = e.Delete(&IssueLabel{
IssueID: issue.ID,
LabelID: label.ID,
}); err != nil {
return err
}
label.NumIssues--
if issue.IsClosed {
label.NumClosedIssues--
}
return updateLabel(e, label)
}
// DeleteIssueLabel deletes issue-label relation.
func DeleteIssueLabel(issue *Issue, label *Label) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = deleteIssueLabel(sess, issue, label); err != nil {
return err
}
return sess.Commit()
}
// _____ .__.__ __
// / \ |__| | ____ _______/ |_ ____ ____ ____
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
@@ -1138,6 +972,7 @@ func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
if m.Deadline.Year() == 9999 {
return
}
m.Deadline = regulateTimeZone(m.Deadline)
m.DeadlineString = m.Deadline.Format("2006-01-02")
if time.Now().After(m.Deadline) {
@@ -1297,7 +1132,7 @@ func changeMilestoneIssueStats(e *xorm.Session, issue *Issue) error {
}
// ChangeMilestoneIssueStats updates the open/closed issues counter and progress
// for the milestone associated witht the given issue.
// for the milestone associated with the given issue.
func ChangeMilestoneIssueStats(issue *Issue) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
@@ -1409,262 +1244,6 @@ func DeleteMilestoneByID(id int64) error {
return sess.Commit()
}
// _________ __
// \_ ___ \ ____ _____ _____ ____ _____/ |_
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
// \ \___( <_> ) Y Y \ Y Y \ ___/| | \ |
// \______ /\____/|__|_| /__|_| /\___ >___| /__|
// \/ \/ \/ \/ \/
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
type CommentType int
const (
// Plain comment, can be associated with a commit (CommitId > 0) and a line (Line > 0)
COMMENT_TYPE_COMMENT CommentType = iota
COMMENT_TYPE_REOPEN
COMMENT_TYPE_CLOSE
// References.
COMMENT_TYPE_ISSUE_REF
// Reference from a commit (not part of a pull request)
COMMENT_TYPE_COMMIT_REF
// Reference from a comment
COMMENT_TYPE_COMMENT_REF
// Reference from a pull request
COMMENT_TYPE_PULL_REF
)
type CommentTag int
const (
COMMENT_TAG_NONE CommentTag = iota
COMMENT_TAG_POSTER
COMMENT_TAG_ADMIN
COMMENT_TAG_OWNER
)
// Comment represents a comment in commit and issue page.
type Comment struct {
ID int64 `xorm:"pk autoincr"`
Type CommentType
PosterID int64
Poster *User `xorm:"-"`
IssueID int64 `xorm:"INDEX"`
CommitID int64
Line int64
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
Created time.Time `xorm:"CREATED"`
// Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"`
Attachments []*Attachment `xorm:"-"`
// For view issue page.
ShowTag CommentTag `xorm:"-"`
}
func (c *Comment) AfterSet(colName string, _ xorm.Cell) {
var err error
switch colName {
case "id":
c.Attachments, err = GetAttachmentsByCommentID(c.ID)
if err != nil {
log.Error(3, "GetAttachmentsByCommentID[%d]: %v", c.ID, err)
}
case "poster_id":
c.Poster, err = GetUserByID(c.PosterID)
if err != nil {
if IsErrUserNotExist(err) {
c.PosterID = -1
c.Poster = NewFakeUser()
} else {
log.Error(3, "GetUserByID[%d]: %v", c.ID, err)
}
}
case "created":
c.Created = regulateTimeZone(c.Created)
}
}
func (c *Comment) AfterDelete() {
_, err := DeleteAttachmentsByComment(c.ID, true)
if err != nil {
log.Info("Could not delete files for comment %d on issue #%d: %s", c.ID, c.IssueID, err)
}
}
// HashTag returns unique hash tag for comment.
func (c *Comment) HashTag() string {
return "issuecomment-" + com.ToStr(c.ID)
}
// EventTag returns unique event hash tag for comment.
func (c *Comment) EventTag() string {
return "event-" + com.ToStr(c.ID)
}
func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, commitID, line int64, cmtType CommentType, content, commitSHA string, uuids []string) (_ *Comment, err error) {
comment := &Comment{
PosterID: u.Id,
Type: cmtType,
IssueID: issue.ID,
CommitID: commitID,
Line: line,
Content: content,
CommitSHA: commitSHA,
}
if _, err = e.Insert(comment); err != nil {
return nil, err
}
// Check comment type.
switch cmtType {
case COMMENT_TYPE_COMMENT:
if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", issue.ID); err != nil {
return nil, err
}
// Check attachments.
attachments := make([]*Attachment, 0, len(uuids))
for _, uuid := range uuids {
attach, err := getAttachmentByUUID(e, uuid)
if err != nil {
if IsErrAttachmentNotExist(err) {
continue
}
return nil, fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err)
}
attachments = append(attachments, attach)
}
for i := range attachments {
attachments[i].IssueID = issue.ID
attachments[i].CommentID = comment.ID
// No assign value could be 0, so ignore AllCols().
if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil {
return nil, fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err)
}
}
// Notify watchers.
act := &Action{
ActUserID: u.Id,
ActUserName: u.LowerName,
ActEmail: u.Email,
OpType: COMMENT_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]),
RepoID: repo.ID,
RepoUserName: repo.Owner.LowerName,
RepoName: repo.LowerName,
IsPrivate: repo.IsPrivate,
}
if err = notifyWatchers(e, act); err != nil {
return nil, err
}
case COMMENT_TYPE_REOPEN:
if issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", repo.ID)
} else {
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", repo.ID)
}
if err != nil {
return nil, err
}
case COMMENT_TYPE_CLOSE:
if issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", repo.ID)
} else {
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", repo.ID)
}
if err != nil {
return nil, err
}
}
return comment, nil
}
func createStatusComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue) (*Comment, error) {
cmtType := COMMENT_TYPE_CLOSE
if !issue.IsClosed {
cmtType = COMMENT_TYPE_REOPEN
}
return createComment(e, doer, repo, issue, 0, 0, cmtType, "", "", nil)
}
// CreateComment creates comment of issue or commit.
func CreateComment(doer *User, repo *Repository, issue *Issue, commitID, line int64, cmtType CommentType, content, commitSHA string, attachments []string) (comment *Comment, err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return nil, err
}
comment, err = createComment(sess, doer, repo, issue, commitID, line, cmtType, content, commitSHA, attachments)
if err != nil {
return nil, err
}
return comment, sess.Commit()
}
// CreateIssueComment creates a plain issue comment.
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
return CreateComment(doer, repo, issue, 0, 0, COMMENT_TYPE_COMMENT, content, "", attachments)
}
// CreateRefComment creates a commit reference comment to issue.
func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commitSHA string) error {
if len(commitSHA) == 0 {
return fmt.Errorf("cannot create reference with empty commit SHA")
}
// Check if same reference from same commit has already existed.
has, err := x.Get(&Comment{
Type: COMMENT_TYPE_COMMIT_REF,
IssueID: issue.ID,
CommitSHA: commitSHA,
})
if err != nil {
return fmt.Errorf("check reference comment: %v", err)
} else if has {
return nil
}
_, err = CreateComment(doer, repo, issue, 0, 0, COMMENT_TYPE_COMMIT_REF, content, commitSHA, nil)
return err
}
// GetCommentByID returns the comment by given ID.
func GetCommentByID(id int64) (*Comment, error) {
c := new(Comment)
has, err := x.Id(id).Get(c)
if err != nil {
return nil, err
} else if !has {
return nil, ErrCommentNotExist{id}
}
return c, nil
}
// GetCommentsByIssueID returns all comments of issue by given ID.
func GetCommentsByIssueID(issueID int64) ([]*Comment, error) {
comments := make([]*Comment, 0, 10)
return comments, x.Where("issue_id=?", issueID).Asc("created").Find(&comments)
}
// UpdateComment updates information of comment.
func UpdateComment(c *Comment) error {
_, err := x.Id(c.ID).AllCols().Update(c)
return err
}
// Attachment represent a attachment of issue/comment/release.
type Attachment struct {
ID int64 `xorm:"pk autoincr"`

312
models/issue_comment.go Normal file
View File

@@ -0,0 +1,312 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"fmt"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/log"
)
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
type CommentType int
const (
// Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
COMMENT_TYPE_COMMENT CommentType = iota
COMMENT_TYPE_REOPEN
COMMENT_TYPE_CLOSE
// References.
COMMENT_TYPE_ISSUE_REF
// Reference from a commit (not part of a pull request)
COMMENT_TYPE_COMMIT_REF
// Reference from a comment
COMMENT_TYPE_COMMENT_REF
// Reference from a pull request
COMMENT_TYPE_PULL_REF
)
type CommentTag int
const (
COMMENT_TAG_NONE CommentTag = iota
COMMENT_TAG_POSTER
COMMENT_TAG_WRITER
COMMENT_TAG_OWNER
)
// Comment represents a comment in commit and issue page.
type Comment struct {
ID int64 `xorm:"pk autoincr"`
Type CommentType
PosterID int64
Poster *User `xorm:"-"`
IssueID int64 `xorm:"INDEX"`
CommitID int64
Line int64
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
Created time.Time `xorm:"CREATED"`
// Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"`
Attachments []*Attachment `xorm:"-"`
// For view issue page.
ShowTag CommentTag `xorm:"-"`
}
func (c *Comment) AfterSet(colName string, _ xorm.Cell) {
var err error
switch colName {
case "id":
c.Attachments, err = GetAttachmentsByCommentID(c.ID)
if err != nil {
log.Error(3, "GetAttachmentsByCommentID[%d]: %v", c.ID, err)
}
case "poster_id":
c.Poster, err = GetUserByID(c.PosterID)
if err != nil {
if IsErrUserNotExist(err) {
c.PosterID = -1
c.Poster = NewFakeUser()
} else {
log.Error(3, "GetUserByID[%d]: %v", c.ID, err)
}
}
case "created":
c.Created = regulateTimeZone(c.Created)
}
}
func (c *Comment) AfterDelete() {
_, err := DeleteAttachmentsByComment(c.ID, true)
if err != nil {
log.Info("Could not delete files for comment %d on issue #%d: %s", c.ID, c.IssueID, err)
}
}
// HashTag returns unique hash tag for comment.
func (c *Comment) HashTag() string {
return "issuecomment-" + com.ToStr(c.ID)
}
// EventTag returns unique event hash tag for comment.
func (c *Comment) EventTag() string {
return "event-" + com.ToStr(c.ID)
}
func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err error) {
comment := &Comment{
Type: opts.Type,
PosterID: opts.Doer.Id,
IssueID: opts.Issue.ID,
CommitID: opts.CommitID,
CommitSHA: opts.CommitSHA,
Line: opts.LineNum,
Content: opts.Content,
}
if _, err = e.Insert(comment); err != nil {
return nil, err
}
// Compose comment action, could be plain comment, close or reopen issue/pull request.
// This object will be used to notify watchers in the end of function.
act := &Action{
ActUserID: opts.Doer.Id,
ActUserName: opts.Doer.Name,
ActEmail: opts.Doer.Email,
Content: fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]),
RepoID: opts.Repo.ID,
RepoUserName: opts.Repo.Owner.Name,
RepoName: opts.Repo.Name,
IsPrivate: opts.Repo.IsPrivate,
}
// Check comment type.
switch opts.Type {
case COMMENT_TYPE_COMMENT:
act.OpType = ACTION_COMMENT_ISSUE
if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", opts.Issue.ID); err != nil {
return nil, err
}
// Check attachments
attachments := make([]*Attachment, 0, len(opts.Attachments))
for _, uuid := range opts.Attachments {
attach, err := getAttachmentByUUID(e, uuid)
if err != nil {
if IsErrAttachmentNotExist(err) {
continue
}
return nil, fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err)
}
attachments = append(attachments, attach)
}
for i := range attachments {
attachments[i].IssueID = opts.Issue.ID
attachments[i].CommentID = comment.ID
// No assign value could be 0, so ignore AllCols().
if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil {
return nil, fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err)
}
}
case COMMENT_TYPE_REOPEN:
act.OpType = ACTION_REOPEN_ISSUE
if opts.Issue.IsPull {
act.OpType = ACTION_REOPEN_PULL_REQUEST
}
if opts.Issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", opts.Repo.ID)
} else {
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", opts.Repo.ID)
}
if err != nil {
return nil, err
}
case COMMENT_TYPE_CLOSE:
act.OpType = ACTION_CLOSE_ISSUE
if opts.Issue.IsPull {
act.OpType = ACTION_CLOSE_PULL_REQUEST
}
if opts.Issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", opts.Repo.ID)
} else {
_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", opts.Repo.ID)
}
if err != nil {
return nil, err
}
}
// Notify watchers for whatever action comes in
if err = notifyWatchers(e, act); err != nil {
return nil, fmt.Errorf("notifyWatchers: %v", err)
}
return comment, nil
}
func createStatusComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue) (*Comment, error) {
cmtType := COMMENT_TYPE_CLOSE
if !issue.IsClosed {
cmtType = COMMENT_TYPE_REOPEN
}
return createComment(e, &CreateCommentOptions{
Type: cmtType,
Doer: doer,
Repo: repo,
Issue: issue,
})
}
type CreateCommentOptions struct {
Type CommentType
Doer *User
Repo *Repository
Issue *Issue
CommitID int64
CommitSHA string
LineNum int64
Content string
Attachments []string // UUIDs of attachments
}
// CreateComment creates comment of issue or commit.
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return nil, err
}
comment, err = createComment(sess, opts)
if err != nil {
return nil, err
}
return comment, sess.Commit()
}
// CreateIssueComment creates a plain issue comment.
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
return CreateComment(&CreateCommentOptions{
Type: COMMENT_TYPE_COMMENT,
Doer: doer,
Repo: repo,
Issue: issue,
Content: content,
Attachments: attachments,
})
}
// CreateRefComment creates a commit reference comment to issue.
func CreateRefComment(doer *User, repo *Repository, issue *Issue, content, commitSHA string) error {
if len(commitSHA) == 0 {
return fmt.Errorf("cannot create reference with empty commit SHA")
}
// Check if same reference from same commit has already existed.
has, err := x.Get(&Comment{
Type: COMMENT_TYPE_COMMIT_REF,
IssueID: issue.ID,
CommitSHA: commitSHA,
})
if err != nil {
return fmt.Errorf("check reference comment: %v", err)
} else if has {
return nil
}
_, err = CreateComment(&CreateCommentOptions{
Type: COMMENT_TYPE_COMMIT_REF,
Doer: doer,
Repo: repo,
Issue: issue,
CommitSHA: commitSHA,
Content: content,
})
return err
}
// GetCommentByID returns the comment by given ID.
func GetCommentByID(id int64) (*Comment, error) {
c := new(Comment)
has, err := x.Id(id).Get(c)
if err != nil {
return nil, err
} else if !has {
return nil, ErrCommentNotExist{id}
}
return c, nil
}
// GetCommentsByIssueID returns all comments of issue by given ID.
func GetCommentsByIssueID(issueID int64) ([]*Comment, error) {
comments := make([]*Comment, 0, 10)
return comments, x.Where("issue_id=?", issueID).Asc("created").Find(&comments)
}
// UpdateComment updates information of comment.
func UpdateComment(c *Comment) error {
_, err := x.Id(c.ID).AllCols().Update(c)
return err
}

234
models/issue_label.go Normal file
View File

@@ -0,0 +1,234 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"fmt"
"html/template"
"strconv"
"strings"
"github.com/go-xorm/xorm"
)
// Label represents a label of repository for issues.
type Label struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
Name string
Color string `xorm:"VARCHAR(7)"`
NumIssues int
NumClosedIssues int
NumOpenIssues int `xorm:"-"`
IsChecked bool `xorm:"-"`
}
// CalOpenIssues calculates the open issues of label.
func (m *Label) CalOpenIssues() {
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
}
// ForegroundColor calculates the text color for labels based
// on their background color.
func (l *Label) ForegroundColor() template.CSS {
if strings.HasPrefix(l.Color, "#") {
if color, err := strconv.ParseUint(l.Color[1:], 16, 64); err == nil {
r := float32(0xFF & (color >> 16))
g := float32(0xFF & (color >> 8))
b := float32(0xFF & color)
luminance := (0.2126*r + 0.7152*g + 0.0722*b) / 255
if luminance < 0.5 {
return template.CSS("#fff")
}
}
}
// default to black
return template.CSS("#000")
}
// NewLabel creates new label of repository.
func NewLabel(l *Label) error {
_, err := x.Insert(l)
return err
}
func getLabelByID(e Engine, id int64) (*Label, error) {
if id <= 0 {
return nil, ErrLabelNotExist{id}
}
l := &Label{ID: id}
has, err := x.Get(l)
if err != nil {
return nil, err
} else if !has {
return nil, ErrLabelNotExist{l.ID}
}
return l, nil
}
// GetLabelByID returns a label by given ID.
func GetLabelByID(id int64) (*Label, error) {
return getLabelByID(x, id)
}
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
func GetLabelsByRepoID(repoID int64) ([]*Label, error) {
labels := make([]*Label, 0, 10)
return labels, x.Where("repo_id=?", repoID).Find(&labels)
}
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
issueLabels, err := getIssueLabels(e, issueID)
if err != nil {
return nil, fmt.Errorf("getIssueLabels: %v", err)
}
var label *Label
labels := make([]*Label, 0, len(issueLabels))
for idx := range issueLabels {
label, err = getLabelByID(e, issueLabels[idx].LabelID)
if err != nil && !IsErrLabelNotExist(err) {
return nil, fmt.Errorf("getLabelByID: %v", err)
}
labels = append(labels, label)
}
return labels, nil
}
// GetLabelsByIssueID returns all labels that belong to given issue by ID.
func GetLabelsByIssueID(issueID int64) ([]*Label, error) {
return getLabelsByIssueID(x, issueID)
}
func updateLabel(e Engine, l *Label) error {
_, err := e.Id(l.ID).AllCols().Update(l)
return err
}
// UpdateLabel updates label information.
func UpdateLabel(l *Label) error {
return updateLabel(x, l)
}
// DeleteLabel delete a label of given repository.
func DeleteLabel(repoID, labelID int64) error {
l, err := GetLabelByID(labelID)
if err != nil {
if IsErrLabelNotExist(err) {
return nil
}
return err
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if _, err = x.Where("label_id=?", labelID).Delete(new(IssueLabel)); err != nil {
return err
} else if _, err = sess.Delete(l); err != nil {
return err
}
return sess.Commit()
}
// .___ .____ ___. .__
// | | ______ ________ __ ____ | | _____ \_ |__ ____ | |
// | |/ ___// ___/ | \_/ __ \| | \__ \ | __ \_/ __ \| |
// | |\___ \ \___ \| | /\ ___/| |___ / __ \| \_\ \ ___/| |__
// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/
// \/ \/ \/ \/ \/ \/ \/
// IssueLabel represetns an issue-lable relation.
type IssueLabel struct {
ID int64 `xorm:"pk autoincr"`
IssueID int64 `xorm:"UNIQUE(s)"`
LabelID int64 `xorm:"UNIQUE(s)"`
}
func hasIssueLabel(e Engine, issueID, labelID int64) bool {
has, _ := e.Where("issue_id=? AND label_id=?", issueID, labelID).Get(new(IssueLabel))
return has
}
// HasIssueLabel returns true if issue has been labeled.
func HasIssueLabel(issueID, labelID int64) bool {
return hasIssueLabel(x, issueID, labelID)
}
func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if _, err = e.Insert(&IssueLabel{
IssueID: issue.ID,
LabelID: label.ID,
}); err != nil {
return err
}
label.NumIssues++
if issue.IsClosed {
label.NumClosedIssues++
}
return updateLabel(e, label)
}
// NewIssueLabel creates a new issue-label relation.
func NewIssueLabel(issue *Issue, label *Label) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = newIssueLabel(sess, issue, label); err != nil {
return err
}
return sess.Commit()
}
func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) {
issueLabels := make([]*IssueLabel, 0, 10)
return issueLabels, e.Where("issue_id=?", issueID).Asc("label_id").Find(&issueLabels)
}
// GetIssueLabels returns all issue-label relations of given issue by ID.
func GetIssueLabels(issueID int64) ([]*IssueLabel, error) {
return getIssueLabels(x, issueID)
}
func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if _, err = e.Delete(&IssueLabel{
IssueID: issue.ID,
LabelID: label.ID,
}); err != nil {
return err
}
label.NumIssues--
if issue.IsClosed {
label.NumClosedIssues--
}
return updateLabel(e, label)
}
// DeleteIssueLabel deletes issue-label relation.
func DeleteIssueLabel(issue *Issue, label *Label) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = deleteIssueLabel(sess, issue, label); err != nil {
return err
}
return sess.Commit()
}

View File

@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"net/smtp"
"net/textproto"
"strings"
"time"
@@ -26,25 +27,24 @@ type LoginType int
// Note: new type must be added at the end of list to maintain compatibility.
const (
NOTYPE LoginType = iota
PLAIN
LDAP
SMTP
PAM
DLDAP
LOGIN_NOTYPE LoginType = iota
LOGIN_PLAIN // 1
LOGIN_LDAP // 2
LOGIN_SMTP // 3
LOGIN_PAM // 4
LOGIN_DLDAP // 5
)
var (
ErrAuthenticationAlreadyExist = errors.New("Authentication already exist")
ErrAuthenticationNotExist = errors.New("Authentication does not exist")
ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users")
)
var LoginNames = map[LoginType]string{
LDAP: "LDAP (via BindDN)",
DLDAP: "LDAP (simple auth)",
SMTP: "SMTP",
PAM: "PAM",
LOGIN_LDAP: "LDAP (via BindDN)",
LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind
LOGIN_SMTP: "SMTP",
LOGIN_PAM: "PAM",
}
// Ensure structs implemented interface.
@@ -105,15 +105,26 @@ type LoginSource struct {
Updated time.Time `xorm:"UPDATED"`
}
// Cell2Int64 converts a xorm.Cell type to int64,
// and handles possible irregular cases.
func Cell2Int64(val xorm.Cell) int64 {
switch (*val).(type) {
case []uint8:
log.Trace("Cell2Int64 ([]uint8): %v", *val)
return com.StrTo(string((*val).([]uint8))).MustInt64()
}
return (*val).(int64)
}
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
switch colName {
case "type":
switch LoginType((*val).(int64)) {
case LDAP, DLDAP:
switch LoginType(Cell2Int64(val)) {
case LOGIN_LDAP, LOGIN_DLDAP:
source.Cfg = new(LDAPConfig)
case SMTP:
case LOGIN_SMTP:
source.Cfg = new(SMTPConfig)
case PAM:
case LOGIN_PAM:
source.Cfg = new(PAMConfig)
default:
panic("unrecognized login source type: " + com.ToStr(*val))
@@ -126,26 +137,26 @@ func (source *LoginSource) TypeName() string {
}
func (source *LoginSource) IsLDAP() bool {
return source.Type == LDAP
return source.Type == LOGIN_LDAP
}
func (source *LoginSource) IsDLDAP() bool {
return source.Type == DLDAP
return source.Type == LOGIN_DLDAP
}
func (source *LoginSource) IsSMTP() bool {
return source.Type == SMTP
return source.Type == LOGIN_SMTP
}
func (source *LoginSource) IsPAM() bool {
return source.Type == PAM
return source.Type == LOGIN_PAM
}
func (source *LoginSource) UseTLS() bool {
switch source.Type {
case LDAP, DLDAP:
case LOGIN_LDAP, LOGIN_DLDAP:
return source.LDAP().UseSSL
case SMTP:
case LOGIN_SMTP:
return source.SMTP().TLS
}
@@ -154,9 +165,9 @@ func (source *LoginSource) UseTLS() bool {
func (source *LoginSource) SkipVerify() bool {
switch source.Type {
case LDAP, DLDAP:
case LOGIN_LDAP, LOGIN_DLDAP:
return source.LDAP().SkipVerify
case SMTP:
case LOGIN_SMTP:
return source.SMTP().SkipVerify
}
@@ -191,13 +202,14 @@ func LoginSources() ([]*LoginSource, error) {
return auths, x.Find(&auths)
}
// GetLoginSourceByID returns login source by given ID.
func GetLoginSourceByID(id int64) (*LoginSource, error) {
source := new(LoginSource)
has, err := x.Id(id).Get(source)
if err != nil {
return nil, err
} else if !has {
return nil, ErrAuthenticationNotExist
return nil, ErrAuthenticationNotExist{id}
}
return source, nil
}
@@ -225,16 +237,16 @@ func DeleteSource(source *LoginSource) error {
// |_______ \/_______ /\____|__ /____|
// \/ \/ \/
// LoginUserLDAPSource queries if name/passwd can login against the LDAP directory pool,
// LoginUserLDAPSource queries if loginName/passwd can login against the LDAP directory pool,
// and create a local user if success when enabled.
// It returns the same LoginUserPlain semantic.
func LoginUserLDAPSource(u *User, name, passwd string, source *LoginSource, autoRegister bool) (*User, error) {
func LoginUserLDAPSource(u *User, loginName, passwd string, source *LoginSource, autoRegister bool) (*User, error) {
cfg := source.Cfg.(*LDAPConfig)
directBind := (source.Type == DLDAP)
fn, sn, mail, admin, logged := cfg.SearchEntry(name, passwd, directBind)
directBind := (source.Type == LOGIN_DLDAP)
name, fn, sn, mail, admin, logged := cfg.SearchEntry(loginName, passwd, directBind)
if !logged {
// User not in LDAP, do nothing
return nil, ErrUserNotExist{0, name}
return nil, ErrUserNotExist{0, loginName}
}
if !autoRegister {
@@ -242,6 +254,9 @@ func LoginUserLDAPSource(u *User, name, passwd string, source *LoginSource, auto
}
// Fallback.
if len(name) == 0 {
name = loginName
}
if len(mail) == 0 {
mail = fmt.Sprintf("%s@localhost", name)
}
@@ -249,10 +264,10 @@ func LoginUserLDAPSource(u *User, name, passwd string, source *LoginSource, auto
u = &User{
LowerName: strings.ToLower(name),
Name: name,
FullName: strings.TrimSpace(fn + " " + sn),
FullName: composeFullName(fn, sn, name),
LoginType: source.Type,
LoginSource: source.ID,
LoginName: name,
LoginName: loginName,
Email: mail,
IsAdmin: admin,
IsActive: true,
@@ -260,6 +275,19 @@ func LoginUserLDAPSource(u *User, name, passwd string, source *LoginSource, auto
return u, CreateUser(u)
}
func composeFullName(firstName, surename, userName string) string {
switch {
case len(firstName) == 0 && len(surename) == 0:
return userName
case len(firstName) == 0:
return surename
case len(surename) == 0:
return firstName
default:
return firstName + " " + surename
}
}
// _________ __________________________
// / _____/ / \__ ___/\______ \
// \_____ \ / \ / \| | | ___/
@@ -334,7 +362,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
// Query if name/passwd can login against the LDAP directory pool
// Create a local user if success
// Return the same LoginUserPlain semantic
func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
func LoginUserSMTPSource(u *User, name, passwd string, sourceID int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
// Verify allowed domains.
if len(cfg.AllowedDomains) > 0 {
idx := strings.Index(name, "@")
@@ -355,7 +383,11 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
}
if err := SMTPAuth(auth, cfg); err != nil {
if strings.Contains(err.Error(), "Username and Password not accepted") {
// Check standard error format first,
// then fallback to worse case.
tperr, ok := err.(*textproto.Error)
if (ok && tperr.Code == 535) ||
strings.Contains(err.Error(), "Username and Password not accepted") {
return nil, ErrUserNotExist{0, name}
}
return nil, err
@@ -374,8 +406,8 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
u = &User{
LowerName: strings.ToLower(loginName),
Name: strings.ToLower(loginName),
LoginType: SMTP,
LoginSource: sourceId,
LoginType: LOGIN_SMTP,
LoginSource: sourceID,
LoginName: name,
IsActive: true,
Passwd: passwd,
@@ -395,7 +427,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
// Query if name/passwd can login against PAM
// Create a local user if success
// Return the same LoginUserPlain semantic
func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
func LoginUserPAMSource(u *User, name, passwd string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
if err := pam.PAMAuth(cfg.ServiceName, name, passwd); err != nil {
if strings.Contains(err.Error(), "Authentication failure") {
return nil, ErrUserNotExist{0, name}
@@ -411,8 +443,8 @@ func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMCo
u = &User{
LowerName: strings.ToLower(name),
Name: name,
LoginType: PAM,
LoginSource: sourceId,
LoginType: LOGIN_PAM,
LoginSource: sourceID,
LoginName: name,
IsActive: true,
Passwd: passwd,
@@ -427,11 +459,11 @@ func ExternalUserLogin(u *User, name, passwd string, source *LoginSource, autoRe
}
switch source.Type {
case LDAP, DLDAP:
case LOGIN_LDAP, LOGIN_DLDAP:
return LoginUserLDAPSource(u, name, passwd, source, autoRegister)
case SMTP:
case LOGIN_SMTP:
return LoginUserSMTPSource(u, name, passwd, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
case PAM:
case LOGIN_PAM:
return LoginUserPAMSource(u, name, passwd, source.ID, source.Cfg.(*PAMConfig), autoRegister)
}
@@ -454,7 +486,7 @@ func UserSignIn(uname, passwd string) (*User, error) {
if userExists {
switch u.LoginType {
case NOTYPE, PLAIN:
case LOGIN_NOTYPE, LOGIN_PLAIN:
if u.ValidatePassword(passwd) {
return u, nil
}

View File

@@ -13,18 +13,18 @@ import (
"path"
"path/filepath"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
gouuid "github.com/satori/go.uuid"
"gopkg.in/ini.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
gouuid "github.com/gogits/gogs/modules/uuid"
)
const _MIN_DB_VER = 0
const _MIN_DB_VER = 4
type Migration interface {
Description() string
@@ -58,16 +58,13 @@ type Version struct {
// If you want to "retire" a migration, remove it from the top of the list and
// update _MIN_VER_DB accordingly
var migrations = []Migration{
NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1:v0.5.13
NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2:v0.5.13
NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3:v0.5.13
NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4:v0.5.13
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5
}
// Migrate database to current version
@@ -81,24 +78,9 @@ func Migrate(x *xorm.Engine) error {
if err != nil {
return fmt.Errorf("get: %v", err)
} else if !has {
// If the user table does not exist it is a fresh installation and we
// can skip all migrations.
needsMigration, err := x.IsTableExist("user")
if err != nil {
return err
}
if needsMigration {
isEmpty, err := x.IsTableEmpty("user")
if err != nil {
return err
}
// If the user table is empty it is a fresh installation and we can
// skip all migrations.
needsMigration = !isEmpty
}
if !needsMigration {
currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
}
// If the version record does not exist we think
// it is a fresh installation and we can skip all migrations.
currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
if _, err = x.InsertOne(currentVersion); err != nil {
return fmt.Errorf("insert: %v", err)
@@ -106,6 +88,12 @@ func Migrate(x *xorm.Engine) error {
}
v := currentVersion.Version
if _MIN_DB_VER > v {
log.Fatal(4, `Gogs no longer supports auto-migration from your previously installed version.
Please try to upgrade to a lower version (>= v0.6.0) first, then upgrade to current version.`)
return nil
}
if int(v-_MIN_DB_VER) > len(migrations) {
// User downgraded Gogs.
currentVersion.Version = int64(len(migrations) + _MIN_DB_VER)
@@ -132,276 +120,6 @@ func sessionRelease(sess *xorm.Session) {
sess.Close()
}
func accessToCollaboration(x *xorm.Engine) (err error) {
type Collaboration struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
Created time.Time
}
if err = x.Sync(new(Collaboration)); err != nil {
return fmt.Errorf("sync: %v", err)
}
results, err := x.Query("SELECT u.id AS `uid`, a.repo_name AS `repo`, a.mode AS `mode`, a.created as `created` FROM `access` a JOIN `user` u ON a.user_name=u.lower_name")
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return err
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
offset := strings.Split(time.Now().String(), " ")[2]
for _, result := range results {
mode := com.StrTo(result["mode"]).MustInt64()
// Collaborators must have write access.
if mode < 2 {
continue
}
userID := com.StrTo(result["uid"]).MustInt64()
repoRefName := string(result["repo"])
var created time.Time
switch {
case setting.UseSQLite3:
created, _ = time.Parse(time.RFC3339, string(result["created"]))
case setting.UseMySQL:
created, _ = time.Parse("2006-01-02 15:04:05-0700", string(result["created"])+offset)
case setting.UsePostgreSQL:
created, _ = time.Parse("2006-01-02T15:04:05Z-0700", string(result["created"])+offset)
}
// find owner of repository
parts := strings.SplitN(repoRefName, "/", 2)
ownerName := parts[0]
repoName := parts[1]
results, err := sess.Query("SELECT u.id as `uid`, ou.uid as `memberid` FROM `user` u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?", ownerName)
if err != nil {
return err
}
if len(results) < 1 {
continue
}
ownerID := com.StrTo(results[0]["uid"]).MustInt64()
if ownerID == userID {
continue
}
// test if user is member of owning organization
isMember := false
for _, member := range results {
memberID := com.StrTo(member["memberid"]).MustInt64()
// We can skip all cases that a user is member of the owning organization
if memberID == userID {
isMember = true
}
}
if isMember {
continue
}
results, err = sess.Query("SELECT id FROM `repository` WHERE owner_id=? AND lower_name=?", ownerID, repoName)
if err != nil {
return err
} else if len(results) < 1 {
continue
}
collaboration := &Collaboration{
UserID: userID,
RepoID: com.StrTo(results[0]["id"]).MustInt64(),
}
has, err := sess.Get(collaboration)
if err != nil {
return err
} else if has {
continue
}
collaboration.Created = created
if _, err = sess.InsertOne(collaboration); err != nil {
return err
}
}
return sess.Commit()
}
func ownerTeamUpdate(x *xorm.Engine) (err error) {
if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
return fmt.Errorf("update owner team table: %v", err)
}
return nil
}
func accessRefactor(x *xorm.Engine) (err error) {
type (
AccessMode int
Access struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
Mode AccessMode
}
UserRepo struct {
UserID int64
RepoID int64
}
)
// We consiously don't start a session yet as we make only reads for now, no writes
accessMap := make(map[UserRepo]AccessMode, 50)
results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
if err != nil {
return fmt.Errorf("select repositories: %v", err)
}
for _, repo := range results {
repoID := com.StrTo(repo["repo_id"]).MustInt64()
isPrivate := com.StrTo(repo["is_private"]).MustInt() > 0
ownerID := com.StrTo(repo["owner_id"]).MustInt64()
ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
if err != nil {
return fmt.Errorf("select collaborators: %v", err)
}
for _, user := range results {
userID := com.StrTo(user["user_id"]).MustInt64()
accessMap[UserRepo{userID, repoID}] = 2 // WRITE ACCESS
}
if !ownerIsOrganization {
continue
}
// The minimum level to add a new access record,
// because public repository has implicit open access.
minAccessLevel := AccessMode(0)
if !isPrivate {
minAccessLevel = 1
}
repoString := "$" + string(repo["repo_id"]) + "|"
results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return fmt.Errorf("select teams from org: %v", err)
}
for _, team := range results {
if !strings.Contains(string(team["repo_ids"]), repoString) {
continue
}
teamID := com.StrTo(team["id"]).MustInt64()
mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
if err != nil {
return fmt.Errorf("select users from team: %v", err)
}
for _, user := range results {
userID := com.StrTo(user["uid"]).MustInt64()
accessMap[UserRepo{userID, repoID}] = mode
}
}
}
// Drop table can't be in a session (at least not in sqlite)
if _, err = x.Exec("DROP TABLE `access`"); err != nil {
return fmt.Errorf("drop access table: %v", err)
}
// Now we start writing so we make a session
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = sess.Sync2(new(Access)); err != nil {
return fmt.Errorf("sync: %v", err)
}
accesses := make([]*Access, 0, len(accessMap))
for ur, mode := range accessMap {
accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
}
if _, err = sess.Insert(accesses); err != nil {
return fmt.Errorf("insert accesses: %v", err)
}
return sess.Commit()
}
func teamToTeamRepo(x *xorm.Engine) error {
type TeamRepo struct {
ID int64 `xorm:"pk autoincr"`
OrgID int64 `xorm:"INDEX"`
TeamID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
}
teamRepos := make([]*TeamRepo, 0, 50)
results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return fmt.Errorf("select teams: %v", err)
}
for _, team := range results {
orgID := com.StrTo(team["org_id"]).MustInt64()
teamID := com.StrTo(team["id"]).MustInt64()
// #1032: legacy code can have duplicated IDs for same repository.
mark := make(map[int64]bool)
for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
if repoID == 0 || mark[repoID] {
continue
}
mark[repoID] = true
teamRepos = append(teamRepos, &TeamRepo{
OrgID: orgID,
TeamID: teamID,
RepoID: repoID,
})
}
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = sess.Sync2(new(TeamRepo)); err != nil {
return fmt.Errorf("sync2: %v", err)
} else if _, err = sess.Insert(teamRepos); err != nil {
return fmt.Errorf("insert team-repos: %v", err)
}
return sess.Commit()
}
func fixLocaleFileLoadPanic(_ *xorm.Engine) error {
cfg, err := ini.Load(setting.CustomConf)
if err != nil {
@@ -489,7 +207,8 @@ func issueToIssueLabel(x *xorm.Engine) error {
issueLabels := make([]*IssueLabel, 0, 50)
results, err := x.Query("SELECT `id`,`label_ids` FROM `issue`")
if err != nil {
if strings.Contains(err.Error(), "no such column") {
if strings.Contains(err.Error(), "no such column") ||
strings.Contains(err.Error(), "Unknown column") {
return nil
}
return fmt.Errorf("select issues: %v", err)
@@ -648,6 +367,9 @@ func renamePullRequestFields(x *xorm.Engine) (err error) {
Index: com.StrTo(pr["pull_index"]).MustInt64(),
HeadBranch: string(pr["head_barcnh"]),
}
if pull.Index == 0 {
continue
}
if _, err = sess.Id(pull.ID).Update(pull); err != nil {
return err
}
@@ -702,3 +424,32 @@ func cleanUpMigrateRepoInfo(x *xorm.Engine) (err error) {
return nil
}
func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
type User struct {
ID int64 `xorm:"pk autoincr"`
Rands string `xorm:"VARCHAR(10)"`
Salt string `xorm:"VARCHAR(10)"`
}
orgs := make([]*User, 0, 10)
if err = x.Where("type=1").And("rands=''").Find(&orgs); err != nil {
return fmt.Errorf("select all organizations: %v", err)
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
for _, org := range orgs {
org.Rands = base.GetRandomString(10)
org.Salt = base.GetRandomString(10)
if _, err = sess.Id(org.ID).Update(org); err != nil {
return err
}
}
return sess.Commit()
}

View File

@@ -191,12 +191,7 @@ func SetEngine() (err error) {
return fmt.Errorf("Fail to create xorm.log: %v", err)
}
x.SetLogger(xorm.NewSimpleLogger(f))
x.ShowSQL = true
x.ShowInfo = true
x.ShowDebug = true
x.ShowErr = true
x.ShowWarn = true
x.ShowSQL(true)
return nil
}

View File

@@ -10,14 +10,13 @@ import (
"os"
"strings"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
)
var (
ErrOrgNotExist = errors.New("Organization does not exist")
ErrTeamAlreadyExist = errors.New("Team already exist")
ErrTeamNotExist = errors.New("Team does not exist")
ErrTeamNameIllegal = errors.New("Team name contains illegal characters")
ErrOrgNotExist = errors.New("Organization does not exist")
ErrTeamNotExist = errors.New("Team does not exist")
)
// IsOwnedBy returns true if given user is in the owner team.
@@ -108,7 +107,10 @@ func CreateOrganization(org, owner *User) (err error) {
org.LowerName = strings.ToLower(org.Name)
org.FullName = org.Name
org.Rands = GetUserSalt()
org.Salt = GetUserSalt()
org.UseCustomAvatar = true
org.MaxRepoCreation = -1
org.NumTeams = 1
org.NumMembers = 1
@@ -252,6 +254,27 @@ func IsPublicMembership(orgId, uid int64) bool {
return has
}
func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
orgs := make([]*User, 0, 10)
if !showAll {
sess.And("`org_user`.is_public=?", true)
}
return orgs, sess.And("`org_user`.uid=?", userID).
Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
}
// GetOrgsByUserID returns a list of organizations that the given user ID
// has joined.
func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
return getOrgsByUserID(x.NewSession(), userID, showAll)
}
// GetOrgsByUserIDDesc returns a list of organizations that the given user ID
// has joined, ordered descending by the given condition.
func GetOrgsByUserIDDesc(userID int64, desc string, showAll bool) ([]*User, error) {
return getOrgsByUserID(x.NewSession().Desc(desc), userID, showAll)
}
func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
orgs := make([]*User, 0, 10)
return orgs, sess.Where("`org_user`.uid=?", userID).And("`org_user`.is_owner=?", true).
@@ -265,16 +288,21 @@ func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
}
// GetOwnedOrganizationsByUserIDDesc returns a list of organizations are owned by
// given user ID and descring order by given condition.
// given user ID, ordered descending by the given condition.
func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
sess := x.NewSession()
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
}
// GetOrgUsersByUserId returns all organization-user relations by user ID.
func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
// GetOrgUsersByUserID returns all organization-user relations by user ID.
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
ous := make([]*OrgUser, 0, 10)
err := x.Where("uid=?", uid).Find(&ous)
sess := x.Where("uid=?", uid)
if !all {
// Only show public organizations
sess.And("is_public=?", true)
}
err := sess.Find(&ous)
return ous, err
}
@@ -590,9 +618,9 @@ func (t *Team) RemoveRepository(repoID int64) error {
// NewTeam creates a record of new team.
// It's caller's responsibility to assign organization ID.
func NewTeam(t *Team) (err error) {
if err = IsUsableName(t.Name); err != nil {
return err
func NewTeam(t *Team) error {
if len(t.Name) == 0 {
return errors.New("empty team name")
}
has, err := x.Id(t.OrgID).Get(new(User))
@@ -607,7 +635,7 @@ func NewTeam(t *Team) (err error) {
if err != nil {
return err
} else if has {
return ErrTeamAlreadyExist
return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
}
sess := x.NewSession()
@@ -666,8 +694,8 @@ func GetTeamById(teamId int64) (*Team, error) {
// UpdateTeam updates information of team.
func UpdateTeam(t *Team, authChanged bool) (err error) {
if err = IsUsableName(t.Name); err != nil {
return err
if len(t.Name) == 0 {
return errors.New("empty team name")
}
if len(t.Description) > 255 {
@@ -681,6 +709,13 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
}
t.LowerName = strings.ToLower(t.Name)
has, err := x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).And("id!=?", t.ID).Get(new(Team))
if err != nil {
return err
} else if has {
return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
}
if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil {
return fmt.Errorf("update: %v", err)
}
@@ -1015,3 +1050,55 @@ func removeOrgRepo(e Engine, orgID, repoID int64) error {
func RemoveOrgRepo(orgID, repoID int64) error {
return removeOrgRepo(x, orgID, repoID)
}
// GetUserRepositories gets all repositories of an organization,
// that the user with the given userID has access to.
func (org *User) GetUserRepositories(userID int64) (err error) {
teams := make([]*Team, 0, org.NumTeams)
if err = x.Sql(`SELECT team.id FROM team
INNER JOIN team_user ON team_user.team_id = team.id
WHERE team_user.org_id = ? AND team_user.uid = ?`, org.Id, userID).Find(&teams); err != nil {
return fmt.Errorf("get teams: %v", err)
}
teamIDs := make([]string, len(teams))
for i := range teams {
teamIDs[i] = com.ToStr(teams[i].ID)
}
if len(teamIDs) == 0 {
// user has no team but "IN ()" is invalid SQL
teamIDs = append(teamIDs, "-1") // there is no repo with id=-1
}
repos := make([]*Repository, 0, 5)
if err = x.Sql(`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 (?)
GROUP BY repository.id`,
org.Id, false, strings.Join(teamIDs, ",")).Find(&repos); err != nil {
return fmt.Errorf("get repositories: %v", err)
}
org.Repos = repos
// FIXME: should I change this value inside method,
// or only in location of caller where it's really needed?
org.NumRepos = len(org.Repos)
return nil
}
// GetTeams returns all teams that belong to organization,
// and that the user has joined.
func (org *User) GetUserTeams(userID int64) error {
teams := make([]*Team, 0, 5)
if err := x.Sql(`SELECT team.* FROM team
INNER JOIN team_user ON team_user.team_id = team.id
WHERE team_user.org_id = ? AND team_user.uid = ?`,
org.Id, userID).Find(&teams); err != nil {
return fmt.Errorf("get teams: %v", err)
}
// FIXME: should I change this value inside method,
// or only in location of caller where it's really needed?
org.NumTeams = len(org.Teams)
return nil
}

View File

@@ -14,7 +14,9 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
@@ -124,28 +126,30 @@ func (pr *PullRequest) CanAutoMerge() bool {
// Merge merges pull request to base repository.
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
if err = pr.GetHeadRepo(); err != nil {
return fmt.Errorf("GetHeadRepo: %v", err)
} else if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = pr.Issue.changeStatus(sess, doer, true); err != nil {
if err = pr.Issue.changeStatus(sess, doer, pr.Issue.Repo, true); err != nil {
return fmt.Errorf("Issue.changeStatus: %v", err)
}
if err = pr.getHeadRepo(sess); err != nil {
return fmt.Errorf("getHeadRepo: %v", err)
}
headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
headGitRepo, err := git.OpenRepository(headRepoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
pr.MergedCommitID, err = headGitRepo.GetCommitIdOfBranch(pr.HeadBranch)
pr.MergedCommitID, err = headGitRepo.GetBranchCommitID(pr.HeadBranch)
if err != nil {
return fmt.Errorf("GetCommitIdOfBranch: %v", err)
return fmt.Errorf("GetBranchCommitID: %v", err)
}
if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil {
@@ -213,7 +217,38 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
return fmt.Errorf("git push: %s", stderr)
}
return sess.Commit()
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
// Compose commit repository action
l, err := headGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
if err != nil {
return fmt.Errorf("CommitsBetween: %v", err)
}
p := &api.PushPayload{
Ref: "refs/heads/" + pr.BaseBranch,
Before: pr.MergeBase,
After: pr.MergedCommitID,
CompareUrl: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.FullRepoLink()),
Repo: pr.BaseRepo.ComposePayload(),
Pusher: &api.PayloadAuthor{
Name: pr.HeadRepo.MustOwner().DisplayName(),
Email: pr.HeadRepo.MustOwner().Email,
UserName: pr.HeadRepo.MustOwner().Name,
},
Sender: &api.PayloadUser{
UserName: doer.Name,
ID: doer.Id,
AvatarUrl: setting.AppUrl + doer.RelAvatarLink(),
},
}
if err = PrepareWebhooks(pr.BaseRepo, HOOK_EVENT_PUSH, p); err != nil {
return fmt.Errorf("PrepareWebhooks: %v", err)
}
go HookQueue.Add(pr.BaseRepo.ID)
return nil
}
// patchConflicts is a list of conflit description from Git.
@@ -221,6 +256,7 @@ 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.
@@ -244,7 +280,7 @@ func (pr *PullRequest) testPatch() (err error) {
return nil
}
log.Trace("PullRequest[%d].testPatch(patchPath): %s", pr.ID, patchPath)
log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
if err := pr.BaseRepo.UpdateLocalCopy(); err != nil {
return fmt.Errorf("UpdateLocalCopy: %v", err)
@@ -252,7 +288,7 @@ func (pr *PullRequest) testPatch() (err error) {
// Checkout base branch.
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
fmt.Sprintf("PullRequest.Merge(git checkout): %s", pr.BaseRepo.ID),
fmt.Sprintf("PullRequest.Merge (git checkout): %v", pr.BaseRepo.ID),
"git", "checkout", pr.BaseBranch)
if err != nil {
return fmt.Errorf("git checkout: %s", stderr)
@@ -260,12 +296,12 @@ func (pr *PullRequest) testPatch() (err error) {
pr.Status = PULL_REQUEST_STATUS_CHECKING
_, stderr, err = process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
fmt.Sprintf("testPatch(git apply --check): %d", pr.BaseRepo.ID),
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)
log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
@@ -294,7 +330,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
ActUserID: pull.Poster.Id,
ActUserName: pull.Poster.Name,
ActEmail: pull.Poster.Email,
OpType: CREATE_PULL_REQUEST,
OpType: ACTION_CREATE_PULL_REQUEST,
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
@@ -411,23 +447,16 @@ func (pr *PullRequest) UpdatePatch() (err error) {
if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
} else if err = pr.BaseRepo.GetOwner(); err != nil {
return fmt.Errorf("GetOwner: %v", err)
}
headRepoPath, err := pr.HeadRepo.RepoPath()
if err != nil {
return fmt.Errorf("HeadRepo.RepoPath: %v", err)
}
headGitRepo, err := git.OpenRepository(headRepoPath)
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
// Add a temporary remote.
tmpRemote := com.ToStr(time.Now().UnixNano())
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.Owner.Name, pr.BaseRepo.Name)); err != nil {
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name), true); err != nil {
return fmt.Errorf("AddRemote: %v", err)
}
defer func() {
@@ -453,6 +482,37 @@ func (pr *PullRequest) UpdatePatch() (err error) {
return nil
}
// PushToBaseRepo pushes commits from branches of head repository to
// corresponding branches of base repository.
// FIXME: Only push branches that are actually updates?
func (pr *PullRequest) PushToBaseRepo() (err error) {
log.Trace("PushToBaseRepo[%d]: pushing commits to base repo 'refs/pull/%d/head'", pr.BaseRepoID, pr.Index)
headRepoPath := pr.HeadRepo.RepoPath()
headGitRepo, err := git.OpenRepository(headRepoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
return fmt.Errorf("headGitRepo.AddRemote: %v", err)
}
// Make sure to remove the remote even if the push fails
defer headGitRepo.RemoveRemote(tmpRemoteName)
headFile := fmt.Sprintf("refs/pull/%d/head", pr.Index)
// Remove head in case there is a conflict.
os.Remove(path.Join(pr.BaseRepo.RepoPath(), headFile))
if err = git.Push(headRepoPath, tmpRemoteName, fmt.Sprintf("%s:%s", pr.HeadBranch, headFile)); err != nil {
return fmt.Errorf("Push: %v", err)
}
return nil
}
// AddToTaskQueue adds itself to pull request test task queue.
func (pr *PullRequest) AddToTaskQueue() {
go PullRequestQueue.AddFunc(pr.ID, func() {
@@ -469,6 +529,9 @@ func addHeadRepoTasks(prs []*PullRequest) {
if err := pr.UpdatePatch(); err != nil {
log.Error(4, "UpdatePatch: %v", err)
continue
} else if err := pr.PushToBaseRepo(); err != nil {
log.Error(4, "PushToBaseRepo: %v", err)
continue
}
pr.AddToTaskQueue()
@@ -497,6 +560,14 @@ func AddTestPullRequestTask(repoID int64, branch string) {
}
}
func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
pr := PullRequest{
HeadUserName: strings.ToLower(newUserName),
}
_, err := x.Cols("head_user_name").Where("head_user_name = ?", strings.ToLower(oldUserName)).Update(pr)
return err
}
// checkAndUpdateStatus checks if pull request is possible to levaing checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {

View File

@@ -12,7 +12,8 @@ import (
"github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/process"
)
@@ -27,8 +28,8 @@ type Release struct {
Target string
Title string
Sha1 string `xorm:"VARCHAR(40)"`
NumCommits int
NumCommitsBehind int `xorm:"-"`
NumCommits int64
NumCommitsBehind int64 `xorm:"-"`
Note string `xorm:"TEXT"`
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsPrerelease bool
@@ -55,23 +56,23 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
// Only actual create when publish.
if !rel.IsDraft {
if !gitRepo.IsTagExist(rel.TagName) {
commit, err := gitRepo.GetCommitOfBranch(rel.Target)
commit, err := gitRepo.GetBranchCommit(rel.Target)
if err != nil {
return err
return fmt.Errorf("GetBranchCommit: %v", err)
}
if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
return err
}
} else {
commit, err := gitRepo.GetCommitOfTag(rel.TagName)
commit, err := gitRepo.GetTagCommit(rel.TagName)
if err != nil {
return err
return fmt.Errorf("GetTagCommit: %v", err)
}
rel.NumCommits, err = commit.CommitsCount()
if err != nil {
return err
return fmt.Errorf("CommitsCount: %v", err)
}
}
}
@@ -175,12 +176,8 @@ func DeleteReleaseByID(id int64) error {
return fmt.Errorf("GetRepositoryByID: %v", err)
}
repoPath, err := repo.RepoPath()
if err != nil {
return fmt.Errorf("RepoPath: %v", err)
}
_, stderr, err := process.ExecDir(-1, repoPath, fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
_, stderr, err := process.ExecDir(-1, repo.RepoPath(),
fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
"git", "tag", "-d", rel.TagName)
if err != nil && !strings.Contains(stderr, "not found") {
return fmt.Errorf("git tag -d: %v - %s", err, stderr)

File diff suppressed because it is too large Load Diff

57
models/repo_branch.go Normal file
View File

@@ -0,0 +1,57 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"github.com/gogits/git-module"
)
type Branch struct {
Path string
Name string
}
func GetBranchesByPath(path string) ([]*Branch, error) {
gitRepo, err := git.OpenRepository(path)
if err != nil {
return nil, err
}
brs, err := gitRepo.GetBranches()
if err != nil {
return nil, err
}
branches := make([]*Branch, len(brs))
for i := range brs {
branches[i] = &Branch{
Path: path,
Name: brs[i],
}
}
return branches, nil
}
func (repo *Repository) GetBranch(br string) (*Branch, error) {
if !git.IsBranchExist(repo.RepoPath(), br) {
return nil, &ErrBranchNotExist{br}
}
return &Branch{
Path: repo.RepoPath(),
Name: br,
}, nil
}
func (repo *Repository) GetBranches() ([]*Branch, error) {
return GetBranchesByPath(repo.RepoPath())
}
func (br *Branch) GetCommit() (*git.Commit, error) {
gitRepo, err := git.OpenRepository(br.Path)
if err != nil {
return nil, err
}
return gitRepo.GetBranchCommit(br.Name)
}

View File

@@ -0,0 +1,161 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"fmt"
"time"
)
// Collaboration represent the relation between an individual and a repository.
type Collaboration struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"`
Created time.Time `xorm:"CREATED"`
}
func (c *Collaboration) ModeName() string {
switch c.Mode {
case ACCESS_MODE_READ:
return "Read"
case ACCESS_MODE_WRITE:
return "Write"
case ACCESS_MODE_ADMIN:
return "Admin"
}
return "Undefined"
}
// AddCollaborator adds new collaboration relation between an individual and a repository.
func (repo *Repository) AddCollaborator(u *User) error {
collaboration := &Collaboration{
RepoID: repo.ID,
UserID: u.Id,
}
has, err := x.Get(collaboration)
if err != nil {
return err
} else if has {
return nil
}
collaboration.Mode = ACCESS_MODE_WRITE
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if _, err = sess.InsertOne(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)
}
return sess.Commit()
}
func (repo *Repository) getCollaborations(e Engine) ([]*Collaboration, error) {
collaborations := make([]*Collaboration, 0)
return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repo.ID})
}
// Collaborator represents a user with collaboration details.
type Collaborator struct {
*User
Collaboration *Collaboration
}
func (repo *Repository) getCollaborators(e Engine) ([]*Collaborator, error) {
collaborations, err := repo.getCollaborations(e)
if err != nil {
return nil, fmt.Errorf("getCollaborations: %v", err)
}
collaborators := make([]*Collaborator, len(collaborations))
for i, c := range collaborations {
user, err := getUserByID(e, c.UserID)
if err != nil {
return nil, err
}
collaborators[i] = &Collaborator{
User: user,
Collaboration: c,
}
}
return collaborators, nil
}
// GetCollaborators returns the collaborators for a repository
func (repo *Repository) GetCollaborators() ([]*Collaborator, error) {
return repo.getCollaborators(x)
}
// ChangeCollaborationAccessMode sets new access mode for the collaboration.
func (repo *Repository) ChangeCollaborationAccessMode(uid int64, mode AccessMode) error {
// Discard invalid input
if mode <= ACCESS_MODE_NONE || mode > ACCESS_MODE_OWNER {
return nil
}
collaboration := &Collaboration{
RepoID: repo.ID,
UserID: uid,
}
has, err := x.Get(collaboration)
if err != nil {
return fmt.Errorf("get collaboration: %v", err)
} else if !has {
return nil
}
collaboration.Mode = mode
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if _, err = sess.Id(collaboration.ID).AllCols().Update(collaboration); err != nil {
return fmt.Errorf("update collaboration: %v", err)
} else if _, err = sess.Exec("UPDATE access SET mode = ? WHERE user_id = ? AND repo_id = ?", mode, uid, repo.ID); err != nil {
return fmt.Errorf("update access table: %v", err)
}
return sess.Commit()
}
// DeleteCollaboration removes collaboration relation between the user and repository.
func (repo *Repository) DeleteCollaboration(uid int64) (err error) {
collaboration := &Collaboration{
RepoID: repo.ID,
UserID: uid,
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if has, err := sess.Delete(collaboration); err != nil || has == 0 {
return err
} else if err = repo.recalculateAccesses(sess); err != nil {
return err
}
return sess.Commit()
}

View File

@@ -12,6 +12,7 @@ import (
"fmt"
"io"
"io/ioutil"
"math/big"
"os"
"path"
"path/filepath"
@@ -21,6 +22,7 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
"golang.org/x/crypto/ssh"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
@@ -33,24 +35,6 @@ const (
)
var sshOpLocker = sync.Mutex{}
var SSHPath string // SSH directory.
// homeDir returns the home directory of current user.
func homeDir() string {
home, err := com.HomeDir()
if err != nil {
log.Fatal(4, "Fail to get home directory: %v", err)
}
return home
}
func init() {
// Determine and create .ssh path.
SSHPath = filepath.Join(homeDir(), ".ssh")
if err := os.MkdirAll(SSHPath, 0700); err != nil {
log.Fatal(4, "fail to create '%s': %v", SSHPath, err)
}
}
type KeyType int
@@ -95,19 +79,18 @@ func (key *PublicKey) GetAuthorizedString() string {
func extractTypeFromBase64Key(key string) (string, error) {
b, err := base64.StdEncoding.DecodeString(key)
if err != nil || len(b) < 4 {
return "", errors.New("Invalid key format")
return "", fmt.Errorf("Invalid key format: %v", err)
}
keyLength := int(binary.BigEndian.Uint32(b))
if len(b) < 4+keyLength {
return "", errors.New("Invalid key format")
return "", fmt.Errorf("Invalid key format: not enough length")
}
return string(b[4 : 4+keyLength]), nil
}
// parseKeyString parses any key string in openssh or ssh2 format to clean openssh string (rfc4253)
// parseKeyString parses any key string in OpenSSH or SSH2 format to clean OpenSSH string (RFC4253)
func parseKeyString(content string) (string, error) {
// Transform all legal line endings to a single "\n"
s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1)
@@ -170,8 +153,115 @@ func parseKeyString(content string) (string, error) {
return keyType + " " + keyContent + " " + keyComment, nil
}
// writeTmpKeyFile writes key content to a temporary file
// and returns the name of that file, along with any possible errors.
func writeTmpKeyFile(content string) (string, error) {
tmpFile, err := ioutil.TempFile(setting.SSH.KeyTestPath, "gogs_keytest")
if err != nil {
return "", fmt.Errorf("TempFile: %v", err)
}
defer tmpFile.Close()
if _, err = tmpFile.WriteString(content); err != nil {
return "", fmt.Errorf("tmpFile.WriteString: %v", err)
}
return tmpFile.Name(), nil
}
// SSHKeyGenParsePublicKey extracts key type and length using ssh-keygen.
func SSHKeyGenParsePublicKey(key string) (string, int, error) {
// The ssh-keygen in Windows does not print key type, so no need go further.
if setting.IsWindows {
return "", 0, nil
}
tmpName, err := writeTmpKeyFile(key)
if err != nil {
return "", 0, fmt.Errorf("writeTmpKeyFile: %v", err)
}
defer os.Remove(tmpName)
stdout, stderr, err := process.Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName)
if err != nil {
return "", 0, fmt.Errorf("Fail to parse public key: %s - %s", err, stderr)
}
if strings.Contains(stdout, "is not a public key file") {
return "", 0, ErrKeyUnableVerify{stdout}
}
fields := strings.Split(stdout, " ")
if len(fields) < 4 {
return "", 0, fmt.Errorf("Invalid public key line: %s", stdout)
}
keyType := strings.Trim(fields[len(fields)-1], "()\r\n")
return strings.ToLower(keyType), com.StrTo(fields[0]).MustInt(), nil
}
// SSHNativeParsePublicKey extracts the key type and length using the golang SSH library.
// NOTE: ed25519 is not supported.
func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
fields := strings.Fields(keyLine)
if len(fields) < 2 {
return "", 0, fmt.Errorf("not enough fields in public key line: %s", string(keyLine))
}
raw, err := base64.StdEncoding.DecodeString(fields[1])
if err != nil {
return "", 0, err
}
pkey, err := ssh.ParsePublicKey(raw)
if err != nil {
if strings.Contains(err.Error(), "ssh: unknown key algorithm") {
return "", 0, ErrKeyUnableVerify{err.Error()}
}
return "", 0, fmt.Errorf("ssh.ParsePublicKey: %v", err)
}
// The ssh library can parse the key, so next we find out what key exactly we have.
switch pkey.Type() {
case ssh.KeyAlgoDSA:
rawPub := struct {
Name string
P, Q, G, Y *big.Int
}{}
if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
return "", 0, err
}
// as per https://bugzilla.mindrot.org/show_bug.cgi?id=1647 we should never
// see dsa keys != 1024 bit, but as it seems to work, we will not check here
return "dsa", rawPub.P.BitLen(), nil // use P as per crypto/dsa/dsa.go (is L)
case ssh.KeyAlgoRSA:
rawPub := struct {
Name string
E *big.Int
N *big.Int
}{}
if err := ssh.Unmarshal(pkey.Marshal(), &rawPub); err != nil {
return "", 0, err
}
return "rsa", rawPub.N.BitLen(), nil // use N as per crypto/rsa/rsa.go (is bits)
case ssh.KeyAlgoECDSA256:
return "ecdsa", 256, nil
case ssh.KeyAlgoECDSA384:
return "ecdsa", 384, nil
case ssh.KeyAlgoECDSA521:
return "ecdsa", 521, nil
case "ssh-ed25519": // TODO replace with ssh constant when available
return "ed25519", 256, nil
}
return "", 0, fmt.Errorf("Unsupported key length detection for type: %s", pkey.Type())
}
// CheckPublicKeyString checks if the given public key string is recognized by SSH.
//
// The function returns the actual public key line on success.
func CheckPublicKeyString(content string) (_ string, err error) {
if setting.SSH.Disabled {
return "", errors.New("SSH is disabled")
}
content, err = parseKeyString(content)
if err != nil {
return "", err
@@ -182,50 +272,32 @@ func CheckPublicKeyString(content string) (_ string, err error) {
return "", errors.New("only a single line with a single key please")
}
// write the key to a file…
tmpFile, err := ioutil.TempFile(os.TempDir(), "keytest")
if err != nil {
return "", err
}
tmpPath := tmpFile.Name()
defer os.Remove(tmpPath)
tmpFile.WriteString(content)
tmpFile.Close()
// remove any unnecessary whitespace now
content = strings.TrimSpace(content)
// Check if ssh-keygen recognizes its contents.
stdout, stderr, err := process.Exec("CheckPublicKeyString", "ssh-keygen", "-lf", tmpPath)
if err != nil {
return "", errors.New("ssh-keygen -lf: " + stderr)
} else if len(stdout) < 2 {
return "", errors.New("ssh-keygen returned not enough output to evaluate the key: " + stdout)
var (
keyType string
length int
)
if setting.SSH.StartBuiltinServer {
keyType, length, err = SSHNativeParsePublicKey(content)
} else {
keyType, length, err = SSHKeyGenParsePublicKey(content)
}
if err != nil {
return "", fmt.Errorf("ParsePublicKey: %v", err)
}
log.Trace("Key info [native: %v]: %s-%d", setting.SSH.StartBuiltinServer, keyType, length)
// The ssh-keygen in Windows does not print key type, so no need go further.
if setting.IsWindows {
if !setting.SSH.MinimumKeySizeCheck {
return content, nil
}
sshKeygenOutput := strings.Split(stdout, " ")
if len(sshKeygenOutput) < 4 {
return content, ErrKeyUnableVerify{stdout}
if minLen, found := setting.SSH.MinimumKeySizes[keyType]; found && length >= minLen {
return content, nil
} else if found && length < minLen {
return "", fmt.Errorf("Key length is not enough: got %d, needs %d", length, minLen)
}
// Check if key type and key size match.
if !setting.Service.DisableMinimumKeySizeCheck {
keySize := com.StrTo(sshKeygenOutput[0]).MustInt()
if keySize == 0 {
return "", errors.New("cannot get key size of the given key")
}
keyType := strings.Trim(sshKeygenOutput[len(sshKeygenOutput)-1], " ()\n")
if minimumKeySize := setting.Service.MinimumKeySizes[keyType]; minimumKeySize == 0 {
return "", fmt.Errorf("unrecognized public key type: %s", keyType)
} else if keySize < minimumKeySize {
return "", fmt.Errorf("the minimum accepted size of a public key %s is %d", keyType, minimumKeySize)
}
}
return content, nil
return "", fmt.Errorf("Key type is not allowed: %s", keyType)
}
// saveAuthorizedKeyFile writes SSH key content to authorized_keys file.
@@ -233,7 +305,7 @@ func saveAuthorizedKeyFile(keys ...*PublicKey) error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
fpath := filepath.Join(SSHPath, "authorized_keys")
fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
return err
@@ -289,7 +361,7 @@ func addKey(e Engine, key *PublicKey) (err error) {
}
stdout, stderr, err := process.Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath)
if err != nil {
return errors.New("ssh-keygen -lf: " + stderr)
return fmt.Errorf("'ssh-keygen -lf %s' failed with error '%s': %s", tmpPath, err, stderr)
} else if len(stdout) < 2 {
return errors.New("not enough output for calculating fingerprint: " + stdout)
}
@@ -299,27 +371,33 @@ func addKey(e Engine, key *PublicKey) (err error) {
if _, err = e.Insert(key); err != nil {
return err
}
// Don't need to rewrite this file if builtin SSH server is enabled.
if setting.SSH.StartBuiltinServer {
return nil
}
return saveAuthorizedKeyFile(key)
}
// AddPublicKey adds new public key to database and authorized_keys file.
func AddPublicKey(ownerID int64, name, content string) (err error) {
if err = checkKeyContent(content); err != nil {
return err
func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
log.Trace(content)
if err := checkKeyContent(content); err != nil {
return nil, err
}
// Key name of same user cannot be duplicated.
has, err := x.Where("owner_id=? AND name=?", ownerID, name).Get(new(PublicKey))
if err != nil {
return err
return nil, err
} else if has {
return ErrKeyNameAlreadyUsed{ownerID, name}
return nil, ErrKeyNameAlreadyUsed{ownerID, name}
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
return nil, err
}
key := &PublicKey{
@@ -330,10 +408,10 @@ func AddPublicKey(ownerID int64, name, content string) (err error) {
Type: KEY_TYPE_USER,
}
if err = addKey(sess, key); err != nil {
return fmt.Errorf("addKey: %v", err)
return nil, fmt.Errorf("addKey: %v", err)
}
return sess.Commit()
return key, sess.Commit()
}
// GetPublicKeyByID returns public key by given ID.
@@ -414,6 +492,11 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
break
}
}
if !isFound {
log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID)
}
return nil
}
@@ -439,8 +522,13 @@ func deletePublicKey(e *xorm.Session, keyID int64) error {
return err
}
fpath := filepath.Join(SSHPath, "authorized_keys")
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
// Don't need to rewrite this file if builtin SSH server is enabled.
if setting.SSH.StartBuiltinServer {
return nil
}
fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
tmpPath := fpath + ".tmp"
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
return err
} else if err = os.Remove(fpath); err != nil {
@@ -450,12 +538,18 @@ func deletePublicKey(e *xorm.Session, keyID int64) error {
}
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
func DeletePublicKey(id int64) (err error) {
has, err := x.Id(id).Get(new(PublicKey))
func DeletePublicKey(doer *User, id int64) (err error) {
key, err := GetPublicKeyByID(id)
if err != nil {
return err
} else if !has {
return nil
if IsErrKeyNotExist(err) {
return nil
}
return fmt.Errorf("GetPublicKeyByID: %v", err)
}
// Check if user has access to delete this key.
if !doer.IsAdmin && doer.Id != key.OwnerID {
return ErrKeyAccessDenied{doer.Id, key.ID, "public"}
}
sess := x.NewSession()
@@ -476,7 +570,8 @@ func RewriteAllPublicKeys() error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
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)
if err != nil {
return err
@@ -492,7 +587,6 @@ func RewriteAllPublicKeys() error {
return err
}
fpath := filepath.Join(SSHPath, "authorized_keys")
if com.IsExist(fpath) {
if err = os.Remove(fpath); err != nil {
return err
@@ -656,13 +750,27 @@ func UpdateDeployKey(key *DeployKey) error {
}
// DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed.
func DeleteDeployKey(id int64) error {
key := &DeployKey{ID: id}
has, err := x.Id(key.ID).Get(key)
func DeleteDeployKey(doer *User, id int64) error {
key, err := GetDeployKeyByID(id)
if err != nil {
return err
} else if !has {
return nil
if IsErrDeployKeyNotExist(err) {
return nil
}
return fmt.Errorf("GetDeployKeyByID: %v", err)
}
// Check if user has access to delete this key.
if !doer.IsAdmin {
repo, err := GetRepositoryByID(key.RepoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID: %v", err)
}
yes, err := HasAccess(doer, repo, ACCESS_MODE_ADMIN)
if err != nil {
return fmt.Errorf("HasAccess: %v", err)
} else if !yes {
return ErrKeyAccessDenied{doer.Id, key.ID, "deploy"}
}
}
sess := x.NewSession()
@@ -676,7 +784,7 @@ func DeleteDeployKey(id int64) error {
}
// Check if this is the last reference to same key content.
has, err = sess.Where("key_id=?", key.KeyID).Get(new(DeployKey))
has, err := sess.Where("key_id=?", key.KeyID).Get(new(DeployKey))
if err != nil {
return err
} else if !has {

45
models/ssh_key_test.go Normal file
View File

@@ -0,0 +1,45 @@
package models
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/gogits/gogs/modules/setting"
)
func init() {
setting.NewContext()
}
func Test_SSHParsePublicKey(t *testing.T) {
testKeys := map[string]struct {
typeName string
length int
content string
}{
"dsa-1024": {"dsa", 1024, "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"},
"rsa-1024": {"rsa", 1024, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
"rsa-2048": {"rsa", 2048, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"},
"ecdsa-256": {"ecdsa", 256, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"},
"ecdsa-384": {"ecdsa", 384, "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBINmioV+XRX1Fm9Qk2ehHXJ2tfVxW30ypUWZw670Zyq5GQfBAH6xjygRsJ5wWsHXBsGYgFUXIHvMKVAG1tpw7s6ax9oA+dJOJ7tj+vhn8joFqT+sg3LYHgZkHrfqryRasQ== nocomment"},
"ecdsa-521": {"ecdsa", 521, "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACGt3UG3EzRwNOI17QR84l6PgiAcvCE7v6aXPj/SC6UWKg4EL8vW9ZBcdYL9wzs4FZXh4MOV8jAzu3KRWNTwb4k2wFNUpGOt7l28MztFFEtH5BDDrtAJSPENPy8pvPLMfnPg5NhvWycqIBzNcHipem5wSJFN5PdpNOC2xMrPWKNqj+ZjQ== nocomment"},
}
Convey("Parse public keys in both native and ssh-keygen", t, func() {
for name, key := range testKeys {
fmt.Println("\nTesting key:", name)
keyTypeN, lengthN, errN := SSHNativeParsePublicKey(key.content)
So(errN, ShouldBeNil)
So(keyTypeN, ShouldEqual, key.typeName)
So(lengthN, ShouldEqual, key.length)
keyTypeK, lengthK, errK := SSHKeyGenParsePublicKey(key.content)
So(errK, ShouldBeNil)
So(keyTypeK, ShouldEqual, key.typeName)
So(lengthK, ShouldEqual, key.length)
}
})
}

View File

@@ -7,8 +7,9 @@ package models
import (
"time"
gouuid "github.com/satori/go.uuid"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/uuid"
)
// AccessToken represents a personal access token.
@@ -25,7 +26,7 @@ type AccessToken struct {
// NewAccessToken creates new access token.
func NewAccessToken(t *AccessToken) error {
t.Sha1 = base.EncodeSha1(uuid.NewV4().String())
t.Sha1 = base.EncodeSha1(gouuid.NewV4().String())
_, err := x.Insert(t)
return err
}
@@ -57,8 +58,8 @@ func ListAccessTokens(uid int64) ([]*AccessToken, error) {
return tokens, nil
}
// UpdateAccessToekn updates information of access token.
func UpdateAccessToekn(t *AccessToken) error {
// UpdateAccessToken updates information of access token.
func UpdateAccessToken(t *AccessToken) error {
_, err := x.Id(t.ID).AllCols().Update(t)
return err
}

View File

@@ -10,7 +10,8 @@ import (
"os/exec"
"strings"
"github.com/gogits/gogs/modules/git"
git "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/log"
)
@@ -46,92 +47,7 @@ func DeleteUpdateTaskByUUID(uuid string) error {
return err
}
func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
isNew := strings.HasPrefix(oldCommitID, "0000000")
if isNew &&
strings.HasPrefix(newCommitID, "0000000") {
return fmt.Errorf("old rev and new rev both 000000")
}
f := RepoPath(repoUserName, repoName)
gitUpdate := exec.Command("git", "update-server-info")
gitUpdate.Dir = f
gitUpdate.Run()
isDel := strings.HasPrefix(newCommitID, "0000000")
if isDel {
log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userID)
return nil
}
gitRepo, err := git.OpenRepository(f)
if err != nil {
return fmt.Errorf("runUpdate.Open repoId: %v", err)
}
user, err := GetUserByName(repoUserName)
if err != nil {
return fmt.Errorf("runUpdate.GetUserByName: %v", err)
}
repo, err := GetRepositoryByName(user.Id, repoName)
if err != nil {
return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
}
// Push tags.
if strings.HasPrefix(refName, "refs/tags/") {
tagName := git.RefEndName(refName)
tag, err := gitRepo.GetTag(tagName)
if err != nil {
log.GitLogger.Fatal(4, "runUpdate.GetTag: %v", err)
}
var actEmail string
if tag.Tagger != nil {
actEmail = tag.Tagger.Email
} else {
cmt, err := tag.Commit()
if err != nil {
log.GitLogger.Fatal(4, "runUpdate.GetTag Commit: %v", err)
}
actEmail = cmt.Committer.Email
}
commit := &PushCommits{}
if err = CommitRepoAction(userID, user.Id, userName, actEmail,
repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil {
log.GitLogger.Fatal(4, "CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
}
return err
}
newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
}
// Push new branch.
var l *list.List
if isNew {
l, err = newCommit.CommitsBefore()
if err != nil {
return fmt.Errorf("CommitsBefore: %v", err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(oldCommitID)
if err != nil {
return fmt.Errorf("CommitsBeforeUntil: %v", err)
}
}
if err != nil {
return fmt.Errorf("runUpdate.Commit repoId: %v", err)
}
// Push commits.
func ListToPushCommits(l *list.List) *PushCommits {
commits := make([]*PushCommit, 0)
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
@@ -146,10 +62,107 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
commit.Author.Name,
})
}
return &PushCommits{l.Len(), commits, "", nil}
}
if err = CommitRepoAction(userID, user.Id, userName, actEmail,
repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
type PushUpdateOptions struct {
RefName string
OldCommitID string
NewCommitID string
PusherID int64
PusherName string
RepoUserName string
RepoName string
}
// PushUpdate must be called for any push actions in order to
// generates necessary push action history feeds.
func PushUpdate(opts PushUpdateOptions) (err error) {
isNewRef := strings.HasPrefix(opts.OldCommitID, "0000000")
isDelRef := strings.HasPrefix(opts.NewCommitID, "0000000")
if isNewRef && isDelRef {
return fmt.Errorf("Old and new revisions both start with 000000")
}
repoPath := RepoPath(opts.RepoUserName, opts.RepoName)
gitUpdate := exec.Command("git", "update-server-info")
gitUpdate.Dir = repoPath
if err = gitUpdate.Run(); err != nil {
return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
}
if isDelRef {
log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d",
opts.RefName, opts.RepoUserName, opts.RepoName, opts.PusherName)
return nil
}
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
repoUser, err := GetUserByName(opts.RepoUserName)
if err != nil {
return fmt.Errorf("GetUserByName: %v", err)
}
repo, err := GetRepositoryByName(repoUser.Id, opts.RepoName)
if err != nil {
return fmt.Errorf("GetRepositoryByName: %v", err)
}
// Push tags.
if strings.HasPrefix(opts.RefName, "refs/tags/") {
tag, err := gitRepo.GetTag(git.RefEndName(opts.RefName))
if err != nil {
return fmt.Errorf("gitRepo.GetTag: %v", err)
}
// When tagger isn't available, fall back to get committer email.
var actEmail string
if tag.Tagger != nil {
actEmail = tag.Tagger.Email
} else {
cmt, err := tag.Commit()
if err != nil {
return fmt.Errorf("tag.Commit: %v", err)
}
actEmail = cmt.Committer.Email
}
commit := &PushCommits{}
if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, actEmail,
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, commit, opts.OldCommitID, opts.NewCommitID); err != nil {
return fmt.Errorf("CommitRepoAction (tag): %v", err)
}
return err
}
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)
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
}
}
if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, repoUser.Email,
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, ListToPushCommits(l),
opts.OldCommitID, opts.NewCommitID); err != nil {
return fmt.Errorf("CommitRepoAction (branch): %v", err)
}
return nil
}

View File

@@ -16,7 +16,6 @@ import (
_ "image/jpeg"
"image/png"
"os"
"path"
"path/filepath"
"strings"
"time"
@@ -25,10 +24,12 @@ import (
"github.com/go-xorm/xorm"
"github.com/nfnt/resize"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/setting"
)
@@ -55,7 +56,7 @@ type User struct {
LowerName string `xorm:"UNIQUE NOT NULL"`
Name string `xorm:"UNIQUE NOT NULL"`
FullName string
// Email is the primary email address (to be used for communication).
// Email is the primary email address (to be used for communication)
Email string `xorm:"NOT NULL"`
Passwd string `xorm:"NOT NULL"`
LoginType LoginType
@@ -74,25 +75,27 @@ type User struct {
// Remember visibility choice for convenience, true for private
LastRepoVisibility bool
// Maximum repository creation limit, -1 means use gloabl default
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
// Permissions.
// Permissions
IsActive bool
IsAdmin bool
AllowGitHook bool
AllowImportLocal bool // Allow migrate repository by local path
// Avatar.
// Avatar
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
AvatarEmail string `xorm:"NOT NULL"`
UseCustomAvatar bool
// Counters.
NumFollowers int
NumFollowings int
NumStars int
NumRepos int
// Counters
NumFollowers int
NumFollowing int `xorm:"NOT NULL DEFAULT 0"`
NumStars int
NumRepos int
// For organization.
// For organization
Description string
NumTeams int
NumMembers int
@@ -100,21 +103,49 @@ type User struct {
Members []*User `xorm:"-"`
}
func (u *User) BeforeUpdate() {
if u.MaxRepoCreation < -1 {
u.MaxRepoCreation = -1
}
}
func (u *User) AfterSet(colName string, _ xorm.Cell) {
switch colName {
case "full_name":
u.FullName = base.Sanitizer.Sanitize(u.FullName)
u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
case "created":
u.Created = regulateTimeZone(u.Created)
}
}
// returns true if user login type is LOGIN_PLAIN.
func (u *User) IsLocal() bool {
return u.LoginType <= LOGIN_PLAIN
}
// HasForkedRepo checks if user has already forked a repository with given ID.
func (u *User) HasForkedRepo(repoID int64) bool {
_, has := HasForkedRepo(u.Id, repoID)
return has
}
func (u *User) RepoCreationNum() int {
if u.MaxRepoCreation <= -1 {
return setting.Repository.MaxCreationLimit
}
return u.MaxRepoCreation
}
func (u *User) CanCreateRepo() bool {
if u.MaxRepoCreation <= -1 {
if setting.Repository.MaxCreationLimit <= -1 {
return true
}
return u.NumRepos < setting.Repository.MaxCreationLimit
}
return u.NumRepos < u.MaxRepoCreation
}
// CanEditGitHook returns true if user can edit Git hooks.
func (u *User) CanEditGitHook() bool {
return u.IsAdmin || u.AllowGitHook
@@ -180,7 +211,7 @@ func (u *User) GenerateRandomAvatar() error {
if err != nil {
return fmt.Errorf("RandomImage: %v", err)
}
if err = os.MkdirAll(path.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
if err = os.MkdirAll(filepath.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
return fmt.Errorf("MkdirAll: %v", err)
}
fw, err := os.Create(u.CustomAvatarPath())
@@ -217,8 +248,6 @@ func (u *User) RelAvatarLink() string {
}
return "/avatars/" + com.ToStr(u.Id)
case setting.Service.EnableCacheAvatar:
return "/avatar/" + u.Avatar
}
return setting.GravatarSource + u.Avatar
}
@@ -232,6 +261,34 @@ func (u *User) AvatarLink() string {
return link
}
// User.GetFollwoers returns range of user's followers.
func (u *User) GetFollowers(page int) ([]*User, error) {
users := make([]*User, 0, ItemsPerPage)
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.follow_id=?", u.Id)
if setting.UsePostgreSQL {
sess = sess.Join("LEFT", "follow", `"user".id=follow.user_id`)
} else {
sess = sess.Join("LEFT", "follow", "user.id=follow.user_id")
}
return users, sess.Find(&users)
}
func (u *User) IsFollowing(followID int64) bool {
return IsFollowing(u.Id, followID)
}
// GetFollowing returns range of user's following.
func (u *User) GetFollowing(page int) ([]*User, error) {
users := make([]*User, 0, ItemsPerPage)
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.user_id=?", u.Id)
if setting.UsePostgreSQL {
sess = sess.Join("LEFT", "follow", `"user".id=follow.follow_id`)
} else {
sess = sess.Join("LEFT", "follow", "user.id=follow.follow_id")
}
return users, sess.Find(&users)
}
// NewGitSig generates and returns the signature of given user.
func (u *User) NewGitSig() *git.Signature {
return &git.Signature{
@@ -289,23 +346,34 @@ func (u *User) UploadAvatar(data []byte) error {
return sess.Commit()
}
// DeleteAvatar deletes the user's custom avatar.
func (u *User) DeleteAvatar() error {
log.Trace("DeleteAvatar[%d]: %s", u.Id, u.CustomAvatarPath())
os.Remove(u.CustomAvatarPath())
u.UseCustomAvatar = false
if err := UpdateUser(u); err != nil {
return fmt.Errorf("UpdateUser: %v", err)
}
return nil
}
// IsAdminOfRepo returns true if user has admin or higher access of repository.
func (u *User) IsAdminOfRepo(repo *Repository) bool {
if err := repo.GetOwner(); err != nil {
log.Error(3, "GetOwner: %v", err)
return false
has, err := HasAccess(u, repo, ACCESS_MODE_ADMIN)
if err != nil {
log.Error(3, "HasAccess: %v", err)
}
return has
}
if repo.Owner.IsOrganization() {
has, err := HasAccess(u, repo, ACCESS_MODE_ADMIN)
if err != nil {
log.Error(3, "HasAccess: %v", err)
return false
}
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)
if err != nil {
log.Error(3, "HasAccess: %v", err)
}
return repo.IsOwnedBy(u.Id)
return has
}
// IsOrganization returns true if user is actually a organization.
@@ -345,8 +413,8 @@ func (u *User) GetOwnedOrganizations() (err error) {
}
// GetOrganizations returns all organizations that user belongs to.
func (u *User) GetOrganizations() error {
ous, err := GetOrgUsersByUserId(u.Id)
func (u *User) GetOrganizations(all bool) error {
ous, err := GetOrgUsersByUserID(u.Id, all)
if err != nil {
return err
}
@@ -370,13 +438,8 @@ func (u *User) DisplayName() string {
return u.Name
}
// ShortName returns shorted user name with given maximum length,
// it adds "..." at the end if user name has more length than maximum.
func (u *User) ShortName(length int) string {
if len(u.Name) < length {
return u.Name
}
return u.Name[:length] + "..."
return base.EllipsisString(u.Name, length)
}
// IsUserExist checks if given user name exist,
@@ -440,10 +503,11 @@ func CreateUser(u *User) (err error) {
u.LowerName = strings.ToLower(u.Name)
u.AvatarEmail = u.Email
u.Avatar = avatar.HashEmail(u.AvatarEmail)
u.Avatar = base.HashEmail(u.AvatarEmail)
u.Rands = GetUserSalt()
u.Salt = GetUserSalt()
u.EncodePasswd()
u.MaxRepoCreation = -1
sess := x.NewSession()
defer sess.Close()
@@ -544,11 +608,24 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return ErrUserAlreadyExist{newUserName}
}
return os.Rename(UserPath(u.LowerName), UserPath(newUserName))
if err = ChangeUsernameInPullRequests(u.Name, newUserName); err != nil {
return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
}
// Delete all local copies of repository wiki that user owns.
if err = x.Where("owner_id=?", u.Id).Iterate(new(Repository), func(idx int, bean interface{}) error {
repo := bean.(*Repository)
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
return nil
}); err != nil {
return fmt.Errorf("Delete repository wiki local copy: %v", err)
}
return os.Rename(UserPath(u.Name), UserPath(newUserName))
}
func updateUser(e Engine, u *User) error {
// Organization does not need e-mail.
// Organization does not need email
if !u.IsOrganization() {
u.Email = strings.ToLower(u.Email)
has, err := e.Where("id!=?", u.Id).And("type=?", u.Type).And("email=?", u.Email).Get(new(User))
@@ -561,22 +638,15 @@ func updateUser(e Engine, u *User) error {
if len(u.AvatarEmail) == 0 {
u.AvatarEmail = u.Email
}
u.Avatar = avatar.HashEmail(u.AvatarEmail)
u.Avatar = base.HashEmail(u.AvatarEmail)
}
u.LowerName = strings.ToLower(u.Name)
u.Location = base.TruncateString(u.Location, 255)
u.Website = base.TruncateString(u.Website, 255)
u.Description = base.TruncateString(u.Description, 255)
if len(u.Location) > 255 {
u.Location = u.Location[:255]
}
if len(u.Website) > 255 {
u.Website = u.Website[:255]
}
if len(u.Description) > 255 {
u.Description = u.Description[:255]
}
u.FullName = base.Sanitizer.Sanitize(u.FullName)
u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
_, err := e.Id(u.Id).AllCols().Update(u)
return err
}
@@ -664,7 +734,7 @@ func deleteUser(e *xorm.Session, u *User) error {
&IssueUser{UID: u.Id},
&EmailAddress{UID: u.Id},
); err != nil {
return fmt.Errorf("deleteUser: %v", err)
return fmt.Errorf("deleteBeans: %v", err)
}
// ***** START: PublicKey *****
@@ -856,7 +926,7 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
}
func AddEmailAddress(email *EmailAddress) error {
email.Email = strings.ToLower(email.Email)
email.Email = strings.ToLower(strings.TrimSpace(email.Email))
used, err := IsEmailUsed(email.Email)
if err != nil {
return err
@@ -868,6 +938,29 @@ func AddEmailAddress(email *EmailAddress) error {
return err
}
func AddEmailAddresses(emails []*EmailAddress) error {
if len(emails) == 0 {
return nil
}
// Check if any of them has been used
for i := range emails {
emails[i].Email = strings.ToLower(strings.TrimSpace(emails[i].Email))
used, err := IsEmailUsed(emails[i].Email)
if err != nil {
return err
} else if used {
return ErrEmailAlreadyUsed{emails[i].Email}
}
}
if _, err := x.Insert(emails); err != nil {
return fmt.Errorf("Insert: %v", err)
}
return nil
}
func (email *EmailAddress) Activate() error {
email.IsActivated = true
if _, err := x.Id(email.ID).AllCols().Update(email); err != nil {
@@ -882,20 +975,23 @@ func (email *EmailAddress) Activate() error {
}
}
func DeleteEmailAddress(email *EmailAddress) error {
has, err := x.Get(email)
if err != nil {
return err
} else if !has {
return ErrEmailNotExist
func DeleteEmailAddress(email *EmailAddress) (err error) {
if email.ID > 0 {
_, err = x.Id(email.ID).Delete(new(EmailAddress))
} else {
_, err = x.Where("email=?", email.Email).Delete(new(EmailAddress))
}
return err
}
if _, err = x.Id(email.ID).Delete(email); err != nil {
return err
func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
for i := range emails {
if err = DeleteEmailAddress(emails[i]); err != nil {
return err
}
}
return nil
}
func MakeEmailPrimary(email *EmailAddress) error {
@@ -1019,100 +1115,73 @@ func SearchUserByName(opt SearchOption) (us []*User, err error) {
return us, err
}
// Follow is connection request for receiving user notification.
// ___________ .__ .__
// \_ _____/___ | | | | ______ _ __
// | __)/ _ \| | | | / _ \ \/ \/ /
// | \( <_> ) |_| |_( <_> ) /
// \___ / \____/|____/____/\____/ \/\_/
// \/
// Follow represents relations of user and his/her followers.
type Follow struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"UNIQUE(follow)"`
FollowID int64 `xorm:"UNIQUE(follow)"`
}
func IsFollowing(userID, followID int64) bool {
has, _ := x.Get(&Follow{UserID: userID, FollowID: followID})
return has
}
// FollowUser marks someone be another's follower.
func FollowUser(userId int64, followId int64) (err error) {
func FollowUser(userID, followID int64) (err error) {
if userID == followID || IsFollowing(userID, followID) {
return nil
}
sess := x.NewSession()
defer sess.Close()
sess.Begin()
if _, err = sess.Insert(&Follow{UserID: userId, FollowID: followId}); err != nil {
sess.Rollback()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?"
if _, err = sess.Exec(rawSql, followId); err != nil {
sess.Rollback()
if _, err = sess.Insert(&Follow{UserID: userID, FollowID: followID}); err != nil {
return err
}
rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?"
if _, err = sess.Exec(rawSql, userId); err != nil {
sess.Rollback()
if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", followID); err != nil {
return err
}
if _, err = sess.Exec("UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", userID); err != nil {
return err
}
return sess.Commit()
}
// UnFollowUser unmarks someone be another's follower.
func UnFollowUser(userId int64, unFollowId int64) (err error) {
session := x.NewSession()
defer session.Close()
session.Begin()
// UnfollowUser unmarks someone be another's follower.
func UnfollowUser(userID, followID int64) (err error) {
if userID == followID || !IsFollowing(userID, followID) {
return nil
}
if _, err = session.Delete(&Follow{UserID: userId, FollowID: unFollowId}); err != nil {
session.Rollback()
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?"
if _, err = session.Exec(rawSql, unFollowId); err != nil {
session.Rollback()
if _, err = sess.Delete(&Follow{UserID: userID, FollowID: followID}); err != nil {
return err
}
rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?"
if _, err = session.Exec(rawSql, userId); err != nil {
session.Rollback()
if _, err = sess.Exec("UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil {
return err
}
return session.Commit()
}
func UpdateMentions(userNames []string, issueId int64) error {
for i := range userNames {
userNames[i] = strings.ToLower(userNames[i])
}
users := make([]*User, 0, len(userNames))
if err := x.Where("lower_name IN (?)", strings.Join(userNames, "\",\"")).OrderBy("lower_name ASC").Find(&users); err != nil {
return err
}
ids := make([]int64, 0, len(userNames))
for _, user := range users {
ids = append(ids, user.Id)
if !user.IsOrganization() {
continue
}
if user.NumMembers == 0 {
continue
}
tempIds := make([]int64, 0, user.NumMembers)
orgUsers, err := GetOrgUsersByOrgId(user.Id)
if err != nil {
return err
}
for _, orgUser := range orgUsers {
tempIds = append(tempIds, orgUser.ID)
}
ids = append(ids, tempIds...)
}
if err := UpdateIssueUsersByMentions(ids, issueId); err != nil {
return err
}
return nil
if _, err = sess.Exec("UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil {
return err
}
return sess.Commit()
}

View File

@@ -15,13 +15,13 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
gouuid "github.com/satori/go.uuid"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/uuid"
)
type HookContentType int
@@ -285,7 +285,7 @@ type HookTask struct {
HookID int64
UUID string
Type HookTaskType
URL string
URL string `xorm:"TEXT"`
api.Payloader `xorm:"-"`
PayloadContent string `xorm:"TEXT"`
ContentType HookContentType
@@ -335,7 +335,7 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) {
t.ResponseInfo = &HookResponse{}
if err = json.Unmarshal([]byte(t.ResponseContent), t.ResponseInfo); err != nil {
log.Error(3, "Unmarshal[%d]: %v", t.ID, err)
log.Error(3, "Unmarshal [%d]: %v", t.ID, err)
}
}
}
@@ -343,7 +343,7 @@ func (t *HookTask) AfterSet(colName string, _ xorm.Cell) {
func (t *HookTask) MarshalJSON(v interface{}) string {
p, err := json.Marshal(v)
if err != nil {
log.Error(3, "Marshal[%d]: %v", t.ID, err)
log.Error(3, "Marshal [%d]: %v", t.ID, err)
}
return string(p)
}
@@ -361,7 +361,7 @@ func CreateHookTask(t *HookTask) error {
if err != nil {
return err
}
t.UUID = uuid.NewV4().String()
t.UUID = gouuid.NewV4().String()
t.PayloadContent = string(data)
_, err = x.Insert(t)
return err
@@ -398,6 +398,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
return nil
}
var payloader api.Payloader
for _, w := range ws {
switch event {
case HOOK_EVENT_CREATE:
@@ -410,14 +411,16 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
}
}
// Use separate objects so modifcations won't be made on payload on non-Gogs type hooks.
switch w.HookTaskType {
case SLACK:
p, err = GetSlackPayload(p, event, w.Meta)
payloader, err = GetSlackPayload(p, event, w.Meta)
if err != nil {
return fmt.Errorf("GetSlackPayload: %v", err)
}
default:
p.SetSecret(w.Secret)
payloader = p
}
if err = CreateHookTask(&HookTask{
@@ -425,7 +428,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
HookID: w.ID,
Type: w.HookTaskType,
URL: w.URL,
Payloader: p,
Payloader: payloader,
ContentType: w.ContentType,
EventType: HOOK_EVENT_PUSH,
IsSSL: w.IsSSL,
@@ -526,6 +529,8 @@ func (t *HookTask) deliver() {
t.Delivered = time.Now().UTC().UnixNano()
if t.IsSucceed {
log.Trace("Hook delivered: %s", t.UUID)
} else {
log.Trace("Hook delivery failed: %s", t.UUID)
}
// Update webhook last delivery status.
@@ -590,24 +595,24 @@ func DeliverHooks() {
// Update hook task status.
for _, t := range tasks {
if err := UpdateHookTask(t); err != nil {
log.Error(4, "UpdateHookTask(%d): %v", t.ID, err)
log.Error(4, "UpdateHookTask [%d]: %v", t.ID, err)
}
}
// Start listening on new hook requests.
for repoID := range HookQueue.Queue() {
log.Trace("DeliverHooks[%v]: processing delivery hooks", repoID)
log.Trace("DeliverHooks [%v]: processing delivery hooks", repoID)
HookQueue.Remove(repoID)
tasks = make([]*HookTask, 0, 5)
if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
log.Error(4, "Get repository(%d) hook tasks: %v", repoID, err)
log.Error(4, "Get repository [%d] hook tasks: %v", repoID, err)
continue
}
for _, t := range tasks {
t.deliver()
if err := UpdateHookTask(t); err != nil {
log.Error(4, "UpdateHookTask[%d]: %v", t.ID, err)
log.Error(4, "UpdateHookTask [%d]: %v", t.ID, err)
continue
}
}

View File

@@ -10,9 +10,8 @@ import (
"fmt"
"strings"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/git"
)
type SlackMeta struct {
@@ -33,8 +32,9 @@ type SlackPayload struct {
}
type SlackAttachment struct {
Color string `json:"color"`
Text string `json:"text"`
Fallback string `json:"fallback"`
Color string `json:"color"`
Text string `json:"text"`
}
func (p *SlackPayload) SetSecret(_ string) {}
@@ -82,19 +82,19 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
// n new commits
var (
branchName = git.RefEndName(p.Ref)
commitDesc string
commitString string
)
if len(p.Commits) == 1 {
commitString = "1 new commit"
if len(p.CompareUrl) > 0 {
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
}
commitDesc = "1 new commit"
} else {
commitString = fmt.Sprintf("%d new commits", len(p.Commits))
if p.CompareUrl != "" {
commitString = SlackLinkFormatter(p.CompareUrl, commitString)
}
commitDesc = fmt.Sprintf("%d new commits", len(p.Commits))
}
if len(p.CompareUrl) > 0 {
commitString = SlackLinkFormatter(p.CompareUrl, commitDesc)
} else {
commitString = commitDesc
}
repoLink := SlackLinkFormatter(p.Repo.URL, p.Repo.Name)
@@ -111,7 +111,10 @@ func getSlackPushPayload(p *api.PushPayload, slack *SlackMeta) (*SlackPayload, e
}
}
slackAttachments := []SlackAttachment{{Color: slack.Color, Text: attachmentText}}
slackAttachments := []SlackAttachment{{
Color: slack.Color,
Text: attachmentText,
}}
return &SlackPayload{
Channel: slack.Channel,

216
models/wiki.go Normal file
View File

@@ -0,0 +1,216 @@
// Copyright 2015 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 models
import (
"fmt"
"io/ioutil"
"net/url"
"os"
"path"
"path/filepath"
"strings"
"sync"
"github.com/Unknwon/com"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/setting"
)
// workingPool represents a pool of working status which makes sure
// that only one instance of same task is performing at a time.
// However, different type of tasks can performing at the same time.
type workingPool struct {
lock sync.Mutex
pool map[string]*sync.Mutex
count map[string]int
}
// CheckIn checks in a task and waits if others are running.
func (p *workingPool) CheckIn(name string) {
p.lock.Lock()
lock, has := p.pool[name]
if !has {
lock = &sync.Mutex{}
p.pool[name] = lock
}
p.count[name]++
p.lock.Unlock()
lock.Lock()
}
// CheckOut checks out a task to let other tasks run.
func (p *workingPool) CheckOut(name string) {
p.lock.Lock()
defer p.lock.Unlock()
p.pool[name].Unlock()
if p.count[name] == 1 {
delete(p.pool, name)
delete(p.count, name)
} else {
p.count[name]--
}
}
var wikiWorkingPool = &workingPool{
pool: make(map[string]*sync.Mutex),
count: make(map[string]int),
}
// ToWikiPageURL formats a string to corresponding wiki URL name.
func ToWikiPageURL(name string) string {
return url.QueryEscape(strings.Replace(name, " ", "-", -1))
}
// ToWikiPageName formats a URL back to corresponding wiki page name.
func ToWikiPageName(urlString string) string {
name, _ := url.QueryUnescape(strings.Replace(urlString, "-", " ", -1))
return name
}
// WikiCloneLink returns clone URLs of repository wiki.
func (repo *Repository) WikiCloneLink() (cl *CloneLink) {
return repo.cloneLink(true)
}
// WikiPath returns wiki data path by given user and repository name.
func WikiPath(userName, repoName string) string {
return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".wiki.git")
}
func (repo *Repository) WikiPath() string {
return WikiPath(repo.MustOwner().Name, repo.Name)
}
// HasWiki returns true if repository has wiki.
func (repo *Repository) HasWiki() bool {
return com.IsDir(repo.WikiPath())
}
// InitWiki initializes a wiki for repository,
// it does nothing when repository already has wiki.
func (repo *Repository) InitWiki() error {
if repo.HasWiki() {
return nil
}
if err := git.InitRepository(repo.WikiPath(), true); err != nil {
return fmt.Errorf("InitRepository: %v", err)
}
return nil
}
func (repo *Repository) LocalWikiPath() string {
return path.Join(setting.AppDataPath, "tmp/local-wiki", com.ToStr(repo.ID))
}
// UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
func (repo *Repository) UpdateLocalWiki() error {
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath())
}
// discardLocalWikiChanges discards local commits make sure
// it is even to remote branch when local copy exists.
func discardLocalWikiChanges(localPath string) error {
if !com.IsExist(localPath) {
return nil
}
// No need to check if nothing in the repository.
if !git.IsBranchExist(localPath, "master") {
return nil
}
if err := git.ResetHEAD(localPath, true, "origin/master"); err != nil {
return fmt.Errorf("ResetHEAD: %v", err)
}
return nil
}
// updateWikiPage adds new page to repository wiki.
func (repo *Repository) updateWikiPage(doer *User, oldTitle, title, content, message string, isNew bool) (err error) {
wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = repo.InitWiki(); err != nil {
return fmt.Errorf("InitWiki: %v", err)
}
localPath := repo.LocalWikiPath()
if err = discardLocalWikiChanges(localPath); err != nil {
return fmt.Errorf("discardLocalWikiChanges: %v", err)
} else if err = repo.UpdateLocalWiki(); err != nil {
return fmt.Errorf("UpdateLocalWiki: %v", err)
}
title = ToWikiPageName(strings.Replace(title, "/", " ", -1))
filename := path.Join(localPath, title+".md")
// If not a new file, show perform update not create.
if isNew {
if com.IsExist(filename) {
return ErrWikiAlreadyExist{filename}
}
} else {
os.Remove(path.Join(localPath, oldTitle+".md"))
}
if err = ioutil.WriteFile(filename, []byte(content), 0666); err != nil {
return fmt.Errorf("WriteFile: %v", err)
}
if len(message) == 0 {
message = "Update page '" + title + "'"
}
if err = git.AddChanges(localPath, true); err != nil {
return fmt.Errorf("AddChanges: %v", err)
} else if err = git.CommitChanges(localPath, message, doer.NewGitSig()); err != nil {
return fmt.Errorf("CommitChanges: %v", err)
} else if err = git.Push(localPath, "origin", "master"); err != nil {
return fmt.Errorf("Push: %v", err)
}
return nil
}
func (repo *Repository) AddWikiPage(doer *User, title, content, message string) error {
return repo.updateWikiPage(doer, "", title, content, message, true)
}
func (repo *Repository) EditWikiPage(doer *User, oldTitle, title, content, message string) error {
return repo.updateWikiPage(doer, oldTitle, title, content, message, false)
}
func (repo *Repository) DeleteWikiPage(doer *User, title string) (err error) {
wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
localPath := repo.LocalWikiPath()
if err = discardLocalWikiChanges(localPath); err != nil {
return fmt.Errorf("discardLocalWikiChanges: %v", err)
} else if err = repo.UpdateLocalWiki(); err != nil {
return fmt.Errorf("UpdateLocalWiki: %v", err)
}
title = ToWikiPageName(strings.Replace(title, "/", " ", -1))
filename := path.Join(localPath, title+".md")
os.Remove(filename)
message := "Delete page '" + title + "'"
if err = git.AddChanges(localPath, true); err != nil {
return fmt.Errorf("AddChanges: %v", err)
} else if err = git.CommitChanges(localPath, message, doer.NewGitSig()); err != nil {
return fmt.Errorf("CommitChanges: %v", err)
} else if err = git.Push(localPath, "origin", "master"); err != nil {
return fmt.Errorf("Push: %v", err)
}
return nil
}

View File

@@ -1,27 +0,0 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -1,11 +0,0 @@
# Copyright 2009 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
include $(GOROOT)/src/Make.inc
TARG=github.com/mmitton/asn1-ber
GOFILES=\
ber.go\
include $(GOROOT)/src/Make.pkg

View File

@@ -1,14 +0,0 @@
ASN1 BER Encoding / Decoding Library for the GO programming language.
Required Librarys:
None
Working:
Very basic encoding / decoding needed for LDAP protocol
Tests Implemented:
None
TODO:
Fix all encoding / decoding to conform to ASN1 BER spec
Implement Tests / Benchmarks

View File

@@ -1,497 +0,0 @@
package ber
import (
"bytes"
"fmt"
"io"
"reflect"
"errors"
)
type Packet struct {
ClassType uint8
TagType uint8
Tag uint8
Value interface{}
ByteValue []byte
Data *bytes.Buffer
Children []*Packet
Description string
}
const (
TagEOC = 0x00
TagBoolean = 0x01
TagInteger = 0x02
TagBitString = 0x03
TagOctetString = 0x04
TagNULL = 0x05
TagObjectIdentifier = 0x06
TagObjectDescriptor = 0x07
TagExternal = 0x08
TagRealFloat = 0x09
TagEnumerated = 0x0a
TagEmbeddedPDV = 0x0b
TagUTF8String = 0x0c
TagRelativeOID = 0x0d
TagSequence = 0x10
TagSet = 0x11
TagNumericString = 0x12
TagPrintableString = 0x13
TagT61String = 0x14
TagVideotexString = 0x15
TagIA5String = 0x16
TagUTCTime = 0x17
TagGeneralizedTime = 0x18
TagGraphicString = 0x19
TagVisibleString = 0x1a
TagGeneralString = 0x1b
TagUniversalString = 0x1c
TagCharacterString = 0x1d
TagBMPString = 0x1e
TagBitmask = 0x1f // xxx11111b
)
var TagMap = map[uint8]string{
TagEOC: "EOC (End-of-Content)",
TagBoolean: "Boolean",
TagInteger: "Integer",
TagBitString: "Bit String",
TagOctetString: "Octet String",
TagNULL: "NULL",
TagObjectIdentifier: "Object Identifier",
TagObjectDescriptor: "Object Descriptor",
TagExternal: "External",
TagRealFloat: "Real (float)",
TagEnumerated: "Enumerated",
TagEmbeddedPDV: "Embedded PDV",
TagUTF8String: "UTF8 String",
TagRelativeOID: "Relative-OID",
TagSequence: "Sequence and Sequence of",
TagSet: "Set and Set OF",
TagNumericString: "Numeric String",
TagPrintableString: "Printable String",
TagT61String: "T61 String",
TagVideotexString: "Videotex String",
TagIA5String: "IA5 String",
TagUTCTime: "UTC Time",
TagGeneralizedTime: "Generalized Time",
TagGraphicString: "Graphic String",
TagVisibleString: "Visible String",
TagGeneralString: "General String",
TagUniversalString: "Universal String",
TagCharacterString: "Character String",
TagBMPString: "BMP String",
}
const (
ClassUniversal = 0 // 00xxxxxxb
ClassApplication = 64 // 01xxxxxxb
ClassContext = 128 // 10xxxxxxb
ClassPrivate = 192 // 11xxxxxxb
ClassBitmask = 192 // 11xxxxxxb
)
var ClassMap = map[uint8]string{
ClassUniversal: "Universal",
ClassApplication: "Application",
ClassContext: "Context",
ClassPrivate: "Private",
}
const (
TypePrimitive = 0 // xx0xxxxxb
TypeConstructed = 32 // xx1xxxxxb
TypeBitmask = 32 // xx1xxxxxb
)
var TypeMap = map[uint8]string{
TypePrimitive: "Primative",
TypeConstructed: "Constructed",
}
var Debug bool = false
func PrintBytes(buf []byte, indent string) {
data_lines := make([]string, (len(buf)/30)+1)
num_lines := make([]string, (len(buf)/30)+1)
for i, b := range buf {
data_lines[i/30] += fmt.Sprintf("%02x ", b)
num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
}
for i := 0; i < len(data_lines); i++ {
fmt.Print(indent + data_lines[i] + "\n")
fmt.Print(indent + num_lines[i] + "\n\n")
}
}
func PrintPacket(p *Packet) {
printPacket(p, 0, false)
}
func printPacket(p *Packet, indent int, printBytes bool) {
indent_str := ""
for len(indent_str) != indent {
indent_str += " "
}
class_str := ClassMap[p.ClassType]
tagtype_str := TypeMap[p.TagType]
tag_str := fmt.Sprintf("0x%02X", p.Tag)
if p.ClassType == ClassUniversal {
tag_str = TagMap[p.Tag]
}
value := fmt.Sprint(p.Value)
description := ""
if p.Description != "" {
description = p.Description + ": "
}
fmt.Printf("%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
if printBytes {
PrintBytes(p.Bytes(), indent_str)
}
for _, child := range p.Children {
printPacket(child, indent+1, printBytes)
}
}
func resizeBuffer(in []byte, new_size uint64) (out []byte) {
out = make([]byte, new_size)
copy(out, in)
return
}
func readBytes(reader io.Reader, buf []byte) error {
idx := 0
buflen := len(buf)
if reader == nil {
return errors.New("reader was nil, aborting")
}
for idx < buflen {
n, err := reader.Read(buf[idx:])
if err != nil {
return err
}
idx += n
}
return nil
}
func ReadPacket(reader io.Reader) (*Packet, error) {
buf := make([]byte, 2)
err := readBytes(reader, buf)
if err != nil {
return nil, err
}
idx := uint64(2)
datalen := uint64(buf[1])
if Debug {
fmt.Printf("Read: datalen = %d len(buf) = %d ", datalen, len(buf))
for _, b := range buf {
fmt.Printf("%02X ", b)
}
fmt.Printf("\n")
}
if datalen&128 != 0 {
a := datalen - 128
idx += a
buf = resizeBuffer(buf, 2+a)
err := readBytes(reader, buf[2:])
if err != nil {
return nil, err
}
datalen = DecodeInteger(buf[2 : 2+a])
if Debug {
fmt.Printf("Read: a = %d idx = %d datalen = %d len(buf) = %d", a, idx, datalen, len(buf))
for _, b := range buf {
fmt.Printf("%02X ", b)
}
fmt.Printf("\n")
}
}
buf = resizeBuffer(buf, idx+datalen)
err = readBytes(reader, buf[idx:])
if err != nil {
return nil, err
}
if Debug {
fmt.Printf("Read: len( buf ) = %d idx=%d datalen=%d idx+datalen=%d\n", len(buf), idx, datalen, idx+datalen)
for _, b := range buf {
fmt.Printf("%02X ", b)
}
}
p := DecodePacket(buf)
return p, nil
}
func DecodeString(data []byte) (ret string) {
// for _, c := range data {
// ret += fmt.Sprintf("%c", c)
// }
return string(data)
}
func DecodeInteger(data []byte) (ret uint64) {
for _, i := range data {
ret = ret * 256
ret = ret + uint64(i)
}
return
}
func EncodeInteger(val uint64) []byte {
var out bytes.Buffer
found := false
shift := uint(56)
mask := uint64(0xFF00000000000000)
for mask > 0 {
if !found && (val&mask != 0) {
found = true
}
if found || (shift == 0) {
out.Write([]byte{byte((val & mask) >> shift)})
}
shift -= 8
mask = mask >> 8
}
return out.Bytes()
}
func DecodePacket(data []byte) *Packet {
p, _ := decodePacket(data)
return p
}
func decodePacket(data []byte) (*Packet, []byte) {
if Debug {
fmt.Printf("decodePacket: enter %d\n", len(data))
}
p := new(Packet)
p.ClassType = data[0] & ClassBitmask
p.TagType = data[0] & TypeBitmask
p.Tag = data[0] & TagBitmask
datalen := DecodeInteger(data[1:2])
datapos := uint64(2)
if datalen&128 != 0 {
datalen -= 128
datapos += datalen
datalen = DecodeInteger(data[2 : 2+datalen])
}
p.Data = new(bytes.Buffer)
p.Children = make([]*Packet, 0, 2)
p.Value = nil
value_data := data[datapos : datapos+datalen]
if p.TagType == TypeConstructed {
for len(value_data) != 0 {
var child *Packet
child, value_data = decodePacket(value_data)
p.AppendChild(child)
}
} else if p.ClassType == ClassUniversal {
p.Data.Write(data[datapos : datapos+datalen])
p.ByteValue = value_data
switch p.Tag {
case TagEOC:
case TagBoolean:
val := DecodeInteger(value_data)
p.Value = val != 0
case TagInteger:
p.Value = DecodeInteger(value_data)
case TagBitString:
case TagOctetString:
p.Value = DecodeString(value_data)
case TagNULL:
case TagObjectIdentifier:
case TagObjectDescriptor:
case TagExternal:
case TagRealFloat:
case TagEnumerated:
p.Value = DecodeInteger(value_data)
case TagEmbeddedPDV:
case TagUTF8String:
case TagRelativeOID:
case TagSequence:
case TagSet:
case TagNumericString:
case TagPrintableString:
p.Value = DecodeString(value_data)
case TagT61String:
case TagVideotexString:
case TagIA5String:
case TagUTCTime:
case TagGeneralizedTime:
case TagGraphicString:
case TagVisibleString:
case TagGeneralString:
case TagUniversalString:
case TagCharacterString:
case TagBMPString:
}
} else {
p.Data.Write(data[datapos : datapos+datalen])
}
return p, data[datapos+datalen:]
}
func (p *Packet) DataLength() uint64 {
return uint64(p.Data.Len())
}
func (p *Packet) Bytes() []byte {
var out bytes.Buffer
out.Write([]byte{p.ClassType | p.TagType | p.Tag})
packet_length := EncodeInteger(p.DataLength())
if p.DataLength() > 127 || len(packet_length) > 1 {
out.Write([]byte{byte(len(packet_length) | 128)})
out.Write(packet_length)
} else {
out.Write(packet_length)
}
out.Write(p.Data.Bytes())
return out.Bytes()
}
func (p *Packet) AppendChild(child *Packet) {
p.Data.Write(child.Bytes())
if len(p.Children) == cap(p.Children) {
newChildren := make([]*Packet, cap(p.Children)*2)
copy(newChildren, p.Children)
p.Children = newChildren[0:len(p.Children)]
}
p.Children = p.Children[0 : len(p.Children)+1]
p.Children[len(p.Children)-1] = child
}
func Encode(ClassType, TagType, Tag uint8, Value interface{}, Description string) *Packet {
p := new(Packet)
p.ClassType = ClassType
p.TagType = TagType
p.Tag = Tag
p.Data = new(bytes.Buffer)
p.Children = make([]*Packet, 0, 2)
p.Value = Value
p.Description = Description
if Value != nil {
v := reflect.ValueOf(Value)
if ClassType == ClassUniversal {
switch Tag {
case TagOctetString:
sv, ok := v.Interface().(string)
if ok {
p.Data.Write([]byte(sv))
}
}
}
}
return p
}
func NewSequence(Description string) *Packet {
return Encode(ClassUniversal, TypePrimitive, TagSequence, nil, Description)
}
func NewBoolean(ClassType, TagType, Tag uint8, Value bool, Description string) *Packet {
intValue := 0
if Value {
intValue = 1
}
p := Encode(ClassType, TagType, Tag, nil, Description)
p.Value = Value
p.Data.Write(EncodeInteger(uint64(intValue)))
return p
}
func NewInteger(ClassType, TagType, Tag uint8, Value uint64, Description string) *Packet {
p := Encode(ClassType, TagType, Tag, nil, Description)
p.Value = Value
p.Data.Write(EncodeInteger(Value))
return p
}
func NewString(ClassType, TagType, Tag uint8, Value, Description string) *Packet {
p := Encode(ClassType, TagType, Tag, nil, Description)
p.Value = Value
p.Data.Write([]byte(Value))
return p
}

View File

@@ -31,6 +31,7 @@ type AdminEditUserForm struct {
Password string `binding:"MaxSize(255)"`
Website string `binding:"MaxSize(50)"`
Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
Active bool
Admin bool
AllowGitHook bool

View File

@@ -1,73 +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 apiv1
import (
"reflect"
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
"github.com/gogits/gogs/modules/auth"
)
type MarkdownForm struct {
Text string
Mode string
Context string
}
func (f *MarkdownForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validateApiReq(errs, ctx.Data, f)
}
func validateApiReq(errs binding.Errors, data map[string]interface{}, f auth.Form) binding.Errors {
if errs.Len() == 0 {
return errs
}
data["HasError"] = true
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 {
switch errs[0].Classification {
case binding.ERR_REQUIRED:
data["ErrorMsg"] = fieldName + " cannot be empty"
case binding.ERR_ALPHA_DASH:
data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) characters"
case binding.ERR_ALPHA_DASH_DOT:
data["ErrorMsg"] = fieldName + " must be valid alpha or numeric or dash(-_) or dot characters"
case binding.ERR_MIN_SIZE:
data["ErrorMsg"] = fieldName + " must contain at least " + auth.GetMinSize(field) + " characters"
case binding.ERR_MAX_SIZE:
data["ErrorMsg"] = fieldName + " must contain at most " + auth.GetMaxSize(field) + " characters"
case binding.ERR_EMAIL:
data["ErrorMsg"] = fieldName + " is not a valid e-mail address"
case binding.ERR_URL:
data["ErrorMsg"] = fieldName + " is not a valid URL"
default:
data["ErrorMsg"] = "Unknown error: " + errs[0].Classification
}
return errs
}
}
return errs
}

View File

@@ -12,13 +12,13 @@ import (
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"github.com/go-macaron/session"
gouuid "github.com/satori/go.uuid"
"gopkg.in/macaron.v1"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/uuid"
)
func IsAPIPath(url string) bool {
@@ -55,8 +55,8 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
return 0
}
t.Updated = time.Now()
if err = models.UpdateAccessToekn(t); err != nil {
log.Error(4, "UpdateAccessToekn: %v", err)
if err = models.UpdateAccessToken(t); err != nil {
log.Error(4, "UpdateAccessToken: %v", err)
}
return t.UID
}
@@ -102,7 +102,7 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool)
if setting.Service.EnableReverseProxyAutoRegister {
u := &models.User{
Name: webAuthUser,
Email: uuid.NewV4().String() + "@localhost",
Email: gouuid.NewV4().String() + "@localhost",
Passwd: webAuthUser,
IsActive: true,
}

View File

@@ -10,28 +10,30 @@ import (
)
type AuthenticationForm struct {
ID int64
Type int `binding:"Range(2,5)"`
Name string `binding:"Required;MaxSize(30)"`
Host string
Port int
BindDN string
BindPassword string
UserBase string
UserDN string `form:"user_dn"`
AttributeName string
AttributeSurname string
AttributeMail string
Filter string
AdminFilter string
IsActive bool
SMTPAuth string
SMTPHost string
SMTPPort int
AllowedDomains string
TLS bool
SkipVerify bool
PAMServiceName string `form:"pam_service_name"`
ID int64
Type int `binding:"Range(2,5)"`
Name string `binding:"Required;MaxSize(30)"`
Host string
Port int
BindDN string
BindPassword string
UserBase string
UserDN string
AttributeUsername string
AttributeName string
AttributeSurname string
AttributeMail string
AttributesInBind bool
Filter string
AdminFilter string
IsActive bool
SMTPAuth string
SMTPHost string
SMTPPort int
AllowedDomains string
TLS bool
SkipVerify bool
PAMServiceName string
}
func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

View File

@@ -11,27 +11,30 @@ import (
"fmt"
"strings"
"github.com/gogits/gogs/modules/ldap"
"gopkg.in/ldap.v2"
"github.com/gogits/gogs/modules/log"
)
// Basic LDAP authentication service
type Source struct {
Name string // canonical name (ie. corporate.ad)
Host string // LDAP host
Port int // port number
UseSSL bool // Use SSL
SkipVerify bool
BindDN string // DN to bind with
BindPassword string // Bind DN password
UserBase string // Base search path for users
UserDN string // Template for the DN of the user for simple auth
AttributeName string // First name attribute
AttributeSurname string // Surname attribute
AttributeMail string // E-mail attribute
Filter string // Query filter to validate entry
AdminFilter string // Query filter to check if user is admin
Enabled bool // if this source is disabled
Name string // canonical name (ie. corporate.ad)
Host string // LDAP host
Port int // port number
UseSSL bool // Use SSL
SkipVerify bool
BindDN string // DN to bind with
BindPassword string // Bind DN password
UserBase string // Base search path for users
UserDN string // Template for the DN of the user for simple auth
AttributeUsername string // Username attribute
AttributeName string // First name attribute
AttributeSurname string // Surname attribute
AttributeMail string // E-mail attribute
AttributesInBind bool // fetch attributes in bind context (not user)
Filter string // Query filter to validate entry
AdminFilter string // Query filter to check if user is admin
Enabled bool // if this source is disabled
}
func (ls *Source) sanitizedUserQuery(username string) (string, bool) {
@@ -56,18 +59,10 @@ func (ls *Source) sanitizedUserDN(username string) (string, bool) {
return fmt.Sprintf(ls.UserDN, username), true
}
func (ls *Source) FindUserDN(name string) (string, bool) {
l, err := ldapDial(ls)
if err != nil {
log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
ls.Enabled = false
return "", false
}
defer l.Close()
func (ls *Source) findUserDN(l *ldap.Conn, name string) (string, bool) {
log.Trace("Search for LDAP user: %s", name)
if ls.BindDN != "" && ls.BindPassword != "" {
err = l.Bind(ls.BindDN, ls.BindPassword)
err := l.Bind(ls.BindDN, ls.BindPassword)
if err != nil {
log.Debug("Failed to bind as BindDN[%s]: %v", ls.BindDN, err)
return "", false
@@ -83,7 +78,7 @@ func (ls *Source) FindUserDN(name string) (string, bool) {
return "", false
}
log.Trace("Searching using filter %s", userFilter)
log.Trace("Searching for DN using filter %s and base %s", userFilter, ls.UserBase)
search := ldap.NewSearchRequest(
ls.UserBase, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0,
false, userFilter, []string{}, nil)
@@ -100,7 +95,7 @@ func (ls *Source) FindUserDN(name string) (string, bool) {
userDN := sr.Entries[0].DN
if userDN == "" {
log.Error(4, "LDAP search was succesful, but found no DN!")
log.Error(4, "LDAP search was successful, but found no DN!")
return "", false
}
@@ -108,7 +103,15 @@ func (ls *Source) FindUserDN(name string) (string, bool) {
}
// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter
func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, string, string, bool, bool) {
func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, string, string, string, bool, bool) {
l, err := ldapDial(ls)
if err != nil {
log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
ls.Enabled = false
return "", "", "", "", false, false
}
defer l.Close()
var userDN string
if directBind {
log.Trace("LDAP will bind directly via UserDN template: %s", ls.UserDN)
@@ -116,48 +119,41 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
var ok bool
userDN, ok = ls.sanitizedUserDN(name)
if !ok {
return "", "", "", false, false
return "", "", "", "", false, false
}
} else {
log.Trace("LDAP will use BindDN.")
var found bool
userDN, found = ls.FindUserDN(name)
userDN, found = ls.findUserDN(l, name)
if !found {
return "", "", "", false, false
return "", "", "", "", false, false
}
}
l, err := ldapDial(ls)
if err != nil {
log.Error(4, "LDAP Connect error (%s): %v", ls.Host, err)
ls.Enabled = false
return "", "", "", false, false
}
defer l.Close()
log.Trace("Binding with userDN: %s", userDN)
err = l.Bind(userDN, passwd)
if err != nil {
log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err)
return "", "", "", false, false
if directBind || !ls.AttributesInBind {
// binds user (checking password) before looking-up attributes in user context
err = bindUser(l, userDN, passwd)
if err != nil {
return "", "", "", "", false, false
}
}
log.Trace("Bound successfully with userDN: %s", userDN)
userFilter, ok := ls.sanitizedUserQuery(name)
if !ok {
return "", "", "", false, false
return "", "", "", "", false, false
}
log.Trace("Fetching attributes '%v', '%v', '%v', '%v' with filter %s and base %s", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN)
search := ldap.NewSearchRequest(
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
[]string{ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
[]string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
nil)
sr, err := l.Search(search)
if err != nil {
log.Error(4, "LDAP Search failed unexpectedly! (%v)", err)
return "", "", "", false, false
return "", "", "", "", false, false
} else if len(sr.Entries) < 1 {
if directBind {
log.Error(4, "User filter inhibited user login.")
@@ -165,15 +161,17 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
log.Error(4, "LDAP Search failed unexpectedly! (0 entries)")
}
return "", "", "", false, false
return "", "", "", "", false, false
}
username_attr := sr.Entries[0].GetAttributeValue(ls.AttributeUsername)
name_attr := sr.Entries[0].GetAttributeValue(ls.AttributeName)
sn_attr := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
mail_attr := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
admin_attr := false
if len(ls.AdminFilter) > 0 {
log.Trace("Checking admin with filter %s and base %s", ls.AdminFilter, userDN)
search = ldap.NewSearchRequest(
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, ls.AdminFilter,
[]string{ls.AttributeName},
@@ -189,7 +187,26 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
}
}
return name_attr, sn_attr, mail_attr, admin_attr, true
if !directBind && ls.AttributesInBind {
// binds user (checking password) after looking-up attributes in BindDN context
err = bindUser(l, userDN, passwd)
if err != nil {
return "", "", "", "", false, false
}
}
return username_attr, name_attr, sn_attr, mail_attr, admin_attr, true
}
func bindUser(l *ldap.Conn, userDN, passwd string) error {
log.Trace("Binding with userDN: %s", userDN)
err := l.Bind(userDN, passwd)
if err != nil {
log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err)
return err
}
log.Trace("Bound successfully with userDN: %s", userDN)
return err
}
func ldapDial(ls *Source) (*ldap.Conn, error) {

View File

@@ -25,11 +25,12 @@ func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) bind
}
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)"`
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 {
@@ -44,9 +45,9 @@ func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Error
// \/ \/ \/
type CreateTeamForm struct {
TeamName string `form:"team_name" binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `form:"desc" binding:"MaxSize(255)"`
Permission string `form:"permission"`
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 {

View File

@@ -57,7 +57,7 @@ func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
// 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) {
remoteAddr := f.CloneAddr
remoteAddr := strings.TrimSpace(f.CloneAddr)
// Remote address can be HTTP/HTTPS/Git URL or local path.
if strings.HasPrefix(remoteAddr, "http://") ||
@@ -81,12 +81,22 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
}
type RepoSettingForm struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
Branch string
Interval int
Private bool
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
Branch string
Interval int
MirrorAddress string
Private bool
// Advanced settings
EnableWiki bool
EnableExternalWiki bool
ExternalWikiURL string
EnableIssues bool
EnableExternalTracker bool
TrackerURLFormat string
EnablePulls bool
}
func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
@@ -229,7 +239,7 @@ func (f *NewReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bin
type EditReleaseForm struct {
Title string `form:"title" binding:"Required"`
Content string `form:"content" binding:"Required"`
Content string `form:"content"`
Draft string `form:"draft"`
Prerelease bool `form:"prerelease"`
}
@@ -237,3 +247,22 @@ type EditReleaseForm struct {
func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
// __ __.__ __ .__
// / \ / \__| | _|__|
// \ \/\/ / | |/ / |
// \ /| | <| |
// \__/\ / |__|__|_ \__|
// \/ \/
type NewWikiForm struct {
OldTitle string
Title string `binding:"Required"`
Content string `binding:"Required"`
Message string
}
// FIXME: use code generation to generate this method.
func (f *NewWikiForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -27,6 +27,7 @@ type InstallForm struct {
SSHPort int
HTTPPort string `binding:"Required"`
AppUrl string `binding:"Required"`
LogRootPath string `binding:"Required"`
SMTPHost string
SMTPFrom string
@@ -87,12 +88,12 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding
// \/ \/ \/ \/ \/
type UpdateProfileForm struct {
Name string `binding:"Required;MaxSize(35)"`
Name string `binding:"OmitEmpty;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)"`
Gravatar string `binding:"Required;Email;MaxSize(254)"`
Gravatar string `binding:"OmitEmpty;Email;MaxSize(254)"`
}
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

View File

@@ -2,74 +2,23 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// for www.gravatar.com image cache
/*
It is recommend to use this way
cacheDir := "./cache"
defaultImg := "./default.jpg"
http.Handle("/avatar/", avatar.CacheServer(cacheDir, defaultImg))
*/
package avatar
import (
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"image"
"image/color/palette"
"image/jpeg"
"image/png"
"io"
"math/rand"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"sync"
"time"
"github.com/issue9/identicon"
"github.com/nfnt/resize"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
//FIXME: remove cache module
var gravatarSource string
func UpdateGravatarSource() {
gravatarSource = setting.GravatarSource
if strings.HasPrefix(gravatarSource, "//") {
gravatarSource = "http:" + gravatarSource
} else if !strings.HasPrefix(gravatarSource, "http://") &&
!strings.HasPrefix(gravatarSource, "https://") {
gravatarSource = "http://" + gravatarSource
}
log.Debug("avatar.UpdateGravatarSource(update gavatar source): %s", gravatarSource)
}
// hash email to md5 string
// keep this func in order to make this package independent
func HashEmail(email string) string {
// https://en.gravatar.com/site/implement/hash/
email = strings.TrimSpace(email)
email = strings.ToLower(email)
h := md5.New()
h.Write([]byte(email))
return hex.EncodeToString(h.Sum(nil))
}
const _RANDOM_AVATAR_SIZE = 200
// RandomImage generates and returns a random avatar image.
func RandomImage(data []byte) (image.Image, error) {
// RandomImage generates and returns a random avatar image unique to input data
// in custom size (height and width).
func RandomImageSize(size int, data []byte) (image.Image, error) {
randExtent := len(palette.WebSafe) - 32
rand.Seed(time.Now().UnixNano())
colorIndex := rand.Intn(randExtent)
@@ -78,262 +27,17 @@ func RandomImage(data []byte) (image.Image, error) {
backColorIndex = randExtent - 1
}
// Size, background, forecolor
imgMaker, err := identicon.New(_RANDOM_AVATAR_SIZE,
// Define size, background, and forecolor
imgMaker, err := identicon.New(size,
palette.WebSafe[backColorIndex], palette.WebSafe[colorIndex:colorIndex+32]...)
if err != nil {
return nil, err
return nil, fmt.Errorf("identicon.New: %v", err)
}
return imgMaker.Make(data), nil
}
// Avatar represents the avatar object.
type Avatar struct {
Hash string
AlterImage string // image path
cacheDir string // image save dir
reqParams string
imagePath string
expireDuration time.Duration
}
func New(hash string, cacheDir string) *Avatar {
return &Avatar{
Hash: hash,
cacheDir: cacheDir,
expireDuration: time.Minute * 10,
reqParams: url.Values{
"d": {"retro"},
"size": {"290"},
"r": {"pg"}}.Encode(),
imagePath: filepath.Join(cacheDir, hash+".image"), //maybe png or jpeg
}
}
func (this *Avatar) HasCache() bool {
fileInfo, err := os.Stat(this.imagePath)
return err == nil && fileInfo.Mode().IsRegular()
}
func (this *Avatar) Modtime() (modtime time.Time, err error) {
fileInfo, err := os.Stat(this.imagePath)
if err != nil {
return
}
return fileInfo.ModTime(), nil
}
func (this *Avatar) Expired() bool {
modtime, err := this.Modtime()
return err != nil || time.Since(modtime) > this.expireDuration
}
// default image format: jpeg
func (this *Avatar) Encode(wr io.Writer, size int) (err error) {
var img image.Image
decodeImageFile := func(file string) (img image.Image, err error) {
fd, err := os.Open(file)
if err != nil {
return
}
defer fd.Close()
if img, err = jpeg.Decode(fd); err != nil {
fd.Seek(0, os.SEEK_SET)
img, err = png.Decode(fd)
}
return
}
imgPath := this.imagePath
if !this.HasCache() {
if this.AlterImage == "" {
return errors.New("request image failed, and no alt image offered")
}
imgPath = this.AlterImage
}
if img, err = decodeImageFile(imgPath); err != nil {
return
}
m := resize.Resize(uint(size), 0, img, resize.Lanczos3)
return jpeg.Encode(wr, m, nil)
}
// get image from gravatar.com
func (this *Avatar) Update() {
UpdateGravatarSource()
thunder.Fetch(gravatarSource+this.Hash+"?"+this.reqParams,
this.imagePath)
}
func (this *Avatar) UpdateTimeout(timeout time.Duration) (err error) {
UpdateGravatarSource()
select {
case <-time.After(timeout):
err = fmt.Errorf("get gravatar image %s timeout", this.Hash)
case err = <-thunder.GoFetch(gravatarSource+this.Hash+"?"+this.reqParams,
this.imagePath):
}
return err
}
type service struct {
cacheDir string
altImage string
}
func (this *service) mustInt(r *http.Request, defaultValue int, keys ...string) (v int) {
for _, k := range keys {
if _, err := fmt.Sscanf(r.FormValue(k), "%d", &v); err == nil {
defaultValue = v
}
}
return defaultValue
}
func (this *service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
urlPath := r.URL.Path
hash := urlPath[strings.LastIndex(urlPath, "/")+1:]
size := this.mustInt(r, 290, "s", "size") // default size = 290*290
avatar := New(hash, this.cacheDir)
avatar.AlterImage = this.altImage
if avatar.Expired() {
if err := avatar.UpdateTimeout(time.Millisecond * 1000); err != nil {
log.Trace("avatar update error: %v", err)
return
}
}
if modtime, err := avatar.Modtime(); err == nil {
etag := fmt.Sprintf("size(%d)", size)
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) && etag == r.Header.Get("If-None-Match") {
h := w.Header()
delete(h, "Content-Type")
delete(h, "Content-Length")
w.WriteHeader(http.StatusNotModified)
return
}
w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat))
w.Header().Set("ETag", etag)
}
w.Header().Set("Content-Type", "image/jpeg")
if err := avatar.Encode(w, size); err != nil {
log.Warn("avatar encode error: %v", err)
w.WriteHeader(500)
}
}
// http.Handle("/avatar/", avatar.CacheServer("./cache"))
func CacheServer(cacheDir string, defaultImgPath string) http.Handler {
return &service{
cacheDir: cacheDir,
altImage: defaultImgPath,
}
}
// thunder downloader
var thunder = &Thunder{QueueSize: 10}
type Thunder struct {
QueueSize int // download queue size
q chan *thunderTask
once sync.Once
}
func (t *Thunder) init() {
if t.QueueSize < 1 {
t.QueueSize = 1
}
t.q = make(chan *thunderTask, t.QueueSize)
for i := 0; i < t.QueueSize; i++ {
go func() {
for {
task := <-t.q
task.Fetch()
}
}()
}
}
func (t *Thunder) Fetch(url string, saveFile string) error {
t.once.Do(t.init)
task := &thunderTask{
Url: url,
SaveFile: saveFile,
}
task.Add(1)
t.q <- task
task.Wait()
return task.err
}
func (t *Thunder) GoFetch(url, saveFile string) chan error {
c := make(chan error)
go func() {
c <- t.Fetch(url, saveFile)
}()
return c
}
// thunder download
type thunderTask struct {
Url string
SaveFile string
sync.WaitGroup
err error
}
func (this *thunderTask) Fetch() {
this.err = this.fetch()
this.Done()
}
var client = &http.Client{}
func (this *thunderTask) fetch() error {
log.Debug("avatar.fetch(fetch new avatar): %s", this.Url)
req, _ := http.NewRequest("GET", this.Url, nil)
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/jpeg,image/png,*/*;q=0.8")
req.Header.Set("Accept-Encoding", "deflate,sdch")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36")
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("status code: %d", resp.StatusCode)
}
/*
log.Println("headers:", resp.Header)
switch resp.Header.Get("Content-Type") {
case "image/jpeg":
this.SaveFile += ".jpeg"
case "image/png":
this.SaveFile += ".png"
}
*/
/*
imgType := resp.Header.Get("Content-Type")
if imgType != "image/jpeg" && imgType != "image/png" {
return errors.New("not png or jpeg")
}
*/
tmpFile := this.SaveFile + ".part" // mv to destination when finished
fd, err := os.Create(tmpFile)
if err != nil {
return err
}
_, err = io.Copy(fd, resp.Body)
fd.Close()
if err != nil {
os.Remove(tmpFile)
return err
}
return os.Rename(tmpFile, this.SaveFile)
// RandomImage generates and returns a random avatar image unique to input data
// in default size (height and width).
func RandomImage(data []byte) (image.Image, error) {
return RandomImageSize(_RANDOM_AVATAR_SIZE, data)
}

View File

@@ -1,61 +1,23 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package avatar_test
package avatar
import (
"errors"
"os"
"strconv"
"testing"
"time"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/log"
. "github.com/smartystreets/goconvey/convey"
)
const TMPDIR = "test-avatar"
func Test_RandomImage(t *testing.T) {
Convey("Generate a random avatar from email", t, func() {
_, err := RandomImage([]byte("gogs@local"))
So(err, ShouldBeNil)
func TestFetch(t *testing.T) {
os.Mkdir(TMPDIR, 0755)
defer os.RemoveAll(TMPDIR)
hash := avatar.HashEmail("ssx205@gmail.com")
a := avatar.New(hash, TMPDIR)
a.UpdateTimeout(time.Millisecond * 200)
}
func TestFetchMany(t *testing.T) {
os.Mkdir(TMPDIR, 0755)
defer os.RemoveAll(TMPDIR)
t.Log("start")
var n = 5
ch := make(chan bool, n)
for i := 0; i < n; i++ {
go func(i int) {
hash := avatar.HashEmail(strconv.Itoa(i) + "ssx205@gmail.com")
a := avatar.New(hash, TMPDIR)
a.Update()
t.Log("finish", hash)
ch <- true
}(i)
}
for i := 0; i < n; i++ {
<-ch
}
t.Log("end")
}
// cat
// wget http://www.artsjournal.com/artfulmanager/wp/wp-content/uploads/2013/12/200x200xmirror_cat.jpg.pagespeed.ic.GOZSv6v1_H.jpg -O default.jpg
/*
func TestHttp(t *testing.T) {
http.Handle("/", avatar.CacheServer("./", "default.jpg"))
http.ListenAndServe(":8001", nil)
}
*/
func TestLogTrace(t *testing.T) {
log.Trace("%v", errors.New("console log test"))
Convey("Try to generate an image with size zero", func() {
_, err := RandomImageSize(0, []byte("gogs@local"))
So(err, ShouldNotBeNil)
})
})
}

View File

@@ -4,29 +4,8 @@
package base
import (
"os"
"os/exec"
"path/filepath"
)
const DOC_URL = "https://github.com/gogits/go-gogs-client/wiki"
type (
TplName string
)
var GoGetMetas = make(map[string]bool)
// ExecPath returns the executable path.
func ExecPath() (string, error) {
file, err := exec.LookPath(os.Args[0])
if err != nil {
return "", err
}
p, err := filepath.Abs(file)
if err != nil {
return "", err
}
return p, nil
}

View File

@@ -1,334 +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 base
import (
"bytes"
"fmt"
"io"
"net/http"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/Unknwon/com"
"github.com/russross/blackfriday"
"golang.org/x/net/html"
"github.com/gogits/gogs/modules/setting"
)
func isletter(c byte) bool {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
func isalnum(c byte) bool {
return (c >= '0' && c <= '9') || isletter(c)
}
var validLinks = [][]byte{[]byte("http://"), []byte("https://"), []byte("ftp://"), []byte("mailto://")}
func isLink(link []byte) bool {
for _, prefix := range validLinks {
if len(link) > len(prefix) && bytes.Equal(bytes.ToLower(link[:len(prefix)]), prefix) && isalnum(link[len(prefix)]) {
return true
}
}
return false
}
func IsMarkdownFile(name string) bool {
name = strings.ToLower(name)
switch filepath.Ext(name) {
case ".md", ".markdown", ".mdown", ".mkd":
return true
}
return false
}
func IsTextFile(data []byte) (string, bool) {
contentType := http.DetectContentType(data)
if strings.Index(contentType, "text/") != -1 {
return contentType, true
}
return contentType, false
}
func IsImageFile(data []byte) (string, bool) {
contentType := http.DetectContentType(data)
if strings.Index(contentType, "image/") != -1 {
return contentType, true
}
return contentType, false
}
// IsReadmeFile returns true if given file name suppose to be a README file.
func IsReadmeFile(name string) bool {
name = strings.ToLower(name)
if len(name) < 6 {
return false
} else if len(name) == 6 {
if name == "readme" {
return true
}
return false
}
if name[:7] == "readme." {
return true
}
return false
}
type CustomRender struct {
blackfriday.Renderer
urlPrefix string
}
func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
if len(link) > 0 && !isLink(link) {
if link[0] == '#' {
// link = append([]byte(options.urlPrefix), link...)
} else {
link = []byte(path.Join(options.urlPrefix, string(link)))
}
}
options.Renderer.Link(out, link, title, content)
}
var (
svgSuffix = []byte(".svg")
svgSuffixWithMark = []byte(".svg?")
)
func (options *CustomRender) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := strings.Replace(options.urlPrefix, "/src/", "/raw/", 1)
if len(link) > 0 {
if isLink(link) {
// External link with .svg suffix usually means CI status.
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) {
options.Renderer.Image(out, link, title, alt)
return
}
} else {
if link[0] != '/' {
prefix += "/"
}
link = []byte(prefix + string(link))
}
}
out.WriteString(`<a href="`)
out.Write(link)
out.WriteString(`">`)
options.Renderer.Image(out, link, title, alt)
out.WriteString("</a>")
}
var (
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_\.]+`)
commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
issueIndexPattern = regexp.MustCompile(`( |^)#[0-9]+\b`)
sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`)
)
func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte {
ms := MentionPattern.FindAll(rawBytes, -1)
for _, m := range ms {
m = bytes.TrimSpace(m)
rawBytes = bytes.Replace(rawBytes, m,
[]byte(fmt.Sprintf(`<a href="%s/%s">%s</a>`, setting.AppSubUrl, m[1:], m)), -1)
}
ms = commitPattern.FindAll(rawBytes, -1)
for _, m := range ms {
m = bytes.TrimSpace(m)
i := strings.Index(string(m), "commit/")
j := strings.Index(string(m), "#")
if j == -1 {
j = len(m)
}
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(
` <code><a href="%s">%s</a></code>`, m, ShortSha(string(m[i+7:j])))), -1)
}
ms = issueFullPattern.FindAll(rawBytes, -1)
for _, m := range ms {
m = bytes.TrimSpace(m)
i := strings.Index(string(m), "issues/")
j := strings.Index(string(m), "#")
if j == -1 {
j = len(m)
}
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(
` <a href="%s">#%s</a>`, m, ShortSha(string(m[i+7:j])))), -1)
}
rawBytes = RenderIssueIndexPattern(rawBytes, urlPrefix)
rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
return rawBytes
}
func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
ms := sha1CurrentPattern.FindAll(rawBytes, -1)
for _, m := range ms {
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(
`<a href="%s/commit/%s"><code>%s</code></a>`, urlPrefix, m, ShortSha(string(m)))), -1)
}
return rawBytes
}
func cutoutVerbosePrefix(prefix string) string {
count := 0
for i := 0; i < len(prefix); i++ {
if prefix[i] == '/' {
count++
}
if count >= 3 {
return prefix[:i]
}
}
return prefix
}
func RenderIssueIndexPattern(rawBytes []byte, urlPrefix string) []byte {
urlPrefix = cutoutVerbosePrefix(urlPrefix)
ms := issueIndexPattern.FindAll(rawBytes, -1)
for _, m := range ms {
var space string
m2 := m
if m2[0] == ' ' {
space = " "
m2 = m2[1:]
}
rawBytes = bytes.Replace(rawBytes, m, []byte(fmt.Sprintf(`%s<a href="%s/issues/%s">%s</a>`,
space, urlPrefix, m2[1:], m2)), 1)
}
return rawBytes
}
func RenderRawMarkdown(body []byte, urlPrefix string) []byte {
htmlFlags := 0
// htmlFlags |= blackfriday.HTML_USE_XHTML
// htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
// htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS
// htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
// htmlFlags |= blackfriday.HTML_SKIP_HTML
htmlFlags |= blackfriday.HTML_SKIP_STYLE
// htmlFlags |= blackfriday.HTML_SKIP_SCRIPT
// htmlFlags |= blackfriday.HTML_GITHUB_BLOCKCODE
htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
// htmlFlags |= blackfriday.HTML_COMPLETE_PAGE
renderer := &CustomRender{
Renderer: blackfriday.HtmlRenderer(htmlFlags, "", ""),
urlPrefix: urlPrefix,
}
// set up the parser
extensions := 0
extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS
extensions |= blackfriday.EXTENSION_TABLES
extensions |= blackfriday.EXTENSION_FENCED_CODE
extensions |= blackfriday.EXTENSION_AUTOLINK
extensions |= blackfriday.EXTENSION_STRIKETHROUGH
extensions |= blackfriday.EXTENSION_SPACE_HEADERS
extensions |= blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
if setting.Markdown.EnableHardLineBreak {
extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK
}
body = blackfriday.Markdown(body, renderer, extensions)
return body
}
var (
leftAngleBracket = []byte("</")
rightAngleBracket = []byte(">")
)
var noEndTags = []string{"img", "input", "br", "hr"}
// PostProcessMarkdown treats different types of HTML differently,
// and only renders special links for plain text blocks.
func PostProcessMarkdown(rawHtml []byte, urlPrefix string) []byte {
startTags := make([]string, 0, 5)
var buf bytes.Buffer
tokenizer := html.NewTokenizer(bytes.NewReader(rawHtml))
OUTER_LOOP:
for html.ErrorToken != tokenizer.Next() {
token := tokenizer.Token()
switch token.Type {
case html.TextToken:
buf.Write(RenderSpecialLink([]byte(token.String()), urlPrefix))
case html.StartTagToken:
buf.WriteString(token.String())
tagName := token.Data
// 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
for html.ErrorToken != tokenizer.Next() {
token = tokenizer.Token()
// Copy the token to the output verbatim
buf.WriteString(token.String())
if token.Type == html.StartTagToken {
stackNum++
}
// If this is the close tag to the outer-most, we are done
if token.Type == html.EndTagToken && strings.EqualFold(tagName, token.Data) {
stackNum--
if stackNum == 0 {
break
}
}
}
continue OUTER_LOOP
}
if !com.IsSliceContainsStr(noEndTags, token.Data) {
startTags = append(startTags, token.Data)
}
case html.EndTagToken:
if len(startTags) == 0 {
buf.WriteString(token.String())
break
}
buf.Write(leftAngleBracket)
buf.WriteString(startTags[len(startTags)-1])
buf.Write(rightAngleBracket)
startTags = startTags[:len(startTags)-1]
default:
buf.WriteString(token.String())
}
}
if io.EOF == tokenizer.Err() {
return buf.Bytes()
}
// If we are not at the end of the input, then some other parsing error has occurred,
// so return the input verbatim.
return rawHtml
}
func RenderMarkdown(rawBytes []byte, urlPrefix string) []byte {
result := RenderRawMarkdown(rawBytes, urlPrefix)
result = PostProcessMarkdown(result, urlPrefix)
result = Sanitizer.SanitizeBytes(result)
return result
}
func RenderMarkdownString(raw, urlPrefix string) string {
return string(RenderMarkdown([]byte(raw), urlPrefix))
}

View File

@@ -15,22 +15,21 @@ import (
"hash"
"html/template"
"math"
"regexp"
"net/http"
"strings"
"time"
"unicode"
"unicode/utf8"
"github.com/Unknwon/com"
"github.com/Unknwon/i18n"
"github.com/microcosm-cc/bluemonday"
"github.com/gogits/chardet"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
var Sanitizer = bluemonday.UGCPolicy().AllowAttrs("class").Matching(regexp.MustCompile(`[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&]*`)).OnElements("code")
// EncodeMD5 encodes string to md5 hex value.
func EncodeMD5(str string) string {
m := md5.New()
@@ -53,11 +52,18 @@ func ShortSha(sha1 string) string {
}
func DetectEncoding(content []byte) (string, error) {
detector := chardet.NewTextDetector()
result, err := detector.DetectBest(content)
if utf8.Valid(content) {
log.Debug("Detected encoding: utf-8 (fast)")
return "UTF-8", nil
}
result, err := chardet.NewTextDetector().DetectBest(content)
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
log.Debug("Using default AnsiCharset: %s", setting.Repository.AnsiCharset)
return setting.Repository.AnsiCharset, err
}
log.Debug("Detected encoding: %s", result.Charset)
return result.Charset, err
}
@@ -188,17 +194,22 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string
return code
}
// AvatarLink returns avatar link by given e-mail.
// HashEmail hashes email address to MD5 string.
// https://en.gravatar.com/site/implement/hash/
func HashEmail(email string) string {
email = strings.ToLower(strings.TrimSpace(email))
h := md5.New()
h.Write([]byte(email))
return hex.EncodeToString(h.Sum(nil))
}
// AvatarLink returns avatar link by given email.
func AvatarLink(email string) string {
if setting.DisableGravatar || setting.OfflineMode {
return setting.AppSubUrl + "/img/avatar_default.jpg"
}
gravatarHash := avatar.HashEmail(email)
if setting.Service.EnableCacheAvatar {
return setting.AppSubUrl + "/avatar/" + gravatarHash
}
return setting.GravatarSource + gravatarHash
return setting.GravatarSource + HashEmail(email)
}
// Seconds-based time units
@@ -444,6 +455,24 @@ func Subtract(left interface{}, right interface{}) interface{} {
}
}
// EllipsisString returns a truncated short string,
// it appends '...' in the end of the length of string is too large.
func EllipsisString(str string, length int) string {
if len(str) < length {
return str
}
return str[:length-3] + "..."
}
// TruncateString returns a truncated string with given limit,
// it returns input string if length is not reached limit.
func TruncateString(str string, limit int) string {
if len(str) < limit {
return str
}
return str[:limit]
}
// StringsToInt64s converts a slice of string to a slice of int64.
func StringsToInt64s(strs []string) []int64 {
ints := make([]int64, len(strs))
@@ -470,3 +499,25 @@ func Int64sToMap(ints []int64) map[int64]bool {
}
return m
}
// IsLetter reports whether the rune is a letter (category L).
// https://github.com/golang/go/blob/master/src/go/scanner/scanner.go#L257
func IsLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
}
func IsTextFile(data []byte) (string, bool) {
contentType := http.DetectContentType(data)
if strings.Index(contentType, "text/") != -1 {
return contentType, true
}
return contentType, false
}
func IsImageFile(data []byte) (string, bool) {
contentType := http.DetectContentType(data)
if strings.Index(contentType, "image/") != -1 {
return contentType, true
}
return contentType, false
}

File diff suppressed because one or more lines are too long

View File

@@ -1,27 +0,0 @@
package cron
import "time"
// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
// It does not support jobs more frequent than once a second.
type ConstantDelaySchedule struct {
Delay time.Duration
}
// Every returns a crontab Schedule that activates once every duration.
// Delays of less than a second are not supported (will round up to 1 second).
// Any fields less than a Second are truncated.
func Every(duration time.Duration) ConstantDelaySchedule {
if duration < time.Second {
duration = time.Second
}
return ConstantDelaySchedule{
Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
}
}
// Next returns the next time this should be run.
// This rounds so that the next activation time will be on the second.
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
}

View File

@@ -1,54 +0,0 @@
package cron
import (
"testing"
"time"
)
func TestConstantDelayNext(t *testing.T) {
tests := []struct {
time string
delay time.Duration
expected string
}{
// Simple cases
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
{"Mon Jul 9 14:59 2012", 15 * time.Minute, "Mon Jul 9 15:14 2012"},
{"Mon Jul 9 14:59:59 2012", 15 * time.Minute, "Mon Jul 9 15:14:59 2012"},
// Wrap around hours
{"Mon Jul 9 15:45 2012", 35 * time.Minute, "Mon Jul 9 16:20 2012"},
// Wrap around days
{"Mon Jul 9 23:46 2012", 14 * time.Minute, "Tue Jul 10 00:00 2012"},
{"Mon Jul 9 23:45 2012", 35 * time.Minute, "Tue Jul 10 00:20 2012"},
{"Mon Jul 9 23:35:51 2012", 44*time.Minute + 24*time.Second, "Tue Jul 10 00:20:15 2012"},
{"Mon Jul 9 23:35:51 2012", 25*time.Hour + 44*time.Minute + 24*time.Second, "Thu Jul 11 01:20:15 2012"},
// Wrap around months
{"Mon Jul 9 23:35 2012", 91*24*time.Hour + 25*time.Minute, "Thu Oct 9 00:00 2012"},
// Wrap around minute, hour, day, month, and year
{"Mon Dec 31 23:59:45 2012", 15 * time.Second, "Tue Jan 1 00:00:00 2013"},
// Round to nearest second on the delay
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
// Round up to 1 second if the duration is less.
{"Mon Jul 9 14:45:00 2012", 15 * time.Millisecond, "Mon Jul 9 14:45:01 2012"},
// Round to nearest second when calculating the next time.
{"Mon Jul 9 14:45:00.005 2012", 15 * time.Minute, "Mon Jul 9 15:00 2012"},
// Round to nearest second for both.
{"Mon Jul 9 14:45:00.005 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
}
for _, c := range tests {
actual := Every(c.delay).Next(getTime(c.time))
expected := getTime(c.expected)
if actual != expected {
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.delay, expected, actual)
}
}
}

View File

@@ -1,4 +1,3 @@
// Copyright 2012 Rob Figueiredo. All rights reserved.
// 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.
@@ -6,207 +5,59 @@
package cron
import (
"sort"
"time"
"github.com/gogits/cron"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
type Cron struct {
entries []*Entry
stop chan struct{}
add chan *Entry
snapshot chan []*Entry
running bool
}
var c = cron.New()
// Job is an interface for submitted cron jobs.
type Job interface {
Run()
}
// The Schedule describes a job's duty cycle.
type Schedule interface {
// Return the next activation time, later than the given time.
// Next is invoked initially, and then each time the job is run.
Next(time.Time) time.Time
}
// Entry consists of a schedule and the func to execute on that schedule.
type Entry struct {
Description string
Spec string
// The schedule on which this job should be run.
Schedule Schedule
// The next time the job will run. This is the zero time if Cron has not been
// started or this entry's schedule is unsatisfiable
Next time.Time
// The last time this job was run. This is the zero time if the job has never
// been run.
Prev time.Time
// The Job to run.
Job Job
ExecTimes int // Execute times count.
}
// byTime is a wrapper for sorting the entry array by time
// (with zero time at the end).
type byTime []*Entry
func (s byTime) Len() int { return len(s) }
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byTime) Less(i, j int) bool {
// Two zero times should return false.
// Otherwise, zero is "greater" than any other time.
// (To sort it at the end of the list.)
if s[i].Next.IsZero() {
return false
}
if s[j].Next.IsZero() {
return true
}
return s[i].Next.Before(s[j].Next)
}
// New returns a new Cron job runner.
func New() *Cron {
return &Cron{
entries: nil,
add: make(chan *Entry),
stop: make(chan struct{}),
snapshot: make(chan []*Entry),
running: false,
}
}
// A wrapper that turns a func() into a cron.Job
type FuncJob func()
func (f FuncJob) Run() { f() }
// AddFunc adds a func to the Cron to be run on the given schedule.
func (c *Cron) AddFunc(desc, spec string, cmd func()) (*Entry, error) {
return c.AddJob(desc, spec, FuncJob(cmd))
}
// AddFunc adds a Job to the Cron to be run on the given schedule.
func (c *Cron) AddJob(desc, spec string, cmd Job) (*Entry, error) {
schedule, err := Parse(spec)
if err != nil {
return nil, err
}
return c.Schedule(desc, spec, schedule, cmd), nil
}
// Schedule adds a Job to the Cron to be run on the given schedule.
func (c *Cron) Schedule(desc, spec string, schedule Schedule, cmd Job) *Entry {
entry := &Entry{
Description: desc,
Spec: spec,
Schedule: schedule,
Job: cmd,
}
if c.running {
c.add <- entry
} else {
c.entries = append(c.entries, entry)
}
return entry
}
// Entries returns a snapshot of the cron entries.
func (c *Cron) Entries() []*Entry {
if c.running {
c.snapshot <- nil
x := <-c.snapshot
return x
}
return c.entrySnapshot()
}
// Start the cron scheduler in its own go-routine.
func (c *Cron) Start() {
c.running = true
go c.run()
}
// Run the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
// Figure out the next activation times for each entry.
now := time.Now().Local()
for _, entry := range c.entries {
entry.Next = entry.Schedule.Next(now)
}
for {
// Determine the next entry to run.
sort.Sort(byTime(c.entries))
var effective time.Time
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
// If there are no entries yet, just sleep - it still handles new entries
// and stop requests.
effective = now.AddDate(10, 0, 0)
} else {
effective = c.entries[0].Next
func NewContext() {
var (
entry *cron.Entry
err error
)
if setting.Cron.UpdateMirror.Enabled {
entry, err = c.AddFunc("Update mirrors", setting.Cron.UpdateMirror.Schedule, models.MirrorUpdate)
if err != nil {
log.Fatal(4, "Cron[Update mirrors]: %v", err)
}
select {
case now = <-time.After(effective.Sub(now)):
// Run every entry whose next time was this effective time.
for _, e := range c.entries {
if e.Next != effective {
break
}
go e.Job.Run()
e.ExecTimes++
e.Prev = e.Next
e.Next = e.Schedule.Next(effective)
}
continue
case newEntry := <-c.add:
c.entries = append(c.entries, newEntry)
newEntry.Next = newEntry.Schedule.Next(now)
case <-c.snapshot:
c.snapshot <- c.entrySnapshot()
case <-c.stop:
return
if setting.Cron.UpdateMirror.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go models.MirrorUpdate()
}
// 'now' should be updated after newEntry and snapshot cases.
now = time.Now().Local()
}
}
// Stop the cron scheduler.
func (c *Cron) Stop() {
c.stop <- struct{}{}
c.running = false
}
// entrySnapshot returns a copy of the current cron entry list.
func (c *Cron) entrySnapshot() []*Entry {
entries := make([]*Entry, 0, len(c.entries))
for _, e := range c.entries {
entries = append(entries, &Entry{
Description: e.Description,
Spec: e.Spec,
Schedule: e.Schedule,
Next: e.Next,
Prev: e.Prev,
Job: e.Job,
ExecTimes: e.ExecTimes,
})
if setting.Cron.RepoHealthCheck.Enabled {
entry, err = c.AddFunc("Repository health check", setting.Cron.RepoHealthCheck.Schedule, models.GitFsck)
if err != nil {
log.Fatal(4, "Cron[Repository health check]: %v", err)
}
if setting.Cron.RepoHealthCheck.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go models.GitFsck()
}
}
return entries
if setting.Cron.CheckRepoStats.Enabled {
entry, err = c.AddFunc("Check repository statistics", setting.Cron.CheckRepoStats.Schedule, models.CheckRepoStats)
if err != nil {
log.Fatal(4, "Cron[Check repository statistics]: %v", err)
}
if setting.Cron.CheckRepoStats.RunAtStart {
entry.Prev = time.Now()
entry.ExecTimes++
go models.CheckRepoStats()
}
}
c.Start()
}
// ListTasks returns all running cron tasks.
func ListTasks() []*cron.Entry {
return c.Entries()
}

View File

@@ -1,255 +0,0 @@
package cron
import (
"fmt"
"sync"
"testing"
"time"
)
// Many tests schedule a job for every second, and then wait at most a second
// for it to run. This amount is just slightly larger than 1 second to
// compensate for a few milliseconds of runtime.
const ONE_SECOND = 1*time.Second + 10*time.Millisecond
// Start and stop cron with no entries.
func TestNoEntries(t *testing.T) {
cron := New()
cron.Start()
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-stop(cron):
}
}
// Start, stop, then add an entry. Verify entry doesn't run.
func TestStopCausesJobsToNotRun(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.Start()
cron.Stop()
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
select {
case <-time.After(ONE_SECOND):
// No job ran!
case <-wait(wg):
t.FailNow()
}
}
// Add a job, start cron, expect it runs.
func TestAddBeforeRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
cron.Start()
defer cron.Stop()
// Give cron 2 seconds to run our job (which is always activated).
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
// Start cron, add a job, expect it runs.
func TestAddWhileRunning(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.Start()
defer cron.Stop()
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
// Test timing with Entries.
func TestSnapshotEntries(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.AddFunc("", "@every 2s", func() { wg.Done() })
cron.Start()
defer cron.Stop()
// Cron should fire in 2 seconds. After 1 second, call Entries.
select {
case <-time.After(ONE_SECOND):
cron.Entries()
}
// Even though Entries was called, the cron should fire at the 2 second mark.
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
// Test that the entries are correctly sorted.
// Add a bunch of long-in-the-future entries, and an immediate entry, and ensure
// that the immediate entry runs immediately.
// Also: Test that multiple jobs run in the same instant.
func TestMultipleEntries(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := New()
cron.AddFunc("", "0 0 0 1 1 ?", func() {})
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
cron.AddFunc("", "0 0 0 31 12 ?", func() {})
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
// Test running the same job twice.
func TestRunningJobTwice(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := New()
cron.AddFunc("", "0 0 0 1 1 ?", func() {})
cron.AddFunc("", "0 0 0 31 12 ?", func() {})
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(2 * ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
func TestRunningMultipleSchedules(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(2)
cron := New()
cron.AddFunc("", "0 0 0 1 1 ?", func() {})
cron.AddFunc("", "0 0 0 31 12 ?", func() {})
cron.AddFunc("", "* * * * * ?", func() { wg.Done() })
cron.Schedule("", "", Every(time.Minute), FuncJob(func() {}))
cron.Schedule("", "", Every(time.Second), FuncJob(func() { wg.Done() }))
cron.Schedule("", "", Every(time.Hour), FuncJob(func() {}))
cron.Start()
defer cron.Stop()
select {
case <-time.After(2 * ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
// Test that the cron is run in the local time zone (as opposed to UTC).
func TestLocalTimezone(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
now := time.Now().Local()
spec := fmt.Sprintf("%d %d %d %d %d ?",
now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
cron := New()
cron.AddFunc("", spec, func() { wg.Done() })
cron.Start()
defer cron.Stop()
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
}
type testJob struct {
wg *sync.WaitGroup
name string
}
func (t testJob) Run() {
t.wg.Done()
}
// Simple test using Runnables.
func TestJob(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
cron := New()
cron.AddJob("", "0 0 0 30 Feb ?", testJob{wg, "job0"})
cron.AddJob("", "0 0 0 1 1 ?", testJob{wg, "job1"})
cron.AddJob("", "* * * * * ?", testJob{wg, "job2"})
cron.AddJob("", "1 0 0 1 1 ?", testJob{wg, "job3"})
cron.Schedule("", "", Every(5*time.Second+5*time.Nanosecond), testJob{wg, "job4"})
cron.Schedule("", "", Every(5*time.Minute), testJob{wg, "job5"})
cron.Start()
defer cron.Stop()
select {
case <-time.After(ONE_SECOND):
t.FailNow()
case <-wait(wg):
}
// Ensure the entries are in the right order.
expecteds := []string{"job2", "job4", "job5", "job1", "job3", "job0"}
var actuals []string
for _, entry := range cron.Entries() {
actuals = append(actuals, entry.Job.(testJob).name)
}
for i, expected := range expecteds {
if actuals[i] != expected {
t.Errorf("Jobs not in the right order. (expected) %s != %s (actual)", expecteds, actuals)
t.FailNow()
}
}
}
func wait(wg *sync.WaitGroup) chan bool {
ch := make(chan bool)
go func() {
wg.Wait()
ch <- true
}()
return ch
}
func stop(cron *Cron) chan bool {
ch := make(chan bool)
go func() {
cron.Stop()
ch <- true
}()
return ch
}

View File

@@ -1,129 +0,0 @@
/*
Package cron implements a cron spec parser and job runner.
Usage
Callers may register Funcs to be invoked on a given schedule. Cron will run
them in their own goroutines.
c := cron.New()
c.AddFunc("Every hour on the half hour","0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("Every hour","@hourly", func() { fmt.Println("Every hour") })
c.AddFunc("Every hour and a half","@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
CRON Expression Format
A cron expression represents a set of times, using 6 space-separated fields.
Field name | Mandatory? | Allowed values | Allowed special characters
---------- | ---------- | -------------- | --------------------------
Seconds | Yes | 0-59 | * / , -
Minutes | Yes | 0-59 | * / , -
Hours | Yes | 0-23 | * / , -
Day of month | Yes | 1-31 | * / , - ?
Month | Yes | 1-12 or JAN-DEC | * / , -
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
Note: Month and Day-of-week field values are case insensitive. "SUN", "Sun",
and "sun" are equally accepted.
Special Characters
Asterisk ( * )
The asterisk indicates that the cron expression will match for all values of the
field; e.g., using an asterisk in the 5th field (month) would indicate every
month.
Slash ( / )
Slashes are used to describe increments of ranges. For example 3-59/15 in the
1st field (minutes) would indicate the 3rd minute of the hour and every 15
minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",
that is, an increment over the largest possible range of the field. The form
"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the
increment until the end of that specific range. It does not wrap around.
Comma ( , )
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in
the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
Hyphen ( - )
Hyphens are used to define ranges. For example, 9-17 would indicate every
hour between 9am and 5pm inclusive.
Question mark ( ? )
Question mark may be used instead of '*' for leaving either day-of-month or
day-of-week blank.
Predefined schedules
You may use one of several pre-defined schedules in place of a cron expression.
Entry | Description | Equivalent To
----- | ----------- | -------------
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 *
@monthly | Run once a month, midnight, first of month | 0 0 0 1 * *
@weekly | Run once a week, midnight on Sunday | 0 0 0 * * 0
@daily (or @midnight) | Run once a day, midnight | 0 0 0 * * *
@hourly | Run once an hour, beginning of hour | 0 0 * * * *
Intervals
You may also schedule a job to execute at fixed intervals. This is supported by
formatting the cron spec like this:
@every <duration>
where "duration" is a string accepted by time.ParseDuration
(http://golang.org/pkg/time/#ParseDuration).
For example, "@every 1h30m10s" would indicate a schedule that activates every
1 hour, 30 minutes, 10 seconds.
Note: The interval does not take the job runtime into account. For example,
if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
it will have only 2 minutes of idle time between each run.
Time zones
All interpretation and scheduling is done in the machine's local time zone (as
provided by the Go time package (http://www.golang.org/pkg/time).
Be aware that jobs scheduled during daylight-savings leap-ahead transitions will
not be run!
Thread safety
Since the Cron service runs concurrently with the calling code, some amount of
care must be taken to ensure proper synchronization.
All cron methods are designed to be correctly synchronized as long as the caller
ensures that invocations have a clear happens-before ordering between them.
Implementation
Cron entries are stored in an array, sorted by their next activation time. Cron
sleeps until the next job is due to be run.
Upon waking:
- it runs each entry that is active on that second
- it calculates the next run times for the jobs that were run
- it re-sorts the array of entries by next activation time.
- it goes to sleep until the soonest job.
*/
package cron

View File

@@ -1,231 +0,0 @@
package cron
import (
"fmt"
"log"
"math"
"strconv"
"strings"
"time"
)
// Parse returns a new crontab schedule representing the given spec.
// It returns a descriptive error if the spec is not valid.
//
// It accepts
// - Full crontab specs, e.g. "* * * * * ?"
// - Descriptors, e.g. "@midnight", "@every 1h30m"
func Parse(spec string) (_ Schedule, err error) {
// Convert panics into errors
defer func() {
if recovered := recover(); recovered != nil {
err = fmt.Errorf("%v", recovered)
}
}()
if spec[0] == '@' {
return parseDescriptor(spec), nil
}
// Split on whitespace. We require 5 or 6 fields.
// (second) (minute) (hour) (day of month) (month) (day of week, optional)
fields := strings.Fields(spec)
if len(fields) != 5 && len(fields) != 6 {
log.Panicf("Expected 5 or 6 fields, found %d: %s", len(fields), spec)
}
// If a sixth field is not provided (DayOfWeek), then it is equivalent to star.
if len(fields) == 5 {
fields = append(fields, "*")
}
schedule := &SpecSchedule{
Second: getField(fields[0], seconds),
Minute: getField(fields[1], minutes),
Hour: getField(fields[2], hours),
Dom: getField(fields[3], dom),
Month: getField(fields[4], months),
Dow: getField(fields[5], dow),
}
return schedule, nil
}
// getField returns an Int with the bits set representing all of the times that
// the field represents. A "field" is a comma-separated list of "ranges".
func getField(field string, r bounds) uint64 {
// list = range {"," range}
var bits uint64
ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
for _, expr := range ranges {
bits |= getRange(expr, r)
}
return bits
}
// getRange returns the bits indicated by the given expression:
// number | number "-" number [ "/" number ]
func getRange(expr string, r bounds) uint64 {
var (
start, end, step uint
rangeAndStep = strings.Split(expr, "/")
lowAndHigh = strings.Split(rangeAndStep[0], "-")
singleDigit = len(lowAndHigh) == 1
)
var extra_star uint64
if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
start = r.min
end = r.max
extra_star = starBit
} else {
start = parseIntOrName(lowAndHigh[0], r.names)
switch len(lowAndHigh) {
case 1:
end = start
case 2:
end = parseIntOrName(lowAndHigh[1], r.names)
default:
log.Panicf("Too many hyphens: %s", expr)
}
}
switch len(rangeAndStep) {
case 1:
step = 1
case 2:
step = mustParseInt(rangeAndStep[1])
// Special handling: "N/step" means "N-max/step".
if singleDigit {
end = r.max
}
default:
log.Panicf("Too many slashes: %s", expr)
}
if start < r.min {
log.Panicf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
}
if end > r.max {
log.Panicf("End of range (%d) above maximum (%d): %s", end, r.max, expr)
}
if start > end {
log.Panicf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
}
return getBits(start, end, step) | extra_star
}
// parseIntOrName returns the (possibly-named) integer contained in expr.
func parseIntOrName(expr string, names map[string]uint) uint {
if names != nil {
if namedInt, ok := names[strings.ToLower(expr)]; ok {
return namedInt
}
}
return mustParseInt(expr)
}
// mustParseInt parses the given expression as an int or panics.
func mustParseInt(expr string) uint {
num, err := strconv.Atoi(expr)
if err != nil {
log.Panicf("Failed to parse int from %s: %s", expr, err)
}
if num < 0 {
log.Panicf("Negative number (%d) not allowed: %s", num, expr)
}
return uint(num)
}
// getBits sets all bits in the range [min, max], modulo the given step size.
func getBits(min, max, step uint) uint64 {
var bits uint64
// If step is 1, use shifts.
if step == 1 {
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
}
// Else, use a simple loop.
for i := min; i <= max; i += step {
bits |= 1 << i
}
return bits
}
// all returns all bits within the given bounds. (plus the star bit)
func all(r bounds) uint64 {
return getBits(r.min, r.max, 1) | starBit
}
// parseDescriptor returns a pre-defined schedule for the expression, or panics
// if none matches.
func parseDescriptor(spec string) Schedule {
switch spec {
case "@yearly", "@annually":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: 1 << months.min,
Dow: all(dow),
}
case "@monthly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: 1 << dom.min,
Month: all(months),
Dow: all(dow),
}
case "@weekly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: 1 << dow.min,
}
case "@daily", "@midnight":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: 1 << hours.min,
Dom: all(dom),
Month: all(months),
Dow: all(dow),
}
case "@hourly":
return &SpecSchedule{
Second: 1 << seconds.min,
Minute: 1 << minutes.min,
Hour: all(hours),
Dom: all(dom),
Month: all(months),
Dow: all(dow),
}
}
const every = "@every "
if strings.HasPrefix(spec, every) {
duration, err := time.ParseDuration(spec[len(every):])
if err != nil {
log.Panicf("Failed to parse duration %s: %s", spec, err)
}
return Every(duration)
}
log.Panicf("Unrecognized descriptor: %s", spec)
return nil
}

View File

@@ -1,117 +0,0 @@
package cron
import (
"reflect"
"testing"
"time"
)
func TestRange(t *testing.T) {
ranges := []struct {
expr string
min, max uint
expected uint64
}{
{"5", 0, 7, 1 << 5},
{"0", 0, 7, 1 << 0},
{"7", 0, 7, 1 << 7},
{"5-5", 0, 7, 1 << 5},
{"5-6", 0, 7, 1<<5 | 1<<6},
{"5-7", 0, 7, 1<<5 | 1<<6 | 1<<7},
{"5-6/2", 0, 7, 1 << 5},
{"5-7/2", 0, 7, 1<<5 | 1<<7},
{"5-7/1", 0, 7, 1<<5 | 1<<6 | 1<<7},
{"*", 1, 3, 1<<1 | 1<<2 | 1<<3 | starBit},
{"*/2", 1, 3, 1<<1 | 1<<3 | starBit},
}
for _, c := range ranges {
actual := getRange(c.expr, bounds{c.min, c.max, nil})
if actual != c.expected {
t.Errorf("%s => (expected) %d != %d (actual)", c.expr, c.expected, actual)
}
}
}
func TestField(t *testing.T) {
fields := []struct {
expr string
min, max uint
expected uint64
}{
{"5", 1, 7, 1 << 5},
{"5,6", 1, 7, 1<<5 | 1<<6},
{"5,6,7", 1, 7, 1<<5 | 1<<6 | 1<<7},
{"1,5-7/2,3", 1, 7, 1<<1 | 1<<5 | 1<<7 | 1<<3},
}
for _, c := range fields {
actual := getField(c.expr, bounds{c.min, c.max, nil})
if actual != c.expected {
t.Errorf("%s => (expected) %d != %d (actual)", c.expr, c.expected, actual)
}
}
}
func TestBits(t *testing.T) {
allBits := []struct {
r bounds
expected uint64
}{
{minutes, 0xfffffffffffffff}, // 0-59: 60 ones
{hours, 0xffffff}, // 0-23: 24 ones
{dom, 0xfffffffe}, // 1-31: 31 ones, 1 zero
{months, 0x1ffe}, // 1-12: 12 ones, 1 zero
{dow, 0x7f}, // 0-6: 7 ones
}
for _, c := range allBits {
actual := all(c.r) // all() adds the starBit, so compensate for that..
if c.expected|starBit != actual {
t.Errorf("%d-%d/%d => (expected) %b != %b (actual)",
c.r.min, c.r.max, 1, c.expected|starBit, actual)
}
}
bits := []struct {
min, max, step uint
expected uint64
}{
{0, 0, 1, 0x1},
{1, 1, 1, 0x2},
{1, 5, 2, 0x2a}, // 101010
{1, 4, 2, 0xa}, // 1010
}
for _, c := range bits {
actual := getBits(c.min, c.max, c.step)
if c.expected != actual {
t.Errorf("%d-%d/%d => (expected) %b != %b (actual)",
c.min, c.max, c.step, c.expected, actual)
}
}
}
func TestSpecSchedule(t *testing.T) {
entries := []struct {
expr string
expected Schedule
}{
{"* 5 * * * *", &SpecSchedule{all(seconds), 1 << 5, all(hours), all(dom), all(months), all(dow)}},
{"@every 5m", ConstantDelaySchedule{time.Duration(5) * time.Minute}},
}
for _, c := range entries {
actual, err := Parse(c.expr)
if err != nil {
t.Error(err)
}
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("%s => (expected) %v != %v (actual)", c.expr, c.expected, actual)
}
}
}

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