Compare commits

...

182 Commits

Author SHA1 Message Date
Unknwon
e0a787b5ee Update locales 2017-04-05 13:26:53 -04:00
Unknwon
63598688e4 pkg/markup: init default sanitizer.policy
App would panic if user has validation error on installation and
the sanitizer is not yet built. Therefore we need a minimal valid
object for sanitizer at start.
2017-04-05 13:12:05 -04:00
Unknwon
497cdc9250 user/setting: reorder navbar 2017-04-05 09:27:42 -04:00
Unknwon
edaf14f2b6 Refactoring: remove tool.TplName 2017-04-05 09:17:21 -04:00
Unknwon
6fbb984ebf Refactoring: rename pkg/base -> pkg/tool 2017-04-05 09:05:40 -04:00
Unknwon
ba151eda0a css: improve fonts under Windows 2017-04-04 21:05:01 -04:00
Unknwon
c05717a5f0 models/mirror: feed git.IsRepoURLAccessible with raw mirror address 2017-04-04 20:42:18 -04:00
Unknwon
5a488b6517 models/mirror: unescape credentials at read (#4014)
If we save credentials already escaped, 'url.QueryEscape' still
escapes it and makes the credentials become incorrect.
2017-04-04 20:21:35 -04:00
Unknwon
ae1d50d19a models/mirror: escape credentials before write mirror address (#4014)
Special characters such as '@', ';', '#' and ':' could occur in
password portion of credentials, which breaks the interpretation
and saves 'config' file in with extra characters that are not
recognized by Git (due to INI library).
2017-04-04 19:40:46 -04:00
Unknwon
fe25effe7c repo/http: fix client is not informed to provide credentials
When Git client has cached credentials for a site, missing response
header 'WWW-Authenticate: Basic realm="."' will result in Git client
does not prompt user to input credentials again but plain error
message and halts push/pull process.
2017-04-04 19:36:30 -04:00
Unknwon
d05395fe90 Refactoring: rename modules -> pkg
Reasons to change:

1. Shorter than 'modules'
2. More generally used by other Go projects
3. Corresponds to the naming of '$GOPATH/pkg' directory
2017-04-04 19:29:59 -04:00
Unknwon
37b10666de modules/context: add *Context. ServerError method
Also use constants from net/http to replace raw integers.
2017-04-04 19:25:05 -04:00
Unknwon
41c8e87be8 repo/commit: improve error detection
Response 404 not 500 for raw diff if object does not exist.
2017-04-04 02:01:29 -04:00
Unknwon
55afc1ad21 models/repo_diff: move core functions to gogits/git-module 2017-04-04 01:45:57 -04:00
Unknwon
16c6ca72cd css: fix font of .ui.label.button style 2017-04-04 01:19:47 -04:00
Unknwon
b873ec2bce templates/repo/branches: hide pull request button if not allowed (#4377) 2017-04-03 22:24:21 -04:00
Unknwon
1bc805bb4b public: update Semantic UI 2.2.7 -> 2.2.10
[CI SKIP]
2017-04-03 22:20:17 -04:00
Unknwon
348c75c91b issue: response wrong type of comment from AJAX 2017-04-03 20:06:15 -04:00
Unknwon
76ebdb265b css: update fonts
[CI SKIP]
2017-04-03 18:20:49 -04:00
Unknwon
88ae3510ff Prepare release 2017-04-03 16:26:43 -04:00
Unknwon
c07899701a vendor: update github.com/gogits/git-module 2017-04-03 15:09:53 -04:00
Unknwon
ab42671c63 repo: handle git.ErrUnsupportedVersion error type 2017-04-01 17:56:55 -04:00
Unknwon
b3ac33cbcf vendor: update github.com/gogits/git-module 2017-04-01 17:50:11 -04:00
Unknwon
3b94162803 modules/setting: set default session GC interval to 3600s 2017-03-31 23:55:42 -04:00
Unknwon
52aade232d modes: fix test compile error 2017-03-31 18:28:08 -04:00
Unknwon
3a9276307c modules/markup: move common functions to markup.go 2017-03-31 17:46:57 -04:00
Unknwon
ca6326c937 modules/base: move file-related functions to file.go 2017-03-31 17:20:05 -04:00
Unknwon
8da16ac302 modules/markup: rename Markdown render fucntions
The unified function 'Markdown' accepts both string or []byte type
input and renders to HTML with []byte type.
2017-03-31 16:37:30 -04:00
Unknwon
761bb3cf53 modules/markup: protect sanitizer from possible modification
Only expose public APIs for 'Sanitize' and 'SanitizeBytes' to
eliminate unintentional modifications to sanitizer policy. Also
use 'sync.Once' to make sure multiple calls of 'NewSanitizer' is
safe (although should never happen, but this is a better way).
2017-03-31 16:19:10 -04:00
Unknwon
c1c269d9ef modules: rename markdown -> markup
To further support more markup languages (e.g. Org-mode, AsciiDoc,
reStructuredText), the name 'markdown' is inappropriate.

This is the first step towards more markup language support.
2017-03-31 15:29:43 -04:00
Unknwon
9edac05e05 templates/repo: improve README icon and font 2017-03-31 15:11:40 -04:00
Unknwon
9c1620d49c css: font-family fixes for Chinese 2017-03-31 14:13:25 -04:00
John Behm
65bb6eb284 locale: update TRANSLATORS (#4372)
* Update TRANSLATORS

* Update TRANSLATORS
2017-03-31 12:37:46 -04:00
Unknwon
aff55ff105 vendor: update github.com/go-macaron/captcha
[CI SKIP]
2017-03-30 12:35:43 -04:00
Unknwon
4a67bb5806 migrations.v17: skip if table not exist 2017-03-30 11:37:27 -04:00
Unknwon
1afafde3b3 user/setting: preserve user input with validation error (#1123) 2017-03-30 01:03:44 -04:00
Unknwon
ab634ce61a cmd/web: fix routes requires sign in (#4359)
Redirect user to sign in page when visit private repository with
public issues if user want to post comment or create new issue.
2017-03-30 00:34:20 -04:00
Unknwon
9d06ebd01a markdown: improve filter of class attribute for code blocks
Only allow HighlightJS specific classes.

Reported by ChALkeR.
2017-03-29 19:52:53 -04:00
Kyle McCullough
09723ec0e5 migration.v17: handle mysql error (#4361) 2017-03-29 19:02:07 -04:00
Hassan Amouhzi
864761c2d0 js: use jQuery .find() (#4343) 2017-03-28 17:36:48 -04:00
Unknwon
abe7f7bc36 migration.v17: add nil error check 2017-03-28 16:38:16 -04:00
Unknwon
717bcc4ad8 migration/v17: skip if protect_branch_whitelist table not exist (#4355) 2017-03-28 11:20:58 -04:00
Unknwon
11ffdac3f8 org/dashboard: fix wrong repository count (#4351)
Should not include count for inaccessible repositories.
2017-03-28 11:16:29 -04:00
David Beitey
cf7d5d0c56 docker: fix heading in README.md (#4353)
The unicode non-breaking space character was breaking the heading format; this switches that character for an ASCII space.
2017-03-28 07:50:36 -04:00
Unknwon
375f1b1fde Prepare release
[CI SKIP]
2017-03-27 14:56:56 -04:00
Unknwon
ad3c6ef205 Update locales 2017-03-27 14:40:55 -04:00
Unknwon
30d9e2ee3c docker: use vendor to replace go get 2017-03-27 14:04:48 -04:00
Unknwon
1038916460 models/protect_branch: fix whitelist with invalid 'protect_branch_id' (#4333)
If user creates a protect branch for the first time (which has ID=0),
it generates invalid whitelist records with 'protect_branch_id=0'.
This prevents future updates of protect branch whitelist.

Migration: remove existing invalid protect branch whitelist records.
2017-03-27 13:13:04 -04:00
Unknwon
73de9f9d6a repo/settings/branches: add prompt for bare repository 2017-03-27 13:12:29 -04:00
Jonas
f40eb9774e modes/mirror: corrected NextUpdate not set (#4345) 2017-03-26 23:24:48 -04:00
Pablo Saavedra
496e07c1c9 models/repo: avoid duplicated results in SearchRepositoryByName (#4344) 2017-03-26 23:23:17 -04:00
Unknwon
c238647020 cmd/web: remove dependency version checker 2017-03-25 04:17:55 -04:00
Unknwon
78f94986e3 user/settings: fix bad error handle of leave organization 2017-03-25 03:44:12 -04:00
Unknwon
8f52ab8201 models/repo_editor: add pull request test task after commit (#4338) 2017-03-25 03:36:13 -04:00
Unknwon
260ebcc1ca repo/milestone: simplify code 2017-03-24 18:54:17 -04:00
Unknwon
09cb48e41c repo: recalculate milestone completeness on issue list (#4316) 2017-03-24 18:36:35 -04:00
Unknwon
674106c7b6 repo: cleanup some code 2017-03-24 16:32:14 -04:00
Unknwon
8196430f47 repo: allow private repository to have public wiki or issues
Relates to #649 and #2157
2017-03-24 16:25:40 -04:00
Unknwon
7a99e56893 repo: update size after fork, migrate and mirror sync (#4336) 2017-03-24 14:22:19 -04:00
Unknwon
79ba0314e9 milestone: only show issue-related count under issue list (#4316) 2017-03-24 14:00:01 -04:00
Unknwon
c441f8080e api/repo: add endpoint to sync mirror (#2235) 2017-03-23 20:46:39 -04:00
Unknwon
bd1e757350 user: remove sanitizer for FullName (#1937) 2017-03-23 20:24:02 -04:00
Unknwon
3144be5c81 repo: remove legacy sanitizer for repository description
Related to #4329.
2017-03-23 20:23:23 -04:00
Unknwon
fdc7cb565d repo: fix unable to propose pull request from secondary fork (#4324) 2017-03-23 20:04:20 -04:00
Unknwon
a6dbde4c46 user/settings: minor input style fix (#4327) 2017-03-23 19:39:05 -04:00
Unknwon
8ce23e2c71 cmd/backup: able to specify archive name (#4320)
Added flag '--archive-name' for backup command.
2017-03-23 18:44:24 -04:00
Unknwon
8a3f4fc616 models: add config options for XORM logger (#3183)
Added new config section '[log.xorm]'.
2017-03-23 18:34:25 -04:00
Unknwon
66c1e6b0e8 user/settings: complete repositories panel (#4312) 2017-03-23 14:28:31 -04:00
Unknwon
beee6e03b1 error: move ErrRepoNotExist -> errors.RepoNotExist 2017-03-23 14:27:34 -04:00
Rob Richards
902372067c user/settings: add repositories panel (#4312)
* Add Repositories panel to user settings
issue #4277

* modified personal repo settings format
2017-03-23 12:57:43 -04:00
Nikolay Korotkiy
7adaf8f812 locale: fix language names (#4330) 2017-03-23 11:37:46 -04:00
Unknwon
71753cdd46 templates/label: another minor style improve 2017-03-22 16:20:31 -04:00
Unknwon
d3363430dc templates/label: minor style improve
Add an empty space to make <span> have width.
2017-03-22 15:54:27 -04:00
Unknwon
945e65eedf README: update alts
[CI SKIP]
2017-03-22 15:28:22 -04:00
Unknwon
85a050fca7 issue: fix redirect to random issue if index does not exist (#4315) 2017-03-22 13:20:29 -04:00
Unknwon
bb86d66496 repo: rename PageIsViewCode -> PageIsViewFiles
Also highlight 'Files' tab when use editor.
2017-03-22 12:58:12 -04:00
Unknwon
aba8789542 vendor: update github.com/go-macaron/session (#3363) 2017-03-20 14:06:41 -04:00
Unknwon
5f1bbbde49 user/settings: fix cannot change profile for non-local users (#4313) 2017-03-20 14:01:23 -04:00
Unknwon
0203eaab00 user/dashboard: hide More button if reached end on first load 2017-03-20 14:00:51 -04:00
Unknwon
2807274e2d repo/webhook: able to retrigger delivery history (#2187) 2017-03-19 17:44:46 -04:00
Unknwon
55a5ad5cdc api/repo: fix incorrect permission values (#4309) 2017-03-18 16:44:40 -04:00
Unknwon
b3c4a39208 setting: add config option for raw file render mode (#3608)
Added '[repository] ENABLE_RAW_FILE_RENDER_MODE'.
2017-03-17 19:42:21 -04:00
Unknwon
cac7af2c78 explore: able list and search for private but accessible repositories (#3088) 2017-03-17 19:17:40 -04:00
Unknwon
2d4dc544be install: able to enable console mode (#3119) 2017-03-17 00:16:46 -04:00
Unknwon
171f97868d repo: allow issues and wiki for bare repository (#4104) 2017-03-16 23:10:45 -04:00
Unknwon
becaec19a7 setting: add login status cookie (#2885)
Added config options EnableLoginStatusCookie and LoginStatusCookieName under section '[security]'.
2017-03-16 22:42:17 -04:00
Unknwon
bc630cc52b repo/commit: able to config default commits page size (#4230)
Added config option '[ui.user] COMMITS_PAGING_NUM'.
2017-03-16 22:28:32 -04:00
Unknwon
d591cb0dfb dashboard/feeds: able to load more history (#2511) 2017-03-16 22:05:53 -04:00
Unknwon
07a9cbe0a9 setting: able to config dashboard news feed paging number (#4247) 2017-03-16 20:25:28 -04:00
Unknwon
7c802f6d83 repo/setting: filter out deleted branch in protect list (#4288) 2017-03-16 20:09:27 -04:00
Unknwon
431e930367 Add Go 1.8 to .travis.yml 2017-03-16 17:46:55 -04:00
Unknwon
9e8ffa14cb webhook: add file status to push event (#3897) 2017-03-16 17:33:04 -04:00
Unknwon
0ccd7c97ab models: rename ErrUserNotExist -> errors.UserNotExist 2017-03-16 17:18:43 -04:00
Unknwon
4e64e71e28 templates/repo/webhook: move to its own directory 2017-03-16 15:50:18 -04:00
Unknwon
86c7f45383 js: minor fix for #4294 2017-03-15 16:38:41 -04:00
Brian Paulson
50b36a732c ui: added Select class to ui.dropdown menus to prevent label changing (#4294) 2017-03-15 16:35:13 -04:00
Unknwon
f54bcba339 Update locales 2017-03-13 23:41:22 -04:00
Unknwon
f0209ac2f6 api: handle new events for hook 2017-03-13 14:32:16 -04:00
Unknwon
e1dcd11051 repo/settings: improve Git hook editor 2017-03-13 06:00:37 -04:00
Unknwon
24734a33e7 release: improve attachment handle 2017-03-13 05:26:17 -04:00
Unknwon
1df54ea0cd release: able to add attchments to release (#1614)
Added new config section '[release.attachment]’.
2017-03-13 04:32:20 -04:00
Unknwon
e6df2259ab explore: panic if search without login (#3088) 2017-03-13 02:41:04 -04:00
Unknwon
96ae0129ef models/repo: minor code style and comment fix (#4273) 2017-03-13 00:53:50 -04:00
Rob Richards
aaadc61ee8 models/repo: allow SearchRepos to return private but accessible repositories (#4273)
* models/repo.go SearchRepositoryByName()
Updated function to return public and private repositories that the logged in user has been given rights to view
issue #3088

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

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

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

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

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

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

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

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

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

Addresses #2072, #3708, #648
2017-02-27 22:48:19 -05:00
Unknwon
b06f299748 webhook: add fork event 2017-02-27 22:48:18 -05:00
Unknwon
beea014343 template: add more icons for news feed 2017-02-27 22:47:33 -05:00
Unknwon
70072e2842 dashboard: add delete branch and tag news feeds 2017-02-27 22:47:33 -05:00
Unknwon
f0086e66ae webhook: able to detect delete branch or tag (#2315) 2017-02-27 22:47:21 -05:00
Unknwon
7fe13e72d8 cmd: refactoring command name 2017-02-27 22:47:12 -05:00
Unknwon
87f0ce793d repo: able to perform initial commit on behave of actual user 2017-02-27 22:47:12 -05:00
Unknwon
25cf755f30 editor: fix compile error 2017-02-27 22:46:42 -05:00
Unknwon
c7a8051a71 mailer: make text/html as default format
Change config option from '[mailer] ENABLE_HTML_ALTERNATIVE' to '[mailer] USE_PLAIN_TEXT'
2017-02-27 22:46:42 -05:00
Unknwon
a47553b7aa admin/config: remove duplicated config info 2017-02-27 22:46:32 -05:00
Unknwon
d7954014a4 markdown: fix links for image nested inside a link (#2636) 2017-02-27 22:46:32 -05:00
Unknwon
429345b9df editor: fix cannot create branch with slashes (#3568) 2017-02-27 22:46:32 -05:00
Unknwon
eaab01fa49 public: update Semantic UI from 2.2.7 -> 2.2.9 2017-02-27 22:45:35 -05:00
Unknwon
4f9c5981a9 refactoring: modules/auth/*_form.go -> modules/form 2017-02-27 22:45:35 -05:00
299 changed files with 17548 additions and 11522 deletions

View File

@@ -7,7 +7,7 @@ watch_all = true
watch_dirs = [
"$WORKDIR/cmd",
"$WORKDIR/models",
"$WORKDIR/modules",
"$WORKDIR/pkg",
"$WORKDIR/routers"
]
watch_exts = [".go"]

View File

@@ -14,6 +14,4 @@ config.codekit
.editorconfig
.gitignore
Dockerfile*
vendor
vendor/**
gogs

View File

@@ -21,5 +21,5 @@ indent_style = space
indent_size = 2
[*.js]
indent_style = space
indent_style = tab
indent_size = 4

9
.gitattributes vendored
View File

@@ -1,11 +1,10 @@
public/conf/gitignore/* linguist-vendored
public/conf/license/* linguist-vendored
conf/gitignore/* linguist-vendored
conf/license/* linguist-vendored
public/assets/* linguist-vendored
public/plugins/* linguist-vendored
public/plugins/* linguist-vendored
public/css/themes/* linguist-vendored
public/css/github.min.css linguist-vendored
public/css/semantic-2.2.9.min.css linguist-vendored
public/css/semantic-2.2.10.min.css linguist-vendored
public/js/libs/* linguist-vendored
public/js/jquery-1.11.3.min.js linguist-vendored
public/js/semantic-2.2.9.min.js linguist-vendored
public/js/semantic-2.2.10.min.js linguist-vendored

View File

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

View File

@@ -3,6 +3,7 @@ go:
- 1.5.x
- 1.6.x
- 1.7.x
- 1.8.x
- master
before_install:

View File

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

View File

@@ -1,9 +1,9 @@
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)"
LDFLAGS += -X "github.com/gogits/gogs/pkg/setting.BuildTime=$(shell date -u '+%Y-%m-%d %I:%M:%S %Z')"
LDFLAGS += -X "github.com/gogits/gogs/pkg/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
GENERATED := pkg/bindata/bindata.go public/css/gogs.css
OS := $(shell uname)
@@ -27,7 +27,7 @@ dist: release
govet:
$(GOVET) gogs.go
$(GOVET) models modules routers
$(GOVET) models pkg routers
build: $(GENERATED)
go install $(BUILD_FLAGS) -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
@@ -50,9 +50,9 @@ pack:
release: build pack
bindata: modules/bindata/bindata.go
bindata: pkg/bindata/bindata.go
modules/bindata/bindata.go: $(DATA_FILES)
pkg/bindata/bindata.go: $(DATA_FILES)
go-bindata -o=$@ -ignore="\\.DS_Store|README.md|TRANSLATORS" -pkg=bindata conf/...
less: public/css/gogs.css
@@ -70,11 +70,11 @@ test:
go test -cover -race ./...
fixme:
grep -rnw "FIXME" cmd routers models modules
grep -rnw "FIXME" cmd routers models pkg
todo:
grep -rnw "TODO" cmd routers models modules
grep -rnw "TODO" cmd routers models pkg
# Legacy code should be remove by the time of release
legacy:
grep -rnw "LEGACY" cmd routers models modules
grep -rnw "LEGACY" cmd routers models pkg

View File

@@ -7,16 +7,16 @@ Gogs [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](http
| 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)|
|![Dashboard](https://gogs.io/img/screenshots/1.png)|![Repository](https://gogs.io/img/screenshots/2.png)|![Editor](https://gogs.io/img/screenshots/3.png)|
|![Profile](https://gogs.io/img/screenshots/4.png)|![Diff](https://gogs.io/img/screenshots/5.png)|![Repository Settings](https://gogs.io/img/screenshots/6.png?ts=20170322)|
|![Webhook](https://gogs.io/img/screenshots/7.png)|![Organization](https://gogs.io/img/screenshots/8.png)|![Admin Dashboard](https://gogs.io/img/screenshots/9.png)|
### Important Notes
1. **YOU MUST READ [Contributing Code](https://github.com/gogits/gogs/wiki/Contributing-Code) BEFORE STARTING TO WORK ON A PULL REQUEST**.
2. Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
3. The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
4. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks!
4. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**, and the name you want to be credited as. Thanks!
5. If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki).
6. If your team/company is using Gogs and would like to put your logo on [our website](https://gogs.io), contact us by any means.
@@ -50,7 +50,7 @@ The goal of this project is to make the easiest, fastest, and most painless way
- Gravatar and Federated avatar with custom source
- Mail service
- Administration panel
- Supports MySQL, PostgreSQL, SQLite3, MSSQL and [TiDB](https://github.com/pingcap/tidb) (experimental)
- Supports MySQL, PostgreSQL, SQLite3, MSSQL and [TiDB](https://github.com/pingcap/tidb) (via MySQL protocol)
- Multi-language support ([23 languages](https://crowdin.com/project/gogs))
## Hardware Requirements

View File

@@ -9,7 +9,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
## 项目概览
- 有关基本用法和变更日志,请通过 [使用手册](https://gogs.io/docs/intro/) 查看。
- 有关基本用法和变更日志,请通过 [使用手册](https://gogs.io/docs/intro) 查看。
- 想要先睹为快?直接去 [在线体验](https://try.gogs.io/gogs/gogs) 。
- 使用过程中遇到问题?尝试从 [故障排查](https://gogs.io/docs/intro/troubleshooting.html) 页面或 [用户论坛](https://discuss.gogs.io/) 获取帮助。
- 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](https://gogs.io/docs/features/i18n.html)
@@ -31,7 +31,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- 支持 Jupyter Notebook
- 支持邮件服务
- 支持后台管理面板
- 支持 MySQL、PostgreSQL、SQLite3、MSSQL 和 [TiDB](https://github.com/pingcap/tidb)实验性支持) 数据库
- 支持 MySQL、PostgreSQL、SQLite3、MSSQL 和 [TiDB](https://github.com/pingcap/tidb)通过 MySQL 协议)数据库
- 支持多语言本地化([23 种语言]([more](https://crowdin.com/project/gogs))
## 硬件要求

View File

@@ -10,11 +10,11 @@ import (
"github.com/urfave/cli"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/setting"
)
var (
CmdAdmin = cli.Command{
Admin = cli.Command{
Name: "admin",
Usage: "Preform admin operations on command line",
Description: `Allow using internal logic of Gogs without hacking into the source code

136
cmd/backup.go Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,11 +15,11 @@ import (
"github.com/Unknwon/com"
"github.com/urfave/cli"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/setting"
)
var (
CmdImport = cli.Command{
Import = cli.Command{
Name: "import",
Usage: "Import portable data as local Gogs data",
Description: `Allow user import data from other Gogs installations to local instance

129
cmd/restore.go Normal file
View File

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

View File

@@ -17,7 +17,8 @@ import (
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/setting"
http "github.com/gogits/gogs/routers/repo"
)
@@ -153,7 +154,7 @@ func runServ(c *cli.Context) error {
owner, err := models.GetUserByName(ownerName)
if err != nil {
if models.IsErrUserNotExist(err) {
if errors.IsUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", ownerName)
}
fail("Internal error", "Fail to get repository owner '%s': %v", ownerName, err)
@@ -161,7 +162,7 @@ func runServ(c *cli.Context) error {
repo, err := models.GetRepositoryByName(owner.ID, repoName)
if err != nil {
if models.IsErrRepoNotExist(err) {
if errors.IsRepoNotExist(err) {
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", owner.Name, repoName)
}
fail("Internal error", "Fail to get repository: %v", err)

View File

@@ -15,6 +15,7 @@ import (
"path"
"strings"
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"github.com/go-macaron/cache"
"github.com/go-macaron/captcha"
@@ -23,23 +24,18 @@ import (
"github.com/go-macaron/i18n"
"github.com/go-macaron/session"
"github.com/go-macaron/toolbox"
"github.com/go-xorm/xorm"
"github.com/mcuadros/go-version"
"github.com/urfave/cli"
log "gopkg.in/clog.v1"
"gopkg.in/ini.v1"
"gopkg.in/macaron.v1"
"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/bindata"
"github.com/gogits/gogs/modules/context"
"github.com/gogits/gogs/modules/mailer"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template"
"github.com/gogits/gogs/pkg/bindata"
"github.com/gogits/gogs/pkg/context"
"github.com/gogits/gogs/pkg/form"
"github.com/gogits/gogs/pkg/mailer"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/template"
"github.com/gogits/gogs/routers"
"github.com/gogits/gogs/routers/admin"
apiv1 "github.com/gogits/gogs/routers/api/v1"
@@ -49,9 +45,9 @@ import (
"github.com/gogits/gogs/routers/user"
)
var CmdWeb = cli.Command{
var Web = cli.Command{
Name: "web",
Usage: "Start Gogs web server",
Usage: "Start web server",
Description: `Gogs web server is the only thing you need to run,
and it takes care of all the other things for you`,
Action: runWeb,
@@ -61,49 +57,19 @@ and it takes care of all the other things for you`,
},
}
type VerChecker struct {
ImportPath string
Version func() string
Expected string
}
// checkVersion checks if binary matches the version of templates files.
func checkVersion() {
// Templates.
data, err := ioutil.ReadFile(setting.StaticRootPath + "/templates/.VERSION")
if err != nil {
log.Fatal(4, "Fail to read 'templates/.VERSION': %v", err)
log.Fatal(2, "Fail to read 'templates/.VERSION': %v", err)
}
tplVer := string(data)
if tplVer != setting.AppVer {
if version.Compare(tplVer, setting.AppVer, ">") {
log.Fatal(4, "Binary version is lower than template file version, did you forget to recompile Gogs?")
log.Fatal(2, "Binary version is lower than template file version, did you forget to recompile Gogs?")
} else {
log.Fatal(4, "Binary version is higher than template file version, did you forget to update template files?")
}
}
// Check dependency version.
// LEGACY [0.11]: no need to check version as we check in vendor into version control
checkers := []VerChecker{
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.6.0"},
{"github.com/go-macaron/binding", binding.Version, "0.3.2"},
{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
{"github.com/go-macaron/csrf", csrf.Version, "0.1.0"},
{"github.com/go-macaron/i18n", i18n.Version, "0.3.0"},
{"github.com/go-macaron/session", session.Version, "0.1.6"},
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.3"},
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
{"gopkg.in/macaron.v1", macaron.Version, "1.1.7"},
{"github.com/gogits/git-module", git.Version, "0.4.12"},
{"github.com/gogits/go-gogs-client", gogs.Version, "0.12.1"},
}
for _, c := range checkers {
if !version.Compare(c.Version(), c.Expected, ">=") {
log.Fatal(4, `Dependency outdated!
Package '%s' current version (%s) is below requirement (%s),
please use following command to update this package and recompile Gogs:
go get -u %[1]s`, c.ImportPath, c.Version(), c.Expected)
log.Fatal(2, "Binary version is higher than template file version, did you forget to update template files?")
}
}
}
@@ -219,49 +185,50 @@ func runWeb(ctx *cli.Context) error {
m.Get("/organizations", routers.ExploreOrganizations)
}, ignSignIn)
m.Combo("/install", routers.InstallInit).Get(routers.Install).
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)
Post(bindIgnErr(form.Install{}), routers.InstallPost)
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
// ***** START: User *****
m.Group("/user", func() {
m.Get("/login", user.SignIn)
m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost)
m.Post("/login", bindIgnErr(form.SignIn{}), user.SignInPost)
m.Get("/sign_up", user.SignUp)
m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost)
m.Post("/sign_up", bindIgnErr(form.Register{}), user.SignUpPost)
m.Get("/reset_password", user.ResetPasswd)
m.Post("/reset_password", user.ResetPasswdPost)
}, reqSignOut)
m.Group("/user/settings", func() {
m.Get("", user.Settings)
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
m.Post("", bindIgnErr(form.UpdateProfile{}), user.SettingsPost)
m.Combo("/avatar").Get(user.SettingsAvatar).
Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
Post(binding.MultipartForm(form.Avatar{}), user.SettingsAvatarPost)
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
m.Combo("/email").Get(user.SettingsEmails).
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
Post(bindIgnErr(form.AddEmail{}), user.SettingsEmailPost)
m.Post("/email/delete", user.DeleteEmail)
m.Get("/password", user.SettingsPassword)
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
m.Post("/password", bindIgnErr(form.ChangePassword{}), user.SettingsPasswordPost)
m.Combo("/ssh").Get(user.SettingsSSHKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
Post(bindIgnErr(form.AddSSHKey{}), user.SettingsSSHKeysPost)
m.Post("/ssh/delete", user.DeleteSSHKey)
m.Combo("/applications").Get(user.SettingsApplications).
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
m.Post("/applications/delete", user.SettingsDeleteApplication)
m.Group("/repositories", func() {
m.Get("", user.SettingsRepos)
m.Post("/leave", user.SettingsLeaveRepo)
})
m.Group("/organizations", func() {
m.Get("", user.SettingsOrganizations)
m.Post("/leave", user.SettingsLeaveOrganization)
})
m.Combo("/applications").Get(user.SettingsApplications).
Post(bindIgnErr(form.NewAccessToken{}), user.SettingsApplicationsPost)
m.Post("/applications/delete", user.SettingsDeleteApplication)
m.Route("/delete", "GET,POST", user.SettingsDelete)
}, reqSignIn, func(ctx *context.Context) {
ctx.Data["PageIsUserSettings"] = true
})
m.Group("/user", func() {
// r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
m.Any("/activate", user.Activate)
m.Any("/activate_email", user.ActivateEmail)
m.Get("/email2user", user.Email2User)
@@ -282,8 +249,8 @@ func runWeb(ctx *cli.Context) error {
m.Group("/users", func() {
m.Get("", admin.Users)
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(form.AdminCrateUser{}), admin.NewUserPost)
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(form.AdminEditUser{}), admin.EditUserPost)
m.Post("/:userid/delete", admin.DeleteUser)
})
@@ -298,9 +265,9 @@ func runWeb(ctx *cli.Context) error {
m.Group("/auths", func() {
m.Get("", admin.Authentications)
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(form.Authentication{}), admin.NewAuthSourcePost)
m.Combo("/:authid").Get(admin.EditAuthSource).
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
Post(bindIgnErr(form.Authentication{}), admin.EditAuthSourcePost)
m.Post("/:authid/delete", admin.DeleteAuthSource)
})
@@ -323,11 +290,10 @@ func runWeb(ctx *cli.Context) error {
m.Get("/attachments/:uuid", func(ctx *context.Context) {
attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid"))
if err != nil {
if models.IsErrAttachmentNotExist(err) {
ctx.Error(404)
} else {
ctx.Handle(500, "GetAttachmentByUUID", err)
}
ctx.NotFoundOrServerError("GetAttachmentByUUID", models.IsErrAttachmentNotExist, err)
return
} else if !com.IsFile(attach.LocalPath()) {
ctx.NotFound()
return
}
@@ -339,15 +305,15 @@ func runWeb(ctx *cli.Context) error {
defer fr.Close()
ctx.Header().Set("Cache-Control", "public,max-age=86400")
fmt.Println("attach.Name:", attach.Name)
ctx.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
// Fix #312. Attachments with , in their name are not handled correctly by Google Chrome.
// We must put the name in " manually.
if err = repo.ServeData(ctx, "\""+attach.Name+"\"", fr); err != nil {
if err = repo.ServeData(ctx, attach.Name, fr); err != nil {
ctx.Handle(500, "ServeData", err)
return
}
})
m.Post("/issues/attachments", repo.UploadIssueAttachment)
m.Post("/releases/attachments", repo.UploadReleaseAttachment)
}, ignSignIn)
m.Group("/:username", func() {
@@ -365,7 +331,7 @@ func runWeb(ctx *cli.Context) error {
m.Group("/org", func() {
m.Group("", func() {
m.Get("/create", org.Create)
m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
m.Post("/create", bindIgnErr(form.CreateOrg{}), org.CreatePost)
}, func(ctx *context.Context) {
if !ctx.User.CanCreateOrganization() {
ctx.NotFound()
@@ -390,28 +356,28 @@ func runWeb(ctx *cli.Context) error {
m.Group("/:org", func() {
m.Get("/teams/new", org.NewTeam)
m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
m.Post("/teams/new", bindIgnErr(form.CreateTeam{}), org.NewTeamPost)
m.Get("/teams/:team/edit", org.EditTeam)
m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost)
m.Post("/teams/:team/edit", bindIgnErr(form.CreateTeam{}), org.EditTeamPost)
m.Post("/teams/:team/delete", org.DeleteTeam)
m.Group("/settings", func() {
m.Combo("").Get(org.Settings).
Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), org.SettingsAvatar)
Post(bindIgnErr(form.UpdateOrgSetting{}), org.SettingsPost)
m.Post("/avatar", binding.MultipartForm(form.Avatar{}), org.SettingsAvatar)
m.Post("/avatar/delete", org.SettingsDeleteAvatar)
m.Group("/hooks", func() {
m.Get("", org.Webhooks)
m.Post("/delete", org.DeleteWebhook)
m.Get("/:type/new", repo.WebhooksNew)
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
m.Get("/:id", repo.WebHooksEdit)
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
})
m.Route("/delete", "GET,POST", org.SettingsDelete)
@@ -425,17 +391,17 @@ func runWeb(ctx *cli.Context) error {
// ***** START: Repository *****
m.Group("/repo", func() {
m.Get("/create", repo.Create)
m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost)
m.Post("/create", bindIgnErr(form.CreateRepo{}), repo.CreatePost)
m.Get("/migrate", repo.Migrate)
m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost)
m.Post("/migrate", bindIgnErr(form.MigrateRepo{}), repo.MigratePost)
m.Combo("/fork/:repoid").Get(repo.Fork).
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost)
Post(bindIgnErr(form.CreateRepo{}), repo.ForkPost)
}, reqSignIn)
m.Group("/:username/:reponame", func() {
m.Group("/settings", func() {
m.Combo("").Get(repo.Settings).
Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost)
Post(bindIgnErr(form.RepoSetting{}), repo.SettingsPost)
m.Group("/collaboration", func() {
m.Combo("").Get(repo.SettingsCollaboration).Post(repo.SettingsCollaborationPost)
m.Post("/access_mode", repo.ChangeCollaborationAccessMode)
@@ -445,7 +411,7 @@ func runWeb(ctx *cli.Context) error {
m.Get("", repo.SettingsBranches)
m.Post("/default_branch", repo.UpdateDefaultBranch)
m.Combo("/*").Get(repo.SettingsProtectedBranch).
Post(bindIgnErr(auth.ProtectBranchForm{}), repo.SettingsProtectedBranchPost)
Post(bindIgnErr(form.ProtectBranch{}), repo.SettingsProtectedBranchPost)
}, func(ctx *context.Context) {
if ctx.Repo.Repository.IsMirror {
ctx.NotFound()
@@ -457,14 +423,18 @@ func runWeb(ctx *cli.Context) error {
m.Get("", repo.Webhooks)
m.Post("/delete", repo.DeleteWebhook)
m.Get("/:type/new", repo.WebhooksNew)
m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost)
m.Get("/:id", repo.WebHooksEdit)
m.Post("/:id/test", repo.TestWebhook)
m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost)
m.Post("/gogs/new", bindIgnErr(form.NewWebhook{}), repo.WebHooksNewPost)
m.Post("/slack/new", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksNewPost)
m.Post("/discord/new", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksNewPost)
m.Post("/gogs/:id", bindIgnErr(form.NewWebhook{}), repo.WebHooksEditPost)
m.Post("/slack/:id", bindIgnErr(form.NewSlackHook{}), repo.SlackHooksEditPost)
m.Post("/discord/:id", bindIgnErr(form.NewDiscordHook{}), repo.DiscordHooksEditPost)
m.Group("/:id", func() {
m.Get("", repo.WebHooksEdit)
m.Post("/test", repo.TestWebhook)
m.Post("/redelivery", repo.RedeliveryWebhook)
})
m.Group("/git", func() {
m.Get("", repo.SettingsGitHooks)
@@ -475,7 +445,7 @@ func runWeb(ctx *cli.Context) error {
m.Group("/keys", func() {
m.Combo("").Get(repo.SettingsDeployKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.SettingsDeployKeysPost)
Post(bindIgnErr(form.AddSSHKey{}), repo.SettingsDeployKeysPost)
m.Post("/delete", repo.DeleteDeployKey)
})
@@ -485,113 +455,135 @@ func runWeb(ctx *cli.Context) error {
}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
m.Group("/:username/:reponame", func() {
m.Get("/issues", repo.RetrieveLabels, repo.Issues)
m.Get("/issues/:index", repo.ViewIssue)
m.Get("/labels/", repo.RetrieveLabels, repo.Labels)
m.Get("/milestones", repo.Milestones)
}, ignSignIn, context.RepoAssignment(true))
m.Group("/:username/:reponame", func() {
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers.
m.Group("/issues", func() {
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost)
m.Group("/:index", func() {
m.Post("/label", repo.UpdateIssueLabel)
m.Post("/milestone", repo.UpdateIssueMilestone)
m.Post("/assignee", repo.UpdateIssueAssignee)
}, reqRepoWriter)
Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost)
m.Group("/:index", func() {
m.Post("/title", repo.UpdateIssueTitle)
m.Post("/content", repo.UpdateIssueContent)
m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment)
m.Combo("/comments").Post(bindIgnErr(form.CreateComment{}), repo.NewComment)
})
})
m.Group("/comments/:id", func() {
m.Post("", repo.UpdateCommentContent)
m.Post("/delete", repo.DeleteComment)
})
}, reqSignIn, context.RepoAssignment(true))
m.Group("/:username/:reponame", func() {
m.Group("/wiki", func() {
m.Get("/?:page", repo.Wiki)
m.Get("/_pages", repo.WikiPages)
}, repo.MustEnableWiki, context.RepoRef())
}, ignSignIn, context.RepoAssignment(false, true))
m.Group("/:username/:reponame", func() {
// FIXME: should use different URLs but mostly same logic for comments of issue and pull reuqest.
// So they can apply their own enable/disable logic on routers.
m.Group("/issues", func() {
m.Group("/:index", func() {
m.Post("/label", repo.UpdateIssueLabel)
m.Post("/milestone", repo.UpdateIssueMilestone)
m.Post("/assignee", repo.UpdateIssueAssignee)
}, reqRepoWriter)
})
m.Group("/labels", func() {
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
m.Post("/new", bindIgnErr(form.CreateLabel{}), repo.NewLabel)
m.Post("/edit", bindIgnErr(form.CreateLabel{}), repo.UpdateLabel)
m.Post("/delete", repo.DeleteLabel)
m.Post("/initialize", bindIgnErr(auth.InitializeLabelsForm{}), repo.InitializeLabels)
m.Post("/initialize", bindIgnErr(form.InitializeLabels{}), repo.InitializeLabels)
}, reqRepoWriter, context.RepoRef())
m.Group("/milestones", func() {
m.Combo("/new").Get(repo.NewMilestone).
Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost)
Post(bindIgnErr(form.CreateMilestone{}), repo.NewMilestonePost)
m.Get("/:id/edit", repo.EditMilestone)
m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost)
m.Post("/:id/edit", bindIgnErr(form.CreateMilestone{}), repo.EditMilestonePost)
m.Get("/:id/:action", repo.ChangeMilestonStatus)
m.Post("/delete", repo.DeleteMilestone)
}, reqRepoWriter, context.RepoRef())
m.Group("/releases", func() {
m.Get("/new", repo.NewRelease)
m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
m.Post("/new", bindIgnErr(form.NewRelease{}), repo.NewReleasePost)
m.Post("/delete", repo.DeleteRelease)
m.Get("/edit/*", repo.EditRelease)
m.Post("/edit/*", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
}, reqRepoWriter, context.RepoRef())
m.Post("/edit/*", bindIgnErr(form.EditRelease{}), repo.EditReleasePost)
}, repo.MustBeNotBare, reqRepoWriter, func(ctx *context.Context) {
ctx.Data["PageIsViewFiles"] = true
})
// FIXME: Should use ctx.Repo.PullRequest to unify template, currently we have inconsistent URL
// for PR in same repository. After select branch on the page, the URL contains redundant head user name.
// e.g. /org1/test-repo/compare/master...org1:develop
// which should be /org1/test-repo/compare/master...develop
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost)
Post(bindIgnErr(form.NewIssue{}), repo.CompareAndPullRequestPost)
m.Group("", func() {
m.Combo("/_edit/*").Get(repo.EditFile).
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.EditFilePost)
Post(bindIgnErr(form.EditRepoFile{}), repo.EditFilePost)
m.Combo("/_new/*").Get(repo.NewFile).
Post(bindIgnErr(auth.EditRepoFileForm{}), repo.NewFilePost)
m.Post("/_preview/*", bindIgnErr(auth.EditPreviewDiffForm{}), repo.DiffPreviewPost)
Post(bindIgnErr(form.EditRepoFile{}), repo.NewFilePost)
m.Post("/_preview/*", bindIgnErr(form.EditPreviewDiff{}), repo.DiffPreviewPost)
m.Combo("/_delete/*").Get(repo.DeleteFile).
Post(bindIgnErr(auth.DeleteRepoFileForm{}), repo.DeleteFilePost)
Post(bindIgnErr(form.DeleteRepoFile{}), repo.DeleteFilePost)
m.Group("", func() {
m.Combo("/_upload/*").Get(repo.UploadFile).
Post(bindIgnErr(auth.UploadRepoFileForm{}), repo.UploadFilePost)
Post(bindIgnErr(form.UploadRepoFile{}), repo.UploadFilePost)
m.Post("/upload-file", repo.UploadFileToServer)
m.Post("/upload-remove", bindIgnErr(auth.RemoveUploadFileForm{}), repo.RemoveUploadFileFromServer)
m.Post("/upload-remove", bindIgnErr(form.RemoveUploadFile{}), repo.RemoveUploadFileFromServer)
}, func(ctx *context.Context) {
if !setting.Repository.Upload.Enabled {
ctx.NotFound()
return
}
})
}, reqRepoWriter, context.RepoRef(), func(ctx *context.Context) {
}, repo.MustBeNotBare, reqRepoWriter, context.RepoRef(), func(ctx *context.Context) {
if !ctx.Repo.CanEnableEditor() {
ctx.NotFound()
return
}
ctx.Data["PageIsViewFiles"] = true
})
}, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare)
}, reqSignIn, context.RepoAssignment())
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)
m.Get("/releases", repo.MustBeNotBare, repo.Releases)
m.Get("/pulls", repo.RetrieveLabels, repo.Pulls)
m.Get("/pulls/:index", repo.ViewPull)
}, context.RepoRef())
// m.Get("/branches", repo.Branches)
m.Post("/branches/delete/*", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
m.Group("/branches", func() {
m.Get("", repo.Branches)
m.Get("/all", repo.AllBranches)
m.Post("/delete/*", reqSignIn, reqRepoWriter, repo.DeleteBranchPost)
}, repo.MustBeNotBare, func(ctx *context.Context) {
ctx.Data["PageIsViewFiles"] = true
})
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)
Post(bindIgnErr(form.NewWiki{}), repo.NewWikiPost)
m.Combo("/:page/_edit").Get(repo.EditWiki).
Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost)
Post(bindIgnErr(form.NewWiki{}), repo.EditWikiPost)
m.Post("/:page/delete", repo.DeleteWikiPagePost)
}, reqSignIn, reqRepoWriter)
}, repo.MustEnableWiki, context.RepoRef())
m.Get("/archive/*", repo.Download)
m.Get("/archive/*", repo.MustBeNotBare, repo.Download)
m.Group("/pulls/:index", func() {
m.Get("/commits", context.RepoRef(), repo.ViewPullCommits)
@@ -605,29 +597,30 @@ func runWeb(ctx *cli.Context) error {
m.Get("/commits/*", repo.RefCommits)
m.Get("/commit/:sha([a-f0-9]{7,40})$", repo.Diff)
m.Get("/forks", repo.Forks)
}, context.RepoRef())
m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff)
}, repo.MustBeNotBare, context.RepoRef())
m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotBare, repo.RawDiff)
m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", context.RepoRef(), repo.CompareDiff)
}, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare)
m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.MustBeNotBare, context.RepoRef(), repo.CompareDiff)
}, ignSignIn, context.RepoAssignment())
m.Group("/:username/:reponame", func() {
m.Get("/stars", repo.Stars)
m.Get("/watchers", repo.Watchers)
}, ignSignIn, context.RepoAssignment(), context.RepoRef())
m.Group("/:username", func() {
m.Group("", func() {
m.Get("/:reponame", repo.Home)
}, ignSignIn, context.RepoAssignment(true), context.RepoRef())
m.Get("/:reponame", ignSignIn, context.RepoAssignment(), context.RepoRef(), repo.Home)
m.Group("/:reponame", func() {
m.Head("/tasks/trigger", repo.TriggerTask)
})
// Use the regexp to match the repository name validation
// Use the regexp to match the repository name
// Duplicated routes to enable different ways of accessing same set of URLs,
// e.g. with or without ".git" suffix.
m.Group("/:reponame([\\d\\w-_\\.]+\\.git$)", func() {
m.Get("", ignSignIn, context.RepoAssignment(true), context.RepoRef(), repo.Home)
m.Get("", ignSignIn, context.RepoAssignment(), context.RepoRef(), repo.Home)
m.Route("/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
})
m.Route("/:reponame/*", "GET,POST", ignSignInAndCsrf, repo.HTTPContexter(), repo.HTTP)
})
// ***** END: Repository *****

View File

@@ -93,6 +93,8 @@ ENABLE_LOCAL_PATH_MIGRATION = false
; value depend of how many CPUs (cores) you have. If the value is set to zero
; or under, GOGS will automatically detect the number of CPUs your system have
COMMITS_FETCH_CONCURRENCY = 0
; Enable render mode for raw file
ENABLE_RAW_FILE_RENDER_MODE = false
[repository.editor]
; List of file extensions that should have line wraps in the CodeMirror editor.
@@ -114,6 +116,19 @@ FILE_MAX_SIZE = 3
; Maximum number of files per upload
MAX_FILES = 5
; Attachment settings for releases
[release.attachment]
; Whether attachments are enabled. Defaults to `true`
ENABLED = true
; Path for attachments. Defaults to `data/attachments`
PATH = data/attachments
; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = */*
; Max size of each file. Defaults to 32MB
MAX_SIZE = 32
; Max number of files per upload. Defaults to 10
MAX_FILES = 10
[markdown]
; Enable hard line break extension
ENABLE_HARD_LINE_BREAK = false
@@ -124,6 +139,13 @@ CUSTOM_URL_SCHEMES =
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
[smartypants]
ENABLED = false
FRACTIONS = true
DASHES = true
LATEX_DASHES = true
ANGLED_QUOTES = true
[http]
; Value for Access-Control-Allow-Origin header, default is not to present
ACCESS_CONTROL_ALLOW_ORIGIN =
@@ -162,6 +184,9 @@ COOKIE_REMEMBER_NAME = gogs_incredible
COOKIE_SECURE = false
; Reverse proxy authentication header name of user name
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
; Enable to set cookie to indicate user login status
ENABLE_LOGIN_STATUS_COOKIE = false
LOGIN_STATUS_COOKIE_NAME = login_status
[service]
ACTIVE_CODE_LIVE_MINUTES = 180
@@ -218,8 +243,8 @@ FROM =
; Mailer user name and password
USER =
PASSWD =
; Use text/html as alternative format of content
ENABLE_HTML_ALTERNATIVE = false
; Use text/plain as format of content
USE_PLAIN_TEXT = false
[cache]
; Either "memory", "redis", or "memcache", default is "memory"
@@ -246,8 +271,8 @@ COOKIE_NAME = i_like_gogits
COOKIE_SECURE = false
; Enable set cookie, default is true
ENABLE_SET_COOKIE = true
; Session GC time interval, default is 86400
GC_INTERVAL_TIME = 86400
; Session GC time interval, default is 3600
GC_INTERVAL_TIME = 3600
; Session life time, default is 86400
SESSION_LIFE_TIME = 86400
; Cookie name for CSRF
@@ -266,6 +291,7 @@ DISABLE_GRAVATAR = false
; This value will be forced to be false in offline mode or Gravatar is disbaled.
ENABLE_FEDERATED_AVATAR = true
; Attachment settings for issues
[attachment]
; Whether attachments are enabled. Defaults to `true`
ENABLE = true
@@ -273,9 +299,9 @@ ENABLE = true
PATH = data/attachments
; One or more allowed types, e.g. image/jpeg|image/png
ALLOWED_TYPES = image/jpeg|image/png
; Max size of each file. Defaults to 32MB
; Max size of each file. Defaults to 4MB
MAX_SIZE = 4
; Max number of files per upload. Defaults to 10
; Max number of files per upload. Defaults to 5
MAX_FILES = 5
[time]
@@ -322,6 +348,16 @@ LEVEL =
; Webhook URL
URL =
[log.xorm]
; Enable file rotation
ROTATE = true
; Rotate every day
ROTATE_DAILY = true
; Rotate once file size excesses x MB
MAX_SIZE = 100
; Maximum days to keep logger files
MAX_DAYS = 3
[cron]
; Enable running cron tasks periodically.
ENABLED = true
@@ -408,10 +444,14 @@ ORG_PAGING_NUM = 50
[ui.user]
; Number of repos that are showed in one page
REPO_PAGING_NUM = 15
; Number of news feeds that are showed in one page
NEWS_FEED_PAGING_NUM = 20
; Number of commits that are showed in one page
COMMITS_PAGING_NUM = 30
[i18n]
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR,gl-ES,uk-UA
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,Français,Nederlands,Latviešu,Русский,日本語,Español,Português do Brasil,Polski,български,Italiano,Suomalainen,Türkçe,čeština,Српски,Svenska,한국어,Galego,Українська
NAMES = English,简体中文,繁體中文(香港),繁體中文(台湾),Deutsch,français,Nederlands,latviešu,русский,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어,galego,українська
; Used for datetimepicker
[i18n.datelang]

View File

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

View File

@@ -18,6 +18,8 @@ Antoine GIRARD <sapk AT sapk DOT fr>
Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com>
Aurelien Darragon <aurelien DOT darragon AT gmail DOT com>
Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
Bo-Yi Wu <appleboy DOT tw AT gmail DOT com>
Breton Corentin <contact AT neodarz DOT net>
Camille Baronnet <gogs AT camillebaronnet DOT fr>
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
Cysioland
@@ -40,6 +42,7 @@ Ilya Makarov
Jamie Mansfield <dev AT jamierocks DOT uk>
Javier Ortiz Bultron <javier DOT ortiz DOT 78 AT gmail DOT com>
Jean THOMAS <contact AT tibounise DOT com>
John Behm <jxsl13 AT googlemail DOT com>
Jonas De Kegel <jonasgithub [AT] gmail [DOT] com>
Joubert RedRat <me+github AT redrat DOT com DOT br>
Juraj Bubniak <contact AT jbub DOT eu>

View File

@@ -82,6 +82,8 @@ app_url=URL адрес на приложението
app_url_helper=Този настройка променя HTTP/HTTPS адреса за клониране, а понякога и адреса на ел. поща.
log_root_path=Път към журналите
log_root_path_helper=Директория в която се записват журналите.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Опционални настройки
email_title=Настройки на пощенска услуга
@@ -201,6 +203,7 @@ Content=Съдържание
require_error=` не може да бъде празен.`
alpha_dash_error=` трябва да e валидна буква, число или тире(-_).`
alpha_dash_dot_error=` трябва да e валидна буква, число, тире(-_) или точка.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` трябва да е с размер %s.`
min_size_error=` трябва да съдържа поне %s знака.`
max_size_error=` трябва да съдържа най-много %s знака.`
@@ -252,11 +255,10 @@ profile=Профил
password=Парола
avatar=Аватар
ssh_keys=SSH ключове
social=Социални профили
applications=Приложения
repos=Repositories
orgs=Организации
applications=Приложения
delete=Изтрий профил
uid=UID
public_profile=Публичен профил
profile_desc=Вашият адрес на ел. поща е публичен и ще бъде използван за всички свързани с профила Ви уведомления и всички уеб базирани операции, направени чрез сайта.
@@ -343,6 +345,11 @@ orgs.none=Не сте член на никоя организация.
orgs.leave_title=Напусни организация
orgs.leave_desc=Ще загубите достъп до всички хранилища и екипи, след като напуснете организацията. Желаете ли да продължите?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Изтриване на собствения профил
delete_prompt=Тази операция ще изтрие Вашия профил завинаги и тя <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие!
confirm_delete_account=Потвърди изтриването
@@ -413,7 +420,7 @@ quick_guide=Бърз справочник
clone_this_repo=Клонирай хранилището
create_new_repo_command=Създай ново хранилище чрез командния ред
push_exist_repo=Предай съществуващо хранилище през командния ред
repo_is_empty=Това хранилище е празно. Моля проверете по-късно пак!
bare_message=This repository does not have any content yet.
files=Файлове
branch=Клон
@@ -426,6 +433,7 @@ pulls=Заявки за сливане
labels=Етикети
milestones=Етапи
commits=Ревизии
git_branches=Branches
releases=Версии
file_raw=Директен файл
file_history=История
@@ -434,6 +442,13 @@ file_permalink=Постоянна връзка
file_too_large=Този файл е твърде голям за да се визуализира
video_not_supported_in_browser=Вашият браузър не поддържа HTML5 видео тагове.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Нов файл
editor.upload_file=Качи файл
editor.edit_file=Редактирай файл
@@ -641,9 +656,11 @@ settings.collaboration.write=За писане
settings.collaboration.read=За четене
settings.collaboration.undefined=Недефинирано
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Тази промяна ще засегне вр
settings.advanced_settings=Разширени настройки
settings.wiki_desc=Включи система за уики
settings.use_internal_wiki=Използвай вградено уики
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Използвай външно уики
settings.external_wiki_url=URL адрес на външно уики
settings.external_wiki_url_desc=Посетителите ще бъдат пренасочени към този URL адрес от връзката за раздел уики.
settings.issues_desc=Включи система за проследяване на задачи
settings.use_internal_issue_tracker=Изполвай вградена система за проследяване на задачи
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Използвай външна система за проследяване на задачи
settings.external_tracker_url=URL адрес на външна система за проследяване на задачи
settings.external_tracker_url_desc=Посетителите ще бъдат пренасочени към този URL адрес от връзката на раздела.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Уеб-куката е изтрита успе
settings.webhook.test_delivery=Тестово изпращане
settings.webhook.test_delivery_desc=Симулира тестово изпращане за тест на настройките на уеб-куката
settings.webhook.test_delivery_success=Тестовата уеб-кука е добавена в опашката за изпращане. Може да отнеме няколко секунди преди да се появи в историята с доставени.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Заявка
settings.webhook.response=Отговор
settings.webhook.headers=Заглавки
@@ -755,10 +776,20 @@ settings.event_send_everything=При <strong>всички</strong> събити
settings.event_choose=Нека избера от какво имам нужда.
settings.event_create=Създаване
settings.event_create_desc=Създаване на клон или маркер
settings.event_pull_request=Заявка за сливане
settings.event_pull_request_desc=Заявка за сливане е отворена, затворена, отворена повторно, редактирана, възложена, отменена, при модифициран етикет, при премахнат етикет или е синхронизирана.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Предаване
settings.event_push_desc=Git предаване към хранилището
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Заявка за сливане
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Активна
settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени.
settings.add_hook_success=Новата уеб-кука е добавена успешно.
@@ -803,7 +834,6 @@ release.releases=Версии
release.new_release=Нова версия
release.draft=Чернови
release.prerelease=Предварителни
release.stable=Стабилни
release.edit=редактиране
release.ahead=<strong>%d</strong> ревизии на %s след тази версия
release.source_code=Изходен код
@@ -1019,6 +1049,7 @@ repos.private=Частно
repos.watches=Наблюдавания
repos.stars=Харесвания
repos.issues=Задачи
repos.size=Size
auths.auth_manage_panel=Управление на удостоверявания
auths.new=Добави нов начин на удостоверяване
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Време за отказ при сливане
config.git_gc_timeout=Време за отказ при GC
config.log_config=Конфигурация на журнал
config.log_mode=Режим на журнал
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron задачи
monitor.name=Име
@@ -1205,19 +1237,23 @@ notices.delete_success=Системните съобщения са изтрит
[action]
create_repo=създаде хранилище <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=предаде към <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
compare_commits=Сравнение между тези %d ревизии
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
create_issue=`отвори задача <a href="%s/issues/%s">%s#%[2]s"</a>`
close_issue=`затвори <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`повторно отвори <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`затвори заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`повторно отвори заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
merge_pull_request=`обедини заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a>
compare_commits=Сравнение между тези %d ревизии
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=преди

File diff suppressed because it is too large Load Diff

View File

@@ -82,6 +82,8 @@ app_url=Anwendungs-URL
app_url_helper=Dies hat Auswirkung auf die HTTP/HTTPS Klon-URLs und den Inhalt der E-Mails.
log_root_path=Logdateipfad
log_root_path_helper=Verzeichnis in das Logdateien geschrieben werden.
enable_console_mode=Konsolen-Modus einschalten
enable_console_mode_popup=Zusätzlich zum Datei-Modus, zeige Logs auch in der Konsole.
optional_title=Optionale Einstellungen
email_title=E-Mail-Service Einstellungen
@@ -201,6 +203,7 @@ Content=Inhalt
require_error=` darf nicht leer sein.`
alpha_dash_error=` kann ausschließlich alphanumerische Zeichen und "-_" enthalten.`
alpha_dash_dot_error=` kann ausschließlich alphanumerische Zeichen und ".-_" enthalten.`
alpha_dash_dot_slash_error=` kann ausschließlich alphanumerische Zeichen und ".-_/" enthalten.`
size_error=` muss die Größe %s haben.`
min_size_error=` muss mindestens %s Zeichen enthalten.`
max_size_error=` darf höchstens %s Zeichen enthalten.`
@@ -252,11 +255,10 @@ profile=Profil
password=Passwort
avatar=Profilbild
ssh_keys=SSH-Schlüssel
social=Soziale Konten
applications=Anwendungen
repos=Repositories
orgs=Organisationen
applications=Anwendungen
delete=Konto löschen
uid=Uid
public_profile=Öffentliches Profil
profile_desc=Ihre E-Mail-Adresse ist öffentlich einsehbar und dient dazu, Ihnen Benachrichtigungen bezüglich Ihres Kontos und Aktivitäten auf der Webseite zu schicken.
@@ -343,6 +345,11 @@ orgs.none=Sie sind kein Mitglied einer Organisation.
orgs.leave_title=Organisation verlassen
orgs.leave_desc=Sie verlieren den Zugriff auf alle Repositories und Teams nach dem Verlassen der Organisation. Möchten Sie fortfahren?
repos.leave=Verlassen
repos.leave_title=Repository verlassen
repos.leave_desc=Der Zugriff zum Repository wird verloren gehen, nachdem diese verlassen wird. Möchten Sie fortfahren?
repos.leave_success=Sie haben die Repository '%s' erfolgreich verlassen!
delete_account=Konto löschen
delete_prompt=Diese Aktion wird Ihr Konto dauerhaft löschen und kann <strong>NICHT</strong> rückgängig gemacht werden!
confirm_delete_account=Löschvorgang bestätigen
@@ -391,7 +398,7 @@ migrate_type_helper=Dieses Repository wird ein <span class="text blue">Mirror</s
migrate_repo=Repository migrieren
migrate.clone_address=Adresse kopieren
migrate.clone_address_desc=Dies kann eine HTTP/HTTPS/GIT-URL sein.
migrate.clone_address_desc_import_local=Sie dürfen auch eine Repository vom lokalen Serverpfad migrieren.
migrate.clone_address_desc_import_local=Sie dürfen auch ein Repository vom lokalen Serverpfad migrieren.
migrate.permission_denied=Ihnen fehlen die Rechte zum Importieren lokaler Repositories.
migrate.invalid_local_path=Der lokale Pfad ist ungültig, existiert nicht oder ist kein Ordner.
migrate.failed=Fehler bei Migration: %v
@@ -413,7 +420,7 @@ quick_guide=Kurzanleitung
clone_this_repo=Dieses Repository klonen
create_new_repo_command=Erstellen Sie ein neues Repository mittels der Kommandozeile
push_exist_repo=Bestehendes Repository von der Kommandozeile pushen
repo_is_empty=Dieses Repository ist leer. Bitte kommen Sie später wieder!
bare_message=Diese Repository hat noch keinen Inhalt.
files=Dateien
branch=Branch
@@ -426,6 +433,7 @@ pulls=Pull-Requests
labels=Label
milestones=Meilensteine
commits=Commits
git_branches=Branches
releases=Releases
file_raw=Originalformat
file_history=Verlauf
@@ -434,6 +442,13 @@ file_permalink=Permalink
file_too_large=Diese Datei ist zu groß zum Anzeigen
video_not_supported_in_browser=Ihr Browser unterstützt HTML5 Video-Tags nicht.
branches.overview=Übersicht
branches.active_branches=Aktive Branches
branches.stale_branches=Alte Branches
branches.all=Alle Branches
branches.updated_by=Aktualisiert %[1]s von %[2]s
branches.change_default_branch=Ändere Standard-Branch
editor.new_file=Neue Datei
editor.upload_file=Datei hochladen
editor.edit_file=Datei bearbeiten
@@ -641,9 +656,11 @@ settings.collaboration.write=Schreibrechte
settings.collaboration.read=Leserechte
settings.collaboration.undefined=Nicht definiert
settings.branches=Branches
settings.branches_bare=Branches leerer Repositories können nicht verwaltet werden. Bitte erst Datei(en) pushen.
settings.default_branch=Standard-Branch
settings.default_branch_desc=Der Standard-Branch gilt als Basis für Commits, Pull-Requests und Online-Bearbeitung.
settings.update=Aktualisieren
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Standard-Branch dieses Repositories wurde erfolgreich aktualisiert!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Schützt Branches vor forcierten Pushes und versehentlichem Löschen. Comitter können freigeschaltet werden.
@@ -654,8 +671,8 @@ settings.protect_this_branch=Diesen Branch schützen
settings.protect_this_branch_desc=Verhindere forcierte Pushes sowie Löschungen.
settings.protect_require_pull_request=Verlange Pull-Request an Stelle von direkten Pushes
settings.protect_require_pull_request_desc=Aktivieren Sie diese Option, um direktes Pushen in diesen Branch zu verhindern. Commits müssen in einen anderen, ungeschützten Branch gepusht werden und dann per Pull-Request in diesen Branch überführt werden.
settings.protect_whitelist_committers=Fügt die Benutzer zu Whitelist hinzu, die in diesen Branch pushen dürfen
settings.protect_whitelist_committers_desc=Benutzer oder Teams zur Whitelist hinzufügen.
settings.protect_whitelist_committers=Hinzufügen von Benutzern oder Teams zur Whitelist, die in diesen Branch pushen dürfen
settings.protect_whitelist_committers_desc=Fügt Benutzer oder Teams zur Push-Whitelist dieses Branches hinzu. Auf der Whitelist geführte Benutze können können ohne Prüfung von Pull-Requests pushen.
settings.protect_whitelist_users=Benutzer, die in diesen Branch pushen können
settings.protect_whitelist_search_users=Benutzer suchen
settings.protect_whitelist_teams=Teams, deren Mitglieder in diesen Branch pushen können
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Diese Änderung wirkt sich darauf aus, wie sich
settings.advanced_settings=Erweiterte Einstellungen
settings.wiki_desc=Wiki einschalten
settings.use_internal_wiki=Eingebautes Wiki verwenden
settings.allow_public_wiki_desc=Erlaube öffentlichen Zugang zum Wiki, auch wenn die Repository privat ist.
settings.use_external_wiki=Externes Wiki verwenden
settings.external_wiki_url=Externe Wiki URL
settings.external_wiki_url_desc=Besucher werden auf diese URL umgeleitet, wenn sie auf den Tab klicken.
settings.issues_desc=Issue-Tracker einschalten
settings.use_internal_issue_tracker=Eingebauten Issue-Tracker verwenden
settings.allow_public_issues_desc=Erlaube öffentlichen Zugriff auf Issues, auch wenn die Repository privat ist.
settings.use_external_issue_tracker=Externes Issue-System verwenden
settings.external_tracker_url=URL eines externen Issue Trackers
settings.external_tracker_url_desc=Besucher werden auf diese URL umgeleitet, wenn sie auf den Tab klicken.
@@ -688,7 +707,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumerisch
settings.tracker_url_format_desc=Sie können die Platzhalter <code>{user} {repo} {index}</code> für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden.
settings.pulls_desc=Pull-Requests aktivieren, um öffentliche Mitwirkung zu ermöglichen
settings.danger_zone=Gefahrenzone
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.cannot_fork_to_same_owner=Besitzer kann das Repository nicht forken.
settings.new_owner_has_same_repo=Der neue Eigentümer hat bereits ein Repository mit dem gleichen Namen. Bitte wählen Sie einen anderen Namen.
settings.convert=In ein normales Repository umwandeln
settings.convert_desc=Dieser Mirror kann in ein normales Repository umgewandelt werden. Dies kann nicht rückgängig gemacht werden.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webhook wurde erfolgreich entfernt!
settings.webhook.test_delivery=Senden testen
settings.webhook.test_delivery_desc=Sendet ein simuliertes Push-Ereignis, um die Webhook-Einstellungen zu testen
settings.webhook.test_delivery_success=Test-Webhook wurde zur Auslieferungswarteschlange hinzugefügt. Es kann einige Sekunden dauern, bevor es in der Auslieferungshistorie erscheint.
settings.webhook.redelivery=Erneuter Versand
settings.webhook.redelivery_success=Hook-Task '%s' wurde wieder zur Auslieferungswarteschlange hinzugefügt. Es kann einige Sekunden, bis sich der Auslieferungsstatus in der History aktualisiert hat.
settings.webhook.request=Anfrage
settings.webhook.response=Antwort
settings.webhook.headers=Kopfzeilen
@@ -745,7 +766,7 @@ settings.add_webhook_desc=Gogs sendet einen <code>POST</code>-Request an die unt
settings.payload_url=Payload URL
settings.content_type=Inhaltstyp
settings.secret=Secret
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.secret_desc=Das Secret wird im <code>X-Gogs-Signature</code> Header als hexadezimalem SHA256 HMAC Stempel der Nutzlast.
settings.slack_username=Benutzername
settings.slack_icon_url=Icon URL
settings.slack_color=Farbe
@@ -755,10 +776,20 @@ settings.event_send_everything=Ich brauche <strong>alles</strong>.
settings.event_choose=Lass mich auswählen, was ich brauche.
settings.event_create=Erstellen
settings.event_create_desc=Branch/Tag erstellt
settings.event_pull_request=Pull-Request
settings.event_pull_request_desc=Pull-Request geöffnet, geschlossen, wieder geöffnet, bearbeitet, zugewiesen, nicht zugewiesen, Label aktualisiert, Label gelöscht oder synchronisiert.
settings.event_delete=Löschen
settings.event_delete_desc=Branch/Tag gelöscht
settings.event_fork=Fork
settings.event_fork_desc=Repository geforkt
settings.event_push=Push
settings.event_push_desc=Git push auf ein Repository
settings.event_issues=Issues
settings.event_issues_desc=Issue geöffnet, geschlossen, wieder geöffnet, bearbeitet, zugewiesen, nicht zugewiesen, Label aktualisiert, Label gelöscht, einem Meilenstein zugewiesen oder davon entfernt.
settings.event_issue_comment=Issue-Kommentar
settings.event_issue_comment_desc=Issue-Kommentar angelegt, geändert oder gelöscht.
settings.event_pull_request=Pull-Request
settings.event_pull_request_desc=Pull-Request geöffnet, geschlossen, wieder geöffnet, bearbeitet, zugewiesen, nicht zugewiesen, Label aktualisiert, Label gelöscht, einem Meilenstein zugewiesen, davon entfernt oder synchronisiert.
settings.event_release=Release
settings.event_release_desc=Release in Repository veröffentlicht.
settings.active=Aktiv
settings.active_helper=Details über das auslösende Ereignis des Webhooks werden ebenfalls mit gesendet
settings.add_hook_success=Webhook hinzugefügt
@@ -803,7 +834,6 @@ release.releases=Releases
release.new_release=Neues Release
release.draft=Entwurf
release.prerelease=Pre-Release
release.stable=Stabil
release.edit=bearbeiten
release.ahead=<strong>%d</strong> Commits zu %s seit diesem Release
release.source_code=Quelltext
@@ -1019,6 +1049,7 @@ repos.private=Privat
repos.watches=Beobachtungen
repos.stars=Favoriten
repos.issues=Issues
repos.size=Größe
auths.auth_manage_panel=Authentifizierung
auths.new=Neue Quelle hinzufügen
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Zeitlimit für Pull
config.git_gc_timeout=Zeitlimit für GC
config.log_config=Konfiguration des Loggings
config.log_mode=Log-Modus
config.log_mode=Modus
config.log_options=Optionen
monitor.cron=Cron-Tasks
monitor.name=Name
@@ -1205,19 +1237,23 @@ notices.delete_success=Systemmitteilungen wurden erfolgreich gelöscht.
[action]
create_repo=hat das Repository <a href="%s">%s</a> erstellt
fork_repo=hat das Repository nach <a href="%s">%s</a> geforkt
rename_repo=hat das Repository von <code>%[1]s</code> zu <a href="%[2]s">%[3]s</a> umbenannt
commit_repo=hat auf <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> gepusht
compare_commits=Zeige Vergleich für diese %d Commits
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
create_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> geöffnet`
close_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> geschlossen`
reopen_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> wieder geöffnet`
comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
create_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> erstellt`
close_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> geschlossen`
reopen_pull_request=`hat den Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> wieder geöffnet`
comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
merge_pull_request=`hat Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> zuammengeführt`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
create_branch=hat neuen Branch <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a> angelegt
delete_branch=hat Branch <code>%[2]s</code> in <a href="%[1]s">%[3]s</a> gelöscht
push_tag=hat Tag <a href="%s/src/%s">%[2]s</a> auf <a href="%[1]s">%[3]s</a> gepusht
compare_commits=Zeige Vergleich für diese %d Commits
delete_tag=hat Tag <code>%[2]s</code> in <a href="%[1]s">%[3]s</a> gelöscht
[tool]
ago=vor

View File

@@ -82,6 +82,8 @@ app_url = Application URL
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.
enable_console_mode = Enable Console Mode
enable_console_mode_popup = In addition to file mode, also print logs to console.
optional_title = Optional Settings
email_title = Email Service Settings
@@ -201,6 +203,7 @@ Content = Content
require_error = ` cannot be empty.`
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot characters.`
alpha_dash_dot_slash_error = ` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error = ` must be size %s.`
min_size_error = ` must contain at least %s characters.`
max_size_error = ` must contain at most %s characters.`
@@ -252,11 +255,10 @@ profile = Profile
password = Password
avatar = Avatar
ssh_keys = SSH Keys
social = Social Accounts
applications = Applications
repos = Repositories
orgs = Organizations
applications = Applications
delete = Delete Account
uid = Uid
public_profile = Public Profile
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.
@@ -340,9 +342,14 @@ access_token_deletion_desc = Delete this personal access token will remove all r
delete_token_success = Personal access token has been removed successfully! Don't forget to update your application as well.
orgs.none = You are not a member of any organizations.
orgs.leave_title = Leave an organization
orgs.leave_title = Leave organization
orgs.leave_desc = You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave = Leave
repos.leave_title = Leave repository
repos.leave_desc = You will lose access to the repository after you left. Do you want to continue?
repos.leave_success = You have left repository '%s' successfully!
delete_account = Delete Your Account
delete_prompt = The operation will delete your account permanently, and <strong>CANNOT</strong> be undone!
confirm_delete_account = Confirm Deletion
@@ -413,7 +420,7 @@ quick_guide = Quick Guide
clone_this_repo = Clone this repository
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!
bare_message = This repository does not have any content yet.
files = Files
branch = Branch
@@ -426,6 +433,7 @@ pulls = Pull Requests
labels = Labels
milestones = Milestones
commits = Commits
git_branches = Branches
releases = Releases
file_raw = Raw
file_history = History
@@ -434,6 +442,13 @@ file_permalink = Permalink
file_too_large = This file is too large to be shown
video_not_supported_in_browser = Your browser doesn't support HTML5 video tag.
branches.overview = Overview
branches.active_branches = Active Branches
branches.stale_branches = Stale Branches
branches.all = All Branches
branches.updated_by = Updated %[1]s by %[2]s
branches.change_default_branch = Change Default Branch
editor.new_file = New file
editor.upload_file = Upload file
editor.edit_file = Edit file
@@ -641,9 +656,11 @@ settings.collaboration.write = Write
settings.collaboration.read = Read
settings.collaboration.undefined = Undefined
settings.branches = Branches
settings.branches_bare = You cannot manage branches for bare repository. Please push some content first.
settings.default_branch = Default Branch
settings.default_branch_desc = The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update = Update
settings.update_default_branch_unsupported = Change default branch is not supported by the Git version on server.
settings.update_default_branch_success = Default branch of this repository has been updated successfully!
settings.protected_branches = Protected Branches
settings.protected_branches_desc = Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc = Disable force pushes and prevent from deleti
settings.protect_require_pull_request = Require pull request instead direct pushing
settings.protect_require_pull_request_desc = Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers = Whitelist who can push to this branch
settings.protect_whitelist_committers_desc = Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc = Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users = Users who can push to this branch
settings.protect_whitelist_search_users = Search users
settings.protect_whitelist_teams = Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt = This change will affect how links relate to th
settings.advanced_settings = Advanced Settings
settings.wiki_desc = Enable wiki system
settings.use_internal_wiki = Use builtin wiki
settings.allow_public_wiki_desc = Allow public access to wiki when repository is private
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 issue tracker
settings.use_internal_issue_tracker = Use builtin lightweight issue tracker
settings.allow_public_issues_desc = Allow public access to issues when repository is private
settings.use_external_issue_tracker = Use external issue tracker
settings.external_tracker_url = External Issue Tracker URL
settings.external_tracker_url_desc = Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ 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.redelivery = Redelivery
settings.webhook.redelivery_success = Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request = Request
settings.webhook.response = Response
settings.webhook.headers = Headers
@@ -754,11 +775,21 @@ settings.event_push_only = Just the <code>push</code> event.
settings.event_send_everything = I need <strong>everything</strong>.
settings.event_choose = Let me choose what I need.
settings.event_create = Create
settings.event_create_desc = Branch, or tag created
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_create_desc = Branch or tag created
settings.event_delete = Delete
settings.event_delete_desc = Branch or tag deleted
settings.event_fork = Fork
settings.event_fork_desc = Repository forked
settings.event_push = Push
settings.event_push_desc = Git push to a repository
settings.event_issues = Issues
settings.event_issues_desc = Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment = Issue Comment
settings.event_issue_comment_desc = Issue comment created, edited, or deleted.
settings.event_pull_request = Pull Request
settings.event_pull_request_desc = Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release = Release
settings.event_release_desc = Release published in a repository.
settings.active = Active
settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
settings.add_hook_success = New webhook has been added.
@@ -803,7 +834,6 @@ release.releases = Releases
release.new_release = New Release
release.draft = Draft
release.prerelease = Pre-Release
release.stable = Stable
release.edit = edit
release.ahead = <strong>%d</strong> commits to %s since this release
release.source_code = Source Code
@@ -1019,6 +1049,7 @@ repos.private = Private
repos.watches = Watches
repos.stars = Stars
repos.issues = Issues
repos.size = Size
auths.auth_manage_panel = Authentication Manage Panel
auths.new = Add New Source
@@ -1176,7 +1207,8 @@ config.git_pull_timeout = Pull Operation Timeout
config.git_gc_timeout = GC Operation Timeout
config.log_config = Log Configuration
config.log_mode = Log Mode
config.log_mode = Mode
config.log_options = Options
monitor.cron = Cron Tasks
monitor.name = Name
@@ -1205,19 +1237,23 @@ notices.delete_success = System notices have been deleted successfully.
[action]
create_repo = created repository <a href="%s">%s</a>
fork_repo = forked a repository to <a href="%s">%s</a>
rename_repo = renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
commit_repo = pushed to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
compare_commits = View comparison for these %d commits
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
create_issue = `opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue = `closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue = `reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request = `created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request = `closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request = `reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
create_branch = created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch = deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_commits = View comparison for these %d commits
delete_tag = deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago = ago

View File

@@ -75,13 +75,15 @@ domain_helper=Esto afecta a las URLs para clonar por SSH.
ssh_port=Puerto SSH
ssh_port_helper=Número de puerto de su servidor SSH, déjelo en blanco para desactivar SSH.
use_builtin_ssh_server=Usar Builtin SSH Server
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
use_builtin_ssh_server_popup=Iniciar servidor SSH integrado para operaciones con Git para distinguirlo del demonio SSH del sistema.
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.
enable_console_mode=Activar Modo Consola
enable_console_mode_popup=Además del modo archivo, también imprime los registros en consola.
optional_title=Configuración opcional
email_title=Configuración del servicio de correo
@@ -201,6 +203,7 @@ Content=Contenido
require_error=` no puede estar vacío.`
alpha_dash_error=` los caracteres deben ser Alfanumericos o dash(-_).`
alpha_dash_dot_error=` debe ser un caracter alfanumérivo válido, un guión alto o bajo (-_) o un signo de puntuación.`
alpha_dash_dot_slash_error=` deben ser caracteres alfanuméricos, guiones(-_), puntos o barras.`
size_error=` debe ser de tamaño %s.`
min_size_error=` debe contener al menos %s caracteres.`
max_size_error=` debe contener como máximo %s caracteres.`
@@ -252,11 +255,10 @@ profile=Perfil
password=Contraseña
avatar=Avatar
ssh_keys=Claves SSH
social=Redes Sociales
applications=Aplicaciones
repos=Repositorios
orgs=Organizaciones
applications=Aplicaciones
delete=Eliminar cuenta
uid=UUID
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.
@@ -343,6 +345,11 @@ orgs.none=No eres un miembro de ninguna organización.
orgs.leave_title=Salir de una organización
orgs.leave_desc=Perderá el acceso a todos los repositorios y equipos después dejar la organización. ¿Desea continuar?
repos.leave=Salir
repos.leave_title=Dejar repositorio
repos.leave_desc=Perderás acceso al repositorio cuando salgas. ¿Quieres continuar?
repos.leave_success=¡Has dejado el repositorio '%s' con éxito!
delete_account=Elimina tu cuenta
delete_prompt=La operación eliminará tu cuenta de forma permanente y ¡<strong>NO</strong> se puede deshacer!
confirm_delete_account=Confirmar Eliminación
@@ -413,7 +420,7 @@ quick_guide=Guía Rápida
clone_this_repo=Clonar este repositorio
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!
bare_message=Este repositorio aun no tiene contenido alguno.
files=Archivos
branch=Rama
@@ -426,6 +433,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Milestones
commits=Commits
git_branches=Ramas
releases=Releases
file_raw=Raw
file_history=Histórico
@@ -434,6 +442,13 @@ file_permalink=Permalink
file_too_large=Este archivo es demasiado grande para ser mostrado
video_not_supported_in_browser=Su navegador no soporta el tag video de HTML5.
branches.overview=Resumen
branches.active_branches=Ramas activas
branches.stale_branches=Ramas Viejas
branches.all=Todas las Ramas
branches.updated_by=%[1]s actualizado por %[2]s
branches.change_default_branch=Cambiar la Rama por Defecto
editor.new_file=Nuevo archivo
editor.upload_file=Subir archivo
editor.edit_file=Editar archivo
@@ -473,7 +488,7 @@ editor.add_subdir=Añadir subdirectorio...
editor.unable_to_upload_files=Error al subir archivos a '%s', error: %v
editor.upload_files_to_dir=Subir archivos a '%s'
commits.commit_history=Commit History
commits.commit_history=Historial de Commits
commits.commits=Commits
commits.search=Buscar commits
commits.find=Buscar
@@ -641,9 +656,11 @@ settings.collaboration.write=Escritura
settings.collaboration.read=Lectura
settings.collaboration.undefined=Indefinido
settings.branches=Ramas
settings.branches_bare=No puedes gestionar ramas en un repositorio vacío. Por favor sube algún contenido primero.
settings.default_branch=Rama predeterminada
settings.default_branch_desc=Se considera la rama «base» como la rama por defecto para commits de código, las solicitudes pull y edición en línea.
settings.update=Actualizar
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=¡La Rama por defecto de este repositorio ha sido actualizado con éxito!
settings.protected_branches=Ramas protegidas
settings.protected_branches_desc=Proteger ramas force pushing, de eliminación accidental y lista blanca de committers de código.
@@ -655,11 +672,11 @@ settings.protect_this_branch_desc=Desactivar force pushes y evite la eliminació
settings.protect_require_pull_request=Requiere una solicitud pull, en lugar de un push directo
settings.protect_require_pull_request_desc=Active esta opción para deshabilitar un push directo a esta rama. Los commits tienen que ser empujados a otra rama no protegida y fusionados a esta rama a través de la solicitud pull.
settings.protect_whitelist_committers=Lista blanca de quienes pueden empujar a esta rama
settings.protect_whitelist_committers_desc=Añadir personas o equipos a la lista blanca de empuje directo a esta rama.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.protect_whitelist_committers_desc=Añadir personas o equipos a la lista blanca de push directo a esta rama. Los usuarios en esta lista se saltan la comprobación de pull request.
settings.protect_whitelist_users=Usuarios que pueden hacer push a esta rama
settings.protect_whitelist_search_users=Buscar usuarios
settings.protect_whitelist_teams=Equipos cuyos miembros pueden hacer push a esta rama
settings.protect_whitelist_search_teams=Buscar equipos
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.hooks=Webhooks
settings.githooks=Git Hooks
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Este cambio afectará a los enlaces al repositor
settings.advanced_settings=Ajustes avanzados
settings.wiki_desc=Activar sistema de wiki
settings.use_internal_wiki=Usar wiki integrada
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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 rastreo de incidencias
settings.use_internal_issue_tracker=Usar rastreo de incidencias ligero incluido
settings.allow_public_issues_desc=Permitir acceso público a las incidencias cuando el repositorio es privado
settings.use_external_issue_tracker=Usar tracker externo de incidencias
settings.external_tracker_url=URL de seguimiento de problemas externos
settings.external_tracker_url_desc=Los visitantes serán redirigidos a la URL cuando hagan click en la barra.
@@ -731,6 +750,8 @@ 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.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Petición
settings.webhook.response=Respuesta
settings.webhook.headers=Encabezado
@@ -755,10 +776,20 @@ settings.event_send_everything=Necesito <strong>todo</strong>.
settings.event_choose=Déjeme elegir lo que necesito.
settings.event_create=Crear
settings.event_create_desc=Rama o etiqueta creada
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request, abierta, cerrada, reabierta, editada, asignada, desasignada, con etiqueta actualizada, con etiqueta eliminada, o sincronizada.
settings.event_delete=Borrar
settings.event_delete_desc=Rama o etiqueta borrada
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push a un repositorio
settings.event_issues=Incidencias
settings.event_issues_desc=Incidencia abierta, cerrada, reabierta, editada, asignada, desasignada, etiqueta actualizada, etiqueta limpiada, hito marcado, o desmarcado,.
settings.event_issue_comment=Comentario de incidencia
settings.event_issue_comment_desc=Comentario de incidencias creado, editado o borrado.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request abierto, cerrado, reabierto, editado, asignado, desasignado, etiqueta actualizada, etiqueta limpiada, hito marcado, hito desmarcado, o sincronizado.
settings.event_release=Lanzamiento
settings.event_release_desc=Lanzamiento publicado en un repositorio.
settings.active=Activo
settings.active_helper=Enviaremos detalles del evento cuando este hook se dispare.
settings.add_hook_success=Se ha añadido un nuevo webhook.
@@ -803,7 +834,6 @@ release.releases=Releases
release.new_release=Nueva Release
release.draft=Borrador
release.prerelease=Pre-Release
release.stable=Estable
release.edit=editar
release.ahead=<strong>%d</strong> commits en %s desde esta release
release.source_code=Código Fuente
@@ -1019,6 +1049,7 @@ repos.private=Privado
repos.watches=Vigilantes
repos.stars=Estrellas
repos.issues=Incidencias
repos.size=Tamaño
auths.auth_manage_panel=Panel de administración de autenticación
auths.new=Añadir nuevo origen
@@ -1097,9 +1128,9 @@ config.ssh_minimum_key_sizes=Tamaños de clave mínimos
config.repo_config=Configuración del repositorio
config.repo_root_path=Ruta del Repositorio
config.script_type=Tipo de Script
config.repo_force_private=Force Private
config.repo_force_private=Forzar Privado
config.max_creation_limit=Limite máximo de creación
config.preferred_licenses=Preferred Licenses
config.preferred_licenses=Licencias Preferidas
config.disable_http_git=Desactivar HTTP Git
config.enable_local_path_migration=Activar la migración de la ruta de acceso Local
config.commits_fetch_concurrency=Commits Fetch Concurrency
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Tiempo de espera de operación de pull
config.git_gc_timeout=Tiempo de espera de operación de GC
config.log_config=Configuración del Log
config.log_mode=Modo del Log
config.log_mode=Modo
config.log_options=Opciones
monitor.cron=Tareas de Cron
monitor.name=Nombre
@@ -1205,19 +1237,23 @@ notices.delete_success=Las notificaciones del sistema han sido eliminadas satisf
[action]
create_repo=creó el repositorio <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
commit_repo=hizo push a <a href="%[1]s/src/%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparación de estos %d commits
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
create_issue=`incidencia abierta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`cerró la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reabrió la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`cerró el pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabrió el pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
create_branch=nueva rama <a href="%[1]s/src/%[2]s">%[3]s</a> creada en <a href="%[1]s">%[4]s</a>
delete_branch=borrada rama <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparación de estos %d commits
delete_tag=borrada etiqueta <code>%[2]s</code> en <a href="%[1]s">%[3]s</a>
[tool]
ago=hace

View File

@@ -64,7 +64,7 @@ no_admin_and_disable_registration=Et voi poistaa käytöstä rekisteröintiä lu
err_empty_admin_password=Ylläpito salasana ei voi olla tyhjä.
general_title=Sovellus yleiset asetukset
app_name=Sovellus nimi
app_name=Sovelluksen nimi
app_name_helper=Laita organisaatiosi nimi tähän isolla ja kovaäänisesti!
repo_path=Repon juuren polku
repo_path_helper=Kaikki Git etä repot tullaan tallentamaan tähän hakemistoon.
@@ -82,6 +82,8 @@ app_url=Sovellus URL
app_url_helper=Tämä vaikuttaa HTTP/HTTPS klooni URLeihin ja joihinkin sähköposteihin.
log_root_path=Lokin polku
log_root_path_helper=Lokien tallennushakemisto.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Valinnaiset asetukset
email_title=Sähköposti palvelu asetukset
@@ -201,6 +203,7 @@ Content=Sisältö
require_error=` ei voi olla tyhjä.`
alpha_dash_error=` täytyy olla kirjaimia tai numeroita tai väliviiva(-_) merkkejä.`
alpha_dash_dot_error=` täytyy olla kirjaimia tai numeroita tai väliviiva(-_) tai piste merkkejä.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` täytyy olla kokoa %s.`
min_size_error=` täytyy sisältää vähintään %s merkkiä.`
max_size_error=` täytyy sisältää enintään %s merkkiä.`
@@ -252,11 +255,10 @@ profile=Profiili
password=Salasana
avatar=Profiilikuva
ssh_keys=SSH avaimet
social=Sosiaaliset tilit
applications=Sovellukset
repos=Repositories
orgs=Organisaatiot
applications=Sovellukset
delete=Poista tili
uid=Käyttäjä ID
public_profile=Julkinen profiili
profile_desc=Sähköposti osoitteesi on julkinen ja käytetään tiliin liittyviin ilmoituksiin, ja nettipohjaisiin toimintoihin joita on tehty sivujen kautta.
@@ -343,6 +345,11 @@ orgs.none=Et ole yhdenkään organisaation jäsen.
orgs.leave_title=Poistu organisaatiosta
orgs.leave_desc=Menetät oikeudet kaikkiin niihin repoihin ja tiimeihin joihin organisaatio on sinulle oikeudet antanut. Haluatko varmasti jatkaa?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Poista tilisi
delete_prompt=Toiminto poistaa tilisi pysyvästi ja tätä <strong>EI VOI</strong> peruuttaa myöhemmin!
confirm_delete_account=Varmista poisto
@@ -413,7 +420,7 @@ quick_guide=Pikaopas
clone_this_repo=Kloonaa tämä repo
create_new_repo_command=Luo uusi repo komentoriviltä
push_exist_repo=Työnnä olemassaoleva repo komentoriviltä
repo_is_empty=Tämä repo on tyhjä, ole hyvä ja tule takaisin myöhemmin!
bare_message=This repository does not have any content yet.
files=Tiedostot
branch=Branch
@@ -426,6 +433,7 @@ pulls=Pull-pyynnöt
labels=Tunnisteet
milestones=Merkkipaalut
commits=Commitit
git_branches=Branches
releases=Julkaisut
file_raw=Raaka
file_history=Historia
@@ -434,6 +442,13 @@ file_permalink=Pysyvä linkki
file_too_large=Tämä tiedosto on liian suuri näytettäväksi
video_not_supported_in_browser=Selaimesi ei tue HTML5 video-tagia.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Uusi tiedosto
editor.upload_file=Liitä tiedosto
editor.edit_file=Muokkaa tiedostoa
@@ -641,9 +656,11 @@ settings.collaboration.write=Kirjoita
settings.collaboration.read=Lue
settings.collaboration.undefined=Määrittelemätön
settings.branches=Haarat
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Oletushaara
settings.default_branch_desc=Oletushaaraa käytetään "pohjahaarana" commiteille, pull-pyynnöille ja sivustolla toteutetuille muokkauksille.
settings.update=Päivitä
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Repositoryn oletushaara päivitetty!
settings.protected_branches=Suojatut haarat
settings.protected_branches_desc=Suojaa haaroja pakotetulta push-operaatiolta, vahinkopoistamisilta ja sallitun listan committereilta.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Kiellä pakoteut push-operaatiot ja estä pois
settings.protect_require_pull_request=Vaadi pull-pyyntö suoran push-operaation sijaan
settings.protect_require_pull_request_desc=Estä suorat push-operaatiot tähän haaraan. Commitit täytyy pushata ei-suojattuun haaraan ja yhdistää tähän haaraan pull-pyynnön kautta.
settings.protect_whitelist_committers=Lista sallituista, jotka voivat pushata tähän haaraan
settings.protect_whitelist_committers_desc=Lisää ihmisiä tai tiimejä sallittujen listaan, jotka voivat pushata suoraan tähän haaraan.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Tämä muutos vaikuttaa siihen miten linkit liit
settings.advanced_settings=Lisäasetukset
settings.wiki_desc=Ota wiki käyttöön
settings.use_internal_wiki=Käytä sisäänrakennettua wikiä
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Käytä ulkoista wikiä
settings.external_wiki_url=Ulkoinen Wiki URL
settings.external_wiki_url_desc=Vierailijat uudelleenohjataan URL-osoitteeseen kun he klikkaavat välilehteä.
settings.issues_desc=Ota virheenseuranta käyttöön
settings.use_internal_issue_tracker=Käytä sisäänrakennettua kevyttä virheenseurantaa
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Käytä ulkoista vikaseurantaa
settings.external_tracker_url=Ulkoisen virheenseurannan URL
settings.external_tracker_url_desc=Vierailijat ohjataan URL-osoitteeseen kun he klikkaavat välilehteä.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webkoukku on poistettu onnistuneesti!
settings.webhook.test_delivery=Testitoimitus
settings.webhook.test_delivery_desc=Lähetä väärennetty push toimitusjakelu testataksesi webkoukku asetuksia
settings.webhook.test_delivery_success=Testi webkoukku on lisätty toimitusjonoon. Muutama sekunti voi mennä ennenkuin se näkyy toimitushistoriassa.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Pyyntö
settings.webhook.response=Vastaus
settings.webhook.headers=Otsikot
@@ -755,10 +776,20 @@ settings.event_send_everything=Tarvitsen <strong>kaiken</strong>.
settings.event_choose=Haluan valita, mitä tarvitsen.
settings.event_create=Luo
settings.event_create_desc=Branch, tai tagi luotu
settings.event_pull_request=Pull-pyyntö
settings.event_pull_request_desc=Pull-pyyntö avattu, suljettu, uudelleenavattu, muokattu, annettu, anto vedottu, tarra päivitetty, tarra poistettu tai synkronoitu.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push repoon
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull-pyyntö
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktiivinen
settings.active_helper=Yksityiskohdat koskien tapahtumaa joka laukaisi koukun toimitetaan myös.
settings.add_hook_success=Uusi webkoukku on lisätty.
@@ -803,7 +834,6 @@ release.releases=Julkaisut
release.new_release=Uusi julkaisu
release.draft=Työversio
release.prerelease=Esiversio
release.stable=Vakaa
release.edit=muokkaa
release.ahead=<strong>%d</strong> committia kohteeseen %s version jälkeen
release.source_code=Lähdekoodi
@@ -1019,6 +1049,7 @@ repos.private=Yksityinen
repos.watches=Tarkkailijat
repos.stars=Äänet
repos.issues=Ongelmat
repos.size=Size
auths.auth_manage_panel=Todennus hallintapaneeli
auths.new=Lisää uusi lähde
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull-operaatio aikakatkaistiin
config.git_gc_timeout=Roskienkeruu aikakatkaistiin
config.log_config=Loki asetukset
config.log_mode=Loki tila
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron tehtävät
monitor.name=Nimi
@@ -1205,19 +1237,23 @@ notices.delete_success=Järjestelmän ilmoitukset on poistettu onnistuneesti.
[action]
create_repo=luotu repo <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=uudelleennimetty repo <code>%[1]s</code> nimelle <a href="%[2]s">%[3]s</a>
commit_repo=pushattu kohteeseen <a href="%[1]s/src/%[2]s">%[3]s</a> paikassa <a href="%[1]s">%[4]s</a>
compare_commits=Näytä vertailu näille %d commiteille
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
create_issue=`avasi ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`sulki ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`avasi uudelleen ongelman <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`kommentoi ongelmaa <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`luotu pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`sulki pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`avasi uudelleen pull-pyynnön <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`kommentoi ongelmaa <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`yhdistetty pull-pyyntö <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=siirretty repo <code>%s</code> kohteeseen <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pushattu tagi <a href="%s/src/%s">%[2]s</a> kohteeseen <a href="%[1]s">%[3]s</a>
compare_commits=Näytä vertailu näille %d commiteille
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=sitten

View File

@@ -82,6 +82,8 @@ 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.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Paramètres facultatifs
email_title=Paramètres du service de messagerie
@@ -201,6 +203,7 @@ Content=Contenu
require_error=` ne peut pas être vide.`
alpha_dash_error=` doivent être des caractères alpha, numériques ou tirets (-_) valides.`
alpha_dash_dot_error=` doivent être des caractères alpha, numériques, tirets (-_) valides ou des points.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` doit être à la taille de %s.`
min_size_error=` %s caractères minimum `
max_size_error=` %s caractères maximum `
@@ -252,11 +255,10 @@ profile=Profil
password=Mot de Passe
avatar=Avatar
ssh_keys=Clés SSH
social=Réseaux Sociaux
applications=Applications
repos=Repositories
orgs=Organisations
applications=Applications
delete=Supprimer le compte
uid=ID d'Utilisateur
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.
@@ -343,6 +345,11 @@ orgs.none=Vous n'êtes membre d'aucune organisation.
orgs.leave_title=Quitter une organisation
orgs.leave_desc=Vous perdrez accès à tous les dépôts et équipes après que vous ayez quitté l'organisation. Voulez-vous continuer ?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
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
@@ -399,7 +406,7 @@ migrate.failed=Echec de migration: %v
mirror_from=miroir de
forked_from=forké depuis
copy_link=Copier
copy_link_success=Copié!
copy_link_success=Copié !
copy_link_error=Appuyez sur ⌘-C ou Ctrl-C pour copier
copied=Copié
unwatch=Ne plus suivre
@@ -413,7 +420,7 @@ 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 dépôt existant par ligne de commande
repo_is_empty=Ce dépôt est vide, veuillez revenir plus tard !
bare_message=This repository does not have any content yet.
files=Fichiers
branch=Branche
@@ -423,9 +430,10 @@ branches=Branches
tags=Tags
issues=Tickets
pulls=Pull Requests
labels=Etiquettes
labels=Étiquettes
milestones=Jalons
commits=Commits
git_branches=Branches
releases=Publications
file_raw=Raw
file_history=Historique
@@ -434,6 +442,13 @@ file_permalink=Lien permanent
file_too_large=Ce fichier est trop gros pour être afficher
video_not_supported_in_browser=Votre navigateur ne supporte pas la balise video HTML5.
branches.overview=Overview
branches.active_branches=Branches Actives
branches.stale_branches=Stale Branches
branches.all=Toutes les Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Changer la Branche par Défaut
editor.new_file=Nouveau fichier
editor.upload_file=Téléverser un fichier
editor.edit_file=Modifier fichier
@@ -484,7 +499,7 @@ commits.older=Précédemment
commits.newer=Récemment
issues.new=Nouveau ticket
issues.new.labels=Etiquettes
issues.new.labels=Étiquettes
issues.new.no_label=Pas d'étiquette
issues.new.clear_labels=Effacer les étiquettes
issues.new.milestone=Jalon
@@ -641,9 +656,11 @@ settings.collaboration.write=Écrire
settings.collaboration.read=Lire
settings.collaboration.undefined=Indéfini
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Branche par défaut
settings.default_branch_desc=La branche par défaut est considérée comme la branche « originale » pour les commits de code, les requêtes de fusion et l'édition en ligne.
settings.update=Actualiser
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=La branche par défaut de ce dépôt a bien été mise à jour.
settings.protected_branches=Branches protégées
settings.protected_branches_desc=Protéger les branches du push forcé, de la suppression accidentelle et des publicateurs de code en liste blanche.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Interdire les push forcés et empêcher la sup
settings.protect_require_pull_request=Exiger une requête de fusion plutôt qu'un push immédiat
settings.protect_require_pull_request_desc=Activez cette option pour empêcher la publication immédiate vers cette branche. Les commits devront être publiés vers une autre branche (non protégée) et fusionnée dans cette branche avec une requête de fusion.
settings.protect_whitelist_committers=Liste blanche de personnes pouvant publier sur cette branche
settings.protect_whitelist_committers_desc=Ajouter des personnes ou des équipes à la liste blanche de publication directe vers cette branche.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Utilisateurs qui peuvent pousser sur cette branche
settings.protect_whitelist_search_users=Rechercher des utilisateurs
settings.protect_whitelist_teams=Les équipes pour lesquelles les membres peuvent pousser sur cette branche
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Ce changement affectera comment les liens sont r
settings.advanced_settings=Paramètres avancés
settings.wiki_desc=Activer le wiki
settings.use_internal_wiki=Utiliser le wiki interne
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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 système de tickets
settings.use_internal_issue_tracker=Utiliser le système simplifié de tickets interne
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Utiliser un bug-tracker externe
settings.external_tracker_url=Adresse de l'issue tracker externe
settings.external_tracker_url_desc=Les visiteurs seront redirigés vers cette URL lorsqu'ils cliqueront sur l'onglet.
@@ -688,7 +707,7 @@ settings.tracker_issue_style.alphanumeric=Alphanumérique
settings.tracker_url_format_desc=Vous pouvez utiliser l'espace réservé <code>{user} {repo} {index}</code> pour le nom d'utilisateur, le nom du dépôt et le numéro de bug.
settings.pulls_desc=Activer les pull requests pour accepter les contributions publiques
settings.danger_zone=Zone de danger
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.cannot_fork_to_same_owner=Vous ne pouvez par créer un fork d'un dépot à son propriétaire actuel.
settings.new_owner_has_same_repo=Le nouveau propriétaire a déjà un dépôt nommé ainsi.
settings.convert=Convertir en dépôt ordinaire
settings.convert_desc=Vous pouvez convertir ce miroir en dépôt ordinaire. Cela ne peut pas être inversée.
@@ -731,6 +750,8 @@ 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.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Requête
settings.webhook.response=Réponse
settings.webhook.headers=Entêtes 
@@ -745,20 +766,30 @@ settings.add_webhook_desc=Une requête <code>POST</code> sera transmise vers l'U
settings.payload_url=URL des Données Utiles
settings.content_type=Type de contenu
settings.secret=Confidentiel
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.secret_desc=Le secret sera envoyé comme digest de payload SHA256 HMAC hex avec l'entête <code>X-Gogs-Signature</code>.
settings.slack_username=Nom d'utilisateur
settings.slack_icon_url=URL de l'icône
settings.slack_color=Couleur
settings.event_desc=Quel évènement ce Webhook doit-il déclencher ?
settings.event_desc=Quand ce webhook doit-il être déclenché ?
settings.event_push_only=Uniquement les <code>push</code> (soumissions).
settings.event_send_everything=J'ai besoin de <strong>tout</strong>.
settings.event_choose=Permettez-moi de choisir ce dont j'ai besoin.
settings.event_create=Créer
settings.event_create_desc=Branche, ou Tag créé
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request ouvert, fermé, rouvert, édité, attribuée, non attribuées, étiquette mise à jour, étiquette désactivée ou synchronisé.
settings.event_delete=Supprimer
settings.event_delete_desc=Branche ou tag supprimé
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push vers un dépôt
settings.event_issues=Tickets
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Actif
settings.active_helper=Les détails seront délivrés lorsque ce Hook sera déclenché.
settings.add_hook_success=Nouveau Webhook ajouté.
@@ -786,7 +817,7 @@ settings.deploy_key_deletion=Supprimer la Clé de Déploiement
settings.deploy_key_deletion_desc=Supprimer cette clé de déploiement effacera tous les accès relatifs pour ce référentiel. Voulez-vous continuer ?
settings.deploy_key_deletion_success=La clé de déploiement a été supprimée avec succès !
diff.browse_source=Parcourir la Source
diff.browse_source=Parcourir la source
diff.parent=Parent
diff.commit=commit
diff.data_not_available=Données Diff indisponibles.
@@ -803,7 +834,6 @@ release.releases=Versions
release.new_release=Nouvelle version
release.draft=Brouillon
release.prerelease=Pré-publication
release.stable=Stable
release.edit=Éditer
release.ahead=<strong>%d</strong> commits jusqu'à %s depuis cette publication
release.source_code=Code source
@@ -1019,6 +1049,7 @@ repos.private=Privé
repos.watches=Suivi par
repos.stars=Votes
repos.issues=Tickets
repos.size=Size
auths.auth_manage_panel=Panel d'administration des authentifications
auths.new=Ajouter une nouvelle source d'authentification
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Délai imparti pour l'opération "Pull"
config.git_gc_timeout=Délai imparti pour l'opération "GC"
config.log_config=Configuration du Journal
config.log_mode=Mode du journal
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tâches Cron
monitor.name=Nom
@@ -1205,19 +1237,23 @@ notices.delete_success=Notifications système supprimées avec succès.
[action]
create_repo=a créé le dépôt <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=a rebaptisé le dépôt de <code>%[1]s</code> vers <a href="%[2]s">%[3]s</a>
commit_repo=a commité dans <a href="%[1]s/src/%[2]s">%[3]s</a> sur <a href="%[1]s">%[4]s</a>
compare_commits=Comparer ces %d commits
transfer_repo=a transféré le dépôt <code>%s</code> à <a href="%s">%s</a>
create_issue=`a ouvert un problème <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`tickets clos <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`tickets ré-ouverts <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`pull request créée le <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`pull request fermé <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`pull request ré-ouverte <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`pull request fusionné le <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=a transféré le dépôt <code>%s</code> à <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=a soumis le tag <a href="%s/src/%s">%[2]s</a> sur <a href="%[1]s">%[3]s</a>
compare_commits=Comparer ces %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=il y a

View File

@@ -82,6 +82,8 @@ app_url=URL da aplicación
app_url_helper=Isto afecta ás URLs para clonar por HTTP/HTTPS e a algúns correos electrónicos.
log_root_path=Ruta do rexistro
log_root_path_helper=Directorio onde almacenar os rexistros.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Configuración opcional
email_title=Configuración do servizo de correo
@@ -201,6 +203,7 @@ Content=Contido
require_error=` non pode estar baleiro.`
alpha_dash_error=` os caracteres deben ser alfanuméricos ou dash(-_).`
alpha_dash_dot_error=` debe ser un carácter alfanumérivo válido, un guión alto ou baixo (-_) ou un signo de puntuación.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` debe ser de tamaño %s.`
min_size_error=` debe conter polo menos %s caracteres.`
max_size_error=` debe conter como máximo %s caracteres.`
@@ -252,11 +255,10 @@ profile=Perfil
password=Contrasinal
avatar=Avatar
ssh_keys=Claves SSH
social=Redes sociais
applications=Aplicacións
repos=Repositories
orgs=Organizacións
applications=Aplicacións
delete=Eliminar conta
uid=UUID
public_profile=Perfil público
profile_desc=O teu correo electrónico é público e será usado para todas as notificacións relacionadas con calquera conta e calquera operación feita a través da web.
@@ -343,6 +345,11 @@ orgs.none=Non es membro de nengunha organización.
orgs.leave_title=Deixar unha organización
orgs.leave_desc=Deixarás de ter aceso ao tódolos repositorios e equipos despois de deixar a organización. Desexas abandonala?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Elimina a túa conta
delete_prompt=A operación eliminará a túa conta de forma permanente e <strong>NON</strong> se pode desfacer!
confirm_delete_account=Confirmar eliminación
@@ -413,7 +420,7 @@ quick_guide=Guía rápida
clone_this_repo=Clonar este repositorio
create_new_repo_command=Crear un novo repositorio desde liña de comandos
push_exist_repo=Facer Push dun repositorio existente desde liña de comandos
repo_is_empty=Este repositorio está baleiro, por favor, volva máis tarde!
bare_message=This repository does not have any content yet.
files=Ficheiros
branch=Rama
@@ -426,6 +433,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Fitos
commits=Achegas
git_branches=Branches
releases=Lanzamentos
file_raw=Raw
file_history=Histórico
@@ -434,6 +442,13 @@ file_permalink=Permalink
file_too_large=Este arquivo é demasiado grande para ser mostrado
video_not_supported_in_browser=O teu navegador non soporte a etiqueta video de HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Novo arquivo
editor.upload_file=Subir arquivo
editor.edit_file=Editar arquivo
@@ -531,7 +546,7 @@ issues.next=Páxina seguinte
issues.open_title=Aberta
issues.closed_title=Cerrada
issues.num_comments=%d comentarios
issues.commented_at='comentado <a href="#%s"> %s'</a>
issues.commented_at=`comentado <a href="#%s"> %s'</a>`
issues.delete_comment_confirm=Seguro que desexas eliminar este comentario?
issues.no_content=Aínda non existe contido.
issues.close_issue=Cerrar
@@ -641,9 +656,11 @@ settings.collaboration.write=Escritura
settings.collaboration.read=Lectura
settings.collaboration.undefined=Indefinido
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Este cambio afectaralles ás ligazóns ao reposi
settings.advanced_settings=Axustes avanzados
settings.wiki_desc=Activar sistema de wiki
settings.use_internal_wiki=Usar wiki integrada
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Usar Wiki externa
settings.external_wiki_url=URL externa da Wiki
settings.external_wiki_url_desc=Os visitantes serán redireccionados á URL cando preman na barra.
settings.issues_desc=Habilitar rastrexo de incidencias
settings.use_internal_issue_tracker=Usar rastrexo de incidencias lixeiro incluído
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Usar tracker externo de incidencias
settings.external_tracker_url=URL de seguimento de problemas externos
settings.external_tracker_url_desc=Os visitantes serán redireccionados á URL cando preman na barra.
@@ -731,6 +750,8 @@ 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 os teus axustes de webhook
settings.webhook.test_delivery_success=Probar que os webhook foron engadidos á cola de entrega. Isto pode levar algúns segundos antes de aparecer no historial de entregas.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Petición
settings.webhook.response=Resposta
settings.webhook.headers=Encabezado
@@ -755,10 +776,20 @@ settings.event_send_everything=Necesito <strong>todo</strong>.
settings.event_choose=Déixeme elixir o que necesito.
settings.event_create=Crear
settings.event_create_desc=Rama ou etiqueta creada
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request aberto, cerrado, reaberto, editado, asignado, desasignado, etiqueta actualizada, etiqueta borrada, ou sincronizado.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push a un repositorio
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Activo
settings.active_helper=Enviaremos detalles do evento cando este hook se dispare.
settings.add_hook_success=Engadiuse un novo webhook.
@@ -803,7 +834,6 @@ release.releases=Lanzamentos
release.new_release=Novo lanzamento
release.draft=Borrador=Borrador
release.prerelease=Pre-Release=Pre-Lanzamento
release.stable=Estable=Estable
release.edit=editar=editar
release.ahead=<strong>%d</strong> achegas en %s desde este release
release.source_code=Código fonte
@@ -1019,6 +1049,7 @@ repos.private=Privado
repos.watches=Vixilantes
repos.stars=Estrelas
repos.issues=Incidencias
repos.size=Size
auths.auth_manage_panel=Panel de administración de autenticación
auths.new=Engadir nova orixe
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Tempo de espera de operación de pull
config.git_gc_timeout=Tempo de espera de operación de GC
config.log_config=Configuración do log
config.log_mode=Modo do log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tarefas de cron
monitor.name=Nome
@@ -1205,19 +1237,23 @@ notices.delete_success=As notificacións do sistema foron eliminadas satisfactor
[action]
create_repo=creou o repositorio <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repositorio renomeado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
commit_repo=fixo push a <a href="%[1]s/src/%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparación destas %d achegas
transfer_repo=transferiu o repositorio <code>%s</code> a <a href="%s">%s</a>
create_issue=`incidencia aberta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`cerrou a incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reabriu a incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentou na incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`cerrou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabriu o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentou na incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transferiu o repositorio <code>%s</code> a <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=fixo push do tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparación destas %d achegas
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=hai

View File

@@ -48,7 +48,7 @@ cancel=Annulla
install=Installazione
title=Passi d'installazione per il primo avvio
docker_helper=Se stai utilizzando Gogs su Docker, per favore leggi le <a target="_blank" href="%s">Linee guida</a> con attenzione prima di cambiare qualcosa su questa pagina!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs richiede MySQL, PostgreSQL, SQLite3, MSSQL o TiDB.
db_title=Impostazioni Database
db_type=Tipo di database
host=Host
@@ -58,8 +58,8 @@ db_name=Nome del database
db_helper=Utilizza il motore INNODB con codifica utf8_general_ci per MySQL.
ssl_mode=Modalità SSL
path=Percorso
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=Il percorso del file di database di SQLite3. <br>Si prega di utilizzare il percorso assoluto quando si avvia come servizio.
err_empty_db_path=Il percorso del database SQLite3 non può essere vuoto.
no_admin_and_disable_registration=Non puoi disabilitare la registrazione senza aver creato un amministratore.
err_empty_admin_password=La password dell'amministratore non puo' essere vuota.
@@ -74,14 +74,16 @@ domain=Dominio
domain_helper=Questo influisce sugli URL per il clonaggio via SSH.
ssh_port=Porta SSH
ssh_port_helper=Numero di porta utilizzato dal server SSH, lasciare vuoto per disabilitare l'integrazione SSH.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
use_builtin_ssh_server=Usa il server SSH integrato
use_builtin_ssh_server_popup=Avvia il server SSH integrato per le operazioni Git per distinguerle dal demone SSH di sistema.
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.
enable_console_mode=Abilita modalità Terminale
enable_console_mode_popup=In aggiunta alla modalità file, invia i log anche al terminale.
optional_title=Impostazioni Facoltative
email_title=Impostazioni E-mail
@@ -201,6 +203,7 @@ Content=Contenuto
require_error=` non può essere vuoto.`
alpha_dash_error=` ammessi solo caratteri alfanumerici o trattini(-_).`
alpha_dash_dot_error=` ammessi solo caratteri alfanumerici o trattini(-_) o punti.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error='deve essere %s.'
min_size_error=` deve contenere almeno %s caratteri.`
max_size_error=` deve contenere massimo %s caratteri.`
@@ -252,11 +255,10 @@ profile=Profilo
password=Password
avatar=Avatar
ssh_keys=Chiavi SSH
social=Account Sociali
applications=Applicazioni
repos=Repositories
orgs=Organizzazioni
applications=Applicazioni
delete=Elimina account
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.
@@ -343,6 +345,11 @@ orgs.none=Non sei membro di alcuna organizzazione.
orgs.leave_title=Abbandona una organizzazione
orgs.leave_desc=Abbandonando l'organizzazione perderai l'accesso a tutti i repository e i gruppi. Confermi?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Elimina Account
delete_prompt=L'operazione eliminerà permanentemente l'account e <strong>NON POTRÀ</strong> essere annullata!
confirm_delete_account=Conferma Eliminazione
@@ -413,7 +420,7 @@ 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=Questo repository è vuoto, si prega di tornare più tardi!
bare_message=This repository does not have any content yet.
files=File
branch=Ramo (Branch)
@@ -426,6 +433,7 @@ pulls=Pull Requests
labels=Etichette
milestones=Traguardi
commits=Commit
git_branches=Branches
releases=Rilasci
file_raw=Originale
file_history=Cronologia
@@ -434,6 +442,13 @@ file_permalink=Permalink
file_too_large=Questo file è troppo grande per essere mostrato
video_not_supported_in_browser=Il tuo browser non supporta i tag "video" di HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nuovo file
editor.upload_file=Carica File
editor.edit_file=Modifica file
@@ -473,7 +488,7 @@ editor.add_subdir=Aggiungi sottocartella...
editor.unable_to_upload_files=È fallito il caricamento dei file su '%s': %v
editor.upload_files_to_dir=Carica file su '%s'
commits.commit_history=Commit History
commits.commit_history=Cronologia Commit
commits.commits=Commits
commits.search=Ricerca una versione
commits.find=Cerca
@@ -641,9 +656,11 @@ settings.collaboration.write=Write
settings.collaboration.read=Read
settings.collaboration.undefined=Undefined
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Questa modifica influirà i link al repository.
settings.advanced_settings=Opzioni avanzate
settings.wiki_desc=Enable wiki system
settings.use_internal_wiki=Use builtin wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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 issue tracker
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Utilizza gestore di problemi esterno
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Il Webhook è stato eliminato con successo!
settings.webhook.test_delivery=Test di consegna
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.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Richiesta
settings.webhook.response=Risposta
settings.webhook.headers=Headers
@@ -755,10 +776,20 @@ settings.event_send_everything=Ho bisogno di <strong>tutto</strong>.
settings.event_choose=Lasciami scegliere ciò di cui ho bisogno.
settings.event_create=Crea
settings.event_create_desc=Branch, o tag creato
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request aperta, chiusa, riaperta, modificata, assegnata, riassegnata, etichettata o sincronizzata.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push in un repository
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Attivo
settings.active_helper=Anche i dettagli riguardanti l'evento che ha innescato l'hook saranno inviati.
settings.add_hook_success=Il nuovo webhook è stato aggiunto.
@@ -803,7 +834,6 @@ release.releases=Rilasci
release.new_release=Nuovo Rilascio
release.draft=Bozza
release.prerelease=Pre-Rilascio
release.stable=Stabile
release.edit=modifica
release.ahead=<strong>%d</strong> commits da %s da questo rilascio
release.source_code=Codice Sorgente
@@ -1019,6 +1049,7 @@ repos.private=Privati
repos.watches=Segue
repos.stars=Voti
repos.issues=Problemi
repos.size=Size
auths.auth_manage_panel=Pannello di configurazione dei meccanismi di autenticazione
auths.new=Aggiungi Nuova Origine
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Timeout per il pull
config.git_gc_timeout=Timeout per le operazioni di GC
config.log_config=Configurazione Log
config.log_mode=Modalità Log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Incarici di cron
monitor.name=Nome
@@ -1205,19 +1237,23 @@ notices.delete_success=Gli avvisi di sistema sono stati successivamente eliminat
[action]
create_repo=ha creato il repository <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=repository rinominato da <code>%[1]s</code> a <a href="%[2]s">[3]s</a>
commit_repo=ha pushato nel <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
compare_commits=Visualizza comparazione tra questi %d commit
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
create_issue=`ha aperto il problema <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`creata pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Visualizza comparazione tra questi %d commit
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=fa

View File

@@ -82,6 +82,8 @@ app_url=アプリケーションの URL
app_url_helper=この設定は、HTTP / HTTPSのクローンURLおよび、一部のメールボックスへのリンクに影響を与えます。
log_root_path=ログのパス
log_root_path_helper=ログファイルを書き込むディレクトリ。
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=オプション設定
email_title=メールサービス設定
@@ -201,6 +203,7 @@ Content=コンテンツ
require_error=空にできません
alpha_dash_error=アルファベット、数字、ハイフン"-"、アンダースコア"_"のいずれかの必要があります
alpha_dash_dot_error=' アルファベット、数値、ダッシュ(-)、アンダースコア(_) 、ドット(.)のいずれかを入力する必要があります。 '
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=`サイズは %s である必要があります`
min_size_error=' 少なくとも %s 文字の必要があります '
max_size_error=' %s 文字以下の必要があります '
@@ -252,11 +255,10 @@ profile=プロフィール
password=パスワード
avatar=アバター
ssh_keys=SSH キー
social=SNSアカウント
applications=アプリケーション
repos=Repositories
orgs=組織
applications=アプリケーション
delete=アカウントを削除
uid=Uid
public_profile=パブリック プロフィール
profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。
@@ -340,9 +342,14 @@ access_token_deletion_desc=パーソナルアクセストークンを削除す
delete_token_success=パーソナルアクセストークンは正常に削除されました!同時にあなたのアプリケーションを更新することを忘れないでください。
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=アカウントを削除
delete_prompt=この操作をするとアカウントが完全に削除され、<strong>二度と元に戻すことができなくなります</strong>
confirm_delete_account=削除の確認
@@ -413,7 +420,7 @@ quick_guide=クイック ガイド
clone_this_repo=このリポジトリのクローンを作成
create_new_repo_command=コマンドラインで新しいリポジトリを作成します。
push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ
repo_is_empty=このリポジトリは空です、後で戻って来て下さい!
bare_message=This repository does not have any content yet.
files=Files
branch=ブランチ
@@ -426,6 +433,7 @@ pulls=プルリクエスト
labels=ラベル
milestones=マイルストーン
commits=コミット
git_branches=Branches
releases=リリース
file_raw=Raw
file_history=履歴
@@ -434,6 +442,13 @@ file_permalink=パーマリンク
file_too_large=このファイルは大きすぎるため、表示できません。
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=ファイルを編集
@@ -641,9 +656,11 @@ settings.collaboration.write=書込
settings.collaboration.read=読込
settings.collaboration.undefined=Undefined
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=この変更はリンクがリポジトリに関
settings.advanced_settings=拡張設定
settings.wiki_desc=Enable wiki system
settings.use_internal_wiki=Use builtin wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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=Enable issue tracker
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=外部課題トラッキングシステムを使用
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ 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.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=リクエスト
settings.webhook.response=レスポンス
settings.webhook.headers=ヘッダ
@@ -755,10 +776,20 @@ settings.event_send_everything=<strong>すべて</strong> が必要です。
settings.event_choose=必要なものを選択しましょう。
settings.event_create=Create
settings.event_create_desc=ブランチ、またはタグを作成
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=プッシュ
settings.event_push_desc=Git リポジトリにプッシュ
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=アクティブ
settings.active_helper=このフックのトリガーが引かれた時に、イベントの詳細を配信します。
settings.add_hook_success=新しい webhook が追加されました。
@@ -776,7 +807,7 @@ settings.deploy_keys=デプロイキー
settings.deploy_keys_helper=<b>Common Gotcha!</b> If you're looking for adding personal public keys, please add them in your <a href="%s%s">account settings</a>.
settings.add_deploy_key=デプロイキーを追加
settings.deploy_key_desc=個人アカウントのSSHキーとは異なり、デプロイキーは読み取り専用アクセスとなります。
settings.no_deploy_keys=プロキーは1つも追加されていません。
settings.no_deploy_keys=プロキーは1つも追加されていません。
settings.title=タイトル
settings.deploy_key_content=コンテント
settings.key_been_used=デプロイキーが使用されています。
@@ -803,7 +834,6 @@ release.releases=リリース
release.new_release=新しいリリース
release.draft=ドラフト
release.prerelease=プレリリース
release.stable=安定
release.edit=編集
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
release.source_code=ソース コード
@@ -1019,6 +1049,7 @@ repos.private=プライベート
repos.watches=Watches
repos.stars=Stars
repos.issues=課題
repos.size=Size
auths.auth_manage_panel=認証管理パネル
auths.new=新しいソースを追加
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=ログの構成
config.log_mode=ログ モード
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron タスク
monitor.name=名前
@@ -1205,19 +1237,23 @@ notices.delete_success=システム通知が正常に削除されました。
[action]
create_repo=がリポジトリ <a href="%s"> %s</a> を作成しました
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s</code> から <a href="%[2]s">[3]s</a> にリポジトリ名を変更しました
commit_repo=<a href="%[1]s">%[4]s</a>を<a href="%[1]s/src/%[2]s">%[3]s</a>にプッシュしました
compare_commits=これらの %d コミットの比較を表示
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
create_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> を開きました`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
create_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>を作成`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
merge_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>をマージしました`
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
compare_commits=これらの %d コミットの比較を表示
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=

View File

@@ -48,7 +48,7 @@ cancel=취소
install=설치
title=첫 실행을 위한 설치단계
docker_helper=Gogs를 Docker에서 운영하고 있다면 <a target="_blank" href="%s">안내</a>를 읽고 변경해 주세요!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs MySQL, PostgreSQL, SQLite3, MSSQL 또는 TiDB 를 필요로 합니다.
db_title=데이터베이스 설정
db_type=데이터베이스 유형
host=호스트
@@ -58,8 +58,8 @@ db_name=데이터베이스 이름
db_helper=MySQL에서는 utf8_general_ci 캐릭터셋으로 INNODB엔진을 이용해 주세요
ssl_mode=SSL 모드
path=경로
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=SQLite3 데이터베이스의 경로입니다.<br>서비스를 시작할 때는 반드시 절대 경로를 사용해주세요.
err_empty_db_path=SQLite3 데이터베이스의 경로는 비워둘 수 없습니다.
no_admin_and_disable_registration=관리자 계정을 만들지 않고 등록을 비활성화할 수 없습니다.
err_empty_admin_password=관리자 암호는 비워둘 수 없습니다.
@@ -74,7 +74,7 @@ domain=도메인
domain_helper=Git SSH url에 영향을 미칩니다.
ssh_port=SSH 포트
ssh_port_helper=SSH서버가 실행되고 있는 포트를 입력하세요. 비워둘 경우 SSH를 사용하지 않습니다.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server=내장 SSH 서버 사용
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
http_port=HTTP 포트
http_port_helper=포트 번호는 애플리케이션에서 열고 있습니다.
@@ -82,6 +82,8 @@ app_url=애플리케이션 URL
app_url_helper=이 작업은 HTTP/HTTPS 클론 URL과 이메일의 어딘가에 영향을 미칩니다.
log_root_path=로그 경로
log_root_path_helper=로그 파일을 쓸 디렉터리.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=추가설정
email_title=이메일 서비스 설정
@@ -201,6 +203,7 @@ Content=컨텐츠
require_error=` 비어 있을 수 없습니다.`
alpha_dash_error=`은(는) 숫자, 알파벳, 대시(-_) 문자로만 구성되어야 합니다.`
alpha_dash_dot_error=` 숫자, 알파벳, 점(.), 대시(-_) 문자로만 구성되어야 합니다.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` %s 글자여야 합니다.`
min_size_error=` 최소 %s 글자여야 합니다.`
max_size_error=` %s 글자를 넘을 수 없습니다.`
@@ -252,11 +255,10 @@ profile=프로필
password=비밀번호
avatar=아바타
ssh_keys=SSH 키
social=소셜 계정
applications=애플리케이션
repos=Repositories
orgs=조직
applications=애플리케이션
delete=계정 삭제
uid=Uid
public_profile=공개 프로필
profile_desc=이메일 주소가 공개되며, 사이트를 통해 작업하거나 계정과 관련된 모든 알림에 사용됩니다.
@@ -343,6 +345,11 @@ orgs.none=당신은 어떤 조직의 구성원도 아닙니다.
orgs.leave_title=조직 떠나기
orgs.leave_desc=조직을 떠난 후에는 모든 리포지토리와 팀에 액세스 할 수 없게 됩니다. 계속 하시겠습니까?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=계정 삭제
delete_prompt=당신의 계정을 삭제합니다. 완료된 후에는 <strong>취소할 수 없습니다</strong>.
confirm_delete_account=삭제 승인
@@ -413,7 +420,7 @@ quick_guide=퀵 가이드
clone_this_repo=이 저장소 복제
create_new_repo_command=커맨드 라인에서 새 저장소 만들기
push_exist_repo=커맨드 라인에서 기존 저장소 푸시하기
repo_is_empty=이 저장소는 비어 있습니다. 나중에 다시 와주세요!
bare_message=This repository does not have any content yet.
files=파일
branch=브렌치
@@ -426,6 +433,7 @@ pulls=풀 리퀘스트
labels=레이블
milestones=마일스톤
commits=커밋
git_branches=Branches
releases=릴리즈
file_raw=Raw
file_history=히스토리
@@ -434,6 +442,13 @@ file_permalink=고유링크
file_too_large=이 파일은 표시하기엔 너무 큽니다.
video_not_supported_in_browser=이 브라우저는 HTML5 비디오 태그를 지원하지 않습니다.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=파일 생성
editor.upload_file=파일 업로드
editor.edit_file=파일 수정
@@ -473,7 +488,7 @@ editor.add_subdir=하위 디렉토리 추가...
editor.unable_to_upload_files=파일 '%s'를 업로드하는데 실패하였습니다. 에러: %v
editor.upload_files_to_dir=파일 업로드 '%s'
commits.commit_history=Commit History
commits.commit_history=커밋 기록
commits.commits=커밋
commits.search=커밋 검색
commits.find=찾기
@@ -641,24 +656,26 @@ settings.collaboration.admin=관리자
settings.collaboration.write=쓰기
settings.collaboration.read=읽기
settings.collaboration.undefined=미정의
settings.branches=Branches
settings.default_branch=Default Branch
settings.branches=브랜치
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=기본 브랜치
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
settings.choose_a_branch=Choose a branch...
settings.branch_protection=Branch Protection
settings.branch_protection_desc=Please choose protect options for branch <b>%s</b>.
settings.protect_this_branch=Protect this branch
settings.protect_this_branch_desc=Disable force pushes and prevent from deletion.
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.update=업데이트
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=이 레포지토리의 기본 브랜치가 성공적으로 설정되었습니다!
settings.protected_branches=보호된 브랜치
settings.protected_branches_desc=보호된 브랜치는 force 푸시, 실수로 인한 코드 삭제를 방지하며 코드 커미터를 화이트리스트 합니다.
settings.choose_a_branch=브랜치를 선택하세요...
settings.branch_protection=브랜치 보호
settings.branch_protection_desc=브랜치 <b>%s</b> 의 보호 설정을 선택하세요.
settings.protect_this_branch=이 브랜치를 보호하기
settings.protect_this_branch_desc=Force 푸시와 삭제를 비활성화합니다.
settings.protect_require_pull_request=직접 push 를 하지 않고 Pull Request 를 필요로 하도록 합니다.
settings.protect_require_pull_request_desc=이 브랜치에 직접 푸시를 하는 것을 막고 싶다면 이 옵션을 활성화하세요. 커밋은 다른 비보호 브랜치에 푸시되어야 하며 이 브랜치에는 Pull Request 를 통해 병합될 것입니다.
settings.protect_whitelist_committers=이 브랜치에 푸시할 수 있는 유저
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=이 브랜치에 푸시를 할 수 있는 유저
settings.protect_whitelist_search_users=유저 검색
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
@@ -674,11 +691,13 @@ settings.change_reponame_prompt=이 변경은 이 저장소와 연관된 링크
settings.advanced_settings=고급 설정
settings.wiki_desc=위키 시스템 활성화
settings.use_internal_wiki=내장 위키 사용
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=외부 위키 사용하기
settings.external_wiki_url=외부 위키 URL
settings.external_wiki_url_desc=탭을 클릭하면 URL로 리다이렉트됩니다.
settings.issues_desc=이슈 추적기를 사용하도록 설정
settings.use_internal_issue_tracker=내장된 경량 이슈 트레커를 사용
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=외부 이슈 트래커 사용하기
settings.external_tracker_url=외부 이슈 트래커 URL
settings.external_tracker_url_desc=방문자는 탭을 클릭하면 URL로 리다이렉트 됩니다.
@@ -732,6 +751,8 @@ settings.webhook_deletion_success=Webhook을 성공적으로 삭제했습니다!
settings.webhook.test_delivery=전달 시험
settings.webhook.test_delivery_desc=가짜 푸시 이벤트 전달하여 웹훅 설정을 테스트합니다.
settings.webhook.test_delivery_success=Webhook 테스트가 delivery 큐에 추가되었습니다. delivery 기록에서 나오기까지 몇 초의 시간이 걸릴 것입니다.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=요청
settings.webhook.response=응답
settings.webhook.headers=제목
@@ -756,10 +777,20 @@ settings.event_send_everything=<strong>모든 것</strong>이 필요합니다.
settings.event_choose=필요한 것을 선택해주세요.
settings.event_create=생성
settings.event_create_desc=브랜치 또는 태그를 생성합니다.
settings.event_pull_request=끌어오기 요청
settings.event_pull_request_desc=끌어오기 요청 열기, 닫기, 다시 열기, 편집, 할당, 할당 해제, 라벨 업데이트, 라벨 지우기 또는 동기화.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=푸시
settings.event_push_desc=깃 저장소로 푸시
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=끌어오기 요청
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=활성
settings.active_helper=후크를 트리거하면 이벤트에 대한 세부 정보도 전달됩니다.
settings.add_hook_success=새로운 웹훅이 생성되었습니다.
@@ -804,7 +835,6 @@ release.releases=릴리즈
release.new_release=새로운 릴리즈
release.draft=초안
release.prerelease=사전 릴리즈
release.stable=안정
release.edit=편집
release.ahead=이 릴리스 이후로 <strong>%d</strong> %s에 커밋합니다.
release.source_code=소스 코드
@@ -1020,6 +1050,7 @@ repos.private=비공개
repos.watches=지켜보기
repos.stars=Stars
repos.issues=이슈
repos.size=Size
auths.auth_manage_panel=인증 관리 패널
auths.new=새로운 소스를 추가
@@ -1177,7 +1208,8 @@ config.git_pull_timeout=끌어오기 작업 시간 제한
config.git_gc_timeout=가비지 콜렉션 작업 시간 제한
config.log_config=로그 설정
config.log_mode=로그 모드
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron 작업
monitor.name=이름
@@ -1206,19 +1238,23 @@ notices.delete_success=시스템 알림들이 성공적으로 삭제되었습니
[action]
create_repo=저장소를 만들었습니다. <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s에서</code>에서 <a href="%[2]s"> %[3]s</a>으로 저장소 이름을 바꾸었습니다.
commit_repo=<a href="%[1]s">%[4]s</a>에서 <a href="%[1]s/src/%[2]s">%[3]s</a>으로 푸시함
compare_commits=이 %d개의 커밋에 대한 비교 보기
transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송되었습니다.
create_issue=`열린 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
close_issue=`닫힌 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
reopen_issue=`다시 열린 이슈 <a href="%s/issues/%s"> %s #%[2]s</a>`
comment_issue=`이슈에 댓글이 달렸습니다. <a href="%s/issues/%s"> %s #%[2]s</a>`
create_pull_request=`만들어진 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
close_pull_request=`닫힌 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
reopen_pull_request=`다시 열린 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
comment_issue=`이슈에 댓글이 달렸습니다. <a href="%s/issues/%s"> %s #%[2]s</a>`
merge_pull_request=`병합된 끌어오기 요청 <a href="%s/pulls/%s"> %s #%[2]s</a>`
transfer_repo=<code>%s</code>에서 <a href="%s">%s</a>로 저장소가 전송되었습니다.
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=태그 <a href="%s/src/%s">%[2]s</a>를 <a href="%[1]s">%[3]s</a>로 푸시함
compare_commits=이 %d개의 커밋에 대한 비교 보기
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=

View File

@@ -82,6 +82,8 @@ 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.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Neobligātie iestatījumi
email_title=E-pasta pakalpojuma iestatījumi
@@ -201,6 +203,7 @@ Content=Saturs
require_error=` nedrīkst būt tukšs.`
alpha_dash_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus vai domuzīmes (-_).`
alpha_dash_dot_error=` drīkst saturēt tikai latīņu alfabēta burtus, ciparus, domuzīmes (-_) vai punktu.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` jābūt %s simbolus garam.`
min_size_error=` jabūt vismaz %s simbolu garumā.`
max_size_error=` jabūt ne mazāk kā %s simbolu garumā.`
@@ -252,11 +255,10 @@ profile=Profils
password=Parole
avatar=Profila attēls
ssh_keys=SSH atslēgas
social=Sociālie konti
applications=Lietotnes
repos=Repositories
orgs=Organizācijas
applications=Lietotnes
delete=Dzēst kontu
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.
@@ -340,9 +342,14 @@ access_token_deletion_desc=Dzēšot personīgo piekļuves talonu, tiks liegta pi
delete_token_success=Personīgās piekļuves talons veiksmīgi izdzēsts! Neaizmirstiet nomainīt uz citu aplikācijās, kas to izmantoja.
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Dzēst savu kontu
delete_prompt=Šī darbība pilnībā izdzēsīs Jūsu kontu, kā arī tā ir <strong>NEATGRIEZENISKA</strong>!
confirm_delete_account=Apstiprināt dzēšanu
@@ -413,7 +420,7 @@ quick_guide=Īsa pamācība
clone_this_repo=Klonēt šo repozitoriju
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!
bare_message=This repository does not have any content yet.
files=Files
branch=Atzars
@@ -426,6 +433,7 @@ pulls=Izmaiņu pieprasījumi
labels=Etiķetes
milestones=Atskaites punkti
commits=Revīzijas
git_branches=Branches
releases=Laidieni
file_raw=Neapstrādāts
file_history=Vēsture
@@ -434,6 +442,13 @@ file_permalink=Patstāvīgā saite
file_too_large=Šis fails ir par lielu, lai to parādītu
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Jauns fails
editor.upload_file=Augšupielādēt failu
editor.edit_file=Labot failu
@@ -641,9 +656,11 @@ settings.collaboration.write=Rakstīšanas
settings.collaboration.read=Skatīšanās
settings.collaboration.undefined=Nedefinētas
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Šī izmaiņa ietekmēs saites, kas ir saistīta
settings.advanced_settings=Papildu iestatījumi
settings.wiki_desc=Iespējot vikivietnes
settings.use_internal_wiki=Izmantot iebūvēto vikivietni
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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 problēmu sekotāju
settings.use_internal_issue_tracker=Izmantot iebūvētu vieglu problēmu sekotāju
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Izmantot ārējo problēmu sekotāju
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ 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.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Pieprasījums
settings.webhook.response=Atbilde
settings.webhook.headers=Galvenes
@@ -755,10 +776,20 @@ settings.event_send_everything=Vēlos saņemt <strong>visu</strong>.
settings.event_choose=Atzīmēt, ko vēlos saņemt.
settings.event_create=Izveidot
settings.event_create_desc=Atzara vai taga izveidošana
settings.event_pull_request=Izmaiņu pieprasījums
settings.event_pull_request_desc=Atvērts, aizvērts, atkāroti atvērts, labots, piešķirts vai noņemts izmaiņu pieprasījums, vai mainīta etiķete, vai veikta sinhronizācija.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Izmaiņu nosūtīšana
settings.event_push_desc=Git izmaiņu nosūtīšana uz repozitoriju
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Izmaiņu pieprasījums
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktīvs
settings.active_helper=Tiks nosūtīti notikuma dati, kad nostrādās šis āķis.
settings.add_hook_success=Jauns tīmekļa āķis tika veiksmīgi pievienots.
@@ -803,7 +834,6 @@ release.releases=Laidieni
release.new_release=Jauns laidiens
release.draft=Melnraksts
release.prerelease=Pirmsizlaides versija
release.stable=Stabila
release.edit=labot
release.ahead=<strong>%d</strong> revīzijas atzarā %s kopš šī laidiena
release.source_code=Izejas kods
@@ -1019,6 +1049,7 @@ repos.private=Privāts
repos.watches=Vērošana
repos.stars=Atzīmētās zvaigznītes
repos.issues=Problēmas
repos.size=Size
auths.auth_manage_panel=Autentifikācijas pārvaldības panelis
auths.new=Pievienot jaunu avotu
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Izmaiņu saņemšanas darbības noilgums
config.git_gc_timeout=GC darbības noilgums
config.log_config=Žurnalizēšanas konfigurācija
config.log_mode=Žurnalizēšanas veids
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron uzdevumi
monitor.name=Nosaukums
@@ -1205,19 +1237,23 @@ notices.delete_success=Sistēmas paziņojumi tika veiksmīgi izdzēstas.
[action]
create_repo=izveidoja repozitoriju <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=pārsauca repozitoriju no <code>%[1]s</code> uz <a href="%[2]s">%[3]s</a>
commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%[1]s/src/%[2]s">%[3]s</a> repozitorijā <a href="%[1]s">%[4]s</a>
compare_commits=Salīdzināt šīs %d revīzijas
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`slēdza problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`atkārtoti atvēra problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`izveidoja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`aizvēra izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`atkārtoti atvēra izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`sapludināja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
compare_commits=Salīdzināt šīs %d revīzijas
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=atpakaļ

View File

@@ -82,6 +82,8 @@ 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.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Optionele instellingen
email_title=E-mail service instellingen
@@ -201,6 +203,7 @@ Content=Inhoud
require_error=kan niet leeg zijn.
alpha_dash_error=moet een valide alfanumeriek of dash(-_) karakter zijn.
alpha_dash_dot_error=moet een valide alfanumeriek, dash(-_) of (.) punt karakter zijn.
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=moet groter zijn dan %s
min_size_error=moet minimaal %s karakters bevatten.
max_size_error=mag maximaal %s karakters bevatten.
@@ -252,11 +255,10 @@ profile=Profiel
password=Wachtwoord
avatar=Profielfoto
ssh_keys=SSH-sleutels
social=Sociale netwerk-accounts
applications=Toepassingen
repos=Repositories
orgs=Organisaties
applications=Toepassingen
delete=Verwijder account
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.
@@ -343,6 +345,11 @@ orgs.none=U bent geen lid van een organisatie.
orgs.leave_title=Een organisatie verlaten
orgs.leave_desc=U verliest toegang tot alle repositories en teams nadat u de organisatie verlaten hebt. Wilt u doorgaan?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Verwijder uw account
delete_prompt=Deze handeling zal uw account definitief verwijderen, u kunt dit <strong> NIET </strong> terug draaien!
confirm_delete_account=Bevestig verwijdering
@@ -413,7 +420,7 @@ 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=Deze repositories is leeg is, probeer het later opnieuw!
bare_message=This repository does not have any content yet.
files=Bestanden
branch=Aftakking
@@ -426,6 +433,7 @@ pulls=Pull-aanvragen
labels=Labels
milestones=Mijlpalen
commits=Commits
git_branches=Branches
releases=Publicaties
file_raw=Ruwe
file_history=Geschiedenis
@@ -434,6 +442,13 @@ file_permalink=Permalink
file_too_large=Dit bestand is te groot om te worden getoond
video_not_supported_in_browser=Uw browser ondersteunt geen HTML5 video label.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nieuw bestand
editor.upload_file=Bestand uploaden
editor.edit_file=Bewerk bestand
@@ -641,9 +656,11 @@ settings.collaboration.write=Schrijven
settings.collaboration.read=Lezen
settings.collaboration.undefined=Niet gedefinieerd
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Deze verandering zal gevolgen hebben voor hoe li
settings.advanced_settings=Geavanceerde opties
settings.wiki_desc=Wiki-systeem inschakelen
settings.use_internal_wiki=Ingebouwde wiki gebruiken
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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=Kwestietracker inschakelen
settings.use_internal_issue_tracker=Gebruik ingebouwde eenvoudige kwestietracker
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Externe issuetracker gebruiken
settings.external_tracker_url=URL externe kwestietracker
settings.external_tracker_url_desc=Bezoekers worden doorgestuurd naar de URL als ze op het tabblad klikken.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webhook is succesvol verwijderd!
settings.webhook.test_delivery=Test-bezorging
settings.webhook.test_delivery_desc=Stuur een nep push bericht om de webhook te testen
settings.webhook.test_delivery_success=De test webhook is toegevoegd aan de wachtrij. Het kan enkele seconden duren voor deze in de geschiedenis wordt weergegeven.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Verzoek
settings.webhook.response=Antwoord
settings.webhook.headers=Headers
@@ -755,10 +776,20 @@ settings.event_send_everything=Ik moet <strong>alles</strong> hebben.
settings.event_choose=Laat me kiezen wat ik nodig heb.
settings.event_create=Creëer
settings.event_create_desc=Branch, of tag aangemaakt
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request geopend, gesloten, opnieuw geopend, bewerkt, toegewezen, niet-toegewezen, label bijgewerkt, label gewist of gesynchroniseerd.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push naar een repository
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Actief
settings.active_helper=We zullen details van de gebeurtenissen af leveren wanneer deze webhook wordt geactiveerd.
settings.add_hook_success=Nieuwe webhook toegevoegd.
@@ -803,7 +834,6 @@ release.releases=Releases
release.new_release=Nieuwe release
release.draft=Concept
release.prerelease=Voorlopige versie
release.stable=Stabiel
release.edit=bewerken
release.ahead=<strong>%d</strong> aanpassingen aan %s sinds deze versie
release.source_code=Broncode
@@ -1019,6 +1049,7 @@ repos.private=Prive
repos.watches=Volgers
repos.stars=Sterren
repos.issues=Kwesties
repos.size=Size
auths.auth_manage_panel=Authenticatie-beheer paneel
auths.new=Nieuwe bron toevoegen
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Logconfiguratie
config.log_mode=Log-modus
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron-taken
monitor.name=Naam
@@ -1205,19 +1237,23 @@ notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=repositorie aangemaakt in <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=hernoemde repository van <code>%[1]s</code> naar <a href="%[2]s">%[3]s</a>
commit_repo=push update naar <a href="%[1]s/src/%[2]s">%[3]s</a> in <a href="%[1]s">%[4]s</a>
compare_commits=Toon vergelijking voor deze %d commits
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
create_issue=`opende issue in <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`sloot kwestie <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`heropende kwestie <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`maakte pull request <a href="%s/issues/%s">%s#%[2]s</a>`
close_pull_request=`sloot pull request <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_pull_request=`heropende pull request <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`voegde pull request samen <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
compare_commits=Toon vergelijking voor deze %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=geleden

View File

@@ -82,6 +82,8 @@ app_url=Adres URL aplikacji
app_url_helper=To wpłynie na adresy klonowania HTTP/HTTPS i w wiadomościach e-mail.
log_root_path=Ścieżka dla logów
log_root_path_helper=Katalog do zapisu logów.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Ustawienia opcjonalne
email_title=Ustawienia serwera e-mail
@@ -201,6 +203,7 @@ Content=Treść
require_error=` nie może być puste.`
alpha_dash_error=` musi się składać z prawidłowych znaków alfanumerycznych, myślników oraz podkreśleń.`
alpha_dash_dot_error=` musi się składać z prawidłowych znaków alfanumerycznych, myślników, podkreśleń oraz kropek.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` musi być wielkości %s.`
min_size_error=` musi zawierać co najwyżej %s znaków.`
max_size_error=` musi zawierać co najwyżej %s znaków.`
@@ -252,11 +255,10 @@ profile=Profil
password=Hasło
avatar=Awatar
ssh_keys=Klucze SSH
social=Konta społecznościowe
applications=Aplikacje
repos=Repositories
orgs=Organizacje
applications=Aplikacje
delete=Usuń konto
uid=UID
public_profile=Profil publiczny
profile_desc=Twój adres e-mail jest publiczny i będzie używany dla wszystkich powiadomień związanych z kontem i dla każdej operacji wykonanej przez tę stronę.
@@ -340,9 +342,14 @@ access_token_deletion_desc=Usunięcie tego tokena osobistego dostęp spowoduje u
delete_token_success=Osobisty token dostępu został usunięty pomyślnie! Nie zapomnij również zaktualizować swoich aplikacji.
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Usuń swoje konto
delete_prompt=Ta operacja trwale usunie Twoje konto i <strong>NIE MOŻE</strong> zostać cofnięta!
confirm_delete_account=Potwierdź usunięcie
@@ -413,7 +420,7 @@ quick_guide=Skrócona instrukcja
clone_this_repo=Klonuj repozytorium
create_new_repo_command=Utwórz nowe repozytorium z wiersza poleceń
push_exist_repo=Prześlij istniejące repozytorium z wiersza poleceń
repo_is_empty=To repozytorium jest puste, proszę wrócić później!
bare_message=This repository does not have any content yet.
files=Files
branch=Gałąź
@@ -426,6 +433,7 @@ pulls=Oczekujące zmiany
labels=Etykiety
milestones=Kamienie milowe
commits=Commity
git_branches=Branches
releases=Wydania
file_raw=Czysty
file_history=Historia
@@ -434,6 +442,13 @@ file_permalink=Bezpośredni odnośnik
file_too_large=Ten plik jest zbyt duży, aby go wyświetlić
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Nowy plik
editor.upload_file=Załaduj plik
editor.edit_file=Edytuj plik
@@ -641,9 +656,11 @@ settings.collaboration.write=Zapis
settings.collaboration.read=Odczyt
settings.collaboration.undefined=Niezdefiniowany
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Zmiana nazwy repozytorium wpłynie na linki do n
settings.advanced_settings=Ustawienia zaawansowane
settings.wiki_desc=Włącz system wiki
settings.use_internal_wiki=Użyj wbudowanego wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Użyj zewnętrznego Wiki
settings.external_wiki_url=Adres URL zewnętrznego Wiki
settings.external_wiki_url_desc=Odwiedzający zostaną przekierowani do adresu URL po kliknięciu zakładki.
settings.issues_desc=Włącz system zgłaszania problemów
settings.use_internal_issue_tracker=Użyj wbudowany lekki system zgłaszania problemów
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Użyj zewnętrznego systemu zgłaszania problemów
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webhook został pomyślnie usunięty!
settings.webhook.test_delivery=Testuj dostawę
settings.webhook.test_delivery_desc=Wyślij fałszywe zdarzenie push aby przetestować ustawienie webhooka
settings.webhook.test_delivery_success=Testowy webhook został dodany do kolejki dostawy. To może zająć kilka sekund, zanim to pojawia się w historii dostawy.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Żądanie
settings.webhook.response=Odpowiedź
settings.webhook.headers=Nagłówki
@@ -755,10 +776,20 @@ settings.event_send_everything=Potrzebuję <strong>wszystkiego</strong>.
settings.event_choose=Pozwól mi wybrać, czego potrzebuję.
settings.event_create=Utwórz
settings.event_create_desc=Utworzono gałąź lub tag
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Otworzono żądanie pull, zamknięto, otwarto ponownie, zaktualizowano, przypisano, nieprzypisano, zaktualizowano etykietę, wyczyszczono etykietę lub zsynchronizowano.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Wypchnięcie
settings.event_push_desc=Wypchnięcie (push) do repozytorium Git
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktywny
settings.active_helper=Dostarczymy szczegóły zdarzenia, gdy ten webhook zostanie wywołany.
settings.add_hook_success=Nowy webhook został dodany.
@@ -803,7 +834,6 @@ release.releases=Wydania
release.new_release=Nowe wydanie
release.draft=Szkic
release.prerelease=Wersja wstępna
release.stable=Stabilny
release.edit=edytuj
release.ahead=<strong>%d</strong> commitów w %s od tego wydania
release.source_code=Kod źródłowy
@@ -1019,6 +1049,7 @@ repos.private=Prywatne
repos.watches=Obserwujących
repos.stars=Polubienia
repos.issues=Problemy
repos.size=Size
auths.auth_manage_panel=Panel zarządzania uwierzytelnianiem
auths.new=Dodaj nowe źródło
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Limit czasu dla operacji pull
config.git_gc_timeout=Limit czasu odśmiecania pamięci
config.log_config=Konfiguracja dziennika
config.log_mode=Tryb dziennika
config.log_mode=Mode
config.log_options=Options
monitor.cron=Zadania cron
monitor.name=Nazwa
@@ -1205,19 +1237,23 @@ notices.delete_success=Powiadomienia systemowe zostały pomyślnie usunięte.
[action]
create_repo=tworzy repozytorium <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=zmienia nazwę repozytorium <code>%[1]s</code> na <a href="%[2]s">%[3]s</a>
commit_repo=wypycha do <a href="%[1]s/src/%[2]s">%[3]s</a> w <a href="%[1]s">%[4]s</a>
compare_commits=Zobacz porównanie tych %d commitów
transfer_repo=przenosi repozytorium <code>%s</code> do <a href="%s">%s</a>
create_issue=`zgłasza problem <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`zamknięcie problemu <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`ponowne otwarcie problemu <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`komentuje problem <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`tworzy pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`zamknięcie pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`ponowne otwarcie pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`komentuje problem <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`scala pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=przenosi repozytorium <code>%s</code> do <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=taguje <a href="%s/src/%s">%[2]s</a> w <a href="%[1]s">%[3]s</a>
compare_commits=Zobacz porównanie tych %d commitów
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=temu

View File

@@ -82,6 +82,8 @@ app_url=URL do aplicativo
app_url_helper=Isto afeta a URL de clone via HTTP/HTTPs e também o e-mail.
log_root_path=Caminho do log
log_root_path_helper=Pasta dos arquivos de log.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Configurações opcionais
email_title=Configurações do serviço de e-mail
@@ -201,6 +203,7 @@ Content=Conteúdo
require_error=` não pode estar vazio.`
alpha_dash_error=` devem ser caracteres alfanuméricos, hífen (-) ou sublinhado (_).`
alpha_dash_dot_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=`deve ser do tamanho %s.`
min_size_error=` deve conter pelo menos %s caracteres.`
max_size_error=` deve conter no máximo %s caracteres.`
@@ -252,11 +255,10 @@ profile=Perfil
password=Senha
avatar=Avatar
ssh_keys=Chaves SSH
social=Contas sociais
applications=Aplicativos
repos=Repositories
orgs=Organizações
applications=Aplicativos
delete=Deletar conta
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.
@@ -343,6 +345,11 @@ orgs.none=Você não é participante de nenhuma organização.
orgs.leave_title=Deixar uma organização
orgs.leave_desc=Você perderá acesso a todos os repositórios e equipes após deixar a organização. Deseja continuar?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Deletar sua conta
delete_prompt=A operação deletará sua conta permanentemente, e <strong>NÃO PODERÁ</strong> ser desfeita!
confirm_delete_account=Confirmar exclusão
@@ -413,7 +420,7 @@ quick_guide=Guia rápido
clone_this_repo=Clonar este repositório
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!
bare_message=This repository does not have any content yet.
files=Arquivos
branch=Branch
@@ -426,6 +433,7 @@ pulls=Pull Requests
labels=Etiquetas
milestones=Milestones
commits=Commits
git_branches=Branches
releases=Versões
file_raw=Raw
file_history=Histórico
@@ -434,6 +442,13 @@ file_permalink=Link permanente
file_too_large=Este arquivo é muito grande para ser exibido
video_not_supported_in_browser=Seu navegador não suporta a tag de vídeo do HTML5.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Novo arquivo
editor.upload_file=Enviar arquivo
editor.edit_file=Editar arquivo
@@ -641,9 +656,11 @@ settings.collaboration.write=Escrita
settings.collaboration.read=Leitura
settings.collaboration.undefined=Indefinido
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Esta mudança irá afetar os links para este rep
settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Habilitar sistema de wiki
settings.use_internal_wiki=Usar wiki nativa
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
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 ao clicar na aba.
settings.issues_desc=Habilitar issue tracker
settings.use_internal_issue_tracker=Usar o issue tracker nativo
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Usar issue tracker externo
settings.external_tracker_url=URL do Issue Tracker Externo
settings.external_tracker_url_desc=Visitantes serão redirecionados ao URL quando clicarem na aba.
@@ -731,6 +750,8 @@ 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 Webhook de teste foi adicionado para a fila de entrega. Pode demorar alguns segundos antes de ser exibido no histórico de entrega.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Solicitação
settings.webhook.response=Resposta
settings.webhook.headers=Cabeçalhos
@@ -755,10 +776,20 @@ settings.event_send_everything=Preciso de <strong>tudo</strong>.
settings.event_choose=Deixe-me escolher o que eu preciso.
settings.event_create=Criar
settings.event_create_desc=Branch ou Tag criado
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request aberto, fechado, reaberto, atribuído, desatribuído, teve etiqueta atualizada ou limpada ou foi sincronizado.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push para o repositório
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Ativo
settings.active_helper=Enviaremos detalhes do evento quando este hook for acionado.
settings.add_hook_success=Novos hooks de web foram adicionados.
@@ -803,7 +834,6 @@ release.releases=Versões
release.new_release=Nova versão
release.draft=Rascunho
release.prerelease=Versão prévia
release.stable=Estável
release.edit=editar
release.ahead=<strong>%d</strong> commits para %s depois desta versão
release.source_code=Código fonte
@@ -1019,6 +1049,7 @@ repos.private=Privado
repos.watches=Observadores
repos.stars=Favoritos
repos.issues=Issues
repos.size=Size
auths.auth_manage_panel=Painel de gerenciamento da autenticação
auths.new=Adicionar nova fonte
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Timeout para operação de pull
config.git_gc_timeout=Timeout para execução do GC
config.log_config=Configuração de log
config.log_mode=Modo do log
config.log_mode=Mode
config.log_options=Options
monitor.cron=Tarefas cron
monitor.name=Nome
@@ -1205,19 +1237,23 @@ notices.delete_success=Avisos do sistema foram excluídos com sucesso.
[action]
create_repo=repositório criado <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=renomeou o o repositório <code>%[1]s</code> para <a href="%[2]s">%[3]s</a>
commit_repo=pushed para <a href="%[1]s/src/%[2]s">%[3]s</a> em <a href="%[1]s">%[4]s</a>
compare_commits=Ver comparação entre esses %d commits
transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a>
create_issue=`questão aberta <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`questão fechada <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`questão reaberta <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`criou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`fechou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reabriu o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`mesclou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=Foi feito push na tag <a href="%s/src/%s">%[2]s</a> para <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparação entre esses %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=atrás

View File

@@ -48,7 +48,7 @@ cancel=Отмена
install=Установка
title=Установочные шаги для первого запуска
docker_helper=Если вы запускаете Gogs внутри Docker, пожалуйста прочтите <a target="_blank" href="%s">эти советы</a> внимательно перед тем как что-либо изменить на этой странице!
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3, MSSQL or TiDB.
requite_db_desc=Gogs требует наличия MySQL, PostgreSQL, SQLite3, MSSQL или TiDB.
db_title=Настройки базы данных
db_type=Тип базы данных
host=Хост
@@ -58,8 +58,8 @@ db_name=Имя базы данных
db_helper=Для MySQL используйте тип таблиц InnoDB с кодировкой utf8_general_ci.
ssl_mode=Режим SSL
path=Путь
sqlite_helper=The file path of SQLite3 database. <br>Please use absolute path when you start as service.
err_empty_db_path=SQLite3 database path cannot be empty.
sqlite_helper=Путь к файлу базы данный SQLite3. <br>Пожалуйста, используйте абсолютный путь если Gogs запускается как сервис.
err_empty_db_path=Путь к файлу базы данных SQLite3 не может быть пустым.
no_admin_and_disable_registration=Вы не можете отключить регистрацию до создания учетной записи администратора.
err_empty_admin_password=Пароль администратора не может быть пустым.
@@ -74,14 +74,16 @@ domain=Домен
domain_helper=Влияет на URL-адреса для клонирования по SSH.
ssh_port=SSH порт
ssh_port_helper=Номер порта, который использует SSH сервер. Оставьте пустым, чтобы отключить SSH.
use_builtin_ssh_server=Use Builtin SSH Server
use_builtin_ssh_server_popup=Start builtin SSH server for Git operations to distinguish from system SSH daemon.
use_builtin_ssh_server=Использовать встроенный SSH сервер
use_builtin_ssh_server_popup=Запустить встроенный SSH сервер для различения операций Git и системного демона SSH.
http_port=Порт HTTP
http_port_helper=Номер порта, который приложение будет слушать.
app_url=URL приложения
app_url_helper=Этот параметр влияет на URL для клонирования по HTTP/HTTPS и на адреса в электронной почте.
log_root_path=Путь к журналу
log_root_path_helper=Каталог для записи файлов журнала.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Расширенные настройки
email_title=Настройки службы электронной почты
@@ -117,7 +119,7 @@ sqlite3_not_available=Ваша версия не поддерживает SQLite
invalid_db_setting=Настройки базы данных не правильные: %v
invalid_repo_path=Недопустимый путь к корню репозитория: %v
run_user_not_match=Текущий пользователь не является пользователем для запуска: %s -> %s
invalid_smtp_from=SMTP From field is not valid: %v
invalid_smtp_from=Поле SMTP From неправильное: %v
save_config_failed=Не удалось сохранить конфигурацию: %v
invalid_admin_setting=Указан недопустимый параметр учетной записи администратора: %v
install_success=Добро пожаловать! Мы рады, что вы выбрали Gogs. Веселитесь и берегите себя.
@@ -201,6 +203,7 @@ Content=Содержимое
require_error=` не может быть пустым.`
alpha_dash_error=«должен быть допустимым символьным, числовым или dash(-_) значением.»
alpha_dash_dot_error=«должен быть допустимым символьным, числовым или dash(-_) символами, включая точку.»
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` должен быть размер %s.`
min_size_error=«должен содержать по крайней мере %s символов.»
max_size_error=` должен содержать максимум %s символов.`
@@ -252,11 +255,10 @@ profile=Профиль
password=Пароль
avatar=Аватар
ssh_keys=SSH ключи
social=Учетные записи в соцсетях
applications=Приложения
repos=Repositories
orgs=Организации
applications=Приложения
delete=Удалить аккаунт
uid=UID
public_profile=Открытый профиль
profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт.
@@ -343,6 +345,11 @@ orgs.none=Вы не состоите ни в одной организации.
orgs.leave_title=Покинуть организацию
orgs.leave_desc=Вы потеряете доступ ко всем репозиториям и командам, как только покинете организацию. Вы хотите продолжить?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Удалить свой аккаунт
delete_prompt=Этим действием вы удалите свою учетную запись навсегда и <strong>НЕ СМОЖЕТЕ</strong> ее вернуть!
confirm_delete_account=Подтвердите удаление
@@ -391,7 +398,7 @@ migrate_type_helper=Этот репозиторий будет <span class="text
migrate_repo=Перенос репозитория
migrate.clone_address=Скопировать адрес
migrate.clone_address_desc=Это может быть HTTP/HTTPS/GIT URL-адрес.
migrate.clone_address_desc_import_local=You're also allowed to migrate a repository by local server path.
migrate.clone_address_desc_import_local=Вы также можете мигрировать репозиторий по локальному пути на сервере.
migrate.permission_denied=У вас нет прав на импорт локальных репозиториев.
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
migrate.failed=Миграция не удалась: %v
@@ -413,7 +420,7 @@ quick_guide=Краткое руководство
clone_this_repo=Клонировать репозиторий
create_new_repo_command=Создать новый репозиторий из командной строки
push_exist_repo=Отправить существующий репозиторий из командной строки
repo_is_empty=Этот репозиторий пуст, пожалуйста, возвращайтесь позже!
bare_message=This repository does not have any content yet.
files=Файлы
branch=Ветка
@@ -426,6 +433,7 @@ pulls=Запросы на слияние
labels=Метки
milestones=Этапы
commits=Коммиты
git_branches=Ветки
releases=Релизы
file_raw=Исходник
file_history=История
@@ -434,6 +442,13 @@ file_permalink=Постоянная ссылка
file_too_large=Этот файл слишком большой, поэтому он не может быть отображен
video_not_supported_in_browser=Ваш браузер не поддерживает HTML5 видео тэг.
branches.overview=Обзор
branches.active_branches=Активные ветки
branches.stale_branches=Устаревшие ветки
branches.all=Все ветки
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Новый файл
editor.upload_file=Загрузить файл
editor.edit_file=Редактировать файл
@@ -473,7 +488,7 @@ editor.add_subdir=Добавьте подкаталог...
editor.unable_to_upload_files=Не удалось загрузить файлы в «%s» из-за ошибки: %v
editor.upload_files_to_dir=Загрузить файлы '%s'
commits.commit_history=Commit History
commits.commit_history=История коммитов
commits.commits=Коммиты
commits.search=Поиск коммитов
commits.find=Найти
@@ -531,7 +546,7 @@ issues.next=Следующая страница
issues.open_title=Открыто
issues.closed_title=Закрыто
issues.num_comments=комментариев: %d
issues.commented_at=«прокомментировал <a href="#%s"> %s</a>»
issues.commented_at=`прокомментировал <a href="#%s"> %s</a>`
issues.delete_comment_confirm=Вы уверены, что хотите удалить этот комментарий?
issues.no_content=Пока нет содержимого.
issues.close_issue=Закрыть
@@ -640,27 +655,29 @@ settings.collaboration.admin=Администратор
settings.collaboration.write=Запись
settings.collaboration.read=Просмотр
settings.collaboration.undefined=Не определено
settings.branches=Branches
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
settings.choose_a_branch=Choose a branch...
settings.branch_protection=Branch Protection
settings.branch_protection_desc=Please choose protect options for branch <b>%s</b>.
settings.protect_this_branch=Protect this branch
settings.protect_this_branch_desc=Disable force pushes and prevent from deletion.
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.update_protect_branch_success=Protect options for this branch has been updated successfully!
settings.branches=Ветки
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Ветка по умолчанию
settings.default_branch_desc=Ветка по-умолчанию считается основной для коммитов, запросов на слияние и онлайн-редактирования.
settings.update=Обновить
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Ветка по умолчанию для этого репозитория была успешно изменена!
settings.protected_branches=Защищенные ветки
settings.protected_branches_desc=Защитить ветки от принудительного push, случайного удаления и разрешить изменения только коммитерам из белого списка.
settings.choose_a_branch=Выберите ветку...
settings.branch_protection=Защита веток
settings.branch_protection_desc=Пожалуйста, выберите параметры защиты для ветки <b>%s</b>.
settings.protect_this_branch=Защитить эту ветку
settings.protect_this_branch_desc=Выключить принудительный push и защитить от удаления.
settings.protect_require_pull_request=Требовать запрос на слияние вместо прямого push
settings.protect_require_pull_request_desc=Включите этот параметр для запрета прямого push в это ветку. Коммит должен быть запушен в незащищенную ветку и слит в эту ветку через запрос на слияние.
settings.protect_whitelist_committers=Белый список тех, кто может делать push в эту ветку
settings.protect_whitelist_committers_desc=Добавьте людей или команды в белый список для прямого доступа к этой ветке. Пользователи из белого списка будут обходить проверку pull request.
settings.protect_whitelist_users=Пользователи которые могут делать push в эту ветку
settings.protect_whitelist_search_users=Поиск пользователей
settings.protect_whitelist_teams=Команды, члены которых могут делать push в эту ветку
settings.protect_whitelist_search_teams=Поиск команд
settings.update_protect_branch_success=Параметры защиты этой ветки были успешно обновлены!
settings.hooks=Автоматическое обновление
settings.githooks=Git хуки
settings.basic_settings=Основные параметры
@@ -673,14 +690,16 @@ settings.change_reponame_prompt=Это изменение повлияет на
settings.advanced_settings=Расширенные настройки
settings.wiki_desc=Включить систему Wiki
settings.use_internal_wiki=Использовать встроенную wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Использовать внешнюю Wiki
settings.external_wiki_url=URL-адрес внешней Вики
settings.external_wiki_url_desc=Посетители будут перенаправлены на URL-адрес, когда они кликнут по вкладке.
settings.issues_desc=Включить систему отслеживания ошибок
settings.use_internal_issue_tracker=Использовать встроенную легковесную систему отслеживания ошибок
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.external_tracker_url=URL внешней системы отслеживания ошибок
settings.external_tracker_url_desc=Посетители будут перенаправлены на URL когда они нажмут на вкладку.
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
settings.tracker_issue_style=Стиль Именования Внешней Системы Учета Задач:
settings.tracker_issue_style.numeric=Цифровой
@@ -688,7 +707,7 @@ settings.tracker_issue_style.alphanumeric=Буквенноцифровой
settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера задачи.
settings.pulls_desc=Включить публичные запросы на слияние
settings.danger_zone=Опасная зона
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.cannot_fork_to_same_owner=Вы не можете ответвить репозиторий его же владельцу.
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
settings.convert=Преобразовать в обычный репозиторий
settings.convert_desc=Это зеркало можно преобразовать в обычный репозиторий. Это не может быть отменено.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Веб-хук успешно удален!
settings.webhook.test_delivery=Проверить доставку
settings.webhook.test_delivery_desc=Отправить push для тестирования настройки веб-хуков
settings.webhook.test_delivery_success=Тест веб-хука была добавлен в очередь доставки. Это может занять несколько секунд, прежде чем он отобразится в истории доставки.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Запрос
settings.webhook.response=Ответ
settings.webhook.headers=Заголовки
@@ -745,7 +766,7 @@ settings.add_webhook_desc=Мы отправим запрос <code>POST</code>
settings.payload_url=URL обработчика
settings.content_type=Тип содержимого
settings.secret=Secret
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.secret_desc=Секрет будет отправлен как SHA256 HMAC контента в шестнадцатеричном виде в заголовке <code>X-Gogs-Signature</code>.
settings.slack_username=Имя пользователя
settings.slack_icon_url=URL иконки
settings.slack_color=Цвет
@@ -755,10 +776,20 @@ settings.event_send_everything=Мне нужно <strong>все</strong>.
settings.event_choose=Позвольте мне выбрать то, что нужно.
settings.event_create=Создать
settings.event_create_desc=Ветка или тэг созданы
settings.event_pull_request=Запросы на слияние
settings.event_pull_request_desc=Запрос слияния открыт, закрыт, переоткрыт, изменён, назначен, снят, метка обновлена, метка убрана, или синхронизирован.
settings.event_delete=Удалить
settings.event_delete_desc=Ветка или метка удалена
settings.event_fork=Ответвить
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Push в репозиторий
settings.event_issues=Вопросы
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Запросы на слияние
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Релиз
settings.event_release_desc=Релиз опубликован в репозитории.
settings.active=Активен
settings.active_helper=Подробности о событии, вызвавшем срабатывание хука, также будут предоставлены.
settings.add_hook_success=Был добавлен новый webhook.
@@ -768,12 +799,12 @@ settings.delete_webhook=Удалить автоматическое обновл
settings.recent_deliveries=Недавние рассылки
settings.hook_type=Тип перехватчика
settings.add_slack_hook_desc=Добавить интеграцию с <a href="%s">Slack</a> в ваш репозиторий.
settings.add_discord_hook_desc=Add <a href="%s">Discord</a> integration to your repository.
settings.add_discord_hook_desc=Добавить интеграцию с <a href="%s">Discord</a> в ваш репозиторий.
settings.slack_token=Token
settings.slack_domain=Домен
settings.slack_channel=Канал
settings.deploy_keys=Ключи развертывания
settings.deploy_keys_helper=<b>Common Gotcha!</b> If you're looking for adding personal public keys, please add them in your <a href="%s%s">account settings</a>.
settings.deploy_keys_helper=<b>Common Gotcha!</b> Если вы ищите куда добавить персональные публичные ключи, добавьте их в <a href="%s%s">настройках вашего аккаунта</a>.
settings.add_deploy_key=Добавить ключ развертывания
settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта.
settings.no_deploy_keys=Вы не добавляли ключи развертывания.
@@ -803,7 +834,6 @@ release.releases=Релизы
release.new_release=Новый релиз
release.draft=Черновик
release.prerelease=Пре-релиз
release.stable=Стабильный
release.edit=Редактировать
release.ahead=<strong>%d</strong> коммитов %s начиная с этого релиза
release.source_code=Исходный код
@@ -852,7 +882,7 @@ team_permission_desc=Какой уровень разрешений должен
form.name_reserved=Наименование организации '%s' зарезервированно.
form.name_pattern_not_allowed=Шаблон организации '%s' не допускается.
form.team_name_reserved=Team name '%s' is reserved.
form.team_name_reserved=Имя команды '%s' зарезервировано.
settings=Настройки
settings.options=Опции
@@ -943,8 +973,8 @@ dashboard.git_gc_repos=Выполнить сборку мусора на реп
dashboard.git_gc_repos_success=Сборка мусора на всех репозиториях успешно выполнена.
dashboard.resync_all_sshkeys=Переписать файл «.ssh/authorized_keys» (осторожно: не Gogs ключи будут утеряны)
dashboard.resync_all_sshkeys_success=Были успешно переписаны все открытые ключи.
dashboard.resync_all_hooks=Resync pre-receive, update and post-receive hooks of all repositories
dashboard.resync_all_hooks_success=All repositories' pre-receive, update and post-receive hooks have been resynced successfully.
dashboard.resync_all_hooks=Повторная синхронизация хуков pre-receive, update и post-receive во всех репозиториях
dashboard.resync_all_hooks_success=Все хуки pre-receive, update и post-receive во всех репозиториях были успешно повторно синхронизированы.
dashboard.reinit_missing_repos=Реинициализировать все репозитории с утерянными Git файлами
dashboard.reinit_missing_repos_success=Все репозитории с утерянными Git файлами успешно реинициализированы.
@@ -1019,6 +1049,7 @@ repos.private=Приватный
repos.watches=Следят
repos.stars=В избранном
repos.issues=Задачи
repos.size=Размер
auths.auth_manage_panel=Панель управления аутнентификациями
auths.new=Добавить новый источник
@@ -1077,7 +1108,7 @@ config.offline_mode=Автономный режим
config.disable_router_log=Отключение журнала маршрутизатора
config.run_user=Запуск пользователем
config.run_mode=Режим выполнения
config.git_version=Git Version
config.git_version=Версия Git
config.static_file_root_path=Статичный путь до файла
config.log_file_root_path=Путь до папки с логами
config.reverse_auth_user=Заголовок с именем пользователя для авторизации на reverse proxy
@@ -1094,15 +1125,15 @@ config.ssh_keygen_path=Путь к генератору ключей ('ssh-keyge
config.ssh_minimum_key_size_check=Минимальный размер ключа проверки
config.ssh_minimum_key_sizes=Минимальные размеры ключа
config.repo_config=Repository Configuration
config.repo_config=Настройка репозитория
config.repo_root_path=Путь до корня репозитория
config.script_type=Тип сценария
config.repo_force_private=Force Private
config.max_creation_limit=Max Creation Limit
config.preferred_licenses=Preferred Licenses
config.disable_http_git=Disable HTTP Git
config.enable_local_path_migration=Enable Local Path Migration
config.commits_fetch_concurrency=Commits Fetch Concurrency
config.repo_force_private=Сделать личным принудительно
config.max_creation_limit=Лимит созданий
config.preferred_licenses=Предпочитаемые лицензии
config.disable_http_git=Выключить HTTP Git
config.enable_local_path_migration=Включить миграцию с локального пути
config.commits_fetch_concurrency=Параллельность получения коммитов
config.db_config=Конфигурация базы данных
config.db_type=Тип
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Время Ожидания Операции Извле
config.git_gc_timeout=Время Ожидания Операции Сборки Мусора
config.log_config=Конфигурация журнала
config.log_mode=Режим журналирования
config.log_mode=Режим
config.log_options=Опции
monitor.cron=Задачи cron
monitor.name=Имя
@@ -1205,19 +1237,23 @@ notices.delete_success=Системное уведомление успешно
[action]
create_repo=создал(а) репозиторий <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=переименовал(а) репозиторий из <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=запушил(а) <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
compare_commits=Просмотр сравнение для этих %d коммитов
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
create_issue=`открыл(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`закрыл(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`возобновил(а) задачу <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`прокомментировал(а) вопрос <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`создал запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`закрыл запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`открыл снова запрос на слияние <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`прокомментировал(а) вопрос <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`слил пул реквест <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=запушил(а) метку <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
compare_commits=Просмотр сравнение для этих %d коммитов
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=назад

View File

@@ -82,6 +82,8 @@ app_url=URL адреса апликације
app_url_helper=Ова поставка утиче на URL за клонирање преко HTTP/HTTPS протокола и на адресама е-поште.
log_root_path=Пут до журнала
log_root_path_helper=Директоријум где ће бити снимане датотеке журнала.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Напредна подешавања
email_title=Подешавања сервиса е-поште
@@ -201,6 +203,7 @@ Content=Садржај
require_error=` не може бити празно.`
alpha_dash_error=` мора се састојати словима, бројевима или dash(-_) карактера.`
alpha_dash_dot_error=` мора се састојати словима, бројевима, dash(-_) карактера, или тачком.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` мора бити величине %s.`
min_size_error=` мора да садржи најмање %s карактера.`
max_size_error=` мора да садржи највише %s карактера.`
@@ -252,11 +255,10 @@ profile=Профил
password=Лозинка
avatar=Аватар
ssh_keys=SSH Кључеви
social=Налози на друштвеним мрежама
applications=Апликације
repos=Repositories
orgs=Организације
applications=Апликације
delete=Уклоните налог
uid=Uid
public_profile=Јавни профил
profile_desc=Ваша адреса е-поште је јавна и коришће се за све обавести везане са налогом, као и друге операције почињене кроз Gogs.
@@ -340,9 +342,14 @@ access_token_deletion_desc=Уклоњење овог токена ће онем
delete_token_success=Лични токен је успешно избришен! Не заборавите да ажурирате апликацију.
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Уклоните ваш налог
delete_prompt=Операција ће трајно избрисати ваш налог, што се <strong>НЕ може</strong> поввратити!
confirm_delete_account=Потврдите брисање
@@ -413,7 +420,7 @@ quick_guide=Кратак водич
clone_this_repo=Клонирај спремиште
create_new_repo_command=Направите ново спремиште са командне линије
push_exist_repo=Push постојећe спремиште са командне линије
repo_is_empty=Овo спремиште je празнo, молимо вас, вратите се касније!
bare_message=This repository does not have any content yet.
files=Files
branch=Грана
@@ -426,6 +433,7 @@ pulls=Захтеви за спајање
labels=Лабеле
milestones=Фазе
commits=Комити
git_branches=Branches
releases=Издања
file_raw=Датотека
file_history=Историја
@@ -434,6 +442,13 @@ file_permalink=Пермалинк
file_too_large=Ова датотека је превише веика да би се приказала
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Нова датотека
editor.upload_file=Отпреми датотеку
editor.edit_file=Ажурирај датотеку
@@ -641,9 +656,11 @@ settings.collaboration.write=За писање
settings.collaboration.read=Читање
settings.collaboration.undefined=Није дефинисано
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Ова промена ће утицати на
settings.advanced_settings=Напредна подешавања
settings.wiki_desc=Омогући систем вики
settings.use_internal_wiki=Користи уграђен вики
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Користи спољни Вики
settings.external_wiki_url=URL адреса спољног Вики
settings.external_wiki_url_desc=Посетиоци ће бити преусмерени URL адреси након што кликну на картицу.
settings.issues_desc=Омогући систем праћења грешака
settings.use_internal_issue_tracker=Користи уграђен систем праћења грешака
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Користи спољни систем праћења грешака
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webhook успешно избрисан!
settings.webhook.test_delivery=Провери испоруку
settings.webhook.test_delivery_desc=Пошаљи push за тестирање подешавања webhook
settings.webhook.test_delivery_success=Тест webhook је додат у месту испоруке. Процес може да потраје неколико секунди пре него што ће показати у историји испоруке.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Захтев
settings.webhook.response=Одговор
settings.webhook.headers=Наслови
@@ -755,10 +776,20 @@ settings.event_send_everything=У <strong>свим</strong> догађајима
settings.event_choose=Изабраћу шта ми је потребно.
settings.event_create=Креирај
settings.event_create_desc=Створена грана или ознака
settings.event_pull_request=Захтев за спајање
settings.event_pull_request_desc=Захтев за спајање отворенo, затворено, додељено, недодељенo, лабела ажурирана, лабела избрисана, или синхронизовано.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Git push у спремиште
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Захтев за спајање
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Активно
settings.active_helper=Детаљи о догађају што је проузроковало hook ће исто бити испоручено.
settings.add_hook_success=Додат је нови webhook.
@@ -803,7 +834,6 @@ release.releases=Издања
release.new_release=Ново издање
release.draft=Нацрт
release.prerelease=Пред-верзија
release.stable=Стабилно
release.edit=уреди
release.ahead=<strong>%d</strong> комита на %s почев од овог издања
release.source_code=Изворни код
@@ -1019,6 +1049,7 @@ repos.private=Приватно
repos.watches=Watches
repos.stars=Фаворити
repos.issues=Задаци
repos.size=Size
auths.auth_manage_panel=Контролна панела аутентикације
auths.new=Додај нови извор
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Време до отказивања pull операци
config.git_gc_timeout=Време до отказивања cакупљање смећа
config.log_config=Kонфигурација журнала
config.log_mode=Режим журналовања
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron задаци
monitor.name=Име
@@ -1205,19 +1237,23 @@ notices.delete_success=Системска обавештавања су успе
[action]
create_repo=креира спремиште <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=преимензје спремиште од <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=извршује push на <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
compare_commits=Поређење ових %d комита
transfer_repo=преноси спремиште <code>%s</code> на <a href="%s">%s</a>
create_issue=`отвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`затвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`поново отвара задатак <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`коментарише на задатаку <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`шаље захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`затвара захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`поново отвара захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментарише на задатаку <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`прихваћује захтев за спајање <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=преноси спремиште <code>%s</code> на <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=извршује push са ознаком <a href="%s/src/%s">%[2]s</a> на <a href="%[1]s">%[3]s</a>
compare_commits=Поређење ових %d комита
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=пре

View File

@@ -82,6 +82,8 @@ app_url=Applikationsadressen
app_url_helper=Detta påverkar HTTP/HTTPS kloningsadressen och på platser i e-post.
log_root_path=Loggsökväg
log_root_path_helper=Katalog till vilken loggfiler skrivs.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=Övriga inställningar
email_title=E-post tjänstens inställningar
@@ -201,6 +203,7 @@ Content=Innehåll
require_error=får inte vara tomt
alpha_dash_error=` får bara innehålla bokstäver, nummer och bindestreck (-_).`
alpha_dash_dot_error=` får bara innehålla bokstäver, nummer, bindestreck (-_) och punkt`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` måste vara av storleken %s`
min_size_error=` måste innehålla minst %s tecken.`
max_size_error=` får inte innehålla mer än %s tecken.`
@@ -252,11 +255,10 @@ profile=Profil
password=Lösenord
avatar=Avatar
ssh_keys=SSH-nycklar
social=Sociala konton
applications=Applikationer
repos=Repositories
orgs=Organisationer
applications=Applikationer
delete=Radera konto
uid=Uid
public_profile=Offentlig profil
profile_desc=Din epostaddress är offentlig och kommer att användas för alla kontorelaterade notifieringar och alla webbaserade åtgärder gjorda på sidan.
@@ -343,6 +345,11 @@ orgs.none=Du är inte en medlem i någon organisation.
orgs.leave_title=Lämna en organisation
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Radera ditt konto
delete_prompt=Åtgärden kommer at ta bort ditt konto permanent, och kan <strong>INTE</strong> ångras!
confirm_delete_account=Bekräfta Borttagelsen
@@ -413,7 +420,7 @@ quick_guide=Snabbguide
clone_this_repo=Klona detta repo
create_new_repo_command=Skapa ett nytt repo på kommandoraden
push_exist_repo=Knuffa ett existerande repo från kommandoraden
repo_is_empty=Detta repo är tomt, vänligen kom tillbaka senare!
bare_message=This repository does not have any content yet.
files=Filer
branch=Gren
@@ -426,6 +433,7 @@ pulls=Pull-förfrågningar
labels=Etiketter
milestones=Milstenar
commits=Incheckningar
git_branches=Branches
releases=Släpp
file_raw=
file_history=Historik
@@ -434,6 +442,13 @@ file_permalink=Permalänk
file_too_large=Denna fil är för stor för att visas
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=Ny fil
editor.upload_file=Ladda upp fil
editor.edit_file=Redigera fil
@@ -641,9 +656,11 @@ settings.collaboration.write=Skriva
settings.collaboration.read=Läsa
settings.collaboration.undefined=Odefinierad
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Denna ändring kommer att påverka hur länkar r
settings.advanced_settings=Advancerade Inställningar
settings.wiki_desc=Aktivera wikisystem
settings.use_internal_wiki=Använd inbyggd wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Använd extern wiki
settings.external_wiki_url=Extern Wiki-URL
settings.external_wiki_url_desc=Besökare kommer att bli omdirigerade till denna URL när dom klickar på fliken.
settings.issues_desc=Aktivera ärendehantering
settings.use_internal_issue_tracker=Använd enkel inbyggd ärendehantering
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Använd extern ärendehanterare
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webbhook har tagits bort!
settings.webhook.test_delivery=Testa Leverans
settings.webhook.test_delivery_desc=Skicka en falsk pushhändelse för att testa dina webbhook-inställningar
settings.webhook.test_delivery_success=Testwebbhook har lagts till leveranskön. Det kan ta några sekunder innan den visas i leveranshistoriken.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=Begäran
settings.webhook.response=Svar
settings.webhook.headers=Huvuden
@@ -755,10 +776,20 @@ settings.event_send_everything=Jag behöver <strong>allt</strong>.
settings.event_choose=Låt mig välja.
settings.event_create=Skapa
settings.event_create_desc=Branch eller tagg skapad
settings.event_pull_request=Hämtningsbegäran
settings.event_pull_request_desc=Hämtningsbegäran öppnad, stängd, återöppnad, redigerad, tilldelad, otilldelad, etikett uppdaterad, etikett rensad eller synkroniserad.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Pusha
settings.event_push_desc=Uppladdning till ett förråd
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Hämtningsbegäran
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktiv
settings.active_helper=Detaljer kring händelsen som triggade kroken kommer också levereras.
settings.add_hook_success=Ny webbkrok har lagts till.
@@ -803,7 +834,6 @@ release.releases=Släpp
release.new_release=Nytt Släpp
release.draft=Utkast
release.prerelease=Försläpp
release.stable=Stabil
release.edit=redigera
release.ahead=<strong>%d</strong> ändringar mot %s sedan detta släpp
release.source_code=Källkod
@@ -1019,6 +1049,7 @@ repos.private=Privat
repos.watches=Vakter
repos.stars=Stjärnor
repos.issues=Ärenden
repos.size=Size
auths.auth_manage_panel=Panel för hantering av autentisering
auths.new=Lägg till ny källa
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Logg-konfiguration
config.log_mode=Loggningsläge
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron-jobb
monitor.name=Namn
@@ -1205,19 +1237,23 @@ notices.delete_success=System notices have been deleted successfully.
[action]
create_repo=skapade utvecklingskatalog <a href="%s"> %s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
commit_repo=pushed to <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
compare_commits=View comparison for these %d commits
transfer_repo=transfered repository <code>%s</code> to <a href="%s">%s</a>
create_issue=`opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transfered repository <code>%s</code> to <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_commits=View comparison for these %d commits
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=sedan

View File

@@ -82,6 +82,8 @@ app_url=Uygulama Bağlantısı
app_url_helper=Bu, HTTP/HTTPS klon bağlantılarını ve e-postadaki bazı kısımları etkiler.
log_root_path=Günlük Dosyaları Yolu
log_root_path_helper=Günlük dosyalarının yazılacağı dizin.
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=İsteğe Bağlı Ayarlar
email_title=E-Posta Servisi Ayarları
@@ -201,6 +203,7 @@ Content=Content
require_error=` boş olamaz.`
alpha_dash_error=` sadece karakter, rakam veya çizgi(-_) içermelidir.`
alpha_dash_dot_error=` sadece karakter, rakam, çizgi(-_) veya nokta içermelidir.`
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=` uzunluk en fazla %s olmalıdır.`
min_size_error=` en az %s karakter içermelidir.`
max_size_error=` en fazla %s karakter içermelidir.`
@@ -252,11 +255,10 @@ profile=Profil
password=Parola
avatar=Avatar
ssh_keys=SSH Anahtarları
social=Sosyal Medya Hesapları
applications=Uygulamalar
repos=Repositories
orgs=Organizasyonlar
applications=Uygulamalar
delete=Hesabı Sil
uid=Tekil ID
public_profile=Herkese Açık Profil
profile_desc=E-posta adresiniz herkese açıktır ve hesabınızla ilgili bilgilendirmelerde ve web tabanlı operasyonlarda kullanılacaktır.
@@ -340,9 +342,14 @@ access_token_deletion_desc=Bu kişisel erişim anahtarını silerseniz uygulaman
delete_token_success=Kişisel erişim anahtarı başarıyla kaldırıldı! Uygulamanızı güncellemeyi de unutmayın!
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=Hesabınızı Silin
delete_prompt=Bu işlem hesabınızı kalıcı olarak silecektir ve <strong>GERİ ALINAMAZ</strong>!
confirm_delete_account=Silmeyi Onayla
@@ -413,7 +420,7 @@ quick_guide=Hızlı Başlangıç Kılavuzu
clone_this_repo=Bu depoyu klonla
create_new_repo_command=Komut satırında yeni bir depo oluştur
push_exist_repo=Var olan bir depoyu komut satırında gönder
repo_is_empty=Bu depo boş. Lütfen daha sonra tekrar gelin!
bare_message=This repository does not have any content yet.
files=Files
branch=Dal
@@ -426,6 +433,7 @@ pulls=Değişiklik İstekleri
labels=Etiketler
milestones=Kilometre Taşları
commits=İşlemeler
git_branches=Branches
releases=Sürümler
file_raw=Ham
file_history=Geçmiş
@@ -434,6 +442,13 @@ file_permalink=Kalıcı Bağlantı
file_too_large=Bu dosya sergilenmek için çok büyük
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=Dosya düzenle
@@ -641,9 +656,11 @@ settings.collaboration.write=Yaz
settings.collaboration.read=Oku
settings.collaboration.undefined=Belirsiz
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Bu değişiklik, bağlantıların depoyla olan i
settings.advanced_settings=Gelişmiş Ayarlar
settings.wiki_desc=Viki sıstemini etkinleştir
settings.use_internal_wiki=Use builtin wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=Harici Wiki kullan
settings.external_wiki_url=Harici Wiki bağlantısı
settings.external_wiki_url_desc=Ziyaretçiler, sekmeye tıkladıklarında bağlantıya yönlendirilecektir.
settings.issues_desc=Enable issue tracker
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=Harici sorun takipçisi kullan
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Web isteği başarıyla silindi!
settings.webhook.test_delivery=Test Dağıtımı
settings.webhook.test_delivery_desc=Web isteği ayarlarınızı test etmek için sahte bir anlık olay gönderin
settings.webhook.test_delivery_success=Test web isteği, dağıtım kuyruğuna eklendi. Bunun dağıtım geçmişinde görünmesi birkaç saniye sürebilir.
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=İstekler
settings.webhook.response=Cevaplar
settings.webhook.headers=Başlıklar
@@ -755,10 +776,20 @@ settings.event_send_everything=<strong>Her şeye</strong> ihtiyacım var.
settings.event_choose=Neye ihtiyacım olduğunu seçtir.
settings.event_create=Oluştur
settings.event_create_desc=Dal veya biçim imi oluşturuldu
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=Push
settings.event_push_desc=Bir depoya git push
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=Aktif
settings.active_helper=Bu isteği tetikleyen olaya ilişkin detaylar da gönderilecektir.
settings.add_hook_success=Yeni web isteği eklendi.
@@ -803,7 +834,6 @@ release.releases=Sürümler
release.new_release=Yeni Sürüm
release.draft=Taslak
release.prerelease=Ön Sürüm
release.stable=Kararlı
release.edit=düzenle
release.ahead=%s son sürümden beri <strong>%d</strong> işleme
release.source_code=Kaynak Kodu
@@ -1019,6 +1049,7 @@ repos.private=Özel
repos.watches=İzlemeler
repos.stars=Yıldızlar
repos.issues=Sorunlar
repos.size=Size
auths.auth_manage_panel=Yetkilendirme Yönetim Paneli
auths.new=Yeni Kaynak Ekle
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=Log Yapılandırması
config.log_mode=Log Modu
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron Görevleri
monitor.name=İsim
@@ -1205,19 +1237,23 @@ notices.delete_success=Sistem bildirimleri başarıyla silindi.
[action]
create_repo=depo <a href="%s">%s</a> oluşturuldu
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=<code>%[1]s</code> olan depo adını <a href="%[2]s">%[3]s</a> buna çevirdi
commit_repo=<a href="%[1]s">%[4]s</a> zamanında <a href="%[1]s/src/%[2]s">%[3]s</a> buraya push yaptı
compare_commits=Bu %d işlemeler için karşılaştırmaları görüntüle
transfer_repo=depo <code>%s</code> <a href="%s">%s</a>'a aktarıldı
create_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu açtı`
close_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu kapattı`
reopen_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununu tekrar açtı`
comment_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununa yorum yazdı`
create_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini oluşturdu`
close_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini kapattı`
reopen_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişiklik isteğini tekrar açtı`
comment_issue=`<a href="%s/issues/%s">%s#%[2]s</a> sorununa yorum yazdı`
merge_pull_request=`<a href="%s/pulls/%s">%s#%[2]s</a> değişim isteğini birleştirdi`
transfer_repo=depo <code>%s</code> <a href="%s">%s</a>'a aktarıldı
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=etiket <a href="%s/src/%s">%[2]s</a> <a href="%[1]s">%[3]s</a>'a itelendi
compare_commits=Bu %d işlemeler için karşılaştırmaları görüntüle
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=önce

View File

@@ -40,7 +40,7 @@ your_settings=Ваші налаштування
activities=Дії
pull_requests=Запити на злиття
issues=Обговорення
issues=Проблеми
cancel=Скасувати
@@ -82,6 +82,8 @@ app_url=Адреса програми
app_url_helper=Це впливає на клонування через HTTP/HTTPS та десь у електроній пошті.
log_root_path=Шлях до лог файлу
log_root_path_helper=Каталог для файлів журналу.
enable_console_mode=Увімкнути консольний режим
enable_console_mode_popup=На додаток до файлового режиму писати логи також і до консолі.
optional_title=Додаткові налаштування
email_title=Параметри електронної пошти
@@ -201,6 +203,7 @@ Content=Вміст
require_error=' не може бути пустим.'
alpha_dash_error=` має складатись з буков, цифр, або рисок(-_).`
alpha_dash_dot_error=` має складатись з буков, цифр, рисок(-_), або крапок.`
alpha_dash_dot_slash_error=` мусить бути валідною буквою, або цифрою, або рискою(-_), або крапкою, або слешем.`
size_error=` має мати розмір %s.`
min_size_error=' має містити принаймні %s символів.'
max_size_error=' має містити принаймні %s символів.'
@@ -252,11 +255,10 @@ profile=Профіль
password=Пароль
avatar=Аватар
ssh_keys=Ключі SSH
social=Соціальні акаунти
applications=Додатки
repos=Репозиторії
orgs=Організації
applications=Додатки
delete=Видалити обліковий запис
uid=Унікальний ідентифікатор користувача
public_profile=Загальнодоступний профіль
profile_desc=Ваша адреса електронної пошти є публічною і буде використовуватися для будь-яких повідомлень щодо вашого облікового запису і будь-яких веб-операцій, що здійснюються через сайт.
@@ -343,6 +345,11 @@ orgs.none=Ви не є членом будь-якої організації.
orgs.leave_title=Залишити організацію
orgs.leave_desc=Ви втратите доступ до всіх репозиторіїв і команд після того, як ви покинете організацію. Ви хочете продовжити?
repos.leave=Покинути
repos.leave_title=Покинути репозиторій
repos.leave_desc=Ви можете втратити доступ до репозиторію після того як покинете його. Бажаєте продовжити?
repos.leave_success=Ви успішно покинули репозиторій '%s'!
delete_account=Видалити ваш обліковий запис
delete_prompt=Ця операція остаточно видалить обліковий запис, і її <strong>НЕМОЖЛИВО</strong> буде скасувати!
confirm_delete_account=Підтвердження видалення
@@ -413,7 +420,7 @@ quick_guide=Короткий посібник
clone_this_repo=Кнонувати цей репозиторій
create_new_repo_command=Створити новий репозиторій з командного рядка
push_exist_repo=Штовхнути існуючий репозиторій з командного рядка
repo_is_empty=Даний репозиторій пустий, будь ласка, повертайтесь пізніше!
bare_message=Цей репозиторій ще не має жодного вмісту.
files=Файли
branch=Гілка
@@ -426,6 +433,7 @@ pulls=Запити на злиття
labels=Мітка
milestones=Проміжні етапи
commits=Коміти
git_branches=Гілки
releases=Релізи
file_raw=Запис
file_history=Історія
@@ -434,6 +442,13 @@ file_permalink=Постійне посилання
file_too_large=Цей файл завеликий для показу
video_not_supported_in_browser=Ваш браузер не підтримує єлемент HTML5 video.
branches.overview=Огляд
branches.active_branches=Активні гілки
branches.stale_branches=Застарілі гілки
branches.all=Усі гілки
branches.updated_by=Оновлено %[1]s з %[2]s
branches.change_default_branch=Гілку за замовчуванням змінено
editor.new_file=Новий файл
editor.upload_file=Завантажити файл
editor.edit_file=Редагування файла
@@ -641,9 +656,11 @@ settings.collaboration.write=Запис
settings.collaboration.read=Читання
settings.collaboration.undefined=Не визначено
settings.branches=Гілки
settings.branches_bare=Ви не можете керувати гілками у bare-репозиторії. Спочатку додайте у нього якогось вмісту, будь ласка.
settings.default_branch=Гілка за замовчуванням
settings.default_branch_desc=Гілка за замовчанням вважається базовою для комітів, запросів злиття та онлайн редагувань.
settings.update=Оновлення
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Гілку за замовчуванням цього репозиторію було успішно оновлено!
settings.protected_branches=Захищені гілки
settings.protected_branches_desc=Захистіть гілки від force push, випадкового видалення та коміттерів з білого списку.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Вимкнути примусовий push т
settings.protect_require_pull_request=Вимагати запрос на злиття замість прямого push
settings.protect_require_pull_request_desc=Увімкніть цю опцію для заборони прямого push у цю гілку. Коміт має бути запушений у іншу, незахищену гілку та влитий у цю через запрос на злиття.
settings.protect_whitelist_committers=Білий список тих, хто може робити push у цю гілку
settings.protect_whitelist_committers_desc=Додати людей або команди у білий список для виконання push до цієї гілки.
settings.protect_whitelist_committers_desc=Додати людей або команди до білого списку тих, хто може робити push у цю гілку. Користувачі з білого списку оминатимуть контроль запитів на злиття.
settings.protect_whitelist_users=Користувачі що можуть виконувати push до цієї гілки
settings.protect_whitelist_search_users=Пошук користувачів
settings.protect_whitelist_teams=Команди, члени яких можуть виконувати push до цієї гілки
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=Ця зміна вплине на відноше
settings.advanced_settings=Додаткові налаштування
settings.wiki_desc=Увімкнути wiki-систему
settings.use_internal_wiki=Використовувати вбудовану wiki
settings.allow_public_wiki_desc=Дозволити публічний доступ до wiki поки репозиторій залишається приватним
settings.use_external_wiki=Використовувати зовнішню wiki
settings.external_wiki_url=URL зовнішньої wiki
settings.external_wiki_url_desc=Відвідувачі будуть переспрямовані до URL коли вони клацнуть на вкладці.
settings.issues_desc=Увімкнути систему відстеження проблем
settings.use_internal_issue_tracker=Використовувати вбудовану легку систему відстеження помилок
settings.allow_public_issues_desc=Дозволити публічний доступ до проблем поки репозиторій залишається приватним
settings.use_external_issue_tracker=Використовувати зовнішній трекер задач
settings.external_tracker_url=URL зовнішньої системи відстеження проблем
settings.external_tracker_url_desc=Відвідувача буде перенаправлено до URL коли він натисне на вкладку.
@@ -688,7 +707,7 @@ settings.tracker_issue_style.alphanumeric=Буквено-цифровий
settings.tracker_url_format_desc=Ви можете використовувати заповнювач <code>{user} {repo} {index}</code> для ім'я користувача, назви репозиторію на номеру проблеми.
settings.pulls_desc=Увімкнути публічні запроси на злиття
settings.danger_zone=Небезпечна зона
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.cannot_fork_to_same_owner=Ви не можете клонувати репозиторій його ж власнику.
settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою.
settings.convert=Перетворити на звичайний репозиторій
settings.convert_desc=Ви можете сконвертувати це дзеркало у звичайний репозиторій. Це не може бути повернуто.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Webhook успішно видалено!
settings.webhook.test_delivery=Перевірити поставку
settings.webhook.test_delivery_desc=Відправити тестовий push для перевірки налаштувань web-хуків
settings.webhook.test_delivery_success=Тестовий web-хук може бути доданий у чергу поставки. Поки він з'явиться у історії поставки, може пройти кілька секунд.
settings.webhook.redelivery=Зворотня доставка
settings.webhook.redelivery_success=Завдання хуку '%s' було передодано у чергу доставки. Оновлення статусу доставки в історії може зайняти якийсь час.
settings.webhook.request=Запит
settings.webhook.response=Відповідь
settings.webhook.headers=Заголовки
@@ -745,7 +766,7 @@ settings.add_webhook_desc=Gogs відправляє <code>POST</code> запит
settings.payload_url=URL розробника
settings.content_type=Тип змісту
settings.secret=Таємний код
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.secret_desc=Секрет буде вислано SHA256 HMAC hex-сумою вміста у хідері <code>X-Gogs-Signature</code>.
settings.slack_username=Ім'я користувача
settings.slack_icon_url=URL іконки
settings.slack_color=Колір
@@ -755,10 +776,20 @@ settings.event_send_everything=Мені потрібно <strong>усе</strong>
settings.event_choose=Дозвольте мені вибрати те, що потрібно.
settings.event_create=Створити
settings.event_create_desc=Гілку або тег створено
settings.event_pull_request=Запити до злиття
settings.event_pull_request_desc=Запрос злиття відкрито, закрито, перевідкрито, змінено, призначено, знято, мітку оновлено, мітку прибрано або синхронізовано.
settings.event_delete=Видалити
settings.event_delete_desc=Гілку або мітку було видалено
settings.event_fork=Відгалуження
settings.event_fork_desc=Репозиторій було відгалуджено
settings.event_push=Push
settings.event_push_desc=Git push до репозиторію
settings.event_issues=Проблеми
settings.event_issues_desc=Проблему відкрито, закрито, перевідкрито, відредаговано, призначено, відкріплено, змінено мітку, очищено мітку, створено етап, очищено етап.
settings.event_issue_comment=Коментар проблеми
settings.event_issue_comment_desc=Коментар проблеми створено, видалено чи відредаговано.
settings.event_pull_request=Запити до злиття
settings.event_pull_request_desc=Запрос на злиття відкрито, закрито, перевідкрито, прикріплено, відкріплено, оновлено мітку, очищено мітку, створено етап, очищено етап або синхронізовано.
settings.event_release=Реліз
settings.event_release_desc=Реліз опубліковано у репозиторії.
settings.active=Активний
settings.active_helper=Подробиці події, що викликала спрацювання хука, будуть надані також.
settings.add_hook_success=Новий web-хук було додано.
@@ -803,7 +834,6 @@ release.releases=Релізи
release.new_release=Новий реліз
release.draft=Чернетка
release.prerelease=Пре-реліз
release.stable=Стабільний
release.edit=редагувати
release.ahead=<strong>%d</strong> коммітів %s після цього релізу
release.source_code=Вихідний код
@@ -1019,6 +1049,7 @@ repos.private=Приватний
repos.watches=Стежать
repos.stars=У обраному
repos.issues=Питання
repos.size=Розмір
auths.auth_manage_panel=Керування автентифікацій
auths.new=Додати нове джерело
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Тайм-аут операції витягання
config.git_gc_timeout=Тайм-аут операції GC
config.log_config=Конфігурація журналу
config.log_mode=Режим журналювання
config.log_mode=Режим
config.log_options=Опції
monitor.cron=Завдання cron
monitor.name=Назва
@@ -1205,19 +1237,23 @@ notices.delete_success=Системні повідомлення було усп
[action]
create_repo=створено репозиторій <a href="%s">%s</a>
fork_repo=відгалуджено репозиторій у <a href="%s">%s</a>
rename_repo=репозиторій перейменовано з <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=запушено до <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
compare_commits=Перегляд порівняння для цих %d комітів
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
create_issue=`відкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`закрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`перевідкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`відкоментовано проблему <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`створено запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`закрито запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`перевідкрито запит на втягування <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`відкоментовано проблему <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`запит на злиття влито <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
create_branch=створено нову гілку <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
delete_branch=видалено гілку <code>%[2]s</code> у <a href="%[1]s">%[3]s</a>
push_tag=заштовхнуто тег <a href="%s/src/%s">%[2]s</a> до <a href="%[1]s">%[3]s</a>
compare_commits=Перегляд порівняння для цих %d комітів
delete_tag=видалено мітку <code>%[2]s</code> у <a href="%[1]s">%[3]s</a>
[tool]
ago=тому

View File

@@ -1,4 +1,4 @@
app_desc=基于 Go 语言的自助 Git 服务
app_desc=一款极易搭建的自助 Git 服务
home=首页
dashboard=控制面板
@@ -82,6 +82,8 @@ app_url=应用 URL
app_url_helper=该设置影响 HTTP/HTTPS 克隆地址和一些邮箱中的链接。
log_root_path=日志路径
log_root_path_helper=存放日志文件的目录
enable_console_mode=启用控制台模式
enable_console_mode_popup=除了使用文件模式外,还将日志输出到控制台
optional_title=可选设置
email_title=邮件服务设置
@@ -201,6 +203,7 @@ Content=内容
require_error=不能为空。
alpha_dash_error=必须为英文字母、阿拉伯数字或横线(-_
alpha_dash_dot_error=必须为英文字母、阿拉伯数字、横线(-_或点。
alpha_dash_dot_slash_error=必须为英文字母、阿拉伯数字、横线(-_、点或斜线。
size_error=长度必须为 %s。
min_size_error=长度最小为 %s 个字符。
max_size_error=长度最大为 %s 个字符。
@@ -251,12 +254,11 @@ form.name_pattern_not_allowed=用户名不允许 '%s' 的格式。
profile=个人信息
password=修改密码
avatar=头像设置
ssh_keys=管理 SSH 密钥
social=社交帐号绑定
applications=管理授权应用
orgs=管理组织
ssh_keys=SSH 密钥
repos=仓库列表
orgs=组织列表
applications=授权应用
delete=删除帐户
uid=用户 ID
public_profile=公开信息
profile_desc=您的邮箱地址将会被公开,并被用于接收帐户的所有提醒和通知。
@@ -343,6 +345,11 @@ orgs.none=您现在还不是任何组织的成员。
orgs.leave_title=离开组织
orgs.leave_desc=离开组织后,组织相关的所有仓库和团队权限将被收回。是否继续?
repos.leave=离开仓库
repos.leave_title=退出仓库协作
repos.leave_desc=离开仓库后,相关权限将被收回。是否继续?
repos.leave_success=您已经成功退出 '%s' 的仓库协作!
delete_account=删除当前帐户
delete_prompt=删除操作会永久清除您的帐户信息,并且 <strong>不可恢复</strong>
confirm_delete_account=确认删除帐户
@@ -413,7 +420,7 @@ quick_guide=快速帮助
clone_this_repo=克隆当前仓库
create_new_repo_command=从命令行创建一个新的仓库
push_exist_repo=从命令行推送已经创建的仓库
repo_is_empty=该仓库不包含任何内容,请稍后再进行访问!
bare_message=这个家伙很懒,什么都没有推送。
files=文件
branch=分支
@@ -426,6 +433,7 @@ pulls=合并请求
labels=标签管理
milestones=里程碑
commits=提交历史
git_branches=代码分支
releases=版本发布
file_raw=原始文件
file_history=文件历史
@@ -434,6 +442,13 @@ file_permalink=永久链接
file_too_large=文件过大导致无法显示
video_not_supported_in_browser=您的浏览器不支持使用 HTML5 播放视频。
branches.overview=概况
branches.active_branches=活跃分支
branches.stale_branches=陈旧分支
branches.all=所有分支
branches.updated_by=由 %[2]s 更新于 %[1]s
branches.change_default_branch=更改默认分支
editor.new_file=新的文件
editor.upload_file=上传文件
editor.edit_file=编辑文件
@@ -638,12 +653,14 @@ settings.options=基本设置
settings.collaboration=管理协作者
settings.collaboration.admin=管理权限
settings.collaboration.write=可写权限
settings.collaboration.read=读权限
settings.collaboration.read=读权限
settings.collaboration.undefined=未定义
settings.branches=管理分支
settings.branches_bare=您无法对空仓库进行分支管理,请先推送一些内容到仓库。
settings.default_branch=默认分支
settings.default_branch_desc=默认分支是被用于代码提交、合并请求和在线编辑的基准分支。
settings.update=更新
settings.update_default_branch_unsupported=服务器上的 Git 版本不支持修改默认分支。
settings.update_default_branch_success=仓库默认分支更新成功!
settings.protected_branches=保护分支
settings.protected_branches_desc=保护分支不被强制推送、意外删除和限制代码提交白名单。
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=禁止强制推送和删除分支。
settings.protect_require_pull_request=要求通过合并请求提交代码
settings.protect_require_pull_request_desc=启用该选项后代码将不能直接被推送到此分支,所有的代码提交都必须通过另一个非保护分支发起合并请求进行合并。
settings.protect_whitelist_committers=限制可以推送代码的成员
settings.protect_whitelist_committers_desc=添加用户或团队到可直接推送代码的白名单。
settings.protect_whitelist_committers_desc=添加用户或团队到可直接推送代码的白名单,列入白名单中的用户将跳过合并请求检查
settings.protect_whitelist_users=允许推送到此分支的用户
settings.protect_whitelist_search_users=搜索用户
settings.protect_whitelist_teams=允许其成员推送到此分支的团队
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=该操作将会影响到所有与该仓库有关
settings.advanced_settings=高级设置
settings.wiki_desc=启用 Wiki 系统
settings.use_internal_wiki=使用内置 Wiki 系统
settings.allow_public_wiki_desc=当仓库为私有时,允许 Wiki 的公开访问
settings.use_external_wiki=使用外部 Wiki
settings.external_wiki_url=外部 Wiki 链接
settings.external_wiki_url_desc=当访问者单击分页标签时,将会被重定向到该链接。
settings.issues_desc=启用工单管理系统
settings.use_internal_issue_tracker=使用内置的轻量级工单管理系统
settings.allow_public_issues_desc=当仓库为私有时,允许工单的公开访问
settings.use_external_issue_tracker=使用外部的工单管理系统
settings.external_tracker_url=外部工单管理系统 URL
settings.external_tracker_url_desc=当访问者单击分页标签时,将会被重定向到该链接。
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Web 钩子删除成功!
settings.webhook.test_delivery=测试推送
settings.webhook.test_delivery_desc=生成并推送一个模拟的 Push 事件
settings.webhook.test_delivery_success=测试推送已经加入到队列,请耐心等待数秒再刷新推送记录。
settings.webhook.redelivery=重新推送
settings.webhook.redelivery_success=任务 '%s' 已经被重新加入到推送队列,请耐心等待数秒再刷新推送记录。
settings.webhook.request=请求内容
settings.webhook.response=响应内容
settings.webhook.headers=头信息
@@ -751,14 +772,24 @@ settings.slack_icon_url=图标 URL
settings.slack_color=颜色代码
settings.event_desc=请设置您希望触发 Web 钩子的事件:
settings.event_push_only=只推送 <code>push</code> 事件。
settings.event_send_everything=请把 <strong>一切</strong> 都给我
settings.event_choose=我的命运自己主宰
settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=选择指定的事件
settings.event_create=创建
settings.event_create_desc=创建分支或标签
settings.event_pull_request=合并请求
settings.event_pull_request_desc=开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签或同步合并请求
settings.event_delete=删除
settings.event_delete_desc=删除分支或标签
settings.event_fork=派生
settings.event_fork_desc=仓库被派生
settings.event_push=推送
settings.event_push_desc=Git 仓库推送
settings.event_issues=工单
settings.event_issues_desc=工单被开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签、设置里程碑或取消设置里程碑
settings.event_issue_comment=工单评论
settings.event_issue_comment_desc=工单评论被创建、编辑和删除
settings.event_pull_request=合并请求
settings.event_pull_request_desc=合并请求被开启、关闭、重新开启、编辑、指派、取消指派、更新标签、清除标签、设置里程碑、取消设置里程碑或代码同步
settings.event_release=版本发布
settings.event_release_desc=仓库发布新的版本
settings.active=是否激活
settings.active_helper=当指定事件发生时我们将会触发此 Web 钩子。
settings.add_hook_success=Web 钩子添加成功!
@@ -803,7 +834,6 @@ release.releases=版本发布
release.new_release=发布新版
release.draft=草稿
release.prerelease=预发行
release.stable=稳定
release.edit=编辑
release.ahead=在该版本发布之后已有 <strong>%d</strong> 次代码提交到 %s 分支
release.source_code=源代码
@@ -1019,6 +1049,7 @@ repos.private=私有库
repos.watches=关注数
repos.stars=点赞数
repos.issues=工单数
repos.size=用量
auths.auth_manage_panel=认证管理面板
auths.new=添加新的源
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=拉取操作超时
config.git_gc_timeout=GC 操作超时
config.log_config=日志配置
config.log_mode=日志模式
config.log_mode=模式
config.log_options=选项
monitor.cron=Cron 任务
monitor.name=任务名称
@@ -1205,24 +1237,28 @@ notices.delete_success=系统提示删除成功!
[action]
create_repo=创建了仓库 <a href="%s">%s</a>
fork_repo=派生了仓库 <a href="%s">%s</a>
rename_repo=重命名仓库 <code>%[1]s</code> 为 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代码到 <a href="%[1]s">%[4]s</a>
compare_commits=对比 %d 次代码提交
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
create_issue=`创建了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`关闭了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`重新开启了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`创建了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`关闭了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`重新开启了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合并了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
create_branch=创建了新的分支 <a href="%[1]s/src/%[2]s">%[3]s</a> 到 <a href="%[1]s">%[4]s</a>
delete_branch=删除了 <a href="%[1]s">%[3]s</a> 的分支 <code>%[2]s</code>
push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=对比 %d 次代码提交
delete_tag=删除了 <a href="%[1]s">%[3]s</a> 的标签 <code>%[2]s</code>
[tool]
ago=之前
from_now=之后
now=现在
now=刚刚
1s=1 秒%s
1m=1 分钟%s
1h=1 小时%s

View File

@@ -82,6 +82,8 @@ app_url=應用程式網址
app_url_helper=該設置影響 HTTP/HTTPS 複製地址和一些郵箱中的連結。
log_root_path=日誌路徑
log_root_path_helper=寫入日誌檔目錄
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=可選設置
email_title=電子郵件服務設定
@@ -201,6 +203,7 @@ Content=Content
require_error=不能為空。
alpha_dash_error=必須為英文字母、阿拉伯數字或橫線(-_
alpha_dash_dot_error=必須為英文字母、阿拉伯數字、橫線(-_或點。
alpha_dash_dot_slash_error=` must be valid alpha or numeric or dash(-_) or dot characters or slashes.`
size_error=長度必須為 %s。
min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。
@@ -252,11 +255,10 @@ profile=個人信息
password=修改密碼
avatar=Avatar
ssh_keys=管理 SSH 密鑰
social=社交帳號綁定
applications=管理授權應用
repos=Repositories
orgs=管理組織
applications=管理授權應用
delete=刪除帳戶
uid=用戶 ID
public_profile=公開信息
profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。
@@ -340,9 +342,14 @@ access_token_deletion_desc=刪除此連接token將會刪除與相關應用程式
delete_token_success=您的連接token已成功刪除。請記得更新您的應用程式。
orgs.none=You are not a member of any organizations.
orgs.leave_title=Leave an organization
orgs.leave_title=Leave organization
orgs.leave_desc=You will lose access to all repositories and teams after you left the organization. Do you want to continue?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=刪除當前帳戶
delete_prompt=刪除操作會永久清除您的帳戶信息,並且 <strong>不可恢復</strong>
confirm_delete_account=確認刪除帳戶
@@ -413,7 +420,7 @@ quick_guide=快速幫助
clone_this_repo=複製當前倉庫
create_new_repo_command=從命令行創建一個新的倉庫
push_exist_repo=從命令行推送已經創建的倉庫
repo_is_empty=這倉庫不包含任何內容,請稍後再訪問!
bare_message=This repository does not have any content yet.
files=Files
branch=分支
@@ -426,6 +433,7 @@ pulls=合併請求
labels=標籤
milestones=里程碑
commits=提交歷史
git_branches=Branches
releases=版本發佈
file_raw=原始文件
file_history=文件歷史
@@ -434,6 +442,13 @@ file_permalink=永久連結
file_too_large=This file is too large to be shown
video_not_supported_in_browser=Your browser doesn't support HTML5 video tag.
branches.overview=Overview
branches.active_branches=Active Branches
branches.stale_branches=Stale Branches
branches.all=All Branches
branches.updated_by=Updated %[1]s by %[2]s
branches.change_default_branch=Change Default Branch
editor.new_file=New file
editor.upload_file=Upload file
editor.edit_file=Edit file
@@ -641,9 +656,11 @@ settings.collaboration.write=Write
settings.collaboration.read=Read
settings.collaboration.undefined=Undefined
settings.branches=Branches
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=Default Branch
settings.default_branch_desc=The default branch is considered the "base" branch for code commits, pull requests and online editing.
settings.update=Update
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=Default branch of this repository has been updated successfully!
settings.protected_branches=Protected Branches
settings.protected_branches_desc=Protect branches from force pushing, accidental deletion and whitelist code committers.
@@ -655,7 +672,7 @@ settings.protect_this_branch_desc=Disable force pushes and prevent from deletion
settings.protect_require_pull_request=Require pull request instead direct pushing
settings.protect_require_pull_request_desc=Enable this option to disable direct pushing to this branch. Commits have to be pushed to another non-protected branch and merged to this branch through pull request.
settings.protect_whitelist_committers=Whitelist who can push to this branch
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch.
settings.protect_whitelist_committers_desc=Add people or teams to whitelist of direct push to this branch. Users in whitelist will bypass require pull request check.
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關
settings.advanced_settings=高級設置
settings.wiki_desc=Enable wiki system
settings.use_internal_wiki=Use builtin wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=使用外部 wiki
settings.external_wiki_url=外部 Wiki 連結
settings.external_wiki_url_desc=當分頁上按一下,訪客將會重新導到 URL。
settings.issues_desc=Enable issue tracker
settings.use_internal_issue_tracker=Use builtin lightweight issue tracker
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=使用外部的問題管理系統
settings.external_tracker_url=External Issue Tracker URL
settings.external_tracker_url_desc=Visitors will be redirected to URL when they click on the tab.
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Web 鉤子刪除成功!
settings.webhook.test_delivery=測試推送
settings.webhook.test_delivery_desc=生成並推送一個模擬的 Push 事件
settings.webhook.test_delivery_success=測試推送已經加入到隊列,請耐心等待數秒再刷新推送記錄。
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=請求內容
settings.webhook.response=響應內容
settings.webhook.headers=標題
@@ -755,10 +776,20 @@ settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=讓我選擇我的需要
settings.event_create=創建
settings.event_create_desc=創建分支或標籤
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, or synchronized.
settings.event_delete=Delete
settings.event_delete_desc=Branch or tag deleted
settings.event_fork=Fork
settings.event_fork_desc=Repository forked
settings.event_push=推送
settings.event_push_desc=Git 倉庫推送
settings.event_issues=Issues
settings.event_issues_desc=Issue opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, or demilestoned.
settings.event_issue_comment=Issue Comment
settings.event_issue_comment_desc=Issue comment created, edited, or deleted.
settings.event_pull_request=Pull Request
settings.event_pull_request_desc=Pull request opened, closed, reopened, edited, assigned, unassigned, label updated, label cleared, milestoned, demilestoned, or synchronized.
settings.event_release=Release
settings.event_release_desc=Release published in a repository.
settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功!
@@ -803,7 +834,6 @@ release.releases=版本發佈
release.new_release=發佈新版本
release.draft=草稿
release.prerelease=預發佈版本
release.stable=穩定
release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼
@@ -1019,6 +1049,7 @@ repos.private=私有庫
repos.watches=關註數
repos.stars=讚好數
repos.issues=問題數
repos.size=Size
auths.auth_manage_panel=認證管理面板
auths.new=添加新認證源
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=Pull Operation Timeout
config.git_gc_timeout=GC Operation Timeout
config.log_config=日誌配置
config.log_mode=日誌模式
config.log_mode=Mode
config.log_options=Options
monitor.cron=Cron 任務
monitor.name=任務名稱
@@ -1205,19 +1237,23 @@ notices.delete_success=系統提示刪除成功!
[action]
create_repo=創建了儲存庫 <a href="%s">%s</a>
fork_repo=forked a repository to <a href="%s">%s</a>
rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
compare_commits=查看 %d 次提交的內容比對
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`closed issue <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`reopened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`closed pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`reopened pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_branch=created new branch <a href="%[1]s/src/%[2]s">%[3]s</a> at <a href="%[1]s">%[4]s</a>
delete_branch=deleted branch <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的內容比對
delete_tag=deleted tag <code>%[2]s</code> at <a href="%[1]s">%[3]s</a>
[tool]
ago=之前

View File

@@ -82,6 +82,8 @@ app_url=應用程式網址
app_url_helper=該設置影響 HTTP/HTTPS 複製地址和一些郵箱中的連結。
log_root_path=日誌路徑
log_root_path_helper=寫入日誌檔目錄
enable_console_mode=Enable Console Mode
enable_console_mode_popup=In addition to file mode, also print logs to console.
optional_title=可選設置
email_title=電子郵件服務設定
@@ -201,6 +203,7 @@ Content=內容
require_error=不能為空。
alpha_dash_error=必須為英文字母、阿拉伯數字或橫線(-_
alpha_dash_dot_error=必須為英文字母、阿拉伯數字、橫線(-_或點。
alpha_dash_dot_slash_error=` 必須是合法的英文字母、數字、分隔符號(-_)、半形句點或斜線。`
size_error=長度必須為 %s。
min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。
@@ -252,11 +255,10 @@ profile=個人信息
password=修改密碼
avatar=頭像
ssh_keys=管理 SSH 密鑰
social=社交帳號綁定
applications=管理授權應用
repos=Repositories
orgs=管理組織
applications=管理授權應用
delete=刪除帳戶
uid=用戶 ID
public_profile=公開信息
profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。
@@ -343,6 +345,11 @@ orgs.none=您現在還不是任何組織的成員。
orgs.leave_title=離開組織
orgs.leave_desc=離開組織後,所有與組織相關的倉庫和團隊權限將被取消。是否繼續?
repos.leave=Leave
repos.leave_title=Leave repository
repos.leave_desc=You will lose access to the repository after you left. Do you want to continue?
repos.leave_success=You have left repository '%s' successfully!
delete_account=刪除當前帳戶
delete_prompt=刪除操作會永久清除您的帳戶信息,並且 <strong>不可恢復</strong>
confirm_delete_account=確認刪除帳戶
@@ -413,7 +420,7 @@ quick_guide=快速幫助
clone_this_repo=複製當前倉庫
create_new_repo_command=從命令行創建一個新的倉庫
push_exist_repo=從命令行推送已經創建的倉庫
repo_is_empty=這倉庫不包含任何內容,請稍後再訪問!
bare_message=This repository does not have any content yet.
files=檔案
branch=分支
@@ -426,6 +433,7 @@ pulls=合併請求
labels=標籤
milestones=里程碑
commits=提交歷史
git_branches=分支列表
releases=版本發佈
file_raw=原始文件
file_history=文件歷史
@@ -434,6 +442,13 @@ file_permalink=永久連結
file_too_large=檔案太大,無法顯示
video_not_supported_in_browser=您的瀏覽器不支援 HTML5 影片播放標籤。
branches.overview=概覽
branches.active_branches=活躍分支
branches.stale_branches=陳舊分支
branches.all=所有分支
branches.updated_by=%[2]s 更新了 %[1]s
branches.change_default_branch=變更預設分支
editor.new_file=開新檔案
editor.upload_file=上傳檔案
editor.edit_file=編輯文件
@@ -641,9 +656,11 @@ settings.collaboration.write=可寫權限
settings.collaboration.read=可讀權限
settings.collaboration.undefined=未定義
settings.branches=分支列表
settings.branches_bare=You cannot manage branches for bare repository. Please push some content first.
settings.default_branch=預設分支
settings.default_branch_desc=預設分支是程式碼 commit、pull requests 及線上編輯的基準分支。
settings.update=更新
settings.update_default_branch_unsupported=Change default branch is not supported by the Git version on server.
settings.update_default_branch_success=這個 repository 的預設分支更新成功!
settings.protected_branches=保護分支
settings.protected_branches_desc=保護分支不被強制 Push、意外刪除以及限制 Commit 者白名單
@@ -655,11 +672,11 @@ settings.protect_this_branch_desc=停用強制Push及分支刪除。
settings.protect_require_pull_request=請使用 pull request 來更新(合併)程式碼。
settings.protect_require_pull_request_desc=啟用這個選項之後,程式碼將無法直接 Push 到這個分支,所有 Commit 必須先 Push 到另一個非保護的分支,再透過 Pull Request 來要求合併。
settings.protect_whitelist_committers=限制誰可以 Push 到這個分支
settings.protect_whitelist_committers_desc=新增用戶或團隊到可以直接push到這個分支的白名單。
settings.protect_whitelist_users=Users who can push to this branch
settings.protect_whitelist_search_users=Search users
settings.protect_whitelist_teams=Teams for which members of them can push to this branch
settings.protect_whitelist_search_teams=Search teams
settings.protect_whitelist_committers_desc=新增成員或團隊到允許直接 push 到這個分支的白名單。白名單中的使用者將會略過 pull request 的檢查。
settings.protect_whitelist_users=限制那些使用者可以 push 到這個分支
settings.protect_whitelist_search_users=搜尋用戶
settings.protect_whitelist_teams=團隊的成員可以 push 到這個分支
settings.protect_whitelist_search_teams=搜尋團隊
settings.update_protect_branch_success=此分支設置保護已更新成功!
settings.hooks=管理 Web 鉤子
settings.githooks=管理 Git 鉤子
@@ -673,11 +690,13 @@ settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關
settings.advanced_settings=高級設置
settings.wiki_desc=啓用 Wiki 系統
settings.use_internal_wiki=使用內建 wiki
settings.allow_public_wiki_desc=Allow public access to wiki when repository is private
settings.use_external_wiki=使用外部 wiki
settings.external_wiki_url=外部 Wiki 連結
settings.external_wiki_url_desc=當分頁上按一下,訪客將會重新導到 URL。
settings.issues_desc=啟用問題追蹤
settings.use_internal_issue_tracker=使用內建輕量級問題追蹤
settings.allow_public_issues_desc=Allow public access to issues when repository is private
settings.use_external_issue_tracker=使用外部的問題管理系統
settings.external_tracker_url=外部Issue Tracker網址
settings.external_tracker_url_desc=當訪客在分頁上按一下,他們將會重新導向到 URL。
@@ -688,7 +707,7 @@ settings.tracker_issue_style.alphanumeric=字母及數字
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
settings.pulls_desc=啟用合併請求以接受社區貢獻
settings.danger_zone=危險操作區
settings.cannot_fork_to_same_owner=You cannot fork a repository to its original owner.
settings.cannot_fork_to_same_owner=你不可以 fork 一個 repository 到它的擁有者。
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
settings.convert=轉換為正規倉庫
settings.convert_desc=您可以將此鏡像轉成正規倉庫。此動做不可逆。
@@ -731,6 +750,8 @@ settings.webhook_deletion_success=Web 鉤子刪除成功!
settings.webhook.test_delivery=測試推送
settings.webhook.test_delivery_desc=生成並推送一個模擬的 Push 事件
settings.webhook.test_delivery_success=測試推送已經加入到隊列,請耐心等待數秒再刷新推送記錄。
settings.webhook.redelivery=Redelivery
settings.webhook.redelivery_success=Hook task '%s' has been readded to delivery queue. It may take few seconds to update delivery status in history.
settings.webhook.request=請求內容
settings.webhook.response=響應內容
settings.webhook.headers=標題
@@ -745,7 +766,7 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
settings.payload_url=推送地址
settings.content_type=數據格式
settings.secret=密鑰文本
settings.secret_desc=Secret will be sent as SHA256 HMAC hex digest of payload via <code>X-Gogs-Signature</code> header.
settings.secret_desc=密鑰將會以 SHA256 HMAC 的十六進位數字放進<code>X-Gogs-Signature</code> 標頭中送出。
settings.slack_username=服務名稱
settings.slack_icon_url=圖標 URL
settings.slack_color=顏色代碼
@@ -755,10 +776,20 @@ settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=讓我選擇我的需要
settings.event_create=創建
settings.event_create_desc=創建分支或標籤
settings.event_pull_request=合併請求
settings.event_pull_request_desc=請求打開,關閉,重新打開,編輯,分配,未分配,標籤更新,標籤清除,或同步。
settings.event_delete=刪除
settings.event_delete_desc=分支或標籤已經被刪除
settings.event_fork=Fork
settings.event_fork_desc=Repository 已經 fork
settings.event_push=推送
settings.event_push_desc=Git 倉庫推送
settings.event_issues=Issues
settings.event_issues_desc=已經開啟、關閉、重啟、修改、指派、取消指派、更新標籤、清除標籤、新增里程碑或刪除里程碑的 issue。
settings.event_issue_comment=Issue 評論
settings.event_issue_comment_desc=已經建立、編輯或刪除的 Issue 評論。
settings.event_pull_request=合併請求
settings.event_pull_request_desc=已經開啟、關閉、重啟、編輯、指派、解除指派、更新標籤、清除標籤、新增里程碑、刪除里程碑或同步的 pull request。
settings.event_release=Release
settings.event_release_desc=Release 將發佈在一個 repository 中。
settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功!
@@ -803,7 +834,6 @@ release.releases=版本發佈
release.new_release=發佈新版本
release.draft=草稿
release.prerelease=預發佈版本
release.stable=穩定
release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼
@@ -1019,6 +1049,7 @@ repos.private=私有庫
repos.watches=關註數
repos.stars=讚好數
repos.issues=問題數
repos.size=大小
auths.auth_manage_panel=認證管理面板
auths.new=添加新認證源
@@ -1176,7 +1207,8 @@ config.git_pull_timeout=操作超時
config.git_gc_timeout=GC 操作超時
config.log_config=日誌配置
config.log_mode=日誌模式
config.log_mode=模式
config.log_options=選項
monitor.cron=Cron 任務
monitor.name=任務名稱
@@ -1205,19 +1237,23 @@ notices.delete_success=系統提示刪除成功!
[action]
create_repo=創建了儲存庫 <a href="%s">%s</a>
fork_repo=已經 fork 一個 repository 到 <a href="%s">%s</a>
rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
compare_commits=查看 %d 次提交的內容比對
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
close_issue=`已關閉問題 <a href="%s/issues/%s">%s#%[2]s</a>`
reopen_issue=`已重新開啟問題 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
close_pull_request=`已關閉合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
reopen_pull_request=`已重新開啟合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=將儲存庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
create_branch=在 <a href="%[1]s">%[4]s</a> 建立新的分支 <a href="%[1]s/src/%[2]s">%[3]s</a>
delete_branch=已經刪除在 <a href="%[1]s">%[3]s</a> 上的分支 <code>%[2]s</code>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的內容比對
delete_tag=已經刪除在 <a href="%[1]s">%[3]s</a> 上的標籤 <code>%[2]s</code>
[tool]
ago=之前

View File

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

View File

@@ -16,7 +16,6 @@ ln -s /app/gogs/build ${GOPATH}/src/github.com/gogits/gogs
cd ${GOPATH}/src/github.com/gogits/gogs
# Needed since git 2.9.3 or 2.9.4
git config --global http.https://gopkg.in.followRedirects true
go get -v -tags "sqlite cert pam" ./...
make build TAGS="sqlite cert pam"
# Cleanup GOPATH

17
gogs.go
View File

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

View File

@@ -8,6 +8,8 @@ import (
"fmt"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/models/errors"
)
type AccessMode int
@@ -109,7 +111,7 @@ func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
for _, access := range accesses {
repo, err := GetRepositoryByID(access.RepoID)
if err != nil {
if IsErrRepoNotExist(err) {
if errors.IsRepoNotExist(err) {
log.Error(4, "GetRepositoryByID: %v", err)
continue
}

View File

@@ -20,12 +20,14 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/setting"
)
type ActionType int
// To maintain backward compatibility only append to the end of list
const (
ACTION_CREATE_REPO ActionType = iota + 1 // 1
ACTION_RENAME_REPO // 2
@@ -42,6 +44,10 @@ const (
ACTION_REOPEN_ISSUE // 13
ACTION_CLOSE_PULL_REQUEST // 14
ACTION_REOPEN_PULL_REQUEST // 15
ACTION_CREATE_BRANCH // 16
ACTION_DELETE_BRANCH // 17
ACTION_DELETE_TAG // 18
ACTION_FORK_REPO // 19
)
var (
@@ -66,7 +72,7 @@ func init() {
// Action represents user operation type and other information to repository,
// it implemented interface base.Actioner so that can be used in template render.
type Action struct {
ID int64 `xorm:"pk autoincr"`
ID int64
UserID int64 // Receiver user id.
OpType ActionType
ActUserID int64 // Action user id.
@@ -102,7 +108,7 @@ func (a *Action) GetActUserName() string {
}
func (a *Action) ShortActUserName() string {
return base.EllipsisString(a.ActUserName, 20)
return tool.EllipsisString(a.ActUserName, 20)
}
func (a *Action) GetRepoUserName() string {
@@ -110,7 +116,7 @@ func (a *Action) GetRepoUserName() string {
}
func (a *Action) ShortRepoUserName() string {
return base.EllipsisString(a.RepoUserName, 20)
return tool.EllipsisString(a.RepoUserName, 20)
}
func (a *Action) GetRepoName() string {
@@ -118,7 +124,7 @@ func (a *Action) GetRepoName() string {
}
func (a *Action) ShortRepoName() string {
return base.EllipsisString(a.RepoName, 33)
return tool.EllipsisString(a.RepoName, 33)
}
func (a *Action) GetRepoPath() string {
@@ -172,26 +178,26 @@ func (a *Action) GetIssueContent() string {
return issue.Content
}
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
if err = notifyWatchers(e, &Action{
ActUserID: u.ID,
ActUserName: u.Name,
OpType: ACTION_CREATE_REPO,
func newRepoAction(e Engine, doer, owner *User, repo *Repository) (err error) {
opType := ACTION_CREATE_REPO
if repo.IsFork {
opType = ACTION_FORK_REPO
}
return notifyWatchers(e, &Action{
ActUserID: doer.ID,
ActUserName: doer.Name,
OpType: opType,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
}
log.Trace("action.newRepoAction: %s/%s", u.Name, repo.Name)
return err
})
}
// NewRepoAction adds new action for creating repository.
func NewRepoAction(u *User, repo *Repository) (err error) {
return newRepoAction(x, u, repo)
func NewRepoAction(doer, owner *User, repo *Repository) (err error) {
return newRepoAction(x, doer, owner, repo)
}
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
@@ -245,20 +251,30 @@ func NewPushCommits() *PushCommits {
}
}
func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit {
func (pc *PushCommits) ToApiPayloadCommits(repoPath, repoLink string) ([]*api.PayloadCommit, error) {
commits := make([]*api.PayloadCommit, len(pc.Commits))
for i, commit := range pc.Commits {
authorUsername := ""
author, err := GetUserByEmail(commit.AuthorEmail)
if err == nil {
authorUsername = author.Name
} else if !errors.IsUserNotExist(err) {
return nil, fmt.Errorf("GetUserByEmail: %v", err)
}
committerUsername := ""
committer, err := GetUserByEmail(commit.CommitterEmail)
if err == nil {
// TODO: check errors other than email not found.
committerUsername = committer.Name
} else if !errors.IsUserNotExist(err) {
return nil, fmt.Errorf("GetUserByEmail: %v", err)
}
fileStatus, err := git.GetCommitFileStatus(repoPath, commit.Sha1)
if err != nil {
return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %v", commit.Sha1, err)
}
commits[i] = &api.PayloadCommit{
ID: commit.Sha1,
Message: commit.Message,
@@ -273,10 +289,13 @@ func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit
Email: commit.CommitterEmail,
UserName: committerUsername,
},
Added: fileStatus.Added,
Removed: fileStatus.Removed,
Modified: fileStatus.Modified,
Timestamp: commit.Timestamp,
}
}
return commits
return commits, nil
}
// AvatarLink tries to match user in database with e-mail
@@ -286,8 +305,8 @@ func (push *PushCommits) AvatarLink(email string) string {
if !ok {
u, err := GetUserByEmail(email)
if err != nil {
push.avatars[email] = base.AvatarLink(email)
if !IsErrUserNotExist(err) {
push.avatars[email] = tool.AvatarLink(email)
if !errors.IsUserNotExist(err) {
log.Error(4, "GetUserByEmail: %v", err)
}
} else {
@@ -324,7 +343,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
issue, err := GetIssueByRef(ref)
if err != nil {
if IsErrIssueNotExist(err) {
if errors.IsIssueNotExist(err) {
continue
}
return err
@@ -367,7 +386,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
issue, err := GetIssueByRef(ref)
if err != nil {
if IsErrIssueNotExist(err) {
if errors.IsIssueNotExist(err) {
continue
}
return err
@@ -407,7 +426,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
issue, err := GetIssueByRef(ref)
if err != nil {
if IsErrIssueNotExist(err) {
if errors.IsIssueNotExist(err) {
continue
}
return err
@@ -458,18 +477,16 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
return fmt.Errorf("UpdateRepository: %v", err)
}
isNewBranch := false
isNewRef := opts.OldCommitID == git.EMPTY_SHA
isDelRef := opts.NewCommitID == git.EMPTY_SHA
opType := ACTION_COMMIT_REPO
// Check it's tag push or branch.
// Check if it's tag push or branch.
if strings.HasPrefix(opts.RefFullName, git.TAG_PREFIX) {
opType = ACTION_PUSH_TAG
opts.Commits = &PushCommits{}
} else {
// TODO: detect branch deletion
// if not the first commit, set the compare URL.
if opts.OldCommitID == git.EMPTY_SHA {
isNewBranch = true
} else {
if !isNewRef && !isDelRef {
opts.Commits.CompareURL = repo.ComposeCompareURL(opts.OldCommitID, opts.NewCommitID)
}
@@ -488,39 +505,63 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
}
refName := git.RefEndName(opts.RefFullName)
if err = NotifyWatchers(&Action{
action := &Action{
ActUserID: pusher.ID,
ActUserName: pusher.Name,
OpType: opType,
Content: string(data),
RepoID: repo.ID,
RepoUserName: repo.MustOwner().Name,
RepoName: repo.Name,
RefName: refName,
IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("NotifyWatchers: %v", err)
}
defer func() {
go HookQueue.Add(repo.ID)
}()
apiPusher := pusher.APIFormat()
apiRepo := repo.APIFormat(nil)
apiPusher := pusher.APIFormat()
switch opType {
case ACTION_COMMIT_REPO: // Push
if isDelRef {
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
Ref: refName,
RefType: "branch",
PusherType: api.PUSHER_TYPE_USER,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(delete branch): %v", err)
}
action.OpType = ACTION_DELETE_BRANCH
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(delete branch): %v", err)
}
// Delete branch doesn't have anything to push or compare
return nil
}
compareURL := setting.AppUrl + opts.Commits.CompareURL
if isNewBranch {
if isNewRef {
compareURL = ""
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "branch",
Repo: apiRepo,
Sender: apiPusher,
Ref: refName,
RefType: "branch",
DefaultBranch: repo.DefaultBranch,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks (new branch): %v", err)
return fmt.Errorf("PrepareWebhooks.(new branch): %v", err)
}
action.OpType = ACTION_CREATE_BRANCH
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new branch): %v", err)
}
}
commits, err := opts.Commits.ToApiPayloadCommits(repo.RepoPath(), repo.HTMLURL())
if err != nil {
return fmt.Errorf("ToApiPayloadCommits: %v", err)
}
if err = PrepareWebhooks(repo, HOOK_EVENT_PUSH, &api.PushPayload{
@@ -528,21 +569,52 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
Before: opts.OldCommitID,
After: opts.NewCommitID,
CompareURL: compareURL,
Commits: opts.Commits.ToApiPayloadCommits(repo.HTMLURL()),
Commits: commits,
Repo: apiRepo,
Pusher: apiPusher,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks (new commit): %v", err)
return fmt.Errorf("PrepareWebhooks.(new commit): %v", err)
}
case ACTION_PUSH_TAG: // Create
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
Repo: apiRepo,
Sender: apiPusher,
})
action.OpType = ACTION_COMMIT_REPO
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new commit): %v", err)
}
case ACTION_PUSH_TAG: // Tag
if isDelRef {
if err = PrepareWebhooks(repo, HOOK_EVENT_DELETE, &api.DeletePayload{
Ref: refName,
RefType: "tag",
PusherType: api.PUSHER_TYPE_USER,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(delete tag): %v", err)
}
action.OpType = ACTION_DELETE_TAG
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(delete tag): %v", err)
}
return nil
}
if err = PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
DefaultBranch: repo.DefaultBranch,
Repo: apiRepo,
Sender: apiPusher,
}); err != nil {
return fmt.Errorf("PrepareWebhooks.(new tag): %v", err)
}
action.OpType = ACTION_PUSH_TAG
if err = NotifyWatchers(action); err != nil {
return fmt.Errorf("NotifyWatchers.(new tag): %v", err)
}
}
return nil
@@ -599,9 +671,12 @@ func MergePullRequestAction(actUser *User, repo *Repository, pull *Issue) error
// GetFeeds returns action list of given user in given context.
// actorID is the user who's requesting, ctxUserID is the user/org that is requested.
// actorID can be -1 when isProfile is true or to skip the permission check.
func GetFeeds(ctxUser *User, actorID, offset int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, 20)
sess := x.Limit(20, int(offset)).Desc("id").Where("user_id = ?", ctxUser.ID)
func GetFeeds(ctxUser *User, actorID, afterID int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, setting.UI.User.NewsFeedPagingNum)
sess := x.Limit(setting.UI.User.NewsFeedPagingNum).Where("user_id = ?", ctxUser.ID).Desc("id")
if afterID > 0 {
sess.And("id < ?", afterID)
}
if isProfile {
sess.And("is_private = ?", false).And("act_user_id = ?", ctxUser.ID)
} else if actorID != -1 && ctxUser.IsOrganization() {

View File

@@ -15,8 +15,8 @@ import (
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/setting"
)
type NoticeType int
@@ -128,6 +128,6 @@ func DeleteNoticesByIDs(ids []int64) error {
if len(ids) == 0 {
return nil
}
_, err := x.Where("id IN (" + strings.Join(base.Int64sToStrings(ids), ",") + ")").Delete(new(Notice))
_, err := x.Where("id IN (" + strings.Join(tool.Int64sToStrings(ids), ",") + ")").Delete(new(Notice))
return err
}

View File

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

View File

@@ -15,7 +15,8 @@ import (
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/markup"
)
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
@@ -95,7 +96,7 @@ func (c *Comment) loadAttributes(e Engine) (err error) {
if c.Poster == nil {
c.Poster, err = GetUserByID(c.PosterID)
if err != nil {
if IsErrUserNotExist(err) {
if errors.IsUserNotExist(err) {
c.PosterID = -1
c.Poster = NewGhostUser()
} else {
@@ -150,9 +151,13 @@ func (c *Comment) APIFormat() *api.Comment {
}
}
func CommentHashTag(id int64) string {
return "issuecomment-" + com.ToStr(id)
}
// HashTag returns unique hash tag for comment.
func (c *Comment) HashTag() string {
return "issuecomment-" + com.ToStr(c.ID)
return CommentHashTag(c.ID)
}
// EventTag returns unique event hash tag for comment.
@@ -163,7 +168,7 @@ func (c *Comment) EventTag() string {
// mailParticipants sends new comment emails to repository watchers
// and mentioned people.
func (cmt *Comment) mailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
mentions := markdown.FindAllMentions(cmt.Content)
mentions := markup.FindAllMentions(cmt.Content)
if err = updateIssueMentions(e, cmt.IssueID, mentions); err != nil {
return fmt.Errorf("UpdateIssueMentions [%d]: %v", cmt.IssueID, err)
}
@@ -330,7 +335,7 @@ func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
// CreateIssueComment creates a plain issue comment.
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) {
return CreateComment(&CreateCommentOptions{
comment, err := CreateComment(&CreateCommentOptions{
Type: COMMENT_TYPE_COMMENT,
Doer: doer,
Repo: repo,
@@ -338,6 +343,22 @@ func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content stri
Content: content,
Attachments: attachments,
})
if err != nil {
return nil, fmt.Errorf("CreateComment: %v", err)
}
comment.Issue = issue
if err = PrepareWebhooks(repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_CREATED,
Issue: issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
return comment, nil
}
// CreateRefComment creates a commit reference comment to issue.
@@ -437,13 +458,33 @@ func GetCommentsByRepoIDSince(repoID, since int64) ([]*Comment, error) {
}
// UpdateComment updates information of comment.
func UpdateComment(c *Comment) error {
_, err := x.Id(c.ID).AllCols().Update(c)
return err
func UpdateComment(doer *User, c *Comment, oldContent string) (err error) {
if _, err = x.Id(c.ID).AllCols().Update(c); err != nil {
return err
}
if err = c.Issue.LoadAttributes(); err != nil {
log.Error(2, "Issue.LoadAttributes [issue_id: %d]: %v", c.IssueID, err)
} else if err = PrepareWebhooks(c.Issue.Repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_EDITED,
Issue: c.Issue.APIFormat(),
Comment: c.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: c.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
}
return nil
}
// DeleteCommentByID deletes the comment by given ID.
func DeleteCommentByID(id int64) error {
func DeleteCommentByID(doer *User, id int64) error {
comment, err := GetCommentByID(id)
if err != nil {
if IsErrCommentNotExist(err) {
@@ -468,5 +509,20 @@ func DeleteCommentByID(id int64) error {
}
}
return sess.Commit()
if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
if err = comment.Issue.LoadAttributes(); err != nil {
log.Error(2, "Issue.LoadAttributes [issue_id: %d]: %v", comment.IssueID, err)
} else if err = PrepareWebhooks(comment.Issue.Repo, HOOK_EVENT_ISSUE_COMMENT, &api.IssueCommentPayload{
Action: api.HOOK_ISSUE_COMMENT_DELETED,
Issue: comment.Issue.APIFormat(),
Comment: comment.APIFormat(),
Repository: comment.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
}
return nil
}

View File

@@ -54,20 +54,6 @@ func (err ErrUserAlreadyExist) Error() string {
return fmt.Sprintf("user already exists [name: %s]", err.Name)
}
type ErrUserNotExist struct {
UID int64
Name string
}
func IsErrUserNotExist(err error) bool {
_, ok := err.(ErrUserNotExist)
return ok
}
func (err ErrUserNotExist) Error() string {
return fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name)
}
type ErrEmailAlreadyUsed struct {
Email string
}
@@ -319,21 +305,6 @@ func (err ErrLastOrgOwner) Error() string {
// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____|
// \/ \/|__| \/ \/
type ErrRepoNotExist struct {
ID int64
UID int64
Name string
}
func IsErrRepoNotExist(err error) bool {
_, ok := err.(ErrRepoNotExist)
return ok
}
func (err ErrRepoNotExist) Error() string {
return fmt.Sprintf("repository does not exist [id: %d, uid: %d, name: %s]", err.ID, err.UID, err.Name)
}
type ErrRepoAlreadyExist struct {
Uname string
Name string
@@ -450,48 +421,6 @@ func (err ErrBranchNotExist) Error() string {
return fmt.Sprintf("branch does not exist [name: %s]", err.Name)
}
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
// \ /\ ___/| \_\ \ Y ( <_> | <_> ) <
// \__/\ / \___ >___ /___| /\____/ \____/|__|_ \
// \/ \/ \/ \/ \/
type ErrWebhookNotExist struct {
ID int64
}
func IsErrWebhookNotExist(err error) bool {
_, ok := err.(ErrWebhookNotExist)
return ok
}
func (err ErrWebhookNotExist) Error() string {
return fmt.Sprintf("webhook does not exist [id: %d]", err.ID)
}
// .___
// | | ______ ________ __ ____
// | |/ ___// ___/ | \_/ __ \
// | |\___ \ \___ \| | /\ ___/
// |___/____ >____ >____/ \___ >
// \/ \/ \/
type ErrIssueNotExist struct {
ID int64
RepoID int64
Index int64
}
func IsErrIssueNotExist(err error) bool {
_, ok := err.(ErrIssueNotExist)
return ok
}
func (err ErrIssueNotExist) Error() string {
return fmt.Sprintf("issue does not exist [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
}
// __________ .__ .__ __________ __
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\

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

@@ -0,0 +1,12 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "errors"
// New is a wrapper of real errors.New function.
func New(text string) error {
return errors.New(text)
}

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

@@ -0,0 +1,35 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type IssueNotExist struct {
ID int64
RepoID int64
Index int64
}
func IsIssueNotExist(err error) bool {
_, ok := err.(IssueNotExist)
return ok
}
func (err IssueNotExist) Error() string {
return fmt.Sprintf("issue does not exist [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
}
type InvalidIssueReference struct {
Ref string
}
func IsInvalidIssueReference(err error) bool {
_, ok := err.(InvalidIssueReference)
return ok
}
func (err InvalidIssueReference) Error() string {
return fmt.Sprintf("invalid issue reference [ref: %s]", err.Ref)
}

View File

@@ -0,0 +1,33 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type LoginSourceNotActivated struct {
SourceID int64
}
func IsLoginSourceNotActivated(err error) bool {
_, ok := err.(LoginSourceNotActivated)
return ok
}
func (err LoginSourceNotActivated) Error() string {
return fmt.Sprintf("login source is not activated [source_id: %d]", err.SourceID)
}
type InvalidLoginSourceType struct {
Type interface{}
}
func IsInvalidLoginSourceType(err error) bool {
_, ok := err.(InvalidLoginSourceType)
return ok
}
func (err InvalidLoginSourceType) Error() string {
return fmt.Sprintf("invalid login source type [type: %v]", err.Type)
}

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

@@ -0,0 +1,48 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type RepoNotExist struct {
ID int64
UserID int64
Name string
}
func IsRepoNotExist(err error) bool {
_, ok := err.(RepoNotExist)
return ok
}
func (err RepoNotExist) Error() string {
return fmt.Sprintf("repository does not exist [id: %d, user_id: %d, name: %s]", err.ID, err.UserID, err.Name)
}
type InvalidRepoReference struct {
Ref string
}
func IsInvalidRepoReference(err error) bool {
_, ok := err.(InvalidRepoReference)
return ok
}
func (err InvalidRepoReference) Error() string {
return fmt.Sprintf("invalid repository reference [ref: %s]", err.Ref)
}
type MirrorNotExist struct {
RepoID int64
}
func IsMirrorNotExist(err error) bool {
_, ok := err.(MirrorNotExist)
return ok
}
func (err MirrorNotExist) Error() string {
return fmt.Sprintf("mirror does not exist [repo_id: %d]", err.RepoID)
}

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

@@ -0,0 +1,45 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type EmptyName struct{}
func IsEmptyName(err error) bool {
_, ok := err.(EmptyName)
return ok
}
func (err EmptyName) Error() string {
return "empty name"
}
type UserNotExist struct {
UserID int64
Name string
}
func IsUserNotExist(err error) bool {
_, ok := err.(UserNotExist)
return ok
}
func (err UserNotExist) Error() string {
return fmt.Sprintf("user does not exist [user_id: %d, name: %s]", err.UserID, err.Name)
}
type UserNotKeyOwner struct {
KeyID int64
}
func IsUserNotKeyOwner(err error) bool {
_, ok := err.(UserNotKeyOwner)
return ok
}
func (err UserNotKeyOwner) Error() string {
return fmt.Sprintf("user is not the owner of public key [key_id: %d]", err.KeyID)
}

View File

@@ -0,0 +1,33 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type EmailNotFound struct {
Email string
}
func IsEmailNotFound(err error) bool {
_, ok := err.(EmailNotFound)
return ok
}
func (err EmailNotFound) Error() string {
return fmt.Sprintf("email is not found [email: %s]", err.Email)
}
type EmailNotVerified struct {
Email string
}
func IsEmailNotVerified(err error) bool {
_, ok := err.(EmailNotVerified)
return ok
}
func (err EmailNotVerified) Error() string {
return fmt.Sprintf("email has not been verified [email: %s]", err.Email)
}

34
models/errors/webhook.go Normal file
View File

@@ -0,0 +1,34 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package errors
import "fmt"
type WebhookNotExist struct {
ID int64
}
func IsWebhookNotExist(err error) bool {
_, ok := err.(WebhookNotExist)
return ok
}
func (err WebhookNotExist) Error() string {
return fmt.Sprintf("webhook does not exist [id: %d]", err.ID)
}
type HookTaskNotExist struct {
HookID int64
UUID string
}
func IsHookTaskNotExist(err error) bool {
_, ok := err.(HookTaskNotExist)
return ok
}
func (err HookTaskNotExist) Error() string {
return fmt.Sprintf("hook task does not exist [hook_id: %d, uuid: %s]", err.HookID, err.UUID)
}

View File

@@ -5,63 +5,25 @@
package models
import (
"bufio"
"bytes"
"fmt"
"html"
"html/template"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"
"github.com/Unknwon/com"
"github.com/sergi/go-diff/diffmatchpatch"
"golang.org/x/net/html/charset"
"golang.org/x/text/transform"
log "gopkg.in/clog.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template/highlight"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/template/highlight"
)
type DiffLineType uint8
const (
DIFF_LINE_PLAIN DiffLineType = iota + 1
DIFF_LINE_ADD
DIFF_LINE_DEL
DIFF_LINE_SECTION
)
type DiffFileType uint8
const (
DIFF_FILE_ADD DiffFileType = iota + 1
DIFF_FILE_CHANGE
DIFF_FILE_DEL
DIFF_FILE_RENAME
)
type DiffLine struct {
LeftIdx int
RightIdx int
Type DiffLineType
Content string
}
func (d *DiffLine) GetType() int {
return int(d.Type)
}
type DiffSection struct {
Name string
Lines []*DiffLine
*git.DiffSection
}
var (
@@ -70,24 +32,24 @@ var (
codeTagSuffix = []byte("</span>")
)
func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
func diffToHTML(diffs []diffmatchpatch.Diff, lineType git.DiffLineType) template.HTML {
buf := bytes.NewBuffer(nil)
// Reproduce signs which are cutted for inline diff before.
switch lineType {
case DIFF_LINE_ADD:
case git.DIFF_LINE_ADD:
buf.WriteByte('+')
case DIFF_LINE_DEL:
case git.DIFF_LINE_DEL:
buf.WriteByte('-')
}
for i := range diffs {
switch {
case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DIFF_LINE_ADD:
case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == git.DIFF_LINE_ADD:
buf.Write(addedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DIFF_LINE_DEL:
case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == git.DIFF_LINE_DEL:
buf.Write(removedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
@@ -99,77 +61,34 @@ func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTM
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 {
var (
difference = 0
addCount = 0
delCount = 0
matchDiffLine *DiffLine
)
LOOP:
for _, diffLine := range diffSection.Lines {
switch diffLine.Type {
case DIFF_LINE_ADD:
addCount++
case DIFF_LINE_DEL:
delCount++
default:
if matchDiffLine != nil {
break LOOP
}
difference = diffLine.RightIdx - diffLine.LeftIdx
addCount = 0
delCount = 0
}
switch lineType {
case DIFF_LINE_DEL:
if diffLine.RightIdx == 0 && diffLine.LeftIdx == idx-difference {
matchDiffLine = diffLine
}
case DIFF_LINE_ADD:
if diffLine.LeftIdx == 0 && diffLine.RightIdx == idx+difference {
matchDiffLine = diffLine
}
}
}
if addCount == delCount {
return matchDiffLine
}
return nil
}
var diffMatchPatch = diffmatchpatch.New()
func init() {
diffMatchPatch.DiffEditCost = 100
}
// computes inline diff for the given line
func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML {
// ComputedInlineDiffFor computes inline diff for the given line.
func (diffSection *DiffSection) ComputedInlineDiffFor(diffLine *git.DiffLine) template.HTML {
if setting.Git.DisableDiffHighlight {
return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
var (
compareDiffLine *DiffLine
compareDiffLine *git.DiffLine
diff1 string
diff2 string
)
// try to find equivalent diff line. ignore, otherwise
switch diffLine.Type {
case DIFF_LINE_ADD:
compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
case git.DIFF_LINE_ADD:
compareDiffLine = diffSection.Line(git.DIFF_LINE_DEL, diffLine.RightIdx)
if compareDiffLine == nil {
return template.HTML(html.EscapeString(diffLine.Content))
}
diff1 = compareDiffLine.Content
diff2 = diffLine.Content
case DIFF_LINE_DEL:
compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
case git.DIFF_LINE_DEL:
compareDiffLine = diffSection.Line(git.DIFF_LINE_ADD, diffLine.LeftIdx)
if compareDiffLine == nil {
return template.HTML(html.EscapeString(diffLine.Content))
}
@@ -186,336 +105,90 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) tem
}
type DiffFile struct {
Name string
OldName string
Index string // 40-byte SHA, Changed/New: new SHA; Deleted: old SHA
Addition, Deletion int
Type DiffFileType
IsCreated bool
IsDeleted bool
IsBin bool
IsRenamed bool
IsSubmodule bool
Sections []*DiffSection
IsIncomplete bool
*git.DiffFile
Sections []*DiffSection
}
func (diffFile *DiffFile) GetType() int {
return int(diffFile.Type)
}
func (diffFile *DiffFile) GetHighlightClass() string {
func (diffFile *DiffFile) HighlightClass() string {
return highlight.FileNameToHighlightClass(diffFile.Name)
}
type Diff struct {
TotalAddition, TotalDeletion int
Files []*DiffFile
IsIncomplete bool
*git.Diff
Files []*DiffFile
}
func (diff *Diff) NumFiles() int {
return len(diff.Files)
}
const DIFF_HEAD = "diff --git "
// TODO: move this function to gogits/git-module
func ParsePatch(maxLines, maxLineCharacteres, maxFiles 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
lineCount int
curFileLinesCount int
)
input := bufio.NewReader(reader)
isEOF := false
for !isEOF {
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, "--- ") || len(line) == 0 {
continue
}
curFileLinesCount++
lineCount++
// Diff data too large, we only show the first about maxlines lines
if curFileLinesCount >= maxLines || len(line) >= maxLineCharacteres {
curFile.IsIncomplete = true
}
switch {
case line[0] == ' ':
diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine}
leftLine++
rightLine++
curSection.Lines = append(curSection.Lines, diffLine)
continue
case line[0] == '@':
curSection = &DiffSection{}
curFile.Sections = append(curFile.Sections, curSection)
ss := strings.Split(line, "@@")
diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line}
curSection.Lines = append(curSection.Lines, diffLine)
// Parse line number.
ranges := strings.Split(ss[1][1:], " ")
leftLine, _ = com.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int()
if len(ranges) > 1 {
rightLine, _ = com.StrTo(strings.Split(ranges[1], ",")[0]).Int()
} else {
log.Warn("Parse line number failed: %v", line)
rightLine = leftLine
}
continue
case line[0] == '+':
curFile.Addition++
diff.TotalAddition++
diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine}
rightLine++
curSection.Lines = append(curSection.Lines, diffLine)
continue
case line[0] == '-':
curFile.Deletion++
diff.TotalDeletion++
diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine}
if leftLine > 0 {
leftLine++
}
curSection.Lines = append(curSection.Lines, diffLine)
case strings.HasPrefix(line, "Binary"):
curFile.IsBin = true
continue
}
// Get new file.
if strings.HasPrefix(line, DIFF_HEAD) {
middle := -1
// Note: In case file name is surrounded by double quotes (it happens only in git-shell).
// e.g. diff --git "a/xxx" "b/xxx"
hasQuote := line[len(DIFF_HEAD)] == '"'
if hasQuote {
middle = strings.Index(line, ` "b/`)
} else {
middle = strings.Index(line, " b/")
}
beg := len(DIFF_HEAD)
a := line[beg+2 : middle]
b := line[middle+3:]
if hasQuote {
a = string(git.UnescapeChars([]byte(a[1 : len(a)-1])))
b = string(git.UnescapeChars([]byte(b[1 : len(b)-1])))
}
curFile = &DiffFile{
Name: a,
Type: DIFF_FILE_CHANGE,
Sections: make([]*DiffSection, 0, 10),
}
diff.Files = append(diff.Files, curFile)
if len(diff.Files) >= maxFiles {
diff.IsIncomplete = true
io.Copy(ioutil.Discard, reader)
break
}
curFileLinesCount = 0
// Check file diff type and submodule.
CHECK_TYPE:
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(line, "new file"):
curFile.Type = DIFF_FILE_ADD
curFile.IsCreated = true
curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
case strings.HasPrefix(line, "deleted"):
curFile.Type = DIFF_FILE_DEL
curFile.IsDeleted = true
curFile.IsSubmodule = strings.HasSuffix(line, " 160000\n")
case strings.HasPrefix(line, "index"):
if curFile.IsDeleted {
curFile.Index = line[6:46]
} else if len(line) >= 88 {
curFile.Index = line[49:88]
} else {
curFile.Index = curFile.Name
}
break CHECK_TYPE
case strings.HasPrefix(line, "similarity index 100%"):
curFile.Type = DIFF_FILE_RENAME
curFile.IsRenamed = true
curFile.OldName = curFile.Name
curFile.Name = b
curFile.Index = b
break CHECK_TYPE
}
}
}
func NewDiff(gitDiff *git.Diff) *Diff {
diff := &Diff{
Diff: gitDiff,
Files: make([]*DiffFile, gitDiff.NumFiles()),
}
// FIXME: detect encoding while parsing.
var buf bytes.Buffer
for _, f := range diff.Files {
for i := range gitDiff.Files {
buf.Reset()
for _, sec := range f.Sections {
for _, l := range sec.Lines {
buf.WriteString(l.Content)
diff.Files[i] = &DiffFile{
DiffFile: gitDiff.Files[i],
Sections: make([]*DiffSection, gitDiff.Files[i].NumSections()),
}
for j := range gitDiff.Files[i].Sections {
diff.Files[i].Sections[j] = &DiffSection{
DiffSection: gitDiff.Files[i].Sections[j],
}
for k := range diff.Files[i].Sections[j].Lines {
buf.WriteString(diff.Files[i].Sections[j].Lines[k].Content)
buf.WriteString("\n")
}
}
charsetLabel, err := base.DetectEncoding(buf.Bytes())
charsetLabel, err := tool.DetectEncoding(buf.Bytes())
if charsetLabel != "UTF-8" && err == nil {
encoding, _ := charset.Lookup(charsetLabel)
if encoding != nil {
d := encoding.NewDecoder()
for _, sec := range f.Sections {
for _, l := range sec.Lines {
if c, _, err := transform.String(d, l.Content); err == nil {
l.Content = c
for j := range diff.Files[i].Sections {
for k := range diff.Files[i].Sections[j].Lines {
if c, _, err := transform.String(d, diff.Files[i].Sections[j].Lines[k].Content); err == nil {
diff.Files[i].Sections[j].Lines[k].Content = c
}
}
}
}
}
}
return diff, nil
return diff
}
func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*Diff, error) {
done := make(chan error)
var gitDiff *git.Diff
go func() {
gitDiff = git.ParsePatch(done, maxLines, maxLineCharacteres, maxFiles, reader)
}()
if err := <-done; err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err)
}
return NewDiff(gitDiff), nil
}
func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
gitRepo, err := git.OpenRepository(repoPath)
gitDiff, err := git.GetDiffRange(repoPath, beforeCommitID, afterCommitID, maxLines, maxLineCharacteres, maxFiles)
if err != nil {
return nil, err
return nil, fmt.Errorf("GetDiffRange: %v", err)
}
commit, err := gitRepo.GetCommit(afterCommitID)
if err != nil {
return nil, err
}
var cmd *exec.Cmd
// if "after" commit given
if len(beforeCommitID) == 0 {
// First commit of repository.
if commit.ParentCount() == 0 {
cmd = exec.Command("git", "show", "--full-index", afterCommitID)
} else {
c, _ := commit.Parent(0)
cmd = exec.Command("git", "diff", "--full-index", "-M", c.ID.String(), afterCommitID)
}
} else {
cmd = exec.Command("git", "diff", "--full-index", "-M", beforeCommitID, afterCommitID)
}
cmd.Dir = repoPath
cmd.Stderr = os.Stderr
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, fmt.Errorf("StdoutPipe: %v", err)
}
if err = cmd.Start(); err != nil {
return nil, fmt.Errorf("Start: %v", err)
}
pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cmd)
defer process.Remove(pid)
diff, err := ParsePatch(maxLines, maxLineCharacteres, maxFiles, 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
}
type RawDiffType string
const (
RAW_DIFF_NORMAL RawDiffType = "diff"
RAW_DIFF_PATCH RawDiffType = "patch"
)
// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
// TODO: move this function to gogits/git-module
func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
repo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository: %v", err)
}
commit, err := repo.GetCommit(commitID)
if err != nil {
return fmt.Errorf("GetCommit: %v", err)
}
var cmd *exec.Cmd
switch diffType {
case RAW_DIFF_NORMAL:
if commit.ParentCount() == 0 {
cmd = exec.Command("git", "show", commitID)
} else {
c, _ := commit.Parent(0)
cmd = exec.Command("git", "diff", "-M", c.ID.String(), commitID)
}
case RAW_DIFF_PATCH:
if commit.ParentCount() == 0 {
cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", "--root", commitID)
} else {
c, _ := commit.Parent(0)
query := fmt.Sprintf("%s...%s", commitID, c.ID.String())
cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", query)
}
default:
return fmt.Errorf("invalid diffType: %s", diffType)
}
stderr := new(bytes.Buffer)
cmd.Dir = repoPath
cmd.Stdout = writer
cmd.Stderr = stderr
if err = cmd.Run(); err != nil {
return fmt.Errorf("Run: %v - %s", err, stderr)
}
return nil
return NewDiff(gitDiff), nil
}
func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
gitDiff, err := git.GetDiffCommit(repoPath, commitID, maxLines, maxLineCharacteres, maxFiles)
if err != nil {
return nil, fmt.Errorf("GetDiffCommit: %v", err)
}
return NewDiff(gitDiff), nil
}

View File

@@ -1,9 +1,15 @@
// 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 (
dmp "github.com/sergi/go-diff/diffmatchpatch"
"html/template"
"testing"
"github.com/gogits/git-module"
dmp "github.com/sergi/go-diff/diffmatchpatch"
)
func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
@@ -12,24 +18,24 @@ func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
}
}
func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) {
func assertLineEqual(t *testing.T, d1 *git.DiffLine, d2 *git.DiffLine) {
if d1 != d2 {
t.Errorf("%v should be equal %v", d1, d2)
}
}
func TestDiffToHTML(t *testing.T) {
func Test_diffToHTML(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))
}, git.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))
}, git.DIFF_LINE_DEL))
}

View File

@@ -5,18 +5,19 @@
package models
import (
"errors"
"fmt"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
api "github.com/gogits/go-gogs-client"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/setting"
)
var (
@@ -89,7 +90,7 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
if issue.Poster == nil {
issue.Poster, err = getUserByID(e, issue.PosterID)
if err != nil {
if IsErrUserNotExist(err) {
if errors.IsUserNotExist(err) {
issue.PosterID = -1
issue.Poster = NewGhostUser()
} else {
@@ -230,7 +231,7 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
if issue.IsPull {
err = issue.PullRequest.LoadIssue()
if err != nil {
log.Error(4, "LoadIssue: %v", err)
log.Error(2, "LoadIssue: %v", err)
return
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -240,11 +241,17 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) {
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_LABEL_UPDATED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
}
@@ -334,7 +341,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
if issue.IsPull {
err = issue.PullRequest.LoadIssue()
if err != nil {
log.Error(4, "LoadIssue: %v", err)
log.Error(2, "LoadIssue: %v", err)
return
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -344,11 +351,17 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_LABEL_CLEARED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -377,7 +390,7 @@ func (i *Issue) GetAssignee() (err error) {
}
i.Assignee, err = GetUserByID(i.AssigneeID)
if IsErrUserNotExist(err) {
if errors.IsUserNotExist(err) {
return nil
}
return err
@@ -470,11 +483,22 @@ func (issue *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (e
apiPullRequest.Action = api.HOOK_ISSUE_REOPENED
}
err = PrepareWebhooks(repo, HOOK_EVENT_PULL_REQUEST, apiPullRequest)
} else {
apiIssues := &api.IssuesPayload{
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: doer.APIFormat(),
}
if isClosed {
apiIssues.Action = api.HOOK_ISSUE_CLOSED
} else {
apiIssues.Action = api.HOOK_ISSUE_REOPENED
}
err = PrepareWebhooks(repo, HOOK_EVENT_ISSUES, apiIssues)
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
} else {
go HookQueue.Add(repo.ID)
log.Error(2, "PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
}
return nil
@@ -490,22 +514,33 @@ func (issue *Issue) ChangeTitle(doer *User, title string) (err error) {
if issue.IsPull {
issue.PullRequest.Issue = issue
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
PullRequest: issue.PullRequest.APIFormat(),
Changes: &api.ChangesPayload{
Title: &api.ChangesFromPayload{
From: oldTitle,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Issue: issue.APIFormat(),
Changes: &api.ChangesPayload{
Title: &api.ChangesFromPayload{
From: oldTitle,
},
},
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -521,22 +556,33 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
if issue.IsPull {
issue.PullRequest.Issue = issue
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
PullRequest: issue.PullRequest.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
PullRequest: issue.PullRequest.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
} else {
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_EDITED,
Index: issue.Index,
Issue: issue.APIFormat(),
Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{
From: oldContent,
},
},
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
})
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
} else {
go HookQueue.Add(issue.RepoID)
log.Error(2, "PrepareWebhooks [is_pull: %v]: %v", issue.IsPull, err)
}
return nil
@@ -549,7 +595,7 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
}
issue.Assignee, err = GetUserByID(issue.AssigneeID)
if err != nil && !IsErrUserNotExist(err) {
if err != nil && !errors.IsUserNotExist(err) {
log.Error(4, "GetUserByID [assignee_id: %v]: %v", issue.AssigneeID, err)
return nil
}
@@ -570,11 +616,22 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
apiPullRequest.Action = api.HOOK_ISSUE_ASSIGNED
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_PULL_REQUEST, apiPullRequest)
} else {
apiIssues := &api.IssuesPayload{
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}
if isRemoveAssignee {
apiIssues.Action = api.HOOK_ISSUE_UNASSIGNED
} else {
apiIssues.Action = api.HOOK_ISSUE_ASSIGNED
}
err = PrepareWebhooks(issue.Repo, HOOK_EVENT_ISSUES, apiIssues)
}
if err != nil {
log.Error(4, "PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, isRemoveAssignee, err)
} else {
go HookQueue.Add(issue.RepoID)
}
return nil
@@ -611,7 +668,7 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
if opts.Issue.AssigneeID > 0 {
assignee, err := getUserByID(e, opts.Issue.AssigneeID)
if err != nil && !IsErrUserNotExist(err) {
if err != nil && !errors.IsUserNotExist(err) {
return fmt.Errorf("getUserByID: %v", err)
}
@@ -684,7 +741,7 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
return opts.Issue.loadAttributes(e)
}
// NewIssue creates new issue with labels for repository.
// NewIssue creates new issue with labels and attachments for repository.
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
@@ -715,10 +772,20 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
log.Error(4, "NotifyWatchers: %v", err)
log.Error(2, "NotifyWatchers: %v", err)
}
if err = issue.MailParticipants(); err != nil {
log.Error(4, "MailParticipants: %v", err)
log.Error(2, "MailParticipants: %v", err)
}
if err = PrepareWebhooks(repo, HOOK_EVENT_ISSUES, &api.IssuesPayload{
Action: api.HOOK_ISSUE_OPENED,
Index: issue.Index,
Issue: issue.APIFormat(),
Repository: repo.APIFormat(nil),
Sender: issue.Poster.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks: %v", err)
}
return nil
@@ -729,7 +796,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
func GetIssueByRef(ref string) (*Issue, error) {
n := strings.IndexByte(ref, byte('#'))
if n == -1 {
return nil, ErrMissingIssueNumber
return nil, errors.InvalidIssueReference{ref}
}
index, err := com.StrTo(ref[n+1:]).Int64()
@@ -760,7 +827,7 @@ func GetRawIssueByIndex(repoID, index int64) (*Issue, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrIssueNotExist{0, repoID, index}
return nil, errors.IssueNotExist{0, repoID, index}
}
return issue, nil
}
@@ -780,7 +847,7 @@ func getRawIssueByID(e Engine, id int64) (*Issue, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrIssueNotExist{id, 0, 0}
return nil, errors.IssueNotExist{id, 0, 0}
}
return issue, nil
}
@@ -828,7 +895,7 @@ func buildIssuesQuery(opts *IssuesOptions) *xorm.Session {
if len(opts.RepoIDs) == 0 {
return nil
}
sess.In("issue.repo_id", base.Int64sToStrings(opts.RepoIDs)).And("issue.is_closed=?", opts.IsClosed)
sess.In("issue.repo_id", opts.RepoIDs).And("issue.is_closed=?", opts.IsClosed)
} else {
sess.Where("issue.is_closed=?", opts.IsClosed)
}
@@ -863,7 +930,7 @@ func buildIssuesQuery(opts *IssuesOptions) *xorm.Session {
}
if len(opts.Labels) > 0 && opts.Labels != "0" {
labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
labelIDs := strings.Split(opts.Labels, ",")
if len(labelIDs) > 0 {
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").In("issue_label.label_id", labelIDs)
}
@@ -914,6 +981,23 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
return issues, nil
}
// GetParticipantsByIssueID returns all users who are participated in comments of an issue.
func GetParticipantsByIssueID(issueID int64) ([]*User, error) {
userIDs := make([]int64, 0, 5)
if err := x.Table("comment").Cols("poster_id").
Where("issue_id = ?", issueID).
Distinct("poster_id").
Find(&userIDs); err != nil {
return nil, fmt.Errorf("get poster IDs: %v", err)
}
if len(userIDs) == 0 {
return nil, nil
}
users := make([]*User, 0, len(userIDs))
return users, x.In("id", userIDs).Find(&users)
}
// .___ ____ ___
// | | ______ ________ __ ____ | | \______ ___________
// | |/ ___// ___/ | \_/ __ \| | / ___// __ \_ __ \
@@ -1129,7 +1213,7 @@ func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
sess := x.Where("issue.repo_id = ?", opts.RepoID).And("is_pull = ?", opts.IsPull)
if len(opts.Labels) > 0 && opts.Labels != "0" {
labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
labelIDs := tool.StringsToInt64s(strings.Split(opts.Labels, ","))
if len(labelIDs) > 0 {
sess.Join("INNER", "issue_label", "issue.id = issue_id").In("label_id", labelIDs)
}

View File

@@ -15,7 +15,7 @@ import (
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/pkg/tool"
)
var labelColorPattern = regexp.MustCompile("#([a-fA-F0-9]{6})")
@@ -138,7 +138,7 @@ func GetLabelOfRepoByID(repoID, labelID int64) (*Label, error) {
// it silently ignores label IDs that are not belong to the repository.
func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
labels := make([]*Label, 0, len(labelIDs))
return labels, x.Where("repo_id = ?", repoID).In("id", base.Int64sToStrings(labelIDs)).Asc("name").Find(&labels)
return labels, x.Where("repo_id = ?", repoID).In("id", tool.Int64sToStrings(labelIDs)).Asc("name").Find(&labels)
}
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
@@ -161,7 +161,7 @@ func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
}
labels := make([]*Label, 0, len(labelIDs))
return labels, e.Where("id > 0").In("id", base.Int64sToStrings(labelIDs)).Asc("name").Find(&labels)
return labels, e.Where("id > 0").In("id", tool.Int64sToStrings(labelIDs)).Asc("name").Find(&labels)
}
// GetLabelsByIssueID returns all labels that belong to given issue by ID.
@@ -240,7 +240,13 @@ func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if issue.IsClosed {
label.NumClosedIssues++
}
return updateLabel(e, label)
if err = updateLabel(e, label); err != nil {
return fmt.Errorf("updateLabel: %v", err)
}
issue.Labels = append(issue.Labels, label)
return nil
}
// NewIssueLabel creates a new issue-label relation.
@@ -313,7 +319,17 @@ func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
if issue.IsClosed {
label.NumClosedIssues--
}
return updateLabel(e, label)
if err = updateLabel(e, label); err != nil {
return fmt.Errorf("updateLabel: %v", err)
}
for i := range issue.Labels {
if issue.Labels[i].ID == label.ID {
issue.Labels = append(issue.Labels[:i], issue.Labels[i+1:]...)
break
}
}
return nil
}
// DeleteIssueLabel deletes issue-label relation.

View File

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

View File

@@ -7,7 +7,6 @@ package models
import (
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"net/smtp"
"net/textproto"
@@ -20,8 +19,9 @@ import (
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/auth/ldap"
"github.com/gogits/gogs/modules/auth/pam"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/auth/ldap"
"github.com/gogits/gogs/pkg/auth/pam"
)
type LoginType int
@@ -296,7 +296,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR
username, fn, sn, mail, isAdmin, succeed := source.Cfg.(*LDAPConfig).SearchEntry(login, password, source.Type == LOGIN_DLDAP)
if !succeed {
// User not in LDAP, do nothing
return nil, ErrUserNotExist{0, login}
return nil, errors.UserNotExist{0, login}
}
if !autoRegister {
@@ -394,7 +394,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
}
return nil
}
return ErrUnsupportedLoginType
return errors.New("Unsupported SMTP authentication method")
}
// LoginViaSMTP queries if login/password is valid against the SMTP,
@@ -404,9 +404,9 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
if len(cfg.AllowedDomains) > 0 {
idx := strings.Index(login, "@")
if idx == -1 {
return nil, ErrUserNotExist{0, login}
return nil, errors.UserNotExist{0, login}
} else if !com.IsSliceContainsStr(strings.Split(cfg.AllowedDomains, ","), login[idx+1:]) {
return nil, ErrUserNotExist{0, login}
return nil, errors.UserNotExist{0, login}
}
}
@@ -416,7 +416,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
} else if cfg.Auth == SMTP_LOGIN {
auth = &smtpLoginAuth{login, password}
} else {
return nil, errors.New("Unsupported SMTP auth type")
return nil, errors.New("Unsupported SMTP authentication type")
}
if err := SMTPAuth(auth, cfg); err != nil {
@@ -425,7 +425,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
tperr, ok := err.(*textproto.Error)
if (ok && tperr.Code == 535) ||
strings.Contains(err.Error(), "Username and Password not accepted") {
return nil, ErrUserNotExist{0, login}
return nil, errors.UserNotExist{0, login}
}
return nil, err
}
@@ -465,7 +465,7 @@ func LoginViaSMTP(user *User, login, password string, sourceID int64, cfg *SMTPC
func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
if err := pam.PAMAuth(cfg.ServiceName, login, password); err != nil {
if strings.Contains(err.Error(), "Authentication failure") {
return nil, ErrUserNotExist{0, login}
return nil, errors.UserNotExist{0, login}
}
return nil, err
}
@@ -489,7 +489,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon
func ExternalUserLogin(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) {
if !source.IsActived {
return nil, ErrLoginSourceNotActived
return nil, errors.LoginSourceNotActivated{source.ID}
}
switch source.Type {
@@ -501,7 +501,7 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
return LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
}
return nil, ErrUnsupportedLoginType
return nil, errors.InvalidLoginSourceType{source.Type}
}
// UserSignIn validates user name and password.
@@ -525,7 +525,7 @@ func UserSignIn(username, password string) (*User, error) {
return user, nil
}
return nil, ErrUserNotExist{user.ID, user.Name}
return nil, errors.UserNotExist{user.ID, user.Name}
default:
var source LoginSource
@@ -554,5 +554,5 @@ func UserSignIn(username, password string) (*User, error) {
log.Warn("Failed to login '%s' via '%s': %v", username, source.Name, err)
}
return nil, ErrUserNotExist{user.ID, user.Name}
return nil, errors.UserNotExist{user.ID, user.Name}
}

View File

@@ -13,7 +13,7 @@ import (
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/pkg/tool"
)
const _MIN_DB_VER = 10
@@ -42,7 +42,7 @@ func (m *migration) Migrate(x *xorm.Engine) error {
// The version table. Should have only one row with id==1
type Version struct {
ID int64 `xorm:"pk autoincr"`
ID int64
Version int64
}
@@ -60,6 +60,10 @@ var migrations = []Migration{
NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
// v14 -> v15:v0.9.147
NewMigration("generate and migrate Git hooks", generateAndMigrateGitHooks),
// v15 -> v16:v0.10.16
NewMigration("update repository sizes", updateRepositorySizes),
// v16 -> v17:v0.10.31
NewMigration("remove invalid protect branch whitelist", removeInvalidProtectBranchWhitelist),
}
// Migrate database to current version
@@ -101,7 +105,7 @@ Please save following instructions to somewhere and start working:
Once finished downloading,
1. Extract the archive and to upgrade steps as usual.
2. Run it once. To verify, you should see some migration traces.
2. Run it once. To verify, you should see some migration traces.
3. Once it starts web server successfully, stop it.
4. Now it's time to put back the release archive you originally intent to upgrade.
5. Enjoy!
@@ -155,10 +159,10 @@ func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
}
for _, org := range orgs {
if org.Rands, err = base.GetRandomString(10); err != nil {
if org.Rands, err = tool.GetRandomString(10); err != nil {
return err
}
if org.Salt, err = base.GetRandomString(10); err != nil {
if org.Salt, err = tool.GetRandomString(10); err != nil {
return err
}
if _, err = sess.Id(org.ID).Update(org); err != nil {

View File

@@ -15,7 +15,7 @@ import (
"github.com/go-xorm/xorm"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/setting"
)
func generateAndMigrateGitHooks(x *xorm.Engine) (err error) {

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

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

22
models/migrations/v17.go Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package migrations
import (
"fmt"
"github.com/go-xorm/xorm"
)
func removeInvalidProtectBranchWhitelist(x *xorm.Engine) error {
exist, err := x.IsTableExist("protect_branch_whitelist")
if err != nil {
return fmt.Errorf("IsTableExist: %v", err)
} else if !exist {
return nil
}
_, err = x.Exec("DELETE FROM protect_branch_whitelist WHERE protect_branch_id = 0")
return err
}

View File

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

View File

@@ -6,6 +6,7 @@ package models
import (
"fmt"
"net/url"
"strings"
"time"
@@ -16,9 +17,10 @@ import (
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/process"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/sync"
)
var MirrorQueue = sync.NewUniqueQueue(setting.Repository.MirrorQueueLength)
@@ -55,11 +57,11 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
case "repo_id":
m.Repo, err = GetRepositoryByID(m.RepoID)
if err != nil {
log.Error(3, "GetRepositoryByID[%d]: %v", m.ID, err)
log.Error(3, "GetRepositoryByID [%d]: %v", m.ID, err)
}
case "updated_unix":
m.Updated = time.Unix(m.UpdatedUnix, 0).Local()
case "next_updated_unix":
case "next_update_unix":
m.NextUpdate = time.Unix(m.NextUpdateUnix, 0).Local()
}
}
@@ -69,6 +71,46 @@ func (m *Mirror) ScheduleNextUpdate() {
m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
}
// findPasswordInMirrorAddress returns start (inclusive) and end index (exclusive)
// of password portion of credentials in given mirror address.
// It returns a boolean value to indicate whether password portion is found.
func findPasswordInMirrorAddress(addr string) (start int, end int, found bool) {
// Find end of credentials (start of path)
end = strings.LastIndex(addr, "@")
if end == -1 {
return -1, -1, false
}
// Find delimiter of credentials (end of username)
start = strings.Index(addr, "://")
if start == -1 {
return -1, -1, false
}
start += 3
delim := strings.Index(addr[start:], ":")
if delim == -1 {
return -1, -1, false
}
delim += 1
if start+delim >= end {
return -1, -1, false // No password portion presented
}
return start + delim, end, true
}
// unescapeMirrorCredentials returns mirror address with unescaped credentials.
func unescapeMirrorCredentials(addr string) string {
start, end, found := findPasswordInMirrorAddress(addr)
if !found {
return addr
}
password, _ := url.QueryUnescape(addr[start:end])
return addr[:start] + password + addr[end:]
}
func (m *Mirror) readAddress() {
if len(m.address) > 0 {
return
@@ -76,16 +118,16 @@ func (m *Mirror) readAddress() {
cfg, err := ini.Load(m.Repo.GitConfigPath())
if err != nil {
log.Error(4, "Load: %v", err)
log.Error(2, "Load: %v", err)
return
}
m.address = cfg.Section("remote \"origin\"").Key("url").Value()
}
// HandleCloneUserCredentials replaces user credentials from HTTP/HTTPS URL
// HandleMirrorCredentials replaces user credentials from HTTP/HTTPS URL
// with placeholder <credentials>.
// It will fail for any other forms of clone addresses.
func HandleCloneUserCredentials(url string, mosaics bool) string {
// It returns original string if protocol is not HTTP/HTTPS.
func HandleMirrorCredentials(url string, mosaics bool) string {
i := strings.Index(url, "@")
if i == -1 {
return url
@@ -103,21 +145,37 @@ func HandleCloneUserCredentials(url string, mosaics bool) string {
// Address returns mirror address from Git repository config without credentials.
func (m *Mirror) Address() string {
m.readAddress()
return HandleCloneUserCredentials(m.address, false)
return HandleMirrorCredentials(m.address, false)
}
// MosaicsAddress returns mirror address from Git repository config with credentials under mosaics.
func (m *Mirror) MosaicsAddress() string {
m.readAddress()
return HandleCloneUserCredentials(m.address, true)
return HandleMirrorCredentials(m.address, true)
}
// FullAddress returns mirror address from Git repository config.
func (m *Mirror) FullAddress() string {
// RawAddress returns raw mirror address directly from Git repository config.
func (m *Mirror) RawAddress() string {
m.readAddress()
return m.address
}
// FullAddress returns mirror address from Git repository config with unescaped credentials.
func (m *Mirror) FullAddress() string {
m.readAddress()
return unescapeMirrorCredentials(m.address)
}
// escapeCredentials returns mirror address with escaped credentials.
func escapeMirrorCredentials(addr string) string {
start, end, found := findPasswordInMirrorAddress(addr)
if !found {
return addr
}
return addr[:start] + url.QueryEscape(addr[start:end]) + addr[end:]
}
// SaveAddress writes new address to Git repository config.
func (m *Mirror) SaveAddress(addr string) error {
configPath := m.Repo.GitConfigPath()
@@ -126,7 +184,7 @@ func (m *Mirror) SaveAddress(addr string) error {
return fmt.Errorf("Load: %v", err)
}
cfg.Section("remote \"origin\"").Key("url").SetValue(addr)
cfg.Section("remote \"origin\"").Key("url").SetValue(escapeMirrorCredentials(addr))
return cfg.SaveToIndent(configPath, "\t")
}
@@ -139,12 +197,12 @@ func (m *Mirror) runSync() bool {
// Do a fast-fail testing against on repository URL to ensure it is accessible under
// good condition to prevent long blocking on URL resolution without syncing anything.
if !git.IsRepoURLAccessible(git.NetworkOptions{
URL: m.FullAddress(),
URL: m.RawAddress(),
Timeout: 10 * time.Second,
}) {
desc := fmt.Sprintf("Mirror repository URL is not accessible: %s", m.MosaicsAddress())
desc := fmt.Sprintf("Source URL of mirror repository '%s' is not accessible: %s", m.Repo.FullName(), m.MosaicsAddress())
if err := CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
@@ -157,20 +215,25 @@ func (m *Mirror) runSync() bool {
timeout, repoPath, fmt.Sprintf("Mirror.runSync: %s", repoPath),
"git", gitArgs...); err != nil {
desc := fmt.Sprintf("Fail to update mirror repository '%s': %s", repoPath, stderr)
log.Error(4, desc)
log.Error(2, desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
if err := m.Repo.UpdateSize(); err != nil {
log.Error(2, "UpdateSize [repo_id: %d]: %v", m.Repo.ID, err)
}
if m.Repo.HasWiki() {
if _, stderr, err := process.ExecDir(
timeout, wikiPath, fmt.Sprintf("Mirror.runSync: %s", wikiPath),
"git", "remote", "update", "--prune"); err != nil {
desc := fmt.Sprintf("Fail to update mirror wiki repository '%s': %s", wikiPath, stderr)
log.Error(4, desc)
log.Error(2, desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
log.Error(2, "CreateRepositoryNotice: %v", err)
}
return false
}
@@ -185,7 +248,7 @@ func getMirrorByRepoID(e Engine, repoID int64) (*Mirror, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrMirrorNotExist
return nil, errors.MirrorNotExist{repoID}
}
return m, nil
}
@@ -222,14 +285,14 @@ func MirrorUpdate() {
if err := x.Where("next_update_unix<=?", time.Now().Unix()).Iterate(new(Mirror), func(idx int, bean interface{}) error {
m := bean.(*Mirror)
if m.Repo == nil {
log.Error(4, "Disconnected mirror repository found: %d", m.ID)
log.Error(2, "Disconnected mirror repository found: %d", m.ID)
return nil
}
MirrorQueue.Add(m.RepoID)
return nil
}); err != nil {
log.Error(4, "MirrorUpdate: %v", err)
log.Error(2, "MirrorUpdate: %v", err)
}
}
@@ -243,7 +306,7 @@ func SyncMirrors() {
m, err := GetMirrorByRepoID(com.StrTo(repoID).MustInt64())
if err != nil {
log.Error(4, "GetMirrorByRepoID [%s]: %v", repoID, err)
log.Error(2, "GetMirrorByRepoID [%s]: %v", m.RepoID, err)
continue
}
@@ -253,9 +316,14 @@ func SyncMirrors() {
m.ScheduleNextUpdate()
if err = UpdateMirror(m); err != nil {
log.Error(4, "UpdateMirror [%s]: %v", repoID, err)
log.Error(2, "UpdateMirror [%s]: %v", m.RepoID, err)
continue
}
// Update repository last updated time
if _, err = x.Exec("UPDATE repository SET updated_unix = ? WHERE id = ?", time.Now().Unix(), m.RepoID); err != nil {
log.Error(2, "Update repository 'updated_unix' [%s]: %v", m.RepoID, err)
}
}
}

74
models/mirror_test.go Normal file
View File

@@ -0,0 +1,74 @@
// Copyright 2017 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_findPasswordInMirrorAddress(t *testing.T) {
Convey("Find password portion in mirror address", t, func() {
testCases := []struct {
addr string
start, end int
found bool
password string
}{
{"http://localhost:3000/user/repo.git", -1, -1, false, ""},
{"http://user@localhost:3000/user/repo.git", -1, -1, false, ""},
{"http://user:@localhost:3000/user/repo.git", -1, -1, false, ""},
{"http://user:password@localhost:3000/user/repo.git", 12, 20, true, "password"},
{"http://username:my%3Asecure%3Bpassword@localhost:3000/user/repo.git", 16, 38, true, "my%3Asecure%3Bpassword"},
{"http://username:my%40secure%23password@localhost:3000/user/repo.git", 16, 38, true, "my%40secure%23password"},
{"http://username:@@localhost:3000/user/repo.git", 16, 17, true, "@"},
}
for _, tc := range testCases {
start, end, found := findPasswordInMirrorAddress(tc.addr)
So(start, ShouldEqual, tc.start)
So(end, ShouldEqual, tc.end)
So(found, ShouldEqual, tc.found)
if found {
So(tc.addr[start:end], ShouldEqual, tc.password)
}
}
})
}
func Test_unescapeMirrorCredentials(t *testing.T) {
Convey("Escape credentials in mirror address", t, func() {
testCases := []string{
"http://localhost:3000/user/repo.git", "http://localhost:3000/user/repo.git",
"http://user@localhost:3000/user/repo.git", "http://user@localhost:3000/user/repo.git",
"http://user:@localhost:3000/user/repo.git", "http://user:@localhost:3000/user/repo.git",
"http://user:password@localhost:3000/user/repo.git", "http://user:password@localhost:3000/user/repo.git",
"http://user:my%3Asecure%3Bpassword@localhost:3000/user/repo.git", "http://user:my:secure;password@localhost:3000/user/repo.git",
"http://user:my%40secure%23password@localhost:3000/user/repo.git", "http://user:my@secure#password@localhost:3000/user/repo.git",
}
for i := 0; i < len(testCases); i += 2 {
So(unescapeMirrorCredentials(testCases[i]), ShouldEqual, testCases[i+1])
}
})
}
func Test_escapeMirrorCredentials(t *testing.T) {
Convey("Escape credentials in mirror address", t, func() {
testCases := []string{
"http://localhost:3000/user/repo.git", "http://localhost:3000/user/repo.git",
"http://user@localhost:3000/user/repo.git", "http://user@localhost:3000/user/repo.git",
"http://user:@localhost:3000/user/repo.git", "http://user:@localhost:3000/user/repo.git",
"http://user:password@localhost:3000/user/repo.git", "http://user:password@localhost:3000/user/repo.git",
"http://user:my:secure;password@localhost:3000/user/repo.git", "http://user:my%3Asecure%3Bpassword@localhost:3000/user/repo.git",
"http://user:my@secure#password@localhost:3000/user/repo.git", "http://user:my%40secure%23password@localhost:3000/user/repo.git",
}
for i := 0; i < len(testCases); i += 2 {
So(escapeMirrorCredentials(testCases[i]), ShouldEqual, testCases[i+1])
}
})
}

View File

@@ -5,7 +5,9 @@
package models
import (
"bufio"
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/url"
@@ -13,14 +15,16 @@ import (
"path"
"strings"
"github.com/Unknwon/com"
_ "github.com/denisenkom/go-mssqldb"
_ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/lib/pq"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/models/migrations"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/setting"
)
// Engine represents a xorm engine or session.
@@ -189,18 +193,22 @@ func SetEngine() (err error) {
// WARNING: for serv command, MUST remove the output to os.stdout,
// so use log file to instead print to stdout.
logPath := path.Join(setting.LogRootPath, "xorm.log")
os.MkdirAll(path.Dir(logPath), os.ModePerm)
f, err := os.Create(logPath)
sec := setting.Cfg.Section("log.xorm")
logger, err := log.NewFileWriter(path.Join(setting.LogRootPath, "xorm.log"),
log.FileRotationConfig{
Rotate: sec.Key("ROTATE").MustBool(true),
Daily: sec.Key("ROTATE_DAILY").MustBool(true),
MaxSize: sec.Key("MAX_SIZE").MustInt64(100) * 1024 * 1024,
MaxDays: sec.Key("MAX_DAYS").MustInt64(3),
})
if err != nil {
return fmt.Errorf("Fail to create xorm.log: %v", err)
return fmt.Errorf("Fail to create 'xorm.log': %v", err)
}
if setting.ProdMode {
x.SetLogger(xorm.NewSimpleLogger3(f, xorm.DEFAULT_LOG_PREFIX, xorm.DEFAULT_LOG_FLAG, core.LOG_WARNING))
x.SetLogger(xorm.NewSimpleLogger3(logger, xorm.DEFAULT_LOG_PREFIX, xorm.DEFAULT_LOG_FLAG, core.LOG_WARNING))
} else {
x.SetLogger(xorm.NewSimpleLogger(f))
x.SetLogger(xorm.NewSimpleLogger(logger))
}
x.ShowSQL(true)
return nil
@@ -262,7 +270,89 @@ func Ping() error {
return x.Ping()
}
// DumpDatabase dumps all data from database to file system.
func DumpDatabase(filePath string) error {
return x.DumpAllToFile(filePath)
// The version table. Should have only one row with id==1
type Version struct {
ID int64
Version int64
}
// DumpDatabase dumps all data from database to file system in JSON format.
func DumpDatabase(dirPath string) (err error) {
os.MkdirAll(dirPath, os.ModePerm)
// Purposely create a local variable to not modify global variable
tables := append(tables, new(Version))
for _, table := range tables {
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
tableFile := path.Join(dirPath, tableName+".json")
f, err := os.Create(tableFile)
if err != nil {
return fmt.Errorf("fail to create JSON file: %v", err)
}
if err = x.Asc("id").Iterate(table, func(idx int, bean interface{}) (err error) {
enc := json.NewEncoder(f)
return enc.Encode(bean)
}); err != nil {
f.Close()
return fmt.Errorf("fail to dump table '%s': %v", tableName, err)
}
f.Close()
}
return nil
}
// ImportDatabase imports data from backup archive.
func ImportDatabase(dirPath string) (err error) {
// Purposely create a local variable to not modify global variable
tables := append(tables, new(Version))
for _, table := range tables {
tableName := strings.TrimPrefix(fmt.Sprintf("%T", table), "*models.")
tableFile := path.Join(dirPath, tableName+".json")
if !com.IsExist(tableFile) {
continue
}
if err = x.DropTables(table); err != nil {
return fmt.Errorf("fail to drop table '%s': %v", tableName, err)
} else if err = x.Sync2(table); err != nil {
return fmt.Errorf("fail to sync table '%s': %v", tableName, err)
}
f, err := os.Open(tableFile)
if err != nil {
return fmt.Errorf("fail to open JSON file: %v", err)
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
switch bean := table.(type) {
case *LoginSource:
meta := make(map[string]interface{})
if err = json.Unmarshal(scanner.Bytes(), &meta); err != nil {
return fmt.Errorf("fail to unmarshal to map: %v", err)
}
tp := LoginType(com.StrTo(com.ToStr(meta["Type"])).MustInt64())
switch tp {
case LOGIN_LDAP, LOGIN_DLDAP:
bean.Cfg = new(LDAPConfig)
case LOGIN_SMTP:
bean.Cfg = new(SMTPConfig)
case LOGIN_PAM:
bean.Cfg = new(PAMConfig)
default:
return fmt.Errorf("unrecognized login source type:: %v", tp)
}
table = bean
}
if err = json.Unmarshal(scanner.Bytes(), table); err != nil {
return fmt.Errorf("fail to unmarshal to struct: %v", err)
}
if _, err = x.Insert(table); err != nil {
return fmt.Errorf("fail to insert strcut: %v", err)
}
}
}
return nil
}

View File

@@ -20,8 +20,8 @@ var (
)
// IsOwnedBy returns true if given user is in the owner team.
func (org *User) IsOwnedBy(uid int64) bool {
return IsOrganizationOwner(org.ID, uid)
func (org *User) IsOwnedBy(userID int64) bool {
return IsOrganizationOwner(org.ID, userID)
}
// IsOrgMember returns true if given user is member of organization.
@@ -246,8 +246,8 @@ type OrgUser struct {
}
// IsOrganizationOwner returns true if given user is in the owner team.
func IsOrganizationOwner(orgId, uid int64) bool {
has, _ := x.Where("is_owner=?", true).And("uid=?", uid).And("org_id=?", orgId).Get(new(OrgUser))
func IsOrganizationOwner(orgID, userID int64) bool {
has, _ := x.Where("is_owner = ?", true).And("uid = ?", userID).And("org_id = ?", orgID).Get(new(OrgUser))
return has
}
@@ -303,16 +303,15 @@ func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
}
// GetOrgUsersByUserID returns all organization-user relations by user ID.
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
ous := make([]*OrgUser, 0, 10)
sess := x.Where("uid=?", uid)
if !all {
// Only show public organizations
sess.And("is_public=?", true)
// GetOrgIDsByUserID returns a list of organization IDs that user belongs to.
// The showPrivate indicates whether to include private memberships.
func GetOrgIDsByUserID(userID int64, showPrivate bool) ([]int64, error) {
orgIDs := make([]int64, 0, 5)
sess := x.Table("org_user").Where("uid = ?", userID)
if !showPrivate {
sess.And("is_public = ?", true)
}
err := sess.Find(&ous)
return ous, err
return orgIDs, sess.Distinct("org_id").Find(&orgIDs)
}
func getOrgUsersByOrgID(e Engine, orgID int64) ([]*OrgUser, error) {

View File

@@ -31,7 +31,7 @@ type Team struct {
func (t *Team) AfterSet(colName string, _ xorm.Cell) {
switch colName {
case "num_repos":
// LEGACY [0.11]: this is backward compatibility bug fix for https://github.com/gogits/gogs/issues/3671
// LEGACY [1.0]: this is backward compatibility bug fix for https://github.com/gogits/gogs/issues/3671
if t.NumRepos < 0 {
t.NumRepos = 0
}
@@ -424,7 +424,7 @@ func IsTeamMember(orgID, teamID, uid int64) bool {
func getTeamMembers(e Engine, teamID int64) (_ []*User, err error) {
teamUsers := make([]*TeamUser, 0, 10)
if err = e.Sql("SELECT `id`, `org_id`, `team_id`, `uid` FROM `team_user` WHERE team_id=?", teamID).
if err = e.Sql("SELECT `id`, `org_id`, `team_id`, `uid` FROM `team_user` WHERE team_id = ?", teamID).
Find(&teamUsers); err != nil {
return nil, fmt.Errorf("get team-users: %v", err)
}

View File

@@ -18,9 +18,10 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/process"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/sync"
)
var PullRequestQueue = sync.NewUniqueQueue(setting.Repository.PullRequestQueueLength)
@@ -87,7 +88,7 @@ func (pr *PullRequest) AfterSet(colName string, _ xorm.Cell) {
func (pr *PullRequest) loadAttributes(e Engine) (err error) {
if pr.HeadRepo == nil {
pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID)
if err != nil && !IsErrRepoNotExist(err) {
if err != nil && !errors.IsRepoNotExist(err) {
return fmt.Errorf("getRepositoryByID.(HeadRepo) [%d]: %v", pr.HeadRepoID, err)
}
}
@@ -101,7 +102,7 @@ func (pr *PullRequest) loadAttributes(e Engine) (err error) {
if pr.HasMerged && pr.Merger == nil {
pr.Merger, err = getUserByID(e, pr.MergerID)
if IsErrUserNotExist(err) {
if errors.IsUserNotExist(err) {
pr.MergerID = -1
pr.Merger = NewGhostUser()
} else if err != nil {
@@ -277,12 +278,12 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
}
if err = MergePullRequestAction(doer, pr.Issue.Repo, pr.Issue); err != nil {
log.Error(4, "MergePullRequestAction [%d]: %v", pr.ID, err)
log.Error(2, "MergePullRequestAction [%d]: %v", pr.ID, err)
}
// Reload pull request information.
if err = pr.LoadAttributes(); err != nil {
log.Error(4, "LoadAttributes: %v", err)
log.Error(2, "LoadAttributes: %v", err)
return nil
}
if err = PrepareWebhooks(pr.Issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -292,13 +293,13 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
Repository: pr.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(4, "PrepareWebhooks: %v", err)
log.Error(2, "PrepareWebhooks: %v", err)
return nil
}
l, err := headGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
if err != nil {
log.Error(4, "CommitsBetweenIDs: %v", err)
log.Error(2, "CommitsBetweenIDs: %v", err)
return nil
}
@@ -308,35 +309,34 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
// to avoid strange diff commits produced.
mergeCommit, err := baseGitRepo.GetBranchCommit(pr.BaseBranch)
if err != nil {
log.Error(4, "GetBranchCommit: %v", err)
log.Error(2, "GetBranchCommit: %v", err)
return nil
}
l.PushFront(mergeCommit)
commits, err := ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.RepoPath(), pr.BaseRepo.HTMLURL())
if err != nil {
log.Error(2, "ToApiPayloadCommits: %v", err)
return nil
}
p := &api.PushPayload{
Ref: git.BRANCH_PREFIX + pr.BaseBranch,
Before: pr.MergeBase,
After: pr.MergedCommitID,
CompareURL: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.HTMLURL()),
Commits: commits,
Repo: pr.BaseRepo.APIFormat(nil),
Pusher: pr.HeadRepo.MustOwner().APIFormat(),
Sender: doer.APIFormat(),
}
if err = PrepareWebhooks(pr.BaseRepo, HOOK_EVENT_PUSH, p); err != nil {
return fmt.Errorf("PrepareWebhooks: %v", err)
log.Error(2, "PrepareWebhooks: %v", err)
return nil
}
return nil
}
// patchConflicts is a list of conflit description from Git.
var patchConflicts = []string{
"patch does not apply",
"already exists in working directory",
"unrecognized input",
"error:",
}
// testPatch checks if patch can be merged to base repository without conflit.
// FIXME: make a mechanism to clean up stable local copies.
func (pr *PullRequest) testPatch() (err error) {
@@ -372,16 +372,9 @@ func (pr *PullRequest) testPatch() (err error) {
fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
"git", "apply", "--check", patchPath)
if err != nil {
for i := range patchConflicts {
if strings.Contains(stderr, patchConflicts[i]) {
log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
}
}
return fmt.Errorf("git apply --check: %v - %s", err, stderr)
log.Trace("PullRequest[%d].testPatch (apply): has conflit\n%s", pr.ID, stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
}
return nil
}
@@ -437,9 +430,10 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
log.Error(4, "NotifyWatchers: %v", err)
} else if err = pull.MailParticipants(); err != nil {
log.Error(4, "MailParticipants: %v", err)
log.Error(2, "NotifyWatchers: %v", err)
}
if err = pull.MailParticipants(); err != nil {
log.Error(2, "MailParticipants: %v", err)
}
pr.Issue = pull
@@ -451,9 +445,8 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
Repository: repo.APIFormat(nil),
Sender: pull.Poster.APIFormat(),
}); err != nil {
log.Error(4, "PrepareWebhooks: %v", err)
log.Error(2, "PrepareWebhooks: %v", err)
}
go HookQueue.Add(repo.ID)
return nil
}
@@ -614,7 +607,7 @@ func (pr *PullRequest) AddToTaskQueue() {
go PullRequestQueue.AddFunc(pr.ID, func() {
pr.Status = PULL_REQUEST_STATUS_CHECKING
if err := pr.UpdateCols("status"); err != nil {
log.Error(5, "AddToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err)
log.Error(3, "AddToTaskQueue.UpdateCols[%d].(add to queue): %v", pr.ID, err)
}
})
}
@@ -627,16 +620,18 @@ func (prs PullRequestList) loadAttributes(e Engine) (err error) {
}
// Load issues
issueIDs := make([]int64, 0, len(prs))
set := make(map[int64]*Issue)
for i := range prs {
issueIDs = append(issueIDs, prs[i].IssueID)
set[prs[i].IssueID] = nil
}
issueIDs := make([]int64, 0, len(prs))
for issueID := range set {
issueIDs = append(issueIDs, issueID)
}
issues := make([]*Issue, 0, len(issueIDs))
if err = e.Where("id > 0").In("id", issueIDs).Find(&issues); err != nil {
return fmt.Errorf("find issues: %v", err)
}
set := make(map[int64]*Issue)
for i := range issues {
set[issues[i].ID] = issues[i]
}
@@ -679,20 +674,20 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
log.Trace("AddTestPullRequestTask [head_repo_id: %d, head_branch: %s]: finding pull requests", repoID, branch)
prs, err := GetUnmergedPullRequestsByHeadInfo(repoID, branch)
if err != nil {
log.Error(4, "Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
log.Error(2, "Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
return
}
if isSync {
if err = PullRequestList(prs).LoadAttributes(); err != nil {
log.Error(4, "PullRequestList.LoadAttributes: %v", err)
log.Error(2, "PullRequestList.LoadAttributes: %v", err)
}
if err == nil {
for _, pr := range prs {
pr.Issue.PullRequest = pr
if err = pr.Issue.LoadAttributes(); err != nil {
log.Error(4, "LoadAttributes: %v", err)
log.Error(2, "LoadAttributes: %v", err)
continue
}
if err = PrepareWebhooks(pr.Issue.Repo, HOOK_EVENT_PULL_REQUEST, &api.PullRequestPayload{
@@ -702,10 +697,9 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
Repository: pr.Issue.Repo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(4, "PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
log.Error(2, "PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
continue
}
go HookQueue.Add(pr.Issue.Repo.ID)
}
}
}
@@ -715,7 +709,7 @@ func AddTestPullRequestTask(doer *User, repoID int64, branch string, isSync bool
log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch)
prs, err = GetUnmergedPullRequestsByBaseInfo(repoID, branch)
if err != nil {
log.Error(4, "Find pull requests [base_repo_id: %d, base_branch: %s]: %v", repoID, branch, err)
log.Error(2, "Find pull requests [base_repo_id: %d, base_branch: %s]: %v", repoID, branch, err)
return
}
for _, pr := range prs {

View File

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

View File

@@ -6,15 +6,12 @@ package models
import (
"bytes"
"errors"
"fmt"
"html/template"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
@@ -29,23 +26,16 @@ import (
git "github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/bindata"
"github.com/gogits/gogs/pkg/markup"
"github.com/gogits/gogs/pkg/process"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/sync"
)
var repoWorkingPool = sync.NewExclusivePool()
var (
ErrRepoFileNotExist = errors.New("Repository file does not exist")
ErrRepoFileNotLoaded = errors.New("Repository file not loaded")
ErrMirrorNotExist = errors.New("Mirror does not exist")
ErrInvalidReference = errors.New("Invalid reference specified")
ErrNameEmpty = errors.New("Name is empty")
)
var (
Gitignores, Licenses, Readmes, LabelTemplates []string
@@ -123,6 +113,7 @@ func NewRepoContext() {
}
git.HookDir = "custom_hooks"
git.HookSampleDir = "hooks"
git.DefaultCommitsPageSize = setting.UI.User.CommitsPagingNum
// Git requires setting user.name and user.email in order to commit changes.
for configKey, defaultValue := range map[string]string{"user.name": "Gogs", "user.email": "gogs@fake.local"} {
@@ -148,7 +139,7 @@ func NewRepoContext() {
RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(setting.AppDataPath, "tmp"))
}
// Repository represents a git repository.
// Repository contains information of a repository.
type Repository struct {
ID int64 `xorm:"pk autoincr"`
OwnerID int64 `xorm:"UNIQUE(s)"`
@@ -158,6 +149,7 @@ type Repository struct {
Description string
Website string
DefaultBranch string
Size int64 `xorm:"NOT NULL DEFAULT 0"`
NumWatches int
NumStars int
@@ -181,9 +173,11 @@ type Repository struct {
// Advanced settings
EnableWiki bool `xorm:"NOT NULL DEFAULT true"`
AllowPublicWiki bool
EnableExternalWiki bool
ExternalWikiURL string
EnableIssues bool `xorm:"NOT NULL DEFAULT true"`
AllowPublicIssues bool
EnableExternalTracker bool
ExternalTrackerURL string
ExternalTrackerFormat string
@@ -225,7 +219,7 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
case "external_tracker_style":
if len(repo.ExternalTrackerStyle) == 0 {
repo.ExternalTrackerStyle = markdown.ISSUE_NAME_STYLE_NUMERIC
repo.ExternalTrackerStyle = markup.ISSUE_NAME_STYLE_NUMERIC
}
case "created_unix":
repo.Created = time.Unix(repo.CreatedUnix, 0).Local()
@@ -234,10 +228,48 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
}
}
// MustOwner always returns a valid *User object to avoid
// conceptually impossible error handling.
// It creates a fake object that contains error deftail
// when error occurs.
func (repo *Repository) loadAttributes(e Engine) (err error) {
if repo.Owner == nil {
repo.Owner, err = getUserByID(e, repo.OwnerID)
if err != nil {
return fmt.Errorf("getUserByID [%d]: %v", repo.OwnerID, err)
}
}
if repo.IsFork && repo.BaseRepo == nil {
repo.BaseRepo, err = getRepositoryByID(e, repo.ForkID)
if err != nil {
if errors.IsRepoNotExist(err) {
repo.IsFork = false
repo.ForkID = 0
} else {
return fmt.Errorf("getRepositoryByID [%d]: %v", repo.ForkID, err)
}
}
}
return nil
}
func (repo *Repository) LoadAttributes() error {
return repo.loadAttributes(x)
}
// IsPartialPublic returns true if repository is public or allow public access to wiki or issues.
func (repo *Repository) IsPartialPublic() bool {
return !repo.IsPrivate || repo.AllowPublicWiki || repo.AllowPublicIssues
}
func (repo *Repository) CanGuestViewWiki() bool {
return repo.EnableWiki && !repo.EnableExternalWiki && repo.AllowPublicWiki
}
func (repo *Repository) CanGuestViewIssues() bool {
return repo.EnableIssues && !repo.EnableExternalTracker && repo.AllowPublicIssues
}
// MustOwner always returns a valid *User object to avoid conceptually impossible error handling.
// It creates a fake object that contains error deftail when error occurs.
func (repo *Repository) MustOwner() *User {
return repo.mustOwner(x)
}
@@ -300,6 +332,19 @@ func (repo *Repository) mustOwner(e Engine) *User {
return repo.Owner
}
func (repo *Repository) UpdateSize() error {
countObject, err := git.GetRepoSize(repo.RepoPath())
if err != nil {
return fmt.Errorf("GetRepoSize: %v", err)
}
repo.Size = countObject.Size + countObject.SizePack
if _, err = x.Id(repo.ID).Cols("size").Update(repo); err != nil {
return fmt.Errorf("update size: %v", err)
}
return nil
}
// ComposeMetas composes a map of metas for rendering external issue tracker URL.
func (repo *Repository) ComposeMetas() map[string]string {
if !repo.EnableExternalTracker {
@@ -311,10 +356,10 @@ func (repo *Repository) ComposeMetas() map[string]string {
"repo": repo.Name,
}
switch repo.ExternalTrackerStyle {
case markdown.ISSUE_NAME_STYLE_ALPHANUMERIC:
repo.ExternalMetas["style"] = markdown.ISSUE_NAME_STYLE_ALPHANUMERIC
case markup.ISSUE_NAME_STYLE_ALPHANUMERIC:
repo.ExternalMetas["style"] = markup.ISSUE_NAME_STYLE_ALPHANUMERIC
default:
repo.ExternalMetas["style"] = markdown.ISSUE_NAME_STYLE_NUMERIC
repo.ExternalMetas["style"] = markup.ISSUE_NAME_STYLE_NUMERIC
}
}
@@ -396,15 +441,6 @@ func (repo *Repository) GetMirror() (err error) {
return err
}
func (repo *Repository) GetBaseRepo() (err error) {
if !repo.IsFork {
return nil
}
repo.BaseRepo, err = GetRepositoryByID(repo.ForkID)
return err
}
func (repo *Repository) repoPath(e Engine) string {
return RepoPath(repo.mustOwner(e).Name, repo.Name)
}
@@ -445,7 +481,7 @@ func (repo *Repository) CanBeForked() bool {
// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
func (repo *Repository) CanEnablePulls() bool {
return !repo.IsMirror
return !repo.IsMirror && !repo.IsBare
}
// AllowPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
@@ -468,18 +504,6 @@ func (repo *Repository) NextIssueIndex() int64 {
return int64(repo.NumIssues+repo.NumPulls) + 1
}
var (
DescPattern = regexp.MustCompile(`https?://\S+`)
)
// DescriptionHtml does special handles to description and return HTML string.
func (repo *Repository) DescriptionHtml() template.HTML {
sanitize := func(s string) string {
return fmt.Sprintf(`<a href="%[1]s" target="_blank">%[1]s</a>`, s)
}
return template.HTML(DescPattern.ReplaceAllStringFunc(markdown.Sanitizer.Sanitize(repo.Description), sanitize))
}
func (repo *Repository) LocalCopyPath() string {
return path.Join(setting.AppDataPath, "tmp/local-repo", com.ToStr(repo.ID))
}
@@ -628,8 +652,8 @@ func wikiRemoteURL(remote string) string {
}
// MigrateRepository migrates a existing repository from other project hosting.
func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
repo, err := CreateRepository(u, CreateRepoOptions{
func MigrateRepository(doer, owner *User, opts MigrateRepoOptions) (*Repository, error) {
repo, err := CreateRepository(doer, owner, CreateRepoOptions{
Name: opts.Name,
Description: opts.Description,
IsPrivate: opts.IsPrivate,
@@ -639,11 +663,11 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
return nil, err
}
repoPath := RepoPath(u.Name, opts.Name)
wikiPath := WikiPath(u.Name, opts.Name)
repoPath := RepoPath(owner.Name, opts.Name)
wikiPath := WikiPath(owner.Name, opts.Name)
if u.IsOrganization() {
t, err := u.GetOwnerTeam()
if owner.IsOrganization() {
t, err := owner.GetOwnerTeam()
if err != nil {
return nil, err
}
@@ -699,6 +723,10 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
if headBranch != nil {
repo.DefaultBranch = headBranch.Name
}
if err = repo.UpdateSize(); err != nil {
log.Error(2, "UpdateSize [repo_id: %d]: %v", repo.ID, err)
}
}
if opts.IsMirror {
@@ -882,8 +910,8 @@ func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRep
return nil
}
// InitRepository initializes README and .gitignore if needed.
func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts CreateRepoOptions) (err error) {
// initRepository performs initial commit with chosen setup files on behave of doer.
func initRepository(e Engine, repoPath string, doer *User, repo *Repository, opts CreateRepoOptions) (err error) {
// Somehow the directory could exist.
if com.IsExist(repoPath) {
return fmt.Errorf("initRepository: path already exists: %s", repoPath)
@@ -908,7 +936,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
}
// Apply changes and commit.
if err = initRepoCommit(tmpDir, u.NewGitSig()); err != nil {
if err = initRepoCommit(tmpDir, doer.NewGitSig()); err != nil {
return fmt.Errorf("initRepoCommit: %v", err)
}
}
@@ -941,32 +969,32 @@ func IsUsableRepoName(name string) error {
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
}
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err error) {
if err = IsUsableRepoName(repo.Name); err != nil {
return err
}
has, err := isRepositoryExist(e, u, repo.Name)
has, err := isRepositoryExist(e, owner, repo.Name)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{u.Name, repo.Name}
return ErrRepoAlreadyExist{owner.Name, repo.Name}
}
if _, err = e.Insert(repo); err != nil {
return err
}
u.NumRepos++
owner.NumRepos++
// Remember visibility preference.
u.LastRepoVisibility = repo.IsPrivate
if err = updateUser(e, u); err != nil {
owner.LastRepoVisibility = repo.IsPrivate
if err = updateUser(e, owner); err != nil {
return fmt.Errorf("updateUser: %v", err)
}
// Give access to all members in owner team.
if u.IsOrganization() {
t, err := u.getOwnerTeam(e)
if owner.IsOrganization() {
t, err := owner.getOwnerTeam(e)
if err != nil {
return fmt.Errorf("getOwnerTeam: %v", err)
} else if err = t.addRepository(e, repo); err != nil {
@@ -979,9 +1007,9 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
}
}
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
if err = watchRepo(e, owner.ID, repo.ID, true); err != nil {
return fmt.Errorf("watchRepo: %v", err)
} else if err = newRepoAction(e, u, repo); err != nil {
} else if err = newRepoAction(e, doer, owner, repo); err != nil {
return fmt.Errorf("newRepoAction: %v", err)
}
@@ -989,14 +1017,14 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
}
// CreateRepository creates a repository for given user or organization.
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
if !u.CanCreateRepo() {
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) {
if !owner.CanCreateRepo() {
return nil, ErrReachLimitOfRepo{owner.MaxRepoCreation}
}
repo := &Repository{
OwnerID: u.ID,
Owner: u,
OwnerID: owner.ID,
Owner: owner,
Name: opts.Name,
LowerName: strings.ToLower(opts.Name),
Description: opts.Description,
@@ -1012,14 +1040,14 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
return nil, err
}
if err = createRepository(sess, u, repo); err != nil {
if err = createRepository(sess, doer, owner, repo); err != nil {
return nil, err
}
// No need for init mirror.
if !opts.IsMirror {
repoPath := RepoPath(u.Name, repo.Name)
if err = initRepository(sess, repoPath, u, repo, opts); err != nil {
repoPath := RepoPath(owner.Name, repo.Name)
if err = initRepository(sess, repoPath, doer, repo, opts); err != nil {
RemoveAllWithNotice("Delete repository for initialization failure", repoPath)
return nil, fmt.Errorf("initRepository: %v", err)
}
@@ -1028,7 +1056,7 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
repoPath, fmt.Sprintf("CreateRepository 'git update-server-info': %s", repoPath),
"git", "update-server-info")
if err != nil {
return nil, errors.New("CreateRepository 'git update-server-info': " + stderr)
return nil, fmt.Errorf("CreateRepository 'git update-server-info': %s", stderr)
}
}
@@ -1359,7 +1387,7 @@ func DeleteRepository(uid, repoID int64) error {
if err != nil {
return err
} else if !has {
return ErrRepoNotExist{repoID, uid, ""}
return errors.RepoNotExist{repoID, uid, ""}
}
// In case is a organization.
@@ -1474,7 +1502,7 @@ func DeleteRepository(uid, repoID int64) error {
func GetRepositoryByRef(ref string) (*Repository, error) {
n := strings.IndexByte(ref, byte('/'))
if n < 2 {
return nil, ErrInvalidReference
return nil, errors.InvalidRepoReference{ref}
}
userName, repoName := ref[:n], ref[n+1:]
@@ -1496,9 +1524,9 @@ func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{0, ownerID, name}
return nil, errors.RepoNotExist{0, ownerID, name}
}
return repo, err
return repo, repo.LoadAttributes()
}
func getRepositoryByID(e Engine, id int64) (*Repository, error) {
@@ -1507,9 +1535,9 @@ func getRepositoryByID(e Engine, id int64) (*Repository, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{id, 0, ""}
return nil, errors.RepoNotExist{id, 0, ""}
}
return repo, nil
return repo, repo.loadAttributes(e)
}
// GetRepositoryByID returns the repository by given id if exists.
@@ -1552,6 +1580,24 @@ func GetRecentUpdatedRepositories(page, pageSize int) (repos []*Repository, err
Where("is_private=?", false).Limit(pageSize).Desc("updated_unix").Find(&repos)
}
// GetUserAndCollaborativeRepositories returns list of repositories the user owns and collaborates.
func GetUserAndCollaborativeRepositories(userID int64) ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
if err := x.Alias("repo").
Join("INNER", "collaboration", "collaboration.repo_id = repo.id").
Where("collaboration.user_id = ?", userID).
Find(&repos); err != nil {
return nil, fmt.Errorf("select collaborative repositories: %v", err)
}
ownRepos := make([]*Repository, 0, 10)
if err := x.Where("owner_id = ?", userID).Find(&ownRepos); err != nil {
return nil, fmt.Errorf("select own repositories: %v", err)
}
return append(repos, ownRepos...), nil
}
func getRepositoryCount(e Engine, u *User) (int64, error) {
return x.Count(&Repository{OwnerID: u.ID})
}
@@ -1564,6 +1610,7 @@ func GetRepositoryCount(u *User) (int64, error) {
type SearchRepoOptions struct {
Keyword string
OwnerID int64
UserID int64 // When set results will contain all public/private repositories user has access to
OrderBy string
Private bool // Include private repositories in results
Page int
@@ -1573,24 +1620,28 @@ type SearchRepoOptions struct {
// SearchRepositoryByName takes keyword and part of repository name to search,
// it returns results in given range and number of total results.
func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int64, _ error) {
if len(opts.Keyword) == 0 {
return repos, 0, nil
}
opts.Keyword = strings.ToLower(opts.Keyword)
if opts.Page <= 0 {
opts.Page = 1
}
repos = make([]*Repository, 0, opts.PageSize)
// Append conditions
sess := x.Where("LOWER(lower_name) LIKE ?", "%"+opts.Keyword+"%")
if opts.OwnerID > 0 {
sess.And("owner_id = ?", opts.OwnerID)
sess := x.Alias("repo")
// Attempt to find repositories that opts.UserID has access to,
// this does not include other people's private repositories even if opts.UserID is an admin.
if !opts.Private && opts.UserID > 0 {
sess.Join("LEFT", "access", "access.repo_id = repo.id").
Where("(repo.owner_id = ? OR access.user_id = ? OR repo.is_private = ?)", opts.UserID, opts.UserID, false)
} else {
// Only return public repositories if opts.Private is not set
if !opts.Private {
sess.And("repo.is_private = ?", false)
}
}
if !opts.Private {
sess.And("is_private=?", false)
if len(opts.Keyword) > 0 {
sess.And("repo.lower_name LIKE ?", "%"+strings.ToLower(opts.Keyword)+"%")
}
if opts.OwnerID > 0 {
sess.And("repo.owner_id = ?", opts.OwnerID)
}
var countSess xorm.Session
@@ -1601,9 +1652,9 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int
}
if len(opts.OrderBy) > 0 {
sess.OrderBy(opts.OrderBy)
sess.OrderBy("repo." + opts.OrderBy)
}
return repos, count, sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&repos)
return repos, count, sess.Distinct("repo.*").Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&repos)
}
func DeleteOldRepositoryArchives() {
@@ -1933,7 +1984,7 @@ func (repos RepositoryList) loadAttributes(e Engine) error {
return nil
}
// Load owners.
// Load owners
set := make(map[int64]*User)
for i := range repos {
set[repos[i].OwnerID] = nil
@@ -2068,25 +2119,28 @@ func (repo *Repository) GetWatchers(page int) ([]*User, error) {
func notifyWatchers(e Engine, act *Action) error {
// Add feeds for user self and all watchers.
watches, err := getWatchers(e, act.RepoID)
watchers, err := getWatchers(e, act.RepoID)
if err != nil {
return fmt.Errorf("get watchers: %v", err)
return fmt.Errorf("getWatchers: %v", err)
}
// Reset ID to reuse Action object
act.ID = 0
// Add feed for actioner.
act.UserID = act.ActUserID
if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new actioner: %v", err)
if _, err = e.Insert(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
for i := range watches {
if act.ActUserID == watches[i].UserID {
for i := range watchers {
if act.ActUserID == watchers[i].UserID {
continue
}
act.ID = 0
act.UserID = watches[i].UserID
if _, err = e.InsertOne(act); err != nil {
act.UserID = watchers[i].UserID
if _, err = e.Insert(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
}
@@ -2161,24 +2215,26 @@ func (repo *Repository) GetStargazers(page int) ([]*User, error) {
// \___ / \____/|__| |__|_ \
// \/ \/
// HasForkedRepo checks if given user has already forked a repository with given ID.
// HasForkedRepo checks if given user has already forked a repository.
// When user has already forked, it returns true along with the repository.
func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
repo := new(Repository)
has, _ := x.Where("owner_id=? AND fork_id=?", ownerID, repoID).Get(repo)
has, _ := x.Where("owner_id = ? AND fork_id = ?", ownerID, repoID).Get(repo)
return repo, has
}
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
// ForkRepository creates a fork of target repository under another user domain.
func ForkRepository(doer, owner *User, baseRepo *Repository, name, desc string) (_ *Repository, err error) {
repo := &Repository{
OwnerID: u.ID,
Owner: u,
OwnerID: owner.ID,
Owner: owner,
Name: name,
LowerName: strings.ToLower(name),
Description: desc,
DefaultBranch: oldRepo.DefaultBranch,
IsPrivate: oldRepo.IsPrivate,
DefaultBranch: baseRepo.DefaultBranch,
IsPrivate: baseRepo.IsPrivate,
IsFork: true,
ForkID: oldRepo.ID,
ForkID: baseRepo.ID,
}
sess := x.NewSession()
@@ -2187,18 +2243,18 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
return nil, err
}
if err = createRepository(sess, u, repo); err != nil {
if err = createRepository(sess, doer, owner, repo); err != nil {
return nil, err
} else if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", baseRepo.ID); err != nil {
return nil, err
}
if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.ID); err != nil {
return nil, err
}
repoPath := repo.repoPath(sess)
RemoveAllWithNotice("Repository path erase before creation", repoPath)
repoPath := RepoPath(u.Name, repo.Name)
_, stderr, err := process.ExecTimeout(10*time.Minute,
fmt.Sprintf("ForkRepository 'git clone': %s/%s", u.Name, repo.Name),
"git", "clone", "--bare", oldRepo.RepoPath(), repoPath)
fmt.Sprintf("ForkRepository 'git clone': %s/%s", owner.Name, repo.Name),
"git", "clone", "--bare", baseRepo.RepoPath(), repoPath)
if err != nil {
return nil, fmt.Errorf("git clone: %v", stderr)
}
@@ -2214,7 +2270,21 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
return nil, fmt.Errorf("createDelegateHooks: %v", err)
}
return repo, sess.Commit()
if err = sess.Commit(); err != nil {
return nil, fmt.Errorf("Commit: %v", err)
}
if err = repo.UpdateSize(); err != nil {
log.Error(2, "UpdateSize [repo_id: %d]: %v", repo.ID, err)
}
if err = PrepareWebhooks(baseRepo, HOOK_EVENT_FORK, &api.ForkPayload{
Forkee: repo.APIFormat(nil),
Repo: baseRepo.APIFormat(nil),
Sender: doer.APIFormat(),
}); err != nil {
log.Error(2, "PrepareWebhooks [repo_id: %d]: %v", baseRepo.ID, err)
}
return repo, nil
}
func (repo *Repository) GetForks() ([]*Repository, error) {

View File

@@ -11,12 +11,15 @@ import (
"github.com/Unknwon/com"
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/pkg/tool"
)
type Branch struct {
Path string
Name string
RepoPath string
Name string
IsProtected bool
Commit *git.Commit
}
func GetBranchesByPath(path string) ([]*Branch, error) {
@@ -33,8 +36,8 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
branches := make([]*Branch, len(brs))
for i := range brs {
branches[i] = &Branch{
Path: path,
Name: brs[i],
RepoPath: path,
Name: brs[i],
}
}
return branches, nil
@@ -45,8 +48,8 @@ func (repo *Repository) GetBranch(br string) (*Branch, error) {
return nil, ErrBranchNotExist{br}
}
return &Branch{
Path: repo.RepoPath(),
Name: br,
RepoPath: repo.RepoPath(),
Name: br,
}, nil
}
@@ -55,7 +58,7 @@ func (repo *Repository) GetBranches() ([]*Branch, error) {
}
func (br *Branch) GetCommit() (*git.Commit, error) {
gitRepo, err := git.OpenRepository(br.Path)
gitRepo, err := git.OpenRepository(br.RepoPath)
if err != nil {
return nil, err
}
@@ -146,10 +149,10 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit
}
hasUsersChanged := false
validUserIDs := base.StringsToInt64s(strings.Split(protectBranch.WhitelistUserIDs, ","))
validUserIDs := tool.StringsToInt64s(strings.Split(protectBranch.WhitelistUserIDs, ","))
if protectBranch.WhitelistUserIDs != whitelistUserIDs {
hasUsersChanged = true
userIDs := base.StringsToInt64s(strings.Split(whitelistUserIDs, ","))
userIDs := tool.StringsToInt64s(strings.Split(whitelistUserIDs, ","))
validUserIDs = make([]int64, 0, len(userIDs))
for _, userID := range userIDs {
has, err := HasAccess(userID, repo, ACCESS_MODE_WRITE)
@@ -162,14 +165,14 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit
validUserIDs = append(validUserIDs, userID)
}
protectBranch.WhitelistUserIDs = strings.Join(base.Int64sToStrings(validUserIDs), ",")
protectBranch.WhitelistUserIDs = strings.Join(tool.Int64sToStrings(validUserIDs), ",")
}
hasTeamsChanged := false
validTeamIDs := base.StringsToInt64s(strings.Split(protectBranch.WhitelistTeamIDs, ","))
validTeamIDs := tool.StringsToInt64s(strings.Split(protectBranch.WhitelistTeamIDs, ","))
if protectBranch.WhitelistTeamIDs != whitelistTeamIDs {
hasTeamsChanged = true
teamIDs := base.StringsToInt64s(strings.Split(whitelistTeamIDs, ","))
teamIDs := tool.StringsToInt64s(strings.Split(whitelistTeamIDs, ","))
teams, err := GetTeamsHaveAccessToRepo(repo.OwnerID, repo.ID, ACCESS_MODE_WRITE)
if err != nil {
return fmt.Errorf("GetTeamsHaveAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
@@ -181,7 +184,14 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit
}
}
protectBranch.WhitelistTeamIDs = strings.Join(base.Int64sToStrings(validTeamIDs), ",")
protectBranch.WhitelistTeamIDs = strings.Join(tool.Int64sToStrings(validTeamIDs), ",")
}
// Make sure protectBranch.ID is not 0 for whitelists
if protectBranch.ID == 0 {
if _, err = x.Insert(protectBranch); err != nil {
return fmt.Errorf("Insert: %v", err)
}
}
// Merge users and members of teams
@@ -223,12 +233,6 @@ func UpdateOrgProtectBranch(repo *Repository, protectBranch *ProtectBranch, whit
return err
}
if protectBranch.ID == 0 {
if _, err = sess.Insert(protectBranch); err != nil {
return fmt.Errorf("Insert: %v", err)
}
}
if _, err = sess.Id(protectBranch.ID).AllCols().Update(protectBranch); err != nil {
return fmt.Errorf("Update: %v", err)
}

View File

@@ -7,6 +7,8 @@ package models
import (
"fmt"
log "gopkg.in/clog.v1"
api "github.com/gogits/go-gogs-client"
)
@@ -31,14 +33,22 @@ func (c *Collaboration) ModeI18nKey() string {
}
}
//IsCollaborator returns true if the user is a collaborator
func (repo *Repository) IsCollaborator(uid int64) (bool, error) {
// IsCollaborator returns true if the user is a collaborator of the repository.
func IsCollaborator(repoID, userID int64) bool {
collaboration := &Collaboration{
RepoID: repo.ID,
UserID: uid,
RepoID: repoID,
UserID: userID,
}
has, err := x.Get(collaboration)
if err != nil {
log.Error(2, "get collaboration [repo_id: %d, user_id: %d]: %v", repoID, userID, err)
return false
}
return has
}
return x.Get(collaboration)
func (repo *Repository) IsCollaborator(userID int64) bool {
return IsCollaborator(repo.ID, userID)
}
// AddCollaborator adds new collaboration to a repository with default access mode.
@@ -186,10 +196,14 @@ func (repo *Repository) ChangeCollaborationAccessMode(userID int64, mode AccessM
}
// DeleteCollaboration removes collaboration relation between the user and repository.
func (repo *Repository) DeleteCollaboration(uid int64) (err error) {
func DeleteCollaboration(repo *Repository, userID int64) (err error) {
if !IsCollaborator(repo.ID, userID) {
return nil
}
collaboration := &Collaboration{
RepoID: repo.ID,
UserID: uid,
UserID: userID,
}
sess := x.NewSession()
@@ -206,3 +220,7 @@ func (repo *Repository) DeleteCollaboration(uid int64) (err error) {
return sess.Commit()
}
func (repo *Repository) DeleteCollaboration(userID int64) error {
return DeleteCollaboration(repo, userID)
}

View File

@@ -21,8 +21,8 @@ import (
git "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/process"
"github.com/gogits/gogs/pkg/setting"
)
// ___________ .___.__ __ ___________.__.__
@@ -135,12 +135,12 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(4, "OpenRepository: %v", err)
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(4, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
@@ -162,10 +162,11 @@ func (repo *Repository) UpdateRepoFile(doer *User, opts UpdateRepoFileOptions) (
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(4, "CommitRepoAction: %v", err)
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return nil
}
@@ -265,12 +266,12 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(4, "OpenRepository: %v", err)
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(4, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
@@ -288,10 +289,11 @@ func (repo *Repository) DeleteRepoFile(doer *User, opts DeleteRepoFileOptions) (
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(4, "CommitRepoAction: %v", err)
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return nil
}
@@ -489,12 +491,12 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
log.Error(4, "OpenRepository: %v", err)
log.Error(2, "OpenRepository: %v", err)
return nil
}
commit, err := gitRepo.GetBranchCommit(opts.NewBranch)
if err != nil {
log.Error(4, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
log.Error(2, "GetBranchCommit [branch: %s]: %v", opts.NewBranch, err)
return nil
}
@@ -512,9 +514,10 @@ func (repo *Repository) UploadRepoFiles(doer *User, opts UploadRepoFileOptions)
NewCommitID: commit.ID.String(),
Commits: pushCommits,
}); err != nil {
log.Error(4, "CommitRepoAction: %v", err)
log.Error(2, "CommitRepoAction: %v", err)
return nil
}
go AddTestPullRequestTask(doer, repo.ID, opts.NewBranch, true)
return DeleteUploads(uploads...)
}

View File

@@ -1,11 +1,12 @@
package models_test
import (
. "github.com/gogits/gogs/models"
. "github.com/smartystreets/goconvey/convey"
"testing"
"github.com/gogits/gogs/modules/markdown"
. "github.com/smartystreets/goconvey/convey"
. "github.com/gogits/gogs/models"
"github.com/gogits/gogs/pkg/markup"
)
func TestRepo(t *testing.T) {
@@ -24,7 +25,7 @@ func TestRepo(t *testing.T) {
Convey("It should be nil even if other settings are present", func() {
repo.EnableExternalTracker = false
repo.ExternalTrackerFormat = "http://someurl.com/{user}/{repo}/{issue}"
repo.ExternalTrackerStyle = markdown.ISSUE_NAME_STYLE_NUMERIC
repo.ExternalTrackerStyle = markup.ISSUE_NAME_STYLE_NUMERIC
So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil))
})
})
@@ -33,17 +34,17 @@ func TestRepo(t *testing.T) {
repo.EnableExternalTracker = true
Convey("It should default to numeric issue style", func() {
metas := repo.ComposeMetas()
So(metas["style"], ShouldEqual, markdown.ISSUE_NAME_STYLE_NUMERIC)
So(metas["style"], ShouldEqual, markup.ISSUE_NAME_STYLE_NUMERIC)
})
Convey("It should pass through numeric issue style setting", func() {
repo.ExternalTrackerStyle = markdown.ISSUE_NAME_STYLE_NUMERIC
repo.ExternalTrackerStyle = markup.ISSUE_NAME_STYLE_NUMERIC
metas := repo.ComposeMetas()
So(metas["style"], ShouldEqual, markdown.ISSUE_NAME_STYLE_NUMERIC)
So(metas["style"], ShouldEqual, markup.ISSUE_NAME_STYLE_NUMERIC)
})
Convey("It should pass through alphanumeric issue style setting", func() {
repo.ExternalTrackerStyle = markdown.ISSUE_NAME_STYLE_ALPHANUMERIC
repo.ExternalTrackerStyle = markup.ISSUE_NAME_STYLE_ALPHANUMERIC
metas := repo.ComposeMetas()
So(metas["style"], ShouldEqual, markdown.ISSUE_NAME_STYLE_ALPHANUMERIC)
So(metas["style"], ShouldEqual, markup.ISSUE_NAME_STYLE_ALPHANUMERIC)
})
Convey("It should contain the user name", func() {
metas := repo.ComposeMetas()

View File

@@ -23,9 +23,9 @@ import (
"golang.org/x/crypto/ssh"
log "gopkg.in/clog.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/process"
"github.com/gogits/gogs/pkg/setting"
)
const (
@@ -484,7 +484,7 @@ func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error {
return nil
}
_, err := e.In("id", strings.Join(base.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey))
_, err := e.In("id", strings.Join(tool.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey))
return err
}
@@ -527,6 +527,7 @@ func RewriteAllPublicKeys() error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
os.MkdirAll(setting.SSH.RootPath, os.ModePerm)
fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
tmpPath := fpath + ".tmp"
f, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)

View File

@@ -11,7 +11,7 @@ import (
. "github.com/smartystreets/goconvey/convey"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/pkg/setting"
)
func init() {

View File

@@ -10,7 +10,7 @@ import (
"github.com/go-xorm/xorm"
gouuid "github.com/satori/go.uuid"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/pkg/tool"
)
// AccessToken represents a personal access token.
@@ -49,7 +49,7 @@ func (t *AccessToken) AfterSet(colName string, _ xorm.Cell) {
// NewAccessToken creates new access token.
func NewAccessToken(t *AccessToken) error {
t.Sha1 = base.EncodeSha1(gouuid.NewV4().String())
t.Sha1 = tool.EncodeSha1(gouuid.NewV4().String())
_, err := x.Insert(t)
return err
}

View File

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

View File

@@ -10,7 +10,6 @@ import (
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
"errors"
"fmt"
"image"
_ "image/jpeg"
@@ -30,10 +29,10 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/avatar"
"github.com/gogits/gogs/pkg/tool"
"github.com/gogits/gogs/pkg/setting"
)
type UserType int
@@ -43,15 +42,6 @@ const (
USER_TYPE_ORGANIZATION
)
var (
ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
ErrEmailNotExist = errors.New("E-mail does not exist")
ErrEmailNotActivated = errors.New("E-mail address has not been activated")
ErrUserNameIllegal = errors.New("User name contains illegal characters")
ErrLoginSourceNotActived = errors.New("Login source is not actived")
ErrUnsupportedLoginType = errors.New("Login source is unknown")
)
// User represents the object of individual and member of organization.
type User struct {
ID int64 `xorm:"pk autoincr"`
@@ -123,8 +113,6 @@ func (u *User) BeforeUpdate() {
func (u *User) AfterSet(colName string, _ xorm.Cell) {
switch colName {
case "full_name":
u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
case "created_unix":
u.Created = time.Unix(u.CreatedUnix, 0).Local()
case "updated_unix":
@@ -203,7 +191,7 @@ func (u *User) HTMLURL() string {
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
func (u *User) GenerateEmailActivateCode(email string) string {
code := base.CreateTimeLimitCode(
code := tool.CreateTimeLimitCode(
com.ToStr(u.ID)+email+u.LowerName+u.Passwd+u.Rands,
setting.Service.ActiveCodeLives, nil)
@@ -274,7 +262,7 @@ func (u *User) RelAvatarLink() string {
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.ID)
}
return base.AvatarLink(u.AvatarEmail)
return tool.AvatarLink(u.AvatarEmail)
}
// AvatarLink returns user avatar absolute link.
@@ -448,18 +436,18 @@ func (u *User) GetOwnedOrganizations() (err error) {
}
// GetOrganizations returns all organizations that user belongs to.
func (u *User) GetOrganizations(all bool) error {
ous, err := GetOrgUsersByUserID(u.ID, all)
func (u *User) GetOrganizations(showPrivate bool) error {
orgIDs, err := GetOrgIDsByUserID(u.ID, showPrivate)
if err != nil {
return err
return fmt.Errorf("GetOrgIDsByUserID: %v", err)
}
if len(orgIDs) == 0 {
return nil
}
u.Orgs = make([]*User, len(ous))
for i, ou := range ous {
u.Orgs[i], err = GetUserByID(ou.OrgID)
if err != nil {
return err
}
u.Orgs = make([]*User, 0, len(orgIDs))
if err = x.Where("type = ?", USER_TYPE_ORGANIZATION).In("id", orgIDs).Find(&u.Orgs); err != nil {
return err
}
return nil
}
@@ -474,7 +462,7 @@ func (u *User) DisplayName() string {
}
func (u *User) ShortName(length int) string {
return base.EllipsisString(u.Name, length)
return tool.EllipsisString(u.Name, length)
}
// IsMailable checks if a user is elegible
@@ -496,7 +484,7 @@ func IsUserExist(uid int64, name string) (bool, error) {
// GetUserSalt returns a ramdom user salt token.
func GetUserSalt() (string, error) {
return base.GetRandomString(10)
return tool.GetRandomString(10)
}
// NewGhostUser creates and returns a fake user for someone has deleted his/her account.
@@ -519,7 +507,7 @@ var (
func isUsableName(names, patterns []string, name string) error {
name = strings.TrimSpace(strings.ToLower(name))
if utf8.RuneCountInString(name) == 0 {
return ErrNameEmpty
return errors.EmptyName{}
}
for i := range names {
@@ -565,7 +553,7 @@ func CreateUser(u *User) (err error) {
u.LowerName = strings.ToLower(u.Name)
u.AvatarEmail = u.Email
u.Avatar = base.HashEmail(u.AvatarEmail)
u.Avatar = tool.HashEmail(u.AvatarEmail)
if u.Rands, err = GetUserSalt(); err != nil {
return err
}
@@ -608,12 +596,12 @@ func Users(page, pageSize int) ([]*User, error) {
// get user by erify code
func getVerifyUser(code string) (user *User) {
if len(code) <= base.TimeLimitCodeLength {
if len(code) <= tool.TimeLimitCodeLength {
return nil
}
// use tail hex username query user
hexStr := code[base.TimeLimitCodeLength:]
hexStr := code[tool.TimeLimitCodeLength:]
if b, err := hex.DecodeString(hexStr); err == nil {
if user, err = GetUserByName(string(b)); user != nil {
return user
@@ -630,10 +618,10 @@ func VerifyUserActiveCode(code string) (user *User) {
if user = getVerifyUser(code); user != nil {
// time limit code
prefix := code[:base.TimeLimitCodeLength]
prefix := code[:tool.TimeLimitCodeLength]
data := com.ToStr(user.ID) + user.Email + user.LowerName + user.Passwd + user.Rands
if base.VerifyTimeLimitCode(data, minutes, prefix) {
if tool.VerifyTimeLimitCode(data, minutes, prefix) {
return user
}
}
@@ -646,10 +634,10 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress {
if user := getVerifyUser(code); user != nil {
// time limit code
prefix := code[:base.TimeLimitCodeLength]
prefix := code[:tool.TimeLimitCodeLength]
data := com.ToStr(user.ID) + email + user.LowerName + user.Passwd + user.Rands
if base.VerifyTimeLimitCode(data, minutes, prefix) {
if tool.VerifyTimeLimitCode(data, minutes, prefix) {
emailAddress := &EmailAddress{Email: email}
if has, _ := x.Get(emailAddress); has {
return emailAddress
@@ -685,7 +673,13 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return fmt.Errorf("Delete repository wiki local copy: %v", err)
}
return os.Rename(UserPath(u.Name), UserPath(newUserName))
// Rename or create user base directory
baseDir := UserPath(u.Name)
newBaseDir := UserPath(newUserName)
if com.IsExist(baseDir) {
return os.Rename(baseDir, newBaseDir)
}
return os.MkdirAll(newBaseDir, os.ModePerm)
}
func updateUser(e Engine, u *User) error {
@@ -702,15 +696,14 @@ func updateUser(e Engine, u *User) error {
if len(u.AvatarEmail) == 0 {
u.AvatarEmail = u.Email
}
u.Avatar = base.HashEmail(u.AvatarEmail)
u.Avatar = tool.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)
u.Location = tool.TruncateString(u.Location, 255)
u.Website = tool.TruncateString(u.Website, 255)
u.Description = tool.TruncateString(u.Description, 255)
u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
_, err := e.Id(u.ID).AllCols().Update(u)
return err
}
@@ -884,11 +877,11 @@ func UserPath(userName string) string {
func GetUserByKeyID(keyID int64) (*User, error) {
user := new(User)
has, err := x.Sql("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyID).Get(user)
has, err := x.SQL("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyID).Get(user)
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotKeyOwner
return nil, errors.UserNotKeyOwner{keyID}
}
return user, nil
}
@@ -899,7 +892,7 @@ func getUserByID(e Engine, id int64) (*User, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotExist{id, ""}
return nil, errors.UserNotExist{id, ""}
}
return u, nil
}
@@ -915,7 +908,7 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotExist{userID, ""}
return nil, errors.UserNotExist{userID, ""}
}
return GetUserByID(userID)
}
@@ -923,14 +916,14 @@ func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
// GetUserByName returns user by given name.
func GetUserByName(name string) (*User, error) {
if len(name) == 0 {
return nil, ErrUserNotExist{0, name}
return nil, errors.UserNotExist{0, name}
}
u := &User{LowerName: strings.ToLower(name)}
has, err := x.Get(u)
if err != nil {
return nil, err
} else if !has {
return nil, ErrUserNotExist{0, name}
return nil, errors.UserNotExist{0, name}
}
return u, nil
}
@@ -1008,7 +1001,7 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
// GetUserByEmail returns the user object by given e-mail if exists.
func GetUserByEmail(email string) (*User, error) {
if len(email) == 0 {
return nil, ErrUserNotExist{0, "email"}
return nil, errors.UserNotExist{0, "email"}
}
email = strings.ToLower(email)
@@ -1032,7 +1025,7 @@ func GetUserByEmail(email string) (*User, error) {
return GetUserByID(emailAddress.UID)
}
return nil, ErrUserNotExist{0, email}
return nil, errors.UserNotExist{0, email}
}
type SearchUserOptions struct {

View File

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

View File

@@ -21,9 +21,10 @@ import (
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
"github.com/gogits/gogs/models/errors"
"github.com/gogits/gogs/pkg/httplib"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/sync"
)
var HookQueue = sync.NewUniqueQueue(setting.Webhook.QueueLength)
@@ -62,9 +63,14 @@ func IsValidHookContentType(name string) bool {
}
type HookEvents struct {
Create bool `json:"create"`
Push bool `json:"push"`
PullRequest bool `json:"pull_request"`
Create bool `json:"create"`
Delete bool `json:"delete"`
Fork bool `json:"fork"`
Push bool `json:"push"`
Issues bool `json:"issues"`
IssueComment bool `json:"issue_comment"`
PullRequest bool `json:"pull_request"`
Release bool `json:"release"`
}
// HookEvent represents events that will delivery hook.
@@ -156,28 +162,69 @@ func (w *Webhook) HasCreateEvent() bool {
(w.ChooseEvents && w.HookEvents.Create)
}
// HasDeleteEvent returns true if hook enabled delete event.
func (w *Webhook) HasDeleteEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Delete)
}
// HasForkEvent returns true if hook enabled fork event.
func (w *Webhook) HasForkEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Fork)
}
// HasPushEvent returns true if hook enabled push event.
func (w *Webhook) HasPushEvent() bool {
return w.PushOnly || w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Push)
}
// HasIssuesEvent returns true if hook enabled issues event.
func (w *Webhook) HasIssuesEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Issues)
}
// HasIssueCommentEvent returns true if hook enabled issue comment event.
func (w *Webhook) HasIssueCommentEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.IssueComment)
}
// HasPullRequestEvent returns true if hook enabled pull request event.
func (w *Webhook) HasPullRequestEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.PullRequest)
}
// HasReleaseEvent returns true if hook enabled release event.
func (w *Webhook) HasReleaseEvent() bool {
return w.SendEverything ||
(w.ChooseEvents && w.HookEvents.Release)
}
type eventChecker struct {
checker func() bool
typ HookEventType
}
func (w *Webhook) EventsArray() []string {
events := make([]string, 0, 3)
if w.HasCreateEvent() {
events = append(events, "create")
events := make([]string, 0, 7)
eventCheckers := []eventChecker{
{w.HasCreateEvent, HOOK_EVENT_CREATE},
{w.HasDeleteEvent, HOOK_EVENT_DELETE},
{w.HasForkEvent, HOOK_EVENT_FORK},
{w.HasPushEvent, HOOK_EVENT_PUSH},
{w.HasIssuesEvent, HOOK_EVENT_ISSUES},
{w.HasIssueCommentEvent, HOOK_EVENT_ISSUE_COMMENT},
{w.HasPullRequestEvent, HOOK_EVENT_PULL_REQUEST},
{w.HasReleaseEvent, HOOK_EVENT_RELEASE},
}
if w.HasPushEvent() {
events = append(events, "push")
}
if w.HasPullRequestEvent() {
events = append(events, "pull_request")
for _, c := range eventCheckers {
if c.checker() {
events = append(events, string(c.typ))
}
}
return events
}
@@ -195,7 +242,7 @@ func getWebhook(bean *Webhook) (*Webhook, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrWebhookNotExist{bean.ID}
return nil, errors.WebhookNotExist{bean.ID}
}
return bean, nil
}
@@ -225,10 +272,10 @@ func GetWebhookByOrgID(orgID, id int64) (*Webhook, error) {
})
}
// GetActiveWebhooksByRepoID returns all active webhooks of repository.
func GetActiveWebhooksByRepoID(repoID int64) ([]*Webhook, error) {
// getActiveWebhooksByRepoID returns all active webhooks of repository.
func getActiveWebhooksByRepoID(e Engine, repoID int64) ([]*Webhook, error) {
webhooks := make([]*Webhook, 0, 5)
return webhooks, x.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
return webhooks, e.Where("repo_id = ?", repoID).And("is_active = ?", true).Find(&webhooks)
}
// GetWebhooksByRepoID returns all webhooks of a repository.
@@ -283,10 +330,10 @@ func GetWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
return ws, err
}
// GetActiveWebhooksByOrgID returns all active webhooks for an organization.
func GetActiveWebhooksByOrgID(orgID int64) (ws []*Webhook, err error) {
err = x.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
return ws, err
// getActiveWebhooksByOrgID returns all active webhooks for an organization.
func getActiveWebhooksByOrgID(e Engine, orgID int64) ([]*Webhook, error) {
ws := make([]*Webhook, 0, 3)
return ws, e.Where("org_id=?", orgID).And("is_active=?", true).Find(&ws)
}
// ___ ___ __ ___________ __
@@ -336,9 +383,14 @@ func IsValidHookTaskType(name string) bool {
type HookEventType string
const (
HOOK_EVENT_CREATE HookEventType = "create"
HOOK_EVENT_PUSH HookEventType = "push"
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
HOOK_EVENT_CREATE HookEventType = "create"
HOOK_EVENT_DELETE HookEventType = "delete"
HOOK_EVENT_FORK HookEventType = "fork"
HOOK_EVENT_PUSH HookEventType = "push"
HOOK_EVENT_ISSUES HookEventType = "issues"
HOOK_EVENT_ISSUE_COMMENT HookEventType = "issue_comment"
HOOK_EVENT_PULL_REQUEST HookEventType = "pull_request"
HOOK_EVENT_RELEASE HookEventType = "release"
)
// HookRequest represents hook task request information.
@@ -430,27 +482,42 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
return tasks, x.Limit(setting.Webhook.PagingNum, (page-1)*setting.Webhook.PagingNum).Where("hook_id=?", hookID).Desc("id").Find(&tasks)
}
// CreateHookTask creates a new hook task,
// createHookTask creates a new hook task,
// it handles conversion from Payload to PayloadContent.
func CreateHookTask(t *HookTask) error {
func createHookTask(e Engine, t *HookTask) error {
data, err := t.Payloader.JSONPayload()
if err != nil {
return err
}
t.UUID = gouuid.NewV4().String()
t.PayloadContent = string(data)
_, err = x.Insert(t)
_, err = e.Insert(t)
return err
}
// GetHookTaskOfWebhookByUUID returns hook task of given webhook by UUID.
func GetHookTaskOfWebhookByUUID(webhookID int64, uuid string) (*HookTask, error) {
hookTask := &HookTask{
HookID: webhookID,
UUID: uuid,
}
has, err := x.Get(hookTask)
if err != nil {
return nil, err
} else if !has {
return nil, errors.HookTaskNotExist{webhookID, uuid}
}
return hookTask, nil
}
// UpdateHookTask updates information of hook task.
func UpdateHookTask(t *HookTask) error {
_, err := x.Id(t.ID).AllCols().Update(t)
return err
}
// prepareWebhooks adds list of webhooks to task queue.
func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
// prepareHookTasks adds list of webhooks to task queue.
func prepareHookTasks(e Engine, repo *Repository, event HookEventType, p api.Payloader, webhooks []*Webhook) (err error) {
if len(webhooks) == 0 {
return nil
}
@@ -462,14 +529,34 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
if !w.HasCreateEvent() {
continue
}
case HOOK_EVENT_DELETE:
if !w.HasDeleteEvent() {
continue
}
case HOOK_EVENT_FORK:
if !w.HasForkEvent() {
continue
}
case HOOK_EVENT_PUSH:
if !w.HasPushEvent() {
continue
}
case HOOK_EVENT_ISSUES:
if !w.HasIssuesEvent() {
continue
}
case HOOK_EVENT_ISSUE_COMMENT:
if !w.HasIssueCommentEvent() {
continue
}
case HOOK_EVENT_PULL_REQUEST:
if !w.HasPullRequestEvent() {
continue
}
case HOOK_EVENT_RELEASE:
if !w.HasReleaseEvent() {
continue
}
}
// Use separate objects so modifcations won't be made on payload on non-Gogs type hooks.
@@ -499,7 +586,7 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
signature = hex.EncodeToString(sig.Sum(nil))
}
if err = CreateHookTask(&HookTask{
if err = createHookTask(e, &HookTask{
RepoID: repo.ID,
HookID: w.ID,
Type: w.HookTaskType,
@@ -510,29 +597,38 @@ func prepareWebhooks(repo *Repository, event HookEventType, p api.Payloader, web
EventType: event,
IsSSL: w.IsSSL,
}); err != nil {
return fmt.Errorf("CreateHookTask: %v", err)
return fmt.Errorf("createHookTask: %v", err)
}
}
// It's safe to fail when the whole function is called during hook execution
// because resource released after exit. Also, there is no process started to
// consume this input during hook execution.
go HookQueue.Add(repo.ID)
return nil
}
func prepareWebhooks(e Engine, repo *Repository, event HookEventType, p api.Payloader) error {
webhooks, err := getActiveWebhooksByRepoID(e, repo.ID)
if err != nil {
return fmt.Errorf("getActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
}
// check if repo belongs to org and append additional webhooks
if repo.mustOwner(e).IsOrganization() {
// get hooks for org
orgws, err := getActiveWebhooksByOrgID(e, repo.OwnerID)
if err != nil {
return fmt.Errorf("getActiveWebhooksByOrgID [%d]: %v", repo.OwnerID, err)
}
webhooks = append(webhooks, orgws...)
}
return prepareHookTasks(e, repo, event, p, webhooks)
}
// PrepareWebhooks adds all active webhooks to task queue.
func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) error {
webhooks, err := GetActiveWebhooksByRepoID(repo.ID)
if err != nil {
return fmt.Errorf("GetActiveWebhooksByRepoID [%d]: %v", repo.ID, err)
}
// check if repo belongs to org and append additional webhooks
if repo.MustOwner().IsOrganization() {
// get hooks for org
orgws, err := GetActiveWebhooksByOrgID(repo.OwnerID)
if err != nil {
return fmt.Errorf("GetActiveWebhooksByOrgID [%d]: %v", repo.OwnerID, err)
}
webhooks = append(webhooks, orgws...)
}
return prepareWebhooks(repo, event, p, webhooks)
return prepareWebhooks(x, repo, event, p)
}
// TestWebhook adds the test webhook matches the ID to task queue.
@@ -541,7 +637,7 @@ func TestWebhook(repo *Repository, event HookEventType, p api.Payloader, webhook
if err != nil {
return fmt.Errorf("GetWebhookOfRepoByID [repo_id: %d, id: %d]: %v", repo.ID, webhookID, err)
}
return prepareWebhooks(repo, event, p, []*Webhook{webhook})
return prepareHookTasks(x, repo, event, p, []*Webhook{webhook})
}
func (t *HookTask) deliver() {
@@ -624,7 +720,7 @@ func (t *HookTask) deliver() {
// TODO: shoot more hooks at same time.
func DeliverHooks() {
tasks := make([]*HookTask, 0, 10)
x.Where("is_delivered=?", false).Iterate(new(HookTask),
x.Where("is_delivered = ?", false).Iterate(new(HookTask),
func(idx int, bean interface{}) error {
t := bean.(*HookTask)
t.deliver()
@@ -645,7 +741,7 @@ func DeliverHooks() {
HookQueue.Remove(repoID)
tasks = make([]*HookTask, 0, 5)
if err := x.Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
if err := x.Where("repo_id = ?", repoID).And("is_delivered = ?", false).Find(&tasks); err != nil {
log.Error(4, "Get repository [%s] hook tasks: %v", repoID, err)
continue
}

View File

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

View File

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

View File

@@ -17,8 +17,8 @@ import (
"github.com/gogits/git-module"
"github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/sync"
"github.com/gogits/gogs/pkg/setting"
"github.com/gogits/gogs/pkg/sync"
)
var wikiWorkingPool = sync.NewExclusivePool()

View File

@@ -1,276 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
import (
"reflect"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/go-macaron/binding"
"github.com/go-macaron/session"
gouuid "github.com/satori/go.uuid"
log "gopkg.in/clog.v1"
"gopkg.in/macaron.v1"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
)
func IsAPIPath(url string) bool {
return strings.HasPrefix(url, "/api/")
}
// SignedInID returns the id of signed in user.
func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
if !models.HasEngine {
return 0
}
// Check access token.
if IsAPIPath(ctx.Req.URL.Path) {
tokenSHA := ctx.Query("token")
if len(tokenSHA) == 0 {
// Well, check with header again.
auHead := ctx.Req.Header.Get("Authorization")
if len(auHead) > 0 {
auths := strings.Fields(auHead)
if len(auths) == 2 && auths[0] == "token" {
tokenSHA = auths[1]
}
}
}
// Let's see if token is valid.
if len(tokenSHA) > 0 {
t, err := models.GetAccessTokenBySHA(tokenSHA)
if err != nil {
if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) {
log.Error(2, "GetAccessTokenBySHA: %v", err)
}
return 0
}
t.Updated = time.Now()
if err = models.UpdateAccessToken(t); err != nil {
log.Error(2, "UpdateAccessToken: %v", err)
}
return t.UID
}
}
uid := sess.Get("uid")
if uid == nil {
return 0
}
if id, ok := uid.(int64); ok {
if _, err := models.GetUserByID(id); err != nil {
if !models.IsErrUserNotExist(err) {
log.Error(2, "GetUserById: %v", err)
}
return 0
}
return id
}
return 0
}
// SignedInUser returns the user object of signed user.
// It returns a bool value to indicate whether user uses basic auth or not.
func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) {
if !models.HasEngine {
return nil, false
}
uid := SignedInID(ctx, sess)
if uid <= 0 {
if setting.Service.EnableReverseProxyAuth {
webAuthUser := ctx.Req.Header.Get(setting.ReverseProxyAuthUser)
if len(webAuthUser) > 0 {
u, err := models.GetUserByName(webAuthUser)
if err != nil {
if !models.IsErrUserNotExist(err) {
log.Error(4, "GetUserByName: %v", err)
return nil, false
}
// Check if enabled auto-registration.
if setting.Service.EnableReverseProxyAutoRegister {
u := &models.User{
Name: webAuthUser,
Email: gouuid.NewV4().String() + "@localhost",
Passwd: webAuthUser,
IsActive: true,
}
if err = models.CreateUser(u); err != nil {
// FIXME: should I create a system notice?
log.Error(4, "CreateUser: %v", err)
return nil, false
} else {
return u, false
}
}
}
return u, false
}
}
// Check with basic auth.
baHead := ctx.Req.Header.Get("Authorization")
if len(baHead) > 0 {
auths := strings.Fields(baHead)
if len(auths) == 2 && auths[0] == "Basic" {
uname, passwd, _ := base.BasicAuthDecode(auths[1])
u, err := models.UserSignIn(uname, passwd)
if err != nil {
if !models.IsErrUserNotExist(err) {
log.Error(4, "UserSignIn: %v", err)
}
return nil, false
}
return u, true
}
}
return nil, false
}
u, err := models.GetUserByID(uid)
if err != nil {
log.Error(4, "GetUserById: %v", err)
return nil, false
}
return u, false
}
type Form interface {
binding.Validator
}
func init() {
binding.SetNameMapper(com.ToSnakeCase)
}
// AssignForm assign form values back to the template data.
func AssignForm(form interface{}, data map[string]interface{}) {
typ := reflect.TypeOf(form)
val := reflect.ValueOf(form)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
} else if len(fieldName) == 0 {
fieldName = com.ToSnakeCase(field.Name)
}
data[fieldName] = val.Field(i).Interface()
}
}
func getRuleBody(field reflect.StructField, prefix string) string {
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
if strings.HasPrefix(rule, prefix) {
return rule[len(prefix) : len(rule)-1]
}
}
return ""
}
func GetSize(field reflect.StructField) string {
return getRuleBody(field, "Size(")
}
func GetMinSize(field reflect.StructField) string {
return getRuleBody(field, "MinSize(")
}
func GetMaxSize(field reflect.StructField) string {
return getRuleBody(field, "MaxSize(")
}
func GetInclude(field reflect.StructField) string {
return getRuleBody(field, "Include(")
}
// FIXME: struct contains a struct
func validateStruct(obj interface{}) binding.Errors {
return nil
}
func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
if errs.Len() == 0 {
return errs
}
data["HasError"] = true
AssignForm(f, data)
typ := reflect.TypeOf(f)
val := reflect.ValueOf(f)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
val = val.Elem()
}
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
fieldName := field.Tag.Get("form")
// Allow ignored fields in the struct
if fieldName == "-" {
continue
}
if errs[0].FieldNames[0] == field.Name {
data["Err_"+field.Name] = true
trName := field.Tag.Get("locale")
if len(trName) == 0 {
trName = l.Tr("form." + field.Name)
} else {
trName = l.Tr(trName)
}
switch errs[0].Classification {
case binding.ERR_REQUIRED:
data["ErrorMsg"] = trName + l.Tr("form.require_error")
case binding.ERR_ALPHA_DASH:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
case binding.ERR_ALPHA_DASH_DOT:
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
case binding.ERR_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
case binding.ERR_MIN_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
case binding.ERR_MAX_SIZE:
data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
case binding.ERR_EMAIL:
data["ErrorMsg"] = trName + l.Tr("form.email_error")
case binding.ERR_URL:
data["ErrorMsg"] = trName + l.Tr("form.url_error")
case binding.ERR_INCLUDE:
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field))
default:
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
}
return errs
}
}
return errs
}

View File

@@ -1,55 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package auth
import (
"github.com/go-macaron/binding"
"gopkg.in/macaron.v1"
)
// ________ .__ __ .__
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
// \/ /_____/ \/ \/ \/ \/ \/
type CreateOrgForm struct {
OrgName string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
}
func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type UpdateOrgSettingForm struct {
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
}
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
// ___________
// \__ ___/___ _____ _____
// | |_/ __ \\__ \ / \
// | |\ ___/ / __ \| Y Y \
// |____| \___ >____ /__|_| /
// \/ \/ \/
type CreateTeamForm struct {
TeamName string `binding:"Required;AlphaDashDot;MaxSize(30)"`
Description string `binding:"MaxSize(255)"`
Permission string
}
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

View File

@@ -1,11 +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
const DOC_URL = "https://github.com/gogits/go-gogs-client/wiki"
type (
TplName string
)

File diff suppressed because one or more lines are too long

View File

@@ -1,440 +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 markdown
import (
"bytes"
"fmt"
"io"
"path"
"path/filepath"
"regexp"
"strings"
"github.com/Unknwon/com"
"github.com/microcosm-cc/bluemonday"
"github.com/russross/blackfriday"
"golang.org/x/net/html"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/setting"
)
const (
ISSUE_NAME_STYLE_NUMERIC = "numeric"
ISSUE_NAME_STYLE_ALPHANUMERIC = "alphanumeric"
)
var Sanitizer = bluemonday.UGCPolicy()
// BuildSanitizer initializes sanitizer with allowed attributes based on settings.
// This function should only be called once during entire application lifecycle.
func BuildSanitizer() {
// Normal markdown-stuff
Sanitizer.AllowAttrs("class").Matching(regexp.MustCompile(`[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&]*`)).OnElements("code")
// Checkboxes
Sanitizer.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
Sanitizer.AllowAttrs("checked", "disabled").OnElements("input")
// Custom URL-Schemes
Sanitizer.AllowURLSchemes(setting.Markdown.CustomURLSchemes...)
}
var validLinksPattern = regexp.MustCompile(`^[a-z][\w-]+://|^mailto:`)
// isLink reports whether link fits valid format.
func isLink(link []byte) bool {
return validLinksPattern.Match(link)
}
// IsMarkdownFile reports whether name looks like a Markdown file
// based on its extension.
func IsMarkdownFile(name string) bool {
extension := strings.ToLower(filepath.Ext(name))
for _, ext := range setting.Markdown.FileExtensions {
if strings.ToLower(ext) == extension {
return true
}
}
return false
}
// IsReadmeFile reports whether name looks like a README file
// based on its extension.
func IsReadmeFile(name string) bool {
name = strings.ToLower(name)
if len(name) < 6 {
return false
} else if len(name) == 6 {
return name == "readme"
}
return name[:7] == "readme."
}
var (
// MentionPattern matches string that mentions someone, e.g. @Unknwon
MentionPattern = regexp.MustCompile(`(\s|^|\W)@[0-9a-zA-Z-_\.]+`)
// CommitPattern matches link to certain commit with or without trailing hash,
// e.g. https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2
CommitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
// IssueFullPattern matches link to an issue with or without trailing hash,
// e.g. https://try.gogs.io/gogs/gogs/issues/4#issue-685
IssueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
// IssueNumericPattern matches string that references to a numeric issue, e.g. #1287
IssueNumericPattern = regexp.MustCompile(`( |^|\()#[0-9]+\b`)
// IssueAlphanumericPattern matches string that references to an alphanumeric issue, e.g. ABC-1234
IssueAlphanumericPattern = regexp.MustCompile(`( |^|\()[A-Z]{1,10}-[1-9][0-9]*\b`)
// CrossReferenceIssueNumericPattern matches string that references a numeric issue in a difference repository
// e.g. gogits/gogs#12345
CrossReferenceIssueNumericPattern = regexp.MustCompile(`( |^)[0-9a-zA-Z-_\.]+/[0-9a-zA-Z-_\.]+#[0-9]+\b`)
// Sha1CurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae
// FIXME: this pattern matches pure numbers as well, right now we do a hack to check in RenderSha1CurrentPattern
// by converting string to a number.
Sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`)
)
// FindAllMentions matches mention patterns in given content
// and returns a list of found user names without @ prefix.
func FindAllMentions(content string) []string {
mentions := MentionPattern.FindAllString(content, -1)
for i := range mentions {
mentions[i] = mentions[i][strings.Index(mentions[i], "@")+1:] // Strip @ character
}
return mentions
}
// Renderer is a extended version of underlying render object.
type Renderer struct {
blackfriday.Renderer
urlPrefix string
}
// Link defines how formal links should be processed to produce corresponding HTML elements.
func (r *Renderer) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
if len(link) > 0 && !isLink(link) {
if link[0] != '#' {
link = []byte(path.Join(r.urlPrefix, string(link)))
}
}
r.Renderer.Link(out, link, title, content)
}
// AutoLink defines how auto-detected links should be processed to produce corresponding HTML elements.
// Reference for kind: https://github.com/russross/blackfriday/blob/master/markdown.go#L69-L76
func (r *Renderer) AutoLink(out *bytes.Buffer, link []byte, kind int) {
if kind != blackfriday.LINK_TYPE_NORMAL {
r.Renderer.AutoLink(out, link, kind)
return
}
// Since this method could only possibly serve one link at a time,
// we do not need to find all.
if bytes.HasPrefix(link, []byte(setting.AppUrl)) {
m := CommitPattern.Find(link)
if m != nil {
m = bytes.TrimSpace(m)
i := strings.Index(string(m), "commit/")
j := strings.Index(string(m), "#")
if j == -1 {
j = len(m)
}
out.WriteString(fmt.Sprintf(` <code><a href="%s">%s</a></code>`, m, base.ShortSha(string(m[i+7:j]))))
return
}
m = IssueFullPattern.Find(link)
if m != nil {
m = bytes.TrimSpace(m)
i := strings.Index(string(m), "issues/")
j := strings.Index(string(m), "#")
if j == -1 {
j = len(m)
}
index := string(m[i+7 : j])
fullRepoURL := setting.AppUrl + strings.TrimPrefix(r.urlPrefix, "/")
var link string
if strings.HasPrefix(string(m), fullRepoURL) {
// Use a short issue reference if the URL refers to this repository
link = fmt.Sprintf(`<a href="%s">#%s</a>`, m, index)
} else {
// Use a cross-repository issue reference if the URL refers to a different repository
repo := string(m[len(setting.AppUrl) : i-1])
link = fmt.Sprintf(`<a href="%s">%s#%s</a>`, m, repo, index)
}
out.WriteString(link)
return
}
}
r.Renderer.AutoLink(out, link, kind)
}
// ListItem defines how list items should be processed to produce corresponding HTML elements.
func (options *Renderer) ListItem(out *bytes.Buffer, text []byte, flags int) {
// Detect procedures to draw checkboxes.
switch {
case bytes.HasPrefix(text, []byte("[ ] ")):
text = append([]byte(`<input type="checkbox" disabled="" />`), text[3:]...)
case bytes.HasPrefix(text, []byte("[x] ")):
text = append([]byte(`<input type="checkbox" disabled="" checked="" />`), text[3:]...)
}
options.Renderer.ListItem(out, text, flags)
}
// Note: this section is for purpose of increase performance and
// reduce memory allocation at runtime since they are constant literals.
var (
svgSuffix = []byte(".svg")
svgSuffixWithMark = []byte(".svg?")
spaceBytes = []byte(" ")
spaceEncodedBytes = []byte("%20")
pound = []byte("#")
space = " "
spaceEncoded = "%20"
)
// Image defines how images should be processed to produce corresponding HTML elements.
func (r *Renderer) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) {
prefix := strings.Replace(r.urlPrefix, "/src/", "/raw/", 1)
if len(link) > 0 {
if isLink(link) {
// External link with .svg suffix usually means CI status.
// TODO: define a keyword to allow non-svg images render as external link.
if bytes.HasSuffix(link, svgSuffix) || bytes.Contains(link, svgSuffixWithMark) {
r.Renderer.Image(out, link, title, alt)
return
}
} else {
if link[0] != '/' {
prefix += "/"
}
link = bytes.Replace([]byte((prefix + string(link))), spaceBytes, spaceEncodedBytes, -1)
fmt.Println(333, string(link))
}
}
out.WriteString(`<a href="`)
out.Write(link)
out.WriteString(`">`)
r.Renderer.Image(out, link, title, alt)
out.WriteString("</a>")
}
// cutoutVerbosePrefix cutouts URL prefix including sub-path to
// return a clean unified string of request URL path.
func cutoutVerbosePrefix(prefix string) string {
if len(prefix) == 0 || prefix[0] != '/' {
return prefix
}
count := 0
for i := 0; i < len(prefix); i++ {
if prefix[i] == '/' {
count++
}
if count >= 3+setting.AppSubUrlDepth {
return prefix[:i]
}
}
return prefix
}
// RenderIssueIndexPattern renders issue indexes to corresponding links.
func RenderIssueIndexPattern(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
urlPrefix = cutoutVerbosePrefix(urlPrefix)
pattern := IssueNumericPattern
if metas["style"] == ISSUE_NAME_STYLE_ALPHANUMERIC {
pattern = IssueAlphanumericPattern
}
ms := pattern.FindAll(rawBytes, -1)
for _, m := range ms {
if m[0] == ' ' || m[0] == '(' {
m = m[1:] // ignore leading space or opening parentheses
}
var link string
if metas == nil {
link = fmt.Sprintf(`<a href="%s/issues/%s">%s</a>`, urlPrefix, m[1:], m)
} else {
// Support for external issue tracker
if metas["style"] == ISSUE_NAME_STYLE_ALPHANUMERIC {
metas["index"] = string(m)
} else {
metas["index"] = string(m[1:])
}
link = fmt.Sprintf(`<a href="%s">%s</a>`, com.Expand(metas["format"], metas), m)
}
rawBytes = bytes.Replace(rawBytes, m, []byte(link), 1)
}
return rawBytes
}
// RenderCrossReferenceIssueIndexPattern renders issue indexes from other repositories to corresponding links.
func RenderCrossReferenceIssueIndexPattern(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
ms := CrossReferenceIssueNumericPattern.FindAll(rawBytes, -1)
for _, m := range ms {
if m[0] == ' ' || m[0] == '(' {
m = m[1:] // ignore leading space or opening parentheses
}
delimIdx := bytes.Index(m, pound)
repo := string(m[:delimIdx])
index := string(m[delimIdx+1:])
link := fmt.Sprintf(`<a href="%s%s/issues/%s">%s</a>`, setting.AppUrl, repo, index, m)
rawBytes = bytes.Replace(rawBytes, m, []byte(link), 1)
}
return rawBytes
}
// RenderSha1CurrentPattern renders SHA1 strings to corresponding links that assumes in the same repository.
func RenderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
return []byte(Sha1CurrentPattern.ReplaceAllStringFunc(string(rawBytes[:]), func(m string) string {
if com.StrTo(m).MustInt() > 0 {
return m
}
return fmt.Sprintf(`<a href="%s/commit/%s"><code>%s</code></a>`, urlPrefix, m, base.ShortSha(string(m)))
}))
}
// RenderSpecialLink renders mentions, indexes and SHA1 strings to corresponding links.
func RenderSpecialLink(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
ms := MentionPattern.FindAll(rawBytes, -1)
for _, m := range ms {
m = m[bytes.Index(m, []byte("@")):]
rawBytes = bytes.Replace(rawBytes, m,
[]byte(fmt.Sprintf(`<a href="%s/%s">%s</a>`, setting.AppSubUrl, m[1:], m)), -1)
}
rawBytes = RenderIssueIndexPattern(rawBytes, urlPrefix, metas)
rawBytes = RenderCrossReferenceIssueIndexPattern(rawBytes, urlPrefix, metas)
rawBytes = RenderSha1CurrentPattern(rawBytes, urlPrefix)
return rawBytes
}
// RenderRaw renders Markdown to HTML without handling special links.
func RenderRaw(body []byte, urlPrefix string) []byte {
htmlFlags := 0
htmlFlags |= blackfriday.HTML_SKIP_STYLE
htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
renderer := &Renderer{
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"}
// PostProcess treats different types of HTML differently,
// and only renders special links for plain text blocks.
func PostProcess(rawHtml []byte, urlPrefix string, metas map[string]string) []byte {
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, metas))
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 {
stackNum--
if stackNum <= 0 && strings.EqualFold(tagName, token.Data) {
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
}
// Render renders Markdown to HTML with special links.
func Render(rawBytes []byte, urlPrefix string, metas map[string]string) []byte {
urlPrefix = strings.Replace(urlPrefix, space, spaceEncoded, -1)
result := RenderRaw(rawBytes, urlPrefix)
result = PostProcess(result, urlPrefix, metas)
result = Sanitizer.SanitizeBytes(result)
return result
}
// RenderString renders Markdown to HTML with special links and returns string type.
func RenderString(raw, urlPrefix string, metas map[string]string) string {
return string(Render([]byte(raw), urlPrefix, metas))
}

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