forked from forgejo/forgejo
Merge branch 'master' into feat/approval-new
# Conflicts: # models/issue_comment.go # models/migrations/migrations.go # models/migrations/v64.go # models/models.go # public/css/index.css
This commit is contained in:
commit
6d00c1a7ce
95 changed files with 4325 additions and 927 deletions
48
.drone.yml
48
.drone.yml
|
@ -1,5 +1,5 @@
|
|||
workspace:
|
||||
base: /srv/app
|
||||
base: /go
|
||||
path: src/code.gitea.io/gitea
|
||||
|
||||
clone:
|
||||
|
@ -56,21 +56,18 @@ pipeline:
|
|||
event: [ push, tag, pull_request ]
|
||||
|
||||
build-without-gcc:
|
||||
image: webhippie/golang:1.8
|
||||
image: golang:1.8
|
||||
pull: true
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
build:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make clean
|
||||
- make generate
|
||||
|
@ -85,12 +82,11 @@ pipeline:
|
|||
event: [ push, tag, pull_request ]
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make unit-test-coverage
|
||||
when:
|
||||
|
@ -98,12 +94,11 @@ pipeline:
|
|||
branch: [ master ]
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test
|
||||
when:
|
||||
|
@ -111,12 +106,11 @@ pipeline:
|
|||
branch: [ release/* ]
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test
|
||||
when:
|
||||
|
@ -124,60 +118,64 @@ pipeline:
|
|||
|
||||
# Commented until db locking have been resolved!
|
||||
# test-sqlite:
|
||||
# image: webhippie/golang:edge
|
||||
# image: golang:1.10
|
||||
# pull: true
|
||||
# group: test
|
||||
# environment:
|
||||
# TAGS: bindata
|
||||
# GOPATH: /srv/app
|
||||
# commands:
|
||||
# - make test-sqlite
|
||||
# when:
|
||||
# event: [ push, tag, pull_request ]
|
||||
|
||||
test-mysql:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
TEST_LDAP: "1"
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- make integration-test-coverage
|
||||
when:
|
||||
event: [ push, pull_request ]
|
||||
branch: [ master ]
|
||||
|
||||
test-mysql:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
TEST_LDAP: "1"
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- make test-mysql
|
||||
when:
|
||||
event: [ tag ]
|
||||
|
||||
test-pgsql:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
TEST_LDAP: "1"
|
||||
commands:
|
||||
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||
- apt-get install -y git-lfs
|
||||
- make test-pgsql
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
generate-coverage:
|
||||
image: webhippie/golang:edge
|
||||
image: golang:1.10
|
||||
pull: true
|
||||
environment:
|
||||
TAGS: bindata
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make coverage
|
||||
when:
|
||||
|
@ -198,7 +196,6 @@ pipeline:
|
|||
pull: true
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make release
|
||||
when:
|
||||
|
@ -342,3 +339,8 @@ services:
|
|||
- POSTGRES_DB=test
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
ldap:
|
||||
image: gitea/test-openldap:latest
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
|
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -59,3 +59,13 @@ coverage.all
|
|||
/integrations/mysql.ini
|
||||
/integrations/pgsql.ini
|
||||
/node_modules
|
||||
|
||||
|
||||
# Snapcraft
|
||||
snap/.snapcraft/
|
||||
parts/
|
||||
stage/
|
||||
prime/
|
||||
*.snap
|
||||
*.snap-build
|
||||
*_source.tar.bz2
|
||||
|
|
2
Makefile
2
Makefile
|
@ -292,7 +292,7 @@ stylesheets-check: generate-stylesheets
|
|||
|
||||
.PHONY: generate-stylesheets
|
||||
generate-stylesheets:
|
||||
node_modules/.bin/lessc --no-ie-compat --clean-css public/less/index.less public/css/index.css
|
||||
node_modules/.bin/lessc --clean-css public/less/index.less public/css/index.css
|
||||
|
||||
.PHONY: swagger-ui
|
||||
swagger-ui:
|
||||
|
|
25
README.md
25
README.md
|
@ -4,12 +4,11 @@
|
|||
|
||||
[](https://drone.gitea.io/go-gitea/gitea)
|
||||
[](https://discord.gg/NsatcWJ)
|
||||
[](https://matrix.to/#/#gitea:matrix.org)
|
||||
[](https://microbadger.com/images/gitea/gitea "Get your own image badge on microbadger.com")
|
||||
[](https://codecov.io/gh/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://www.codetriage.com/go-gitea/gitea)
|
||||
[](https://opencollective.com/gitea)
|
||||
|
||||
|
@ -63,7 +62,6 @@ For more information and instructions about how to install Gitea, please look
|
|||
at our [documentation](https://docs.gitea.io/en-us/). If you have questions
|
||||
that are not covered by the documentation, you can get in contact with us on
|
||||
our [Discord server](https://discord.gg/NsatcWJ),
|
||||
[Matrix room](https://matrix.to/#/#gitea:matrix.org),
|
||||
or [forum](https://discourse.gitea.io/)!
|
||||
|
||||
## Authors
|
||||
|
@ -72,6 +70,27 @@ or [forum](https://discourse.gitea.io/)!
|
|||
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
* [Translators](options/locale/TRANSLATORS)
|
||||
|
||||
## Backers
|
||||
|
||||
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/gitea#backer)]
|
||||
|
||||
<a href="https://opencollective.com/gitea#backers" target="_blank"><img src="https://opencollective.com/gitea/backers.svg?width=890"></a>
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/gitea#sponsor)]
|
||||
|
||||
<a href="https://opencollective.com/gitea/sponsor/0/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/1/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/2/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/3/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/4/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/5/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/6/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/7/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/8/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/gitea/sponsor/9/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/9/avatar.svg"></a>
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
[](https://coverage.gitea.io/go-gitea/gitea)
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea)
|
||||
[](https://godoc.org/code.gitea.io/gitea)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://github.com/go-gitea/gitea/releases/latest)
|
||||
[](https://opencollective.com/gitea)
|
||||
|
||||
| | | |
|
||||
|
|
|
@ -22,6 +22,11 @@ WorkingDirectory=/home/git/gitea
|
|||
ExecStart=/home/git/gitea/gitea web
|
||||
Restart=always
|
||||
Environment=USER=git HOME=/home/git
|
||||
# If you want to bind Gitea to a port below 1024 uncomment
|
||||
# the two values below
|
||||
###
|
||||
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
#AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
; Copy required sections to your own app.ini (default is custom/conf/app.ini)
|
||||
; and modify as needed.
|
||||
|
||||
; App name that shows on every page title
|
||||
; see https://docs.gitea.io/en-us/config-cheat-sheet/ for additional documentation.
|
||||
|
||||
; App name that shows in every page title
|
||||
APP_NAME = Gitea: Git with a cup of tea
|
||||
; Change it if you run locally
|
||||
RUN_USER = git
|
||||
|
@ -16,28 +18,28 @@ SCRIPT_TYPE = bash
|
|||
ANSI_CHARSET =
|
||||
; Force every new repository to be private
|
||||
FORCE_PRIVATE = false
|
||||
; Default private when create a new repository, could be: last, private, public. Default is last which means last user repo visiblity.
|
||||
; Default privacy setting when creating a new repository, allowed values: last, private, public. Default is last which means the last setting used.
|
||||
DEFAULT_PRIVATE = last
|
||||
; Global maximum creation limit of repository per user, -1 means no limit
|
||||
; Global limit of repositories per user, applied at creation time. -1 means no limit
|
||||
MAX_CREATION_LIMIT = -1
|
||||
; Mirror sync queue length, increase if mirror syncing starts hanging
|
||||
MIRROR_QUEUE_LENGTH = 1000
|
||||
; Patch test queue length, increase if pull request patch testing starts hanging
|
||||
PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||
; Preferred Licenses to place at the top of the List
|
||||
; Name must match file name in conf/license or custom/conf/license
|
||||
; The name here must match the filename in conf/license or custom/conf/license
|
||||
PREFERRED_LICENSES = Apache License 2.0,MIT License
|
||||
; Disable ability to interact with repositories by HTTP protocol
|
||||
; Disable the ability to interact with repositories using the HTTP protocol
|
||||
DISABLE_HTTP_GIT = false
|
||||
; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
||||
USE_COMPAT_SSH_URI = false
|
||||
|
||||
[repository.editor]
|
||||
; List of file extensions that should have line wraps in the CodeMirror editor
|
||||
; Separate extensions with a comma. To line wrap files w/o extension, just put a comma
|
||||
; List of file extensions for which lines should be wrapped in the CodeMirror editor
|
||||
; Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||
; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
|
||||
; Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match
|
||||
PREVIEWABLE_FILE_MODES = markdown
|
||||
|
||||
[repository.local]
|
||||
|
@ -53,39 +55,39 @@ ENABLED = true
|
|||
TEMP_PATH = data/tmp/uploads
|
||||
; One or more allowed types, e.g. image/jpeg|image/png. Nothing means any file type
|
||||
ALLOWED_TYPES =
|
||||
; Max size of each file in MB. Defaults to 3MB
|
||||
; Max size of each file in megabytes. Defaults to 3MB
|
||||
FILE_MAX_SIZE = 3
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[ui]
|
||||
; Number of repositories that are showed in one explore page
|
||||
; Number of repositories that are displayed on one explore page
|
||||
EXPLORE_PAGING_NUM = 20
|
||||
; Number of issues that are showed in one page
|
||||
; Number of issues that are displayed on one page
|
||||
ISSUE_PAGING_NUM = 10
|
||||
; Number of maximum commits showed in one activity feed
|
||||
; Number of maximum commits displayed in one activity feed
|
||||
FEED_MAX_COMMIT_NUM = 5
|
||||
; Value of `theme-color` meta tag, used by Android >= 5.0
|
||||
; An invalid color like "none" or "disable" will have the default style
|
||||
; More info: https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
|
||||
THEME_COLOR_META_TAG = `#6cc644`
|
||||
; Max size of files to be displayed (defaults is 8MiB)
|
||||
; Max size of files to be displayed (default is 8MiB)
|
||||
MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
; Whether show the user email in the Explore Users page
|
||||
; Whether the email of the user should be shown in the Explore Users page
|
||||
SHOW_USER_EMAIL = true
|
||||
|
||||
[ui.admin]
|
||||
; Number of users that are showed in one page
|
||||
; Number of users that are displayed on one page
|
||||
USER_PAGING_NUM = 50
|
||||
; Number of repos that are showed in one page
|
||||
; Number of repos that are displayed on one page
|
||||
REPO_PAGING_NUM = 50
|
||||
; Number of notices that are showed in one page
|
||||
; Number of notices that are displayed on in one page
|
||||
NOTICE_PAGING_NUM = 25
|
||||
; Number of organization that are showed in one page
|
||||
; Number of organizations that are displayed on one page
|
||||
ORG_PAGING_NUM = 50
|
||||
|
||||
[ui.user]
|
||||
; Number of repos that are showed in one page
|
||||
; Number of repos that are displayed on one page
|
||||
REPO_PAGING_NUM = 15
|
||||
|
||||
[ui.meta]
|
||||
|
@ -100,19 +102,19 @@ ENABLE_HARD_LINE_BREAK = false
|
|||
; for example git,magnet
|
||||
CUSTOM_URL_SCHEMES =
|
||||
; List of file extensions that should be rendered/edited as Markdown
|
||||
; Separate extensions with a comma. To render files w/o extension as markdown, just put a comma
|
||||
; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma
|
||||
FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
|
||||
[server]
|
||||
; Listen protocol. One of 'http', 'https', 'unix' or 'fcgi'.
|
||||
; The protocol the server listens on. One of 'http', 'https', 'unix' or 'fcgi'.
|
||||
PROTOCOL = http
|
||||
DOMAIN = localhost
|
||||
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
; Listen address. Either a IPv4/IPv6 address or the path to a unix socket.
|
||||
; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
|
||||
HTTP_ADDR = 0.0.0.0
|
||||
HTTP_PORT = 3000
|
||||
; If REDIRECT_OTHER_PORT is true, and PROTOCOL is set to https an http server
|
||||
; will be started on PORT_TO_REDIRECT and redirect request to the main
|
||||
; will be started on PORT_TO_REDIRECT and it will redirect plain, non-secure http requests to the main
|
||||
; ROOT_URL. Defaults are false for REDIRECT_OTHER_PORT and 80 for
|
||||
; PORT_TO_REDIRECT.
|
||||
REDIRECT_OTHER_PORT = false
|
||||
|
@ -125,33 +127,33 @@ UNIX_SOCKET_PERMISSION = 666
|
|||
LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
||||
; Disable SSH feature when not available
|
||||
DISABLE_SSH = false
|
||||
; Whether use builtin SSH server or not.
|
||||
; Whether to use the builtin SSH server or not.
|
||||
START_SSH_SERVER = false
|
||||
; Username to use for builtin SSH server. If blank, then it is the value of RUN_USER.
|
||||
; Username to use for the builtin SSH server. If blank, then it is the value of RUN_USER.
|
||||
BUILTIN_SSH_SERVER_USER =
|
||||
; Domain name to be exposed in clone URL
|
||||
SSH_DOMAIN = %(DOMAIN)s
|
||||
; Network interface builtin SSH server listens on
|
||||
; THe network interface the builtin SSH server should listen on
|
||||
SSH_LISTEN_HOST =
|
||||
; Port number to be exposed in clone URL
|
||||
SSH_PORT = 22
|
||||
; Port number builtin SSH server listens on
|
||||
; The port number the builtin SSH server should listen on
|
||||
SSH_LISTEN_PORT = %(SSH_PORT)s
|
||||
; Root path of SSH directory, default is '~/.ssh', but you have to use '/home/git/.ssh'.
|
||||
SSH_ROOT_PATH =
|
||||
; For built-in SSH server only, choose the ciphers to support for SSH connections,
|
||||
; For the built-in SSH server, choose the ciphers to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_CIPHERS = aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, arcfour256, arcfour128
|
||||
; For built-in SSH server only, choose the key exchange algorithms to support for SSH connections,
|
||||
; For the built-in SSH server, choose the key exchange algorithms to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_KEY_EXCHANGES = diffie-hellman-group1-sha1, diffie-hellman-group14-sha1, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, curve25519-sha256@libssh.org
|
||||
; For built-in SSH server only, choose the MACs to support for SSH connections,
|
||||
; For the built-in SSH server, choose the MACs to support for SSH connections,
|
||||
; for system SSH this setting has no effect
|
||||
SSH_SERVER_MACS = hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1, hmac-sha1-96
|
||||
; Directory to create temporary files when test public key using ssh-keygen,
|
||||
; default is system temporary directory.
|
||||
; Directory to create temporary files in when testing public keys using ssh-keygen,
|
||||
; default is the system temporary directory.
|
||||
SSH_KEY_TEST_PATH =
|
||||
; Path to ssh-keygen, default is 'ssh-keygen' and let shell find out which one to call.
|
||||
; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||
SSH_KEYGEN_PATH = ssh-keygen
|
||||
; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
||||
SSH_BACKUP_AUTHORIZED_KEYS = true
|
||||
|
@ -171,7 +173,7 @@ DISABLE_ROUTER_LOG = false
|
|||
; $ openssl pkcs12 -in cert.pfx -out key.pem -nocerts -nodes
|
||||
CERT_FILE = custom/https/cert.pem
|
||||
KEY_FILE = custom/https/key.pem
|
||||
; Upper level of template and static file path
|
||||
; Root directory containing templates and static files.
|
||||
; default is the path where Gitea is executed
|
||||
STATIC_ROOT_PATH =
|
||||
; Default path for App data
|
||||
|
@ -182,9 +184,9 @@ ENABLE_GZIP = false
|
|||
LANDING_PAGE = home
|
||||
; Enables git-lfs support. true or false, default is false.
|
||||
LFS_START_SERVER = false
|
||||
; Where your lfs files put on, default is data/lfs.
|
||||
; Where your lfs files reside, default is data/lfs.
|
||||
LFS_CONTENT_PATH = data/lfs
|
||||
; LFS authentication secret, changed this to yourself.
|
||||
; LFS authentication secret, change this yourself
|
||||
LFS_JWT_SECRET =
|
||||
|
||||
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
|
||||
|
@ -204,7 +206,7 @@ USER = root
|
|||
PASSWD =
|
||||
; For "postgres" only, either "disable", "require" or "verify-full"
|
||||
SSL_MODE = disable
|
||||
; For "sqlite3" and "tidb", use absolute path when you start as service
|
||||
; For "sqlite3" and "tidb", use absolute path when you start gitea as service
|
||||
PATH = data/gitea.db
|
||||
; For "sqlite3" only. Query timeout
|
||||
SQLITE_TIMEOUT = 500
|
||||
|
@ -222,7 +224,7 @@ UPDATE_BUFFER_LEN = 20
|
|||
MAX_FILE_SIZE = 1048576
|
||||
|
||||
[admin]
|
||||
; Disable regular (non-admin) users to create organizations
|
||||
; Disallow regular (non-admin) users from creating organizations.
|
||||
DISABLE_REGULAR_ORG_CREATION = false
|
||||
|
||||
[security]
|
||||
|
@ -230,13 +232,13 @@ DISABLE_REGULAR_ORG_CREATION = false
|
|||
INSTALL_LOCK = false
|
||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
|
||||
SECRET_KEY = !#@FDEWREWR&*(
|
||||
; Auto-login remember days
|
||||
; How long to remember that an user is logged in before requiring relogin (in days)
|
||||
LOGIN_REMEMBER_DAYS = 7
|
||||
COOKIE_USERNAME = gitea_awesome
|
||||
COOKIE_REMEMBER_NAME = gitea_incredible
|
||||
; Reverse proxy authentication header name of user name
|
||||
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
||||
; Sets the minimum password length for new Users
|
||||
; The minimum password length for new Users
|
||||
MIN_PASSWORD_LENGTH = 6
|
||||
; True when users are allowed to import local server paths
|
||||
IMPORT_LOCAL_PATHS = false
|
||||
|
@ -245,7 +247,7 @@ DISABLE_GIT_HOOKS = false
|
|||
|
||||
[openid]
|
||||
;
|
||||
; OpenID is an open standard and decentralized authentication protocol.
|
||||
; OpenID is an open, standard and decentralized authentication protocol.
|
||||
; Your identity is the address of a webpage you provide, which describes
|
||||
; how to prove you are in control of that page.
|
||||
;
|
||||
|
@ -264,7 +266,7 @@ DISABLE_GIT_HOOKS = false
|
|||
; Whether to allow signin in via OpenID
|
||||
ENABLE_OPENID_SIGNIN = true
|
||||
; Whether to allow registering via OpenID
|
||||
; Do not include to rely on DISABLE_REGISTRATION setting
|
||||
; Do not include to rely on rhw DISABLE_REGISTRATION setting
|
||||
;ENABLE_OPENID_SIGNUP = true
|
||||
; Allowed URI patterns (POSIX regexp).
|
||||
; Space separated.
|
||||
|
@ -280,12 +282,14 @@ BLACKLISTED_URIS =
|
|||
[service]
|
||||
; Time limit to confirm account/email registration
|
||||
ACTIVE_CODE_LIVE_MINUTES = 180
|
||||
; Time limit to confirm forgot password reset process
|
||||
; Time limit to perform the reset of a forgotten password
|
||||
RESET_PASSWD_CODE_LIVE_MINUTES = 180
|
||||
; User need to confirm e-mail for registration
|
||||
; Whether a new user needs to confirm their email when registering.
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
; Does not allow register and admin create account only
|
||||
; Disallow registration, only allow admins to create accounts.
|
||||
DISABLE_REGISTRATION = false
|
||||
; Allow registration only using third part services, it works only when DISABLE_REGISTRATION is false
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
|
||||
; User must sign in to view anything.
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
; Mail notification
|
||||
|
@ -296,10 +300,10 @@ ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
|
|||
; Enable captcha validation for registration
|
||||
ENABLE_CAPTCHA = true
|
||||
; Default value for KeepEmailPrivate
|
||||
; New user will get the value of this setting copied into their profile
|
||||
; Each new user will get the value of this setting copied into their profile
|
||||
DEFAULT_KEEP_EMAIL_PRIVATE = false
|
||||
; Default value for AllowCreateOrganization
|
||||
; New user will have rights set to create organizations depending on this setting
|
||||
; Every new user will have rights set to create organizations depending on this setting
|
||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
|
||||
; Enable Timetracking
|
||||
ENABLE_TIMETRACKING = true
|
||||
|
@ -307,10 +311,10 @@ ENABLE_TIMETRACKING = true
|
|||
; Repositories will use timetracking by default depending on this setting
|
||||
DEFAULT_ENABLE_TIMETRACKING = true
|
||||
; Default value for AllowOnlyContributorsToTrackTime
|
||||
; Only users with write permissions could track time if this is true
|
||||
; Only users with write permissions can track time if this is true
|
||||
DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = true
|
||||
; Default value for the domain part of the user's email address in the git log
|
||||
; if he has set KeepEmailPrivate true. The user's email replaced with a
|
||||
; if he has set KeepEmailPrivate to true. The user's email will be replaced with a
|
||||
; concatenation of the user name in lower case, "@" and NO_REPLY_ADDRESS.
|
||||
NO_REPLY_ADDRESS = noreply.example.org
|
||||
|
||||
|
@ -335,9 +339,9 @@ SUBJECT = %(APP_NAME)s
|
|||
; QQ: smtp.qq.com:465
|
||||
; Note, if the port ends with "465", SMTPS will be used. Using STARTTLS on port 587 is recommended per RFC 6409. If the server supports STARTTLS it will always be used.
|
||||
HOST =
|
||||
; Disable HELO operation when hostname are different.
|
||||
; Disable HELO operation when hostnames are different.
|
||||
DISABLE_HELO =
|
||||
; Custom hostname for HELO operation, default is from system.
|
||||
; Custom hostname for HELO operation, if no value is provided, one is retrieved from system.
|
||||
HELO_HOSTNAME =
|
||||
; Do not verify the certificate of the server. Only use this for self-signed certificates
|
||||
SKIP_VERIFY =
|
||||
|
@ -377,7 +381,7 @@ ITEM_TTL = 16h
|
|||
; Either "memory", "file", or "redis", default is "memory"
|
||||
PROVIDER = memory
|
||||
; Provider config options
|
||||
; memory: not have any config yet
|
||||
; memory: doesn't have any config yet
|
||||
; file: session file path, e.g. `data/sessions`
|
||||
; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||
; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
|
@ -398,11 +402,11 @@ AVATAR_UPLOAD_PATH = data/avatars
|
|||
; Chinese users can choose "duoshuo"
|
||||
; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
GRAVATAR_SOURCE = gravatar
|
||||
; This value will be forced to be true in offline mode.
|
||||
; This value will always be true in offline mode.
|
||||
DISABLE_GRAVATAR = false
|
||||
; Federated avatar lookup uses DNS to discover avatar associated
|
||||
; with emails, see https://www.libravatar.org
|
||||
; This value will be forced to be false in offline mode or Gravatar is disabled.
|
||||
; This value will always be false in offline mode or when Gravatar is disabled.
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[attachment]
|
||||
|
@ -412,9 +416,9 @@ ENABLE = true
|
|||
PATH = data/attachments
|
||||
; One or more allowed types, e.g. image/jpeg|image/png
|
||||
ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip
|
||||
; 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]
|
||||
|
@ -428,7 +432,7 @@ ROOT_PATH =
|
|||
; Either "console", "file", "conn", "smtp" or "database", default is "console"
|
||||
; Use comma to separate multiple modes, e.g. "console, file"
|
||||
MODE = console
|
||||
; Buffer length of channel, keep it as it is if you don't know what it is.
|
||||
; Buffer length of the channel, keep it as it is if you don't know what it is.
|
||||
BUFFER_LEN = 10000
|
||||
; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace"
|
||||
LEVEL = Trace
|
||||
|
@ -442,13 +446,13 @@ LEVEL =
|
|||
LEVEL =
|
||||
; This enables automated log rotate(switch of following options), default is true
|
||||
LOG_ROTATE = true
|
||||
; Max line number of single file, default is 1000000
|
||||
; Max number of lines in a single file, default is 1000000
|
||||
MAX_LINES = 1000000
|
||||
; Max size shift of single file, default is 28 means 1 << 28, 256MB
|
||||
; Max size shift of a single file, default is 28 means 1 << 28, 256MB
|
||||
MAX_SIZE_SHIFT = 28
|
||||
; Segment log daily, default is true
|
||||
DAILY_ROTATE = true
|
||||
; Expired days of log file(delete after max days), default is 7
|
||||
; delete the log file after n days, default is 7
|
||||
MAX_DAYS = 7
|
||||
|
||||
; For "conn" mode only
|
||||
|
@ -532,9 +536,9 @@ UPDATE_EXISTING = true
|
|||
[git]
|
||||
; Disables highlight of added and removed changes
|
||||
DISABLE_DIFF_HIGHLIGHT = false
|
||||
; Max number of lines allowed of a single file in diff view
|
||||
; Max number of lines allowed in a single file in diff view
|
||||
MAX_GIT_DIFF_LINES = 1000
|
||||
; Max number of characters of a line allowed in diff view
|
||||
; Max number of allowed characters in a line in diff view
|
||||
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
|
||||
; Max number of files shown in diff view
|
||||
MAX_GIT_DIFF_FILES = 100
|
||||
|
@ -559,7 +563,7 @@ MIN_INTERVAL = 10m
|
|||
[api]
|
||||
; Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
|
||||
ENABLE_SWAGGER_ENDPOINT = true
|
||||
; Max number of items will response in a page
|
||||
; Max number of items in a page
|
||||
MAX_RESPONSE_ITEMS = 50
|
||||
|
||||
[i18n]
|
||||
|
@ -598,7 +602,7 @@ ko-KR = ko
|
|||
SHOW_FOOTER_BRANDING = false
|
||||
; Show version information about Gitea and Go in the footer
|
||||
SHOW_FOOTER_VERSION = true
|
||||
; Show time of template execution in the footer
|
||||
; Show template execution time in the footer
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
||||
|
||||
[markup.asciidoc]
|
||||
|
@ -607,5 +611,5 @@ ENABLED = false
|
|||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
; External command to render all matching extensions
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
; Input is not a standard input but a file
|
||||
; Don't pass the file on STDIN, pass the filename as argument instead.
|
||||
IS_INPUT_FILE = false
|
||||
|
|
|
@ -201,8 +201,6 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
|||
## Cache (`cache`)
|
||||
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, or `memcache`.
|
||||
- To use `redis` or `memcache`, be sure to rebuild everything with build tags `redis` or
|
||||
`memcache`: `go build -tags='redis'`.
|
||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory cache only.
|
||||
- `HOST`: **\<empty\>**: Connection string for `redis` and `memcache`.
|
||||
- Redis: `network=tcp,addr=127.0.0.1:6379,password=macaron,db=0,pool_size=100,idle_timeout=180`
|
||||
|
|
611
docs/content/doc/features/comparison.en-us.md
Normal file
611
docs/content/doc/features/comparison.en-us.md
Normal file
|
@ -0,0 +1,611 @@
|
|||
---
|
||||
date: "2018-05-07T13:00:00+02:00"
|
||||
title: "Gitea compared to other Git hosting options"
|
||||
slug: "comparison"
|
||||
weight: 5
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "features"
|
||||
name: "Comparison"
|
||||
weight: 5
|
||||
identifier: "comparison"
|
||||
---
|
||||
|
||||
# Gitea compared to other Git hosting options
|
||||
|
||||
To help decide if Gitea is suited for your needs here is how it compares to other Git self hosted options.
|
||||
|
||||
Be warned that we don't regularly check for feature changes in other products so this list can be outdated. If you find anything that needs to be updated in table below please report [issue on Github](https://github.com/go-gitea/gitea/issues).
|
||||
|
||||
_Symbols used in table:_
|
||||
|
||||
* _✓ - supported_
|
||||
|
||||
* _⁄ - supported with limited functionality_
|
||||
|
||||
* _✘ - unsupported_
|
||||
|
||||
<table border="1" cellpadding="4">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Feature</td>
|
||||
<td>Gitea</td>
|
||||
<td>Gogs</td>
|
||||
<td>GitHub EE</td>
|
||||
<td>GitLab CE</td>
|
||||
<td>GitLab EE</td>
|
||||
<td>BitBucket</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Open source and free</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issue tracker</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pull/Merge requests</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Squash merging</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rebase merging</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>⁄</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pull/Merge request inline comments</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pull/Merge request approval</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Merge conflict resolution</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Restrict push and merge access to certain users</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Markdown support</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issues and pull/merge requests templates</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Revert specific commits or a merge request</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Labels</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time tracking</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Multiple assignees for issues</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Related issues</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>⁄</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Confidential issues</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Comment reactions</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Lock Discussion</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Batch issue handling</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issue Boards</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Create new branches from issues</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Commit graph</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Web code editor</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Branch manager</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Create new branches</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Repository topics</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Repository code search</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Global code search</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issue search</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Global issue search</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Git LFS 2.0</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>⁄</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Integrated Git-powered wiki</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Static Git-powered pages</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Group Milestones</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Granular user roles (Code, Issues, Wiki etc)</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cherry-picking changes</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GPG Signed Commits</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reject unsigned commits</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Verified Committer</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>?</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Subgroups: groups within groups</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Custom Git Hooks</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Repository Activity page</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deploy Tokens</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Repository Tokens with write rights</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Easy upgrade process</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Built-in Container Registry</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>External git mirroring</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AD / LDAP integration</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Multiple LDAP / AD server support</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LDAP user synchronization</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OpenId Connect support</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>OAuth 2.0 integration (external authorization)</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Act as OAuth 2.0 provider</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Two factor authentication (2FA)</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Webhook support</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mattermost/Slack integration</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>⁄</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Discord integration</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Built-in CI/CD</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>External CI/CD status display</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Multiple database support</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>⁄</td>
|
||||
<td>⁄</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Multiple OS support</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low resource usage (RAM/CPU)</td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
<td>✘</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
41
docs/content/doc/usage/issue-pull-request-templates.en-us.md
Normal file
41
docs/content/doc/usage/issue-pull-request-templates.en-us.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
date: "2018-05-10T16:00:00+02:00"
|
||||
title: "Usage: Issue and Pull Request templates"
|
||||
slug: "issue-pull-request-templates"
|
||||
weight: 15
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "usage"
|
||||
name: "Issue and Pull Request templates"
|
||||
weight: 15
|
||||
identifier: "issue-pull-request-templates"
|
||||
---
|
||||
|
||||
# Issue and Pull Request Templates
|
||||
|
||||
For some projects there are a standard list of questions that users need to be asked
|
||||
for creating an issue, or adding a pull request. Gitea supports adding templates to the
|
||||
main branch of the repository so that they can autopopulate the form when users are
|
||||
creating issues, and pull requests. This will cut down on the initial back and forth
|
||||
of getting some clarifiying details.
|
||||
|
||||
Possible file names for issue templates:
|
||||
|
||||
* ISSUE_TEMPLATE.md
|
||||
* issue_template.md
|
||||
* .gitea/ISSUE_TEMPLATE.md
|
||||
* .gitea/issue_template.md
|
||||
* .github/ISSUE_TEMPLATE.md
|
||||
* .github/issue_template.md
|
||||
|
||||
|
||||
Possible file names for PR templates:
|
||||
|
||||
* PULL_REQUEST_TEMPLATE.md
|
||||
* pull_request_template.md
|
||||
* .gitea/PULL_REQUEST_TEMPLATE.md
|
||||
* .gitea/pull_request_template.md
|
||||
* .github/PULL_REQUEST_TEMPLATE.md
|
||||
* .github/pull_request_template.md
|
194
integrations/auth_ldap_test.go
Normal file
194
integrations/auth_ldap_test.go
Normal file
|
@ -0,0 +1,194 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type ldapUser struct {
|
||||
UserName string
|
||||
Password string
|
||||
FullName string
|
||||
Email string
|
||||
OtherEmails []string
|
||||
IsAdmin bool
|
||||
SSHKeys []string
|
||||
}
|
||||
|
||||
var gitLDAPUsers = []ldapUser{
|
||||
{
|
||||
UserName: "professor",
|
||||
Password: "professor",
|
||||
FullName: "Hubert Farnsworth",
|
||||
Email: "professor@planetexpress.com",
|
||||
OtherEmails: []string{"hubert@planetexpress.com"},
|
||||
IsAdmin: true,
|
||||
},
|
||||
{
|
||||
UserName: "hermes",
|
||||
Password: "hermes",
|
||||
FullName: "Conrad Hermes",
|
||||
Email: "hermes@planetexpress.com",
|
||||
IsAdmin: true,
|
||||
},
|
||||
{
|
||||
UserName: "fry",
|
||||
Password: "fry",
|
||||
FullName: "Philip Fry",
|
||||
Email: "fry@planetexpress.com",
|
||||
},
|
||||
{
|
||||
UserName: "leela",
|
||||
Password: "leela",
|
||||
FullName: "Leela Turanga",
|
||||
Email: "leela@planetexpress.com",
|
||||
},
|
||||
{
|
||||
UserName: "bender",
|
||||
Password: "bender",
|
||||
FullName: "Bender Rodríguez",
|
||||
Email: "bender@planetexpress.com",
|
||||
},
|
||||
}
|
||||
|
||||
var otherLDAPUsers = []ldapUser{
|
||||
{
|
||||
UserName: "zoidberg",
|
||||
Password: "zoidberg",
|
||||
FullName: "John Zoidberg",
|
||||
Email: "zoidberg@planetexpress.com",
|
||||
},
|
||||
{
|
||||
UserName: "amy",
|
||||
Password: "amy",
|
||||
FullName: "Amy Kroker",
|
||||
Email: "amy@planetexpress.com",
|
||||
},
|
||||
}
|
||||
|
||||
func skipLDAPTests() bool {
|
||||
return os.Getenv("TEST_LDAP") != "1"
|
||||
}
|
||||
|
||||
func getLDAPServerHost() string {
|
||||
host := os.Getenv("TEST_LDAP_HOST")
|
||||
if len(host) == 0 {
|
||||
host = "ldap"
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
func addAuthSourceLDAP(t *testing.T) {
|
||||
session := loginUser(t, "user1")
|
||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", map[string]string{
|
||||
"_csrf": csrf,
|
||||
"type": "2",
|
||||
"name": "ldap",
|
||||
"host": getLDAPServerHost(),
|
||||
"port": "389",
|
||||
"bind_dn": "uid=gitea,ou=service,dc=planetexpress,dc=com",
|
||||
"bind_password": "password",
|
||||
"user_base": "ou=people,dc=planetexpress,dc=com",
|
||||
"filter": "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))",
|
||||
"admin_filter": "(memberOf=cn=admin_staff,ou=people,dc=planetexpress,dc=com)",
|
||||
"attribute_username": "uid",
|
||||
"attribute_name": "givenName",
|
||||
"attribute_surname": "sn",
|
||||
"attribute_mail": "mail",
|
||||
"is_sync_enabled": "on",
|
||||
"is_active": "on",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusFound)
|
||||
}
|
||||
|
||||
func TestLDAPUserSignin(t *testing.T) {
|
||||
if skipLDAPTests() {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
prepareTestEnv(t)
|
||||
addAuthSourceLDAP(t)
|
||||
|
||||
u := gitLDAPUsers[0]
|
||||
|
||||
session := loginUserWithPassword(t, u.UserName, u.Password)
|
||||
req := NewRequest(t, "GET", "/user/settings")
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
assert.Equal(t, u.UserName, htmlDoc.GetInputValueByName("name"))
|
||||
assert.Equal(t, u.FullName, htmlDoc.GetInputValueByName("full_name"))
|
||||
assert.Equal(t, u.Email, htmlDoc.GetInputValueByName("email"))
|
||||
}
|
||||
|
||||
func TestLDAPUserSync(t *testing.T) {
|
||||
if skipLDAPTests() {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
prepareTestEnv(t)
|
||||
addAuthSourceLDAP(t)
|
||||
models.SyncExternalUsers()
|
||||
|
||||
session := loginUser(t, "user1")
|
||||
// Check if users exists
|
||||
for _, u := range gitLDAPUsers {
|
||||
req := NewRequest(t, "GET", "/admin/users?q="+u.UserName)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
tr := htmlDoc.doc.Find("table.table tbody tr")
|
||||
if !assert.True(t, tr.Length() == 1) {
|
||||
continue
|
||||
}
|
||||
tds := tr.Find("td")
|
||||
if !assert.True(t, tds.Length() > 0) {
|
||||
continue
|
||||
}
|
||||
assert.Equal(t, u.UserName, strings.TrimSpace(tds.Find("td:nth-child(2) a").Text()))
|
||||
assert.Equal(t, u.Email, strings.TrimSpace(tds.Find("td:nth-child(3) span").Text()))
|
||||
if u.IsAdmin {
|
||||
assert.True(t, tds.Find("td:nth-child(5) i").HasClass("fa-check-square-o"))
|
||||
} else {
|
||||
assert.True(t, tds.Find("td:nth-child(5) i").HasClass("fa-square-o"))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if no users exist
|
||||
for _, u := range otherLDAPUsers {
|
||||
req := NewRequest(t, "GET", "/admin/users?q="+u.UserName)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
|
||||
tr := htmlDoc.doc.Find("table.table tbody tr")
|
||||
assert.True(t, tr.Length() == 0)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLDAPUserSigninFailed(t *testing.T) {
|
||||
if skipLDAPTests() {
|
||||
t.Skip()
|
||||
return
|
||||
}
|
||||
prepareTestEnv(t)
|
||||
addAuthSourceLDAP(t)
|
||||
|
||||
u := otherLDAPUsers[0]
|
||||
|
||||
testLoginFailed(t, u.UserName, u.Password, i18n.Tr("en", "form.username_password_incorrect"))
|
||||
}
|
|
@ -733,6 +733,22 @@ func (err ErrRepoFileAlreadyExist) Error() string {
|
|||
return fmt.Sprintf("repository file already exists [file_name: %s]", err.FileName)
|
||||
}
|
||||
|
||||
// ErrUserDoesNotHaveAccessToRepo represets an error where the user doesn't has access to a given repo
|
||||
type ErrUserDoesNotHaveAccessToRepo struct {
|
||||
UserID int64
|
||||
RepoName string
|
||||
}
|
||||
|
||||
// IsErrUserDoesNotHaveAccessToRepo checks if an error is a ErrRepoFileAlreadyExist.
|
||||
func IsErrUserDoesNotHaveAccessToRepo(err error) bool {
|
||||
_, ok := err.(ErrUserDoesNotHaveAccessToRepo)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserDoesNotHaveAccessToRepo) Error() string {
|
||||
return fmt.Sprintf("user doesn't have acces to repo [user_id: %d, repo_name: %s]", err.UserID, err.RepoName)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \____________ ____ ____ | |__
|
||||
// | | _/\_ __ \__ \ / \_/ ___\| | \
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
repo_id: 1
|
||||
index: 1
|
||||
poster_id: 1
|
||||
assignee_id: 1
|
||||
name: issue1
|
||||
content: content for the first issue
|
||||
is_closed: false
|
||||
|
@ -67,7 +66,6 @@
|
|||
repo_id: 3
|
||||
index: 1
|
||||
poster_id: 1
|
||||
assignee_id: 1
|
||||
name: issue6
|
||||
content: content6
|
||||
is_closed: false
|
||||
|
|
8
models/fixtures/issue_assignees.yml
Normal file
8
models/fixtures/issue_assignees.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
-
|
||||
id: 1
|
||||
assignee_id: 1
|
||||
issue_id: 1
|
||||
-
|
||||
id: 2
|
||||
assignee_id: 1
|
||||
issue_id: 6
|
|
@ -3,7 +3,6 @@
|
|||
uid: 1
|
||||
issue_id: 1
|
||||
is_read: true
|
||||
is_assigned: true
|
||||
is_mentioned: false
|
||||
|
||||
-
|
||||
|
@ -11,7 +10,6 @@
|
|||
uid: 2
|
||||
issue_id: 1
|
||||
is_read: true
|
||||
is_assigned: false
|
||||
is_mentioned: false
|
||||
|
||||
-
|
||||
|
@ -19,5 +17,4 @@
|
|||
uid: 4
|
||||
issue_id: 1
|
||||
is_read: false
|
||||
is_assigned: false
|
||||
is_mentioned: false
|
||||
|
|
1
models/fixtures/login_source.yml
Normal file
1
models/fixtures/login_source.yml
Normal file
|
@ -0,0 +1 @@
|
|||
[] # empty
|
159
models/issue.go
159
models/issue.go
|
@ -37,7 +37,7 @@ type Issue struct {
|
|||
MilestoneID int64 `xorm:"INDEX"`
|
||||
Milestone *Milestone `xorm:"-"`
|
||||
Priority int
|
||||
AssigneeID int64 `xorm:"INDEX"`
|
||||
AssigneeID int64 `xorm:"-"`
|
||||
Assignee *User `xorm:"-"`
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
IsRead bool `xorm:"-"`
|
||||
|
@ -56,6 +56,7 @@ type Issue struct {
|
|||
Comments []*Comment `xorm:"-"`
|
||||
Reactions ReactionList `xorm:"-"`
|
||||
TotalTrackedTime int64 `xorm:"-"`
|
||||
Assignees []*User `xorm:"-"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -140,22 +141,6 @@ func (issue *Issue) loadPoster(e Engine) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (issue *Issue) loadAssignee(e Engine) (err error) {
|
||||
if issue.Assignee == nil && issue.AssigneeID > 0 {
|
||||
issue.Assignee, err = getUserByID(e, issue.AssigneeID)
|
||||
if err != nil {
|
||||
issue.AssigneeID = -1
|
||||
issue.Assignee = NewGhostUser()
|
||||
if !IsErrUserNotExist(err) {
|
||||
return fmt.Errorf("getUserByID.(assignee) [%d]: %v", issue.AssigneeID, err)
|
||||
}
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (issue *Issue) loadPullRequest(e Engine) (err error) {
|
||||
if issue.IsPull && issue.PullRequest == nil {
|
||||
issue.PullRequest, err = getPullRequestByIssueID(e, issue.ID)
|
||||
|
@ -231,7 +216,7 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if err = issue.loadAssignee(e); err != nil {
|
||||
if err = issue.loadAssignees(e); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -343,8 +328,11 @@ func (issue *Issue) APIFormat() *api.Issue {
|
|||
if issue.Milestone != nil {
|
||||
apiIssue.Milestone = issue.Milestone.APIFormat()
|
||||
}
|
||||
if issue.Assignee != nil {
|
||||
apiIssue.Assignee = issue.Assignee.APIFormat()
|
||||
if len(issue.Assignees) > 0 {
|
||||
for _, assignee := range issue.Assignees {
|
||||
apiIssue.Assignees = append(apiIssue.Assignees, assignee.APIFormat())
|
||||
}
|
||||
apiIssue.Assignee = issue.Assignees[0].APIFormat() // For compatibility, we're keeping the first assignee as `apiIssue.Assignee`
|
||||
}
|
||||
if issue.IsPull {
|
||||
apiIssue.PullRequest = &api.PullRequestMeta{
|
||||
|
@ -605,19 +593,6 @@ func (issue *Issue) ReplaceLabels(labels []*Label, doer *User) (err error) {
|
|||
return sess.Commit()
|
||||
}
|
||||
|
||||
// GetAssignee sets the Assignee attribute of this issue.
|
||||
func (issue *Issue) GetAssignee() (err error) {
|
||||
if issue.AssigneeID == 0 || issue.Assignee != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
issue.Assignee, err = GetUserByID(issue.AssigneeID)
|
||||
if IsErrUserNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ReadBy sets issue to be read by given user.
|
||||
func (issue *Issue) ReadBy(userID int64) error {
|
||||
if err := UpdateIssueUserByRead(userID, issue.ID); err != nil {
|
||||
|
@ -823,55 +798,6 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ChangeAssignee changes the Assignee field of this issue.
|
||||
func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
|
||||
var oldAssigneeID = issue.AssigneeID
|
||||
issue.AssigneeID = assigneeID
|
||||
if err = UpdateIssueUserByAssignee(issue); err != nil {
|
||||
return fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err = issue.loadRepo(sess); err != nil {
|
||||
return fmt.Errorf("loadRepo: %v", err)
|
||||
}
|
||||
|
||||
if _, err = createAssigneeComment(sess, doer, issue.Repo, issue, oldAssigneeID, assigneeID); err != nil {
|
||||
return fmt.Errorf("createAssigneeComment: %v", err)
|
||||
}
|
||||
|
||||
issue.Assignee, err = GetUserByID(issue.AssigneeID)
|
||||
if err != nil && !IsErrUserNotExist(err) {
|
||||
log.Error(4, "GetUserByID [assignee_id: %v]: %v", issue.AssigneeID, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Error not nil here means user does not exist, which is remove assignee.
|
||||
isRemoveAssignee := err != nil
|
||||
if issue.IsPull {
|
||||
issue.PullRequest.Issue = issue
|
||||
apiPullRequest := &api.PullRequestPayload{
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Sender: doer.APIFormat(),
|
||||
}
|
||||
if isRemoveAssignee {
|
||||
apiPullRequest.Action = api.HookIssueUnassigned
|
||||
} else {
|
||||
apiPullRequest.Action = api.HookIssueAssigned
|
||||
}
|
||||
if err := PrepareWebhooks(issue.Repo, HookEventPullRequest, apiPullRequest); err != nil {
|
||||
log.Error(4, "PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, isRemoveAssignee, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
go HookQueue.Add(issue.RepoID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTasks returns the amount of tasks in the issues content
|
||||
func (issue *Issue) GetTasks() int {
|
||||
return len(issueTasksPat.FindAllStringIndex(issue.Content, -1))
|
||||
|
@ -887,6 +813,7 @@ type NewIssueOptions struct {
|
|||
Repo *Repository
|
||||
Issue *Issue
|
||||
LabelIDs []int64
|
||||
AssigneeIDs []int64
|
||||
Attachments []string // In UUID format.
|
||||
IsPull bool
|
||||
}
|
||||
|
@ -909,14 +836,32 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if assigneeID := opts.Issue.AssigneeID; assigneeID > 0 {
|
||||
valid, err := hasAccess(e, assigneeID, opts.Repo, AccessModeWrite)
|
||||
if err != nil {
|
||||
return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", assigneeID, opts.Repo.ID, err)
|
||||
// Keep the old assignee id thingy for compatibility reasons
|
||||
if opts.Issue.AssigneeID > 0 {
|
||||
isAdded := false
|
||||
// Check if the user has already been passed to issue.AssigneeIDs, if not, add it
|
||||
for _, aID := range opts.AssigneeIDs {
|
||||
if aID == opts.Issue.AssigneeID {
|
||||
isAdded = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !valid {
|
||||
opts.Issue.AssigneeID = 0
|
||||
opts.Issue.Assignee = nil
|
||||
|
||||
if !isAdded {
|
||||
opts.AssigneeIDs = append(opts.AssigneeIDs, opts.Issue.AssigneeID)
|
||||
}
|
||||
}
|
||||
|
||||
// Check for and validate assignees
|
||||
if len(opts.AssigneeIDs) > 0 {
|
||||
for _, assigneeID := range opts.AssigneeIDs {
|
||||
valid, err := hasAccess(e, assigneeID, opts.Repo, AccessModeWrite)
|
||||
if err != nil {
|
||||
return fmt.Errorf("hasAccess [user_id: %d, repo_id: %d]: %v", assigneeID, opts.Repo.ID, err)
|
||||
}
|
||||
if !valid {
|
||||
return ErrUserDoesNotHaveAccessToRepo{UserID: assigneeID, RepoName: opts.Repo.Name}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -931,11 +876,10 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if opts.Issue.AssigneeID > 0 {
|
||||
if err = opts.Issue.loadRepo(e); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = createAssigneeComment(e, doer, opts.Issue.Repo, opts.Issue, -1, opts.Issue.AssigneeID); err != nil {
|
||||
// Insert the assignees
|
||||
for _, assigneeID := range opts.AssigneeIDs {
|
||||
err = opts.Issue.changeAssignee(e, doer, assigneeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -995,7 +939,7 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
|
|||
}
|
||||
|
||||
// NewIssue creates new issue with labels for repository.
|
||||
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, assigneeIDs []int64, uuids []string) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
|
@ -1007,7 +951,11 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
|
|||
Issue: issue,
|
||||
LabelIDs: labelIDs,
|
||||
Attachments: uuids,
|
||||
AssigneeIDs: assigneeIDs,
|
||||
}); err != nil {
|
||||
if IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %v", err)
|
||||
}
|
||||
|
||||
|
@ -1150,7 +1098,8 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) error {
|
|||
}
|
||||
|
||||
if opts.AssigneeID > 0 {
|
||||
sess.And("issue.assignee_id=?", opts.AssigneeID)
|
||||
sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", opts.AssigneeID)
|
||||
}
|
||||
|
||||
if opts.PosterID > 0 {
|
||||
|
@ -1372,7 +1321,8 @@ func GetIssueStats(opts *IssueStatsOptions) (*IssueStats, error) {
|
|||
}
|
||||
|
||||
if opts.AssigneeID > 0 {
|
||||
sess.And("issue.assignee_id = ?", opts.AssigneeID)
|
||||
sess.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", opts.AssigneeID)
|
||||
}
|
||||
|
||||
if opts.PosterID > 0 {
|
||||
|
@ -1438,13 +1388,15 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
|
|||
}
|
||||
case FilterModeAssign:
|
||||
stats.OpenCount, err = x.Where(cond).And("is_closed = ?", false).
|
||||
And("assignee_id = ?", opts.UserID).
|
||||
Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", opts.UserID).
|
||||
Count(new(Issue))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stats.ClosedCount, err = x.Where(cond).And("is_closed = ?", true).
|
||||
And("assignee_id = ?", opts.UserID).
|
||||
Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", opts.UserID).
|
||||
Count(new(Issue))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1466,7 +1418,8 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
|
|||
|
||||
cond = cond.And(builder.Eq{"issue.is_closed": opts.IsClosed})
|
||||
stats.AssignCount, err = x.Where(cond).
|
||||
And("assignee_id = ?", opts.UserID).
|
||||
Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", opts.UserID).
|
||||
Count(new(Issue))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1505,8 +1458,10 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen
|
|||
|
||||
switch filterMode {
|
||||
case FilterModeAssign:
|
||||
openCountSession.And("assignee_id = ?", uid)
|
||||
closedCountSession.And("assignee_id = ?", uid)
|
||||
openCountSession.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", uid)
|
||||
closedCountSession.Join("INNER", "issue_assignees", "issue.id = issue_assignees.issue_id").
|
||||
And("issue_assignees.assignee_id = ?", uid)
|
||||
case FilterModeCreate:
|
||||
openCountSession.And("poster_id = ?", uid)
|
||||
closedCountSession.And("poster_id = ?", uid)
|
||||
|
|
263
models/issue_assignees.go
Normal file
263
models/issue_assignees.go
Normal file
|
@ -0,0 +1,263 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
// IssueAssignees saves all issue assignees
|
||||
type IssueAssignees struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
AssigneeID int64 `xorm:"INDEX"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
// This loads all assignees of an issue
|
||||
func (issue *Issue) loadAssignees(e Engine) (err error) {
|
||||
// Reset maybe preexisting assignees
|
||||
issue.Assignees = []*User{}
|
||||
|
||||
err = e.Table("`user`").
|
||||
Join("INNER", "issue_assignees", "assignee_id = `user`.id").
|
||||
Where("issue_assignees.issue_id = ?", issue.ID).
|
||||
Find(&issue.Assignees)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if we have at least one assignee and if yes put it in as `Assignee`
|
||||
if len(issue.Assignees) > 0 {
|
||||
issue.Assignee = issue.Assignees[0]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetAssigneesByIssue returns everyone assigned to that issue
|
||||
func GetAssigneesByIssue(issue *Issue) (assignees []*User, err error) {
|
||||
err = issue.loadAssignees(x)
|
||||
if err != nil {
|
||||
return assignees, err
|
||||
}
|
||||
|
||||
return issue.Assignees, nil
|
||||
}
|
||||
|
||||
// IsUserAssignedToIssue returns true when the user is assigned to the issue
|
||||
func IsUserAssignedToIssue(issue *Issue, user *User) (isAssigned bool, err error) {
|
||||
isAssigned, err = x.Exist(&IssueAssignees{IssueID: issue.ID, AssigneeID: user.ID})
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteNotPassedAssignee deletes all assignees who aren't passed via the "assignees" array
|
||||
func DeleteNotPassedAssignee(issue *Issue, doer *User, assignees []*User) (err error) {
|
||||
var found bool
|
||||
|
||||
for _, assignee := range issue.Assignees {
|
||||
|
||||
found = false
|
||||
for _, alreadyAssignee := range assignees {
|
||||
if assignee.ID == alreadyAssignee.ID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
// This function also does comments and hooks, which is why we call it seperatly instead of directly removing the assignees here
|
||||
if err := UpdateAssignee(issue, doer, assignee.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MakeAssigneeList concats a string with all names of the assignees. Useful for logs.
|
||||
func MakeAssigneeList(issue *Issue) (assigneeList string, err error) {
|
||||
err = issue.loadAssignees(x)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for in, assignee := range issue.Assignees {
|
||||
assigneeList += assignee.Name
|
||||
|
||||
if len(issue.Assignees) > (in + 1) {
|
||||
assigneeList += ", "
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ClearAssigneeByUserID deletes all assignments of an user
|
||||
func clearAssigneeByUserID(sess *xorm.Session, userID int64) (err error) {
|
||||
_, err = sess.Delete(&IssueAssignees{AssigneeID: userID})
|
||||
return
|
||||
}
|
||||
|
||||
// AddAssigneeIfNotAssigned adds an assignee only if he isn't aleady assigned to the issue
|
||||
func AddAssigneeIfNotAssigned(issue *Issue, doer *User, assigneeID int64) (err error) {
|
||||
// Check if the user is already assigned
|
||||
isAssigned, err := IsUserAssignedToIssue(issue, &User{ID: assigneeID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !isAssigned {
|
||||
return issue.ChangeAssignee(doer, assigneeID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAssignee deletes or adds an assignee to an issue
|
||||
func UpdateAssignee(issue *Issue, doer *User, assigneeID int64) (err error) {
|
||||
return issue.ChangeAssignee(doer, assigneeID)
|
||||
}
|
||||
|
||||
// ChangeAssignee changes the Assignee of this issue.
|
||||
func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := issue.changeAssignee(sess, doer, assigneeID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64) (err error) {
|
||||
|
||||
// Update the assignee
|
||||
removed, err := updateIssueAssignee(sess, issue, assigneeID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("UpdateIssueUserByAssignee: %v", err)
|
||||
}
|
||||
|
||||
// Repo infos
|
||||
if err = issue.loadRepo(sess); err != nil {
|
||||
return fmt.Errorf("loadRepo: %v", err)
|
||||
}
|
||||
|
||||
// Comment
|
||||
if _, err = createAssigneeComment(sess, doer, issue.Repo, issue, assigneeID, removed); err != nil {
|
||||
return fmt.Errorf("createAssigneeComment: %v", err)
|
||||
}
|
||||
|
||||
if issue.IsPull {
|
||||
issue.PullRequest = &PullRequest{Issue: issue}
|
||||
apiPullRequest := &api.PullRequestPayload{
|
||||
Index: issue.Index,
|
||||
PullRequest: issue.PullRequest.APIFormat(),
|
||||
Repository: issue.Repo.APIFormat(AccessModeNone),
|
||||
Sender: doer.APIFormat(),
|
||||
}
|
||||
if removed {
|
||||
apiPullRequest.Action = api.HookIssueUnassigned
|
||||
} else {
|
||||
apiPullRequest.Action = api.HookIssueAssigned
|
||||
}
|
||||
if err := PrepareWebhooks(issue.Repo, HookEventPullRequest, apiPullRequest); err != nil {
|
||||
log.Error(4, "PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
go HookQueue.Add(issue.RepoID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAPIAssignee is a helper function to add or delete one or multiple issue assignee(s)
|
||||
// Deleting is done the Github way (quote from their api documentation):
|
||||
// https://developer.github.com/v3/issues/#edit-an-issue
|
||||
// "assignees" (array): Logins for Users to assign to this issue.
|
||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
func UpdateAPIAssignee(issue *Issue, oneAssignee string, multipleAssignees []string, doer *User) (err error) {
|
||||
var allNewAssignees []*User
|
||||
|
||||
// Keep the old assignee thingy for compatibility reasons
|
||||
if oneAssignee != "" {
|
||||
// Prevent double adding assignees
|
||||
var isDouble bool
|
||||
for _, assignee := range multipleAssignees {
|
||||
if assignee == oneAssignee {
|
||||
isDouble = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isDouble {
|
||||
multipleAssignees = append(multipleAssignees, oneAssignee)
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through all assignees to add them
|
||||
for _, assigneeName := range multipleAssignees {
|
||||
assignee, err := GetUserByName(assigneeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allNewAssignees = append(allNewAssignees, assignee)
|
||||
}
|
||||
|
||||
// Delete all old assignees not passed
|
||||
if err = DeleteNotPassedAssignee(issue, doer, allNewAssignees); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add all new assignees
|
||||
// Update the assignee. The function will check if the user exists, is already
|
||||
// assigned (which he shouldn't as we deleted all assignees before) and
|
||||
// has access to the repo.
|
||||
for _, assignee := range allNewAssignees {
|
||||
// Extra method to prevent double adding (which would result in removing)
|
||||
err = AddAssigneeIfNotAssigned(issue, doer, assignee.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
|
||||
func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) {
|
||||
|
||||
// Keeping the old assigning method for compatibility reasons
|
||||
if oneAssignee != "" {
|
||||
|
||||
// Prevent double adding assignees
|
||||
var isDouble bool
|
||||
for _, assignee := range multipleAssignees {
|
||||
if assignee == oneAssignee {
|
||||
isDouble = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isDouble {
|
||||
multipleAssignees = append(multipleAssignees, oneAssignee)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the IDs of all assignees
|
||||
assigneeIDs = GetUserIDsByNames(multipleAssignees)
|
||||
|
||||
return
|
||||
}
|
71
models/issue_assignees_test.go
Normal file
71
models/issue_assignees_test.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2018 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUpdateAssignee(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
|
||||
// Fake issue with assignees
|
||||
issue, err := GetIssueByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Assign multiple users
|
||||
user2, err := GetUserByID(2)
|
||||
assert.NoError(t, err)
|
||||
err = UpdateAssignee(issue, &User{ID: 1}, user2.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
user3, err := GetUserByID(3)
|
||||
assert.NoError(t, err)
|
||||
err = UpdateAssignee(issue, &User{ID: 1}, user3.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
user1, err := GetUserByID(1) // This user is already assigned (see the definition in fixtures), so running UpdateAssignee should unassign him
|
||||
assert.NoError(t, err)
|
||||
err = UpdateAssignee(issue, &User{ID: 1}, user1.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if he got removed
|
||||
isAssigned, err := IsUserAssignedToIssue(issue, user1)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isAssigned)
|
||||
|
||||
// Check if they're all there
|
||||
assignees, err := GetAssigneesByIssue(issue)
|
||||
assert.NoError(t, err)
|
||||
|
||||
var expectedAssignees []*User
|
||||
expectedAssignees = append(expectedAssignees, user2)
|
||||
expectedAssignees = append(expectedAssignees, user3)
|
||||
|
||||
for in, assignee := range assignees {
|
||||
assert.Equal(t, assignee.ID, expectedAssignees[in].ID)
|
||||
}
|
||||
|
||||
// Check if the user is assigned
|
||||
isAssigned, err = IsUserAssignedToIssue(issue, user2)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, isAssigned)
|
||||
|
||||
// This user should not be assigned
|
||||
isAssigned, err = IsUserAssignedToIssue(issue, &User{ID: 4})
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, isAssigned)
|
||||
|
||||
// Clean everyone
|
||||
err = DeleteNotPassedAssignee(issue, user1, []*User{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check they're gone
|
||||
assignees, err = GetAssigneesByIssue(issue)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(assignees))
|
||||
}
|
|
@ -88,23 +88,22 @@ const (
|
|||
|
||||
// Comment represents a comment in commit and issue page.
|
||||
type Comment struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type CommentType
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
Poster *User `xorm:"-"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
LabelID int64
|
||||
Label *Label `xorm:"-"`
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldMilestone *Milestone `xorm:"-"`
|
||||
Milestone *Milestone `xorm:"-"`
|
||||
OldAssigneeID int64
|
||||
AssigneeID int64
|
||||
Assignee *User `xorm:"-"`
|
||||
OldAssignee *User `xorm:"-"`
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type CommentType
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
Poster *User `xorm:"-"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
LabelID int64
|
||||
Label *Label `xorm:"-"`
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldMilestone *Milestone `xorm:"-"`
|
||||
Milestone *Milestone `xorm:"-"`
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
Assignee *User `xorm:"-"`
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
|
||||
CommitID int64
|
||||
Line int64 // - previous line / + proposed line
|
||||
|
@ -259,18 +258,9 @@ func (c *Comment) LoadMilestone() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// LoadAssignees if comment.Type is CommentTypeAssignees, then load assignees
|
||||
func (c *Comment) LoadAssignees() error {
|
||||
// LoadAssigneeUser if comment.Type is CommentTypeAssignees, then load assignees
|
||||
func (c *Comment) LoadAssigneeUser() error {
|
||||
var err error
|
||||
if c.OldAssigneeID > 0 {
|
||||
c.OldAssignee, err = getUserByID(x, c.OldAssigneeID)
|
||||
if err != nil {
|
||||
if !IsErrUserNotExist(err) {
|
||||
return err
|
||||
}
|
||||
c.OldAssignee = NewGhostUser()
|
||||
}
|
||||
}
|
||||
|
||||
if c.AssigneeID > 0 {
|
||||
c.Assignee, err = getUserByID(x, c.AssigneeID)
|
||||
|
@ -382,21 +372,21 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
|||
LabelID = opts.Label.ID
|
||||
}
|
||||
comment := &Comment{
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.ID,
|
||||
Poster: opts.Doer,
|
||||
IssueID: opts.Issue.ID,
|
||||
LabelID: LabelID,
|
||||
OldMilestoneID: opts.OldMilestoneID,
|
||||
MilestoneID: opts.MilestoneID,
|
||||
OldAssigneeID: opts.OldAssigneeID,
|
||||
AssigneeID: opts.AssigneeID,
|
||||
CommitID: opts.CommitID,
|
||||
CommitSHA: opts.CommitSHA,
|
||||
Line: opts.LineNum,
|
||||
Content: opts.Content,
|
||||
OldTitle: opts.OldTitle,
|
||||
NewTitle: opts.NewTitle,
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.ID,
|
||||
Poster: opts.Doer,
|
||||
IssueID: opts.Issue.ID,
|
||||
LabelID: LabelID,
|
||||
OldMilestoneID: opts.OldMilestoneID,
|
||||
MilestoneID: opts.MilestoneID,
|
||||
RemovedAssignee: opts.RemovedAssignee,
|
||||
AssigneeID: opts.AssigneeID,
|
||||
CommitID: opts.CommitID,
|
||||
CommitSHA: opts.CommitSHA,
|
||||
Line: opts.LineNum,
|
||||
Content: opts.Content,
|
||||
OldTitle: opts.OldTitle,
|
||||
NewTitle: opts.NewTitle,
|
||||
TreePath: opts.TreePath,
|
||||
ReviewID: opts.ReviewID,
|
||||
}
|
||||
|
@ -540,14 +530,14 @@ func createMilestoneComment(e *xorm.Session, doer *User, repo *Repository, issue
|
|||
})
|
||||
}
|
||||
|
||||
func createAssigneeComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, oldAssigneeID, assigneeID int64) (*Comment, error) {
|
||||
func createAssigneeComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue, assigneeID int64, removedAssignee bool) (*Comment, error) {
|
||||
return createComment(e, &CreateCommentOptions{
|
||||
Type: CommentTypeAssignees,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
Issue: issue,
|
||||
OldAssigneeID: oldAssigneeID,
|
||||
AssigneeID: assigneeID,
|
||||
Type: CommentTypeAssignees,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
Issue: issue,
|
||||
RemovedAssignee: removedAssignee,
|
||||
AssigneeID: assigneeID,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -608,19 +598,19 @@ type CreateCommentOptions struct {
|
|||
Issue *Issue
|
||||
Label *Label
|
||||
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldAssigneeID int64
|
||||
AssigneeID int64
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
CommitID int64
|
||||
CommitSHA string
|
||||
LineNum int64
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
CommitID int64
|
||||
CommitSHA string
|
||||
LineNum int64
|
||||
TreePath string
|
||||
ReviewID int64
|
||||
Content string
|
||||
Attachments []string // UUIDs of attachments
|
||||
Content string
|
||||
Attachments []string // UUIDs of attachments
|
||||
}
|
||||
|
||||
// CreateComment creates comment of issue or commit.
|
||||
|
|
|
@ -154,38 +154,38 @@ func (issues IssueList) loadMilestones(e Engine) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (issues IssueList) getAssigneeIDs() []int64 {
|
||||
var ids = make(map[int64]struct{}, len(issues))
|
||||
for _, issue := range issues {
|
||||
if _, ok := ids[issue.AssigneeID]; !ok {
|
||||
ids[issue.AssigneeID] = struct{}{}
|
||||
}
|
||||
}
|
||||
return keysInt64(ids)
|
||||
}
|
||||
|
||||
func (issues IssueList) loadAssignees(e Engine) error {
|
||||
assigneeIDs := issues.getAssigneeIDs()
|
||||
if len(assigneeIDs) == 0 {
|
||||
if len(issues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
assigneeMaps := make(map[int64]*User, len(assigneeIDs))
|
||||
err := e.
|
||||
In("id", assigneeIDs).
|
||||
Find(&assigneeMaps)
|
||||
type AssigneeIssue struct {
|
||||
IssueAssignee *IssueAssignees `xorm:"extends"`
|
||||
Assignee *User `xorm:"extends"`
|
||||
}
|
||||
|
||||
var assignees = make(map[int64][]*User, len(issues))
|
||||
rows, err := e.Table("issue_assignees").
|
||||
Join("INNER", "user", "`user`.id = `issue_assignees`.assignee_id").
|
||||
In("`issue_assignees`.issue_id", issues.getIssueIDs()).
|
||||
Rows(new(AssigneeIssue))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var assigneeIssue AssigneeIssue
|
||||
err = rows.Scan(&assigneeIssue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
assignees[assigneeIssue.IssueAssignee.IssueID] = append(assignees[assigneeIssue.IssueAssignee.IssueID], assigneeIssue.Assignee)
|
||||
}
|
||||
|
||||
for _, issue := range issues {
|
||||
if issue.AssigneeID <= 0 {
|
||||
continue
|
||||
}
|
||||
var ok bool
|
||||
if issue.Assignee, ok = assigneeMaps[issue.AssigneeID]; !ok {
|
||||
issue.Assignee = NewGhostUser()
|
||||
}
|
||||
issue.Assignees = assignees[issue.ID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -46,9 +46,16 @@ func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content
|
|||
participants = append(participants, issue.Poster)
|
||||
}
|
||||
|
||||
// Assignee must receive any communications
|
||||
if issue.Assignee != nil && issue.AssigneeID > 0 && issue.AssigneeID != doer.ID {
|
||||
participants = append(participants, issue.Assignee)
|
||||
// Assignees must receive any communications
|
||||
assignees, err := GetAssigneesByIssue(issue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, assignee := range assignees {
|
||||
if assignee.ID != doer.ID {
|
||||
participants = append(participants, assignee)
|
||||
}
|
||||
}
|
||||
|
||||
tos := make([]string, 0, len(watchers)) // List of email addresses.
|
||||
|
|
|
@ -24,7 +24,7 @@ type Milestone struct {
|
|||
NumClosedIssues int
|
||||
NumOpenIssues int `xorm:"-"`
|
||||
Completeness int // Percentage(1-100).
|
||||
IsOverDue bool `xorm:"-"`
|
||||
IsOverdue bool `xorm:"-"`
|
||||
|
||||
DeadlineString string `xorm:"-"`
|
||||
DeadlineUnix util.TimeStamp
|
||||
|
@ -52,7 +52,7 @@ func (m *Milestone) AfterLoad() {
|
|||
|
||||
m.DeadlineString = m.DeadlineUnix.Format("2006-01-02")
|
||||
if util.TimeStampNow() >= m.DeadlineUnix {
|
||||
m.IsOverDue = true
|
||||
m.IsOverdue = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ package models
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
// IssueUser represents an issue-user relation.
|
||||
|
@ -14,7 +16,6 @@ type IssueUser struct {
|
|||
UID int64 `xorm:"INDEX"` // User ID.
|
||||
IssueID int64
|
||||
IsRead bool
|
||||
IsAssigned bool
|
||||
IsMentioned bool
|
||||
}
|
||||
|
||||
|
@ -32,9 +33,8 @@ func newIssueUsers(e Engine, repo *Repository, issue *Issue) error {
|
|||
issueUsers := make([]*IssueUser, 0, len(assignees)+1)
|
||||
for _, assignee := range assignees {
|
||||
issueUsers = append(issueUsers, &IssueUser{
|
||||
IssueID: issue.ID,
|
||||
UID: assignee.ID,
|
||||
IsAssigned: assignee.ID == issue.AssigneeID,
|
||||
IssueID: issue.ID,
|
||||
UID: assignee.ID,
|
||||
})
|
||||
isPosterAssignee = isPosterAssignee || assignee.ID == issue.PosterID
|
||||
}
|
||||
|
@ -51,34 +51,38 @@ func newIssueUsers(e Engine, repo *Repository, issue *Issue) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func updateIssueUserByAssignee(e Engine, issue *Issue) (err error) {
|
||||
if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE issue_id = ?", false, issue.ID); err != nil {
|
||||
return err
|
||||
func updateIssueAssignee(e *xorm.Session, issue *Issue, assigneeID int64) (removed bool, err error) {
|
||||
|
||||
// Check if the user exists
|
||||
_, err = GetUserByID(assigneeID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Assignee ID equals to 0 means clear assignee.
|
||||
if issue.AssigneeID > 0 {
|
||||
if _, err = e.Exec("UPDATE `issue_user` SET is_assigned = ? WHERE uid = ? AND issue_id = ?", true, issue.AssigneeID, issue.ID); err != nil {
|
||||
return err
|
||||
// Check if the submitted user is already assigne, if yes delete him otherwise add him
|
||||
var toBeDeleted bool
|
||||
for _, assignee := range issue.Assignees {
|
||||
if assignee.ID == assigneeID {
|
||||
toBeDeleted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return updateIssue(e, issue)
|
||||
}
|
||||
assigneeIn := IssueAssignees{AssigneeID: assigneeID, IssueID: issue.ID}
|
||||
|
||||
// UpdateIssueUserByAssignee updates issue-user relation for assignee.
|
||||
func UpdateIssueUserByAssignee(issue *Issue) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
if toBeDeleted {
|
||||
_, err = e.Delete(assigneeIn)
|
||||
if err != nil {
|
||||
return toBeDeleted, err
|
||||
}
|
||||
} else {
|
||||
_, err = e.Insert(assigneeIn)
|
||||
if err != nil {
|
||||
return toBeDeleted, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = updateIssueUserByAssignee(sess, issue); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
return toBeDeleted, nil
|
||||
}
|
||||
|
||||
// UpdateIssueUserByRead updates issue-user relation for reading.
|
||||
|
|
|
@ -32,23 +32,6 @@ func Test_newIssueUsers(t *testing.T) {
|
|||
AssertExistsAndLoadBean(t, &IssueUser{IssueID: newIssue.ID, UID: repo.OwnerID})
|
||||
}
|
||||
|
||||
func TestUpdateIssueUserByAssignee(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
|
||||
|
||||
// artificially change assignee in issue_user table
|
||||
AssertSuccessfulInsert(t, &IssueUser{IssueID: issue.ID, UID: 5, IsAssigned: true})
|
||||
_, err := x.Cols("is_assigned").
|
||||
Update(&IssueUser{IsAssigned: false}, &IssueUser{IssueID: issue.ID, UID: issue.AssigneeID})
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, UpdateIssueUserByAssignee(issue))
|
||||
|
||||
// issue_user table should now be correct again
|
||||
AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: issue.AssigneeID}, "is_assigned=1")
|
||||
AssertExistsAndLoadBean(t, &IssueUser{IssueID: issue.ID, UID: 5}, "is_assigned=0")
|
||||
}
|
||||
|
||||
func TestUpdateIssueUserByRead(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
|
||||
|
|
|
@ -181,6 +181,8 @@ var migrations = []Migration{
|
|||
// v63 -> v64
|
||||
NewMigration("add language column for user setting", addLanguageSetting),
|
||||
// v64 -> v65
|
||||
NewMigration("add multiple assignees", addMultipleAssignees),
|
||||
// v65 -> v66
|
||||
NewMigration("add review", addReview),
|
||||
}
|
||||
|
||||
|
@ -231,7 +233,7 @@ Please try to upgrade to a lower version (>= v0.6.0) first, then upgrade to curr
|
|||
return nil
|
||||
}
|
||||
|
||||
func dropTableColumns(x *xorm.Engine, tableName string, columnNames ...string) (err error) {
|
||||
func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...string) (err error) {
|
||||
if tableName == "" || len(columnNames) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -247,17 +249,10 @@ func dropTableColumns(x *xorm.Engine, tableName string, columnNames ...string) (
|
|||
}
|
||||
cols += "DROP COLUMN `" + col + "`"
|
||||
}
|
||||
if _, err := x.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
||||
if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil {
|
||||
return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err)
|
||||
}
|
||||
case setting.UseMSSQL:
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cols := ""
|
||||
for _, col := range columnNames {
|
||||
if cols != "" {
|
||||
|
|
|
@ -9,5 +9,15 @@ import (
|
|||
)
|
||||
|
||||
func removeIsOwnerColumnFromOrgUser(x *xorm.Engine) (err error) {
|
||||
return dropTableColumns(x, "org_user", "is_owner", "num_teams")
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dropTableColumns(sess, "org_user", "is_owner", "num_teams"); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
|
@ -5,27 +5,127 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addReview(x *xorm.Engine) error {
|
||||
// Review see models/review.go
|
||||
type Review struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type string
|
||||
ReviewerID int64 `xorm:"index"`
|
||||
IssueID int64 `xorm:"index"`
|
||||
Content string
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
func addMultipleAssignees(x *xorm.Engine) error {
|
||||
|
||||
// Redeclare issue struct
|
||||
type Issue struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"`
|
||||
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository.
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
Title string `xorm:"name"`
|
||||
Content string `xorm:"TEXT"`
|
||||
MilestoneID int64 `xorm:"INDEX"`
|
||||
Priority int
|
||||
AssigneeID int64 `xorm:"INDEX"`
|
||||
IsClosed bool `xorm:"INDEX"`
|
||||
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
|
||||
NumComments int
|
||||
Ref string
|
||||
|
||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
ClosedUnix util.TimeStamp `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(Review)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
// Updated the comment table
|
||||
type Comment struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type int
|
||||
PosterID int64 `xorm:"INDEX"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
LabelID int64
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
OldAssigneeID int64
|
||||
AssigneeID int64
|
||||
RemovedAssignee bool
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
|
||||
CommitID int64
|
||||
Line int64
|
||||
Content string `xorm:"TEXT"`
|
||||
RenderedContent string `xorm:"-"`
|
||||
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
// Reference issue in commit message
|
||||
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||
}
|
||||
return nil
|
||||
|
||||
// Create the table
|
||||
type IssueAssignees struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
AssigneeID int64 `xorm:"INDEX"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(IssueAssignees{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := x.Sync2(Comment{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Range over all issues and insert a new entry for each issue/assignee
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allIssues := []Issue{}
|
||||
if err := sess.Find(&allIssues); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, issue := range allIssues {
|
||||
if issue.AssigneeID != 0 {
|
||||
_, err := sess.Insert(IssueAssignees{IssueID: issue.ID, AssigneeID: issue.AssigneeID})
|
||||
if err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate comments
|
||||
// First update everything to not have nulls in db
|
||||
if _, err := sess.Where("type = ?", 9).Cols("removed_assignee").Update(Comment{RemovedAssignee: false}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allAssignementComments := []Comment{}
|
||||
if err := sess.Where("type = ?", 9).Find(&allAssignementComments); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, comment := range allAssignementComments {
|
||||
// Everytime where OldAssigneeID is > 0, the assignement was removed.
|
||||
if comment.OldAssigneeID > 0 {
|
||||
_, err := sess.ID(comment.ID).Update(Comment{RemovedAssignee: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := dropTableColumns(sess, "issue", "assignee_id"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dropTableColumns(sess, "issue_user", "is_assigned"); err != nil {
|
||||
return err
|
||||
}
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ func init() {
|
|||
new(RepoIndexerStatus),
|
||||
new(LFSLock),
|
||||
new(Reaction),
|
||||
new(IssueAssignees),
|
||||
new(Review),
|
||||
)
|
||||
|
||||
|
|
|
@ -198,6 +198,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
|||
Labels: apiIssue.Labels,
|
||||
Milestone: apiIssue.Milestone,
|
||||
Assignee: apiIssue.Assignee,
|
||||
Assignees: apiIssue.Assignees,
|
||||
State: apiIssue.State,
|
||||
Comments: apiIssue.Comments,
|
||||
HTMLURL: pr.Issue.HTMLURL(),
|
||||
|
@ -719,7 +720,7 @@ func (pr *PullRequest) testPatch() (err error) {
|
|||
}
|
||||
|
||||
// NewPullRequest creates new pull request with labels for repository.
|
||||
func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest, patch []byte) (err error) {
|
||||
func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []string, pr *PullRequest, patch []byte, assigneeIDs []int64) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err = sess.Begin(); err != nil {
|
||||
|
@ -732,7 +733,11 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
|||
LabelIDs: labelIDs,
|
||||
Attachments: uuids,
|
||||
IsPull: true,
|
||||
AssigneeIDs: assigneeIDs,
|
||||
}); err != nil {
|
||||
if IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("newIssue: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -600,9 +600,9 @@ func (repo *Repository) GetAssignees() (_ []*User, err error) {
|
|||
return repo.getAssignees(x)
|
||||
}
|
||||
|
||||
// GetAssigneeByID returns the user that has write access of repository by given ID.
|
||||
func (repo *Repository) GetAssigneeByID(userID int64) (*User, error) {
|
||||
return GetAssigneeByID(repo, userID)
|
||||
// GetUserIfHasWriteAccess returns the user that has write access of repository by given ID.
|
||||
func (repo *Repository) GetUserIfHasWriteAccess(userID int64) (*User, error) {
|
||||
return GetUserIfHasWriteAccess(repo, userID)
|
||||
}
|
||||
|
||||
// GetMilestoneByID returns the milestone belongs to repository by given ID.
|
||||
|
|
|
@ -993,7 +993,7 @@ func deleteUser(e *xorm.Session, u *User) error {
|
|||
// ***** END: PublicKey *****
|
||||
|
||||
// Clear assignee.
|
||||
if _, err = e.Exec("UPDATE `issue` SET assignee_id=0 WHERE assignee_id=?", u.ID); err != nil {
|
||||
if err = clearAssigneeByUserID(e, u.ID); err != nil {
|
||||
return fmt.Errorf("clear assignee: %v", err)
|
||||
}
|
||||
|
||||
|
@ -1110,8 +1110,8 @@ func GetUserByID(id int64) (*User, error) {
|
|||
return getUserByID(x, id)
|
||||
}
|
||||
|
||||
// GetAssigneeByID returns the user with write access of repository by given ID.
|
||||
func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
|
||||
// GetUserIfHasWriteAccess returns the user with write access of repository by given ID.
|
||||
func GetUserIfHasWriteAccess(repo *Repository, userID int64) (*User, error) {
|
||||
has, err := HasAccess(userID, repo, AccessModeWrite)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -118,8 +118,12 @@ func getDingtalkPullRequestPayload(p *api.PullRequestPayload) (*DingtalkPayload,
|
|||
title = fmt.Sprintf("[%s] Pull request edited: #%d %s", p.Repository.FullName, p.Index, p.PullRequest.Title)
|
||||
text = p.PullRequest.Body
|
||||
case api.HookIssueAssigned:
|
||||
list, err := MakeAssigneeList(&Issue{ID: p.PullRequest.ID})
|
||||
if err != nil {
|
||||
return &DingtalkPayload{}, err
|
||||
}
|
||||
title = fmt.Sprintf("[%s] Pull request assigned to %s: #%d %s", p.Repository.FullName,
|
||||
p.PullRequest.Assignee.UserName, p.Index, p.PullRequest.Title)
|
||||
list, p.Index, p.PullRequest.Title)
|
||||
text = p.PullRequest.Body
|
||||
case api.HookIssueUnassigned:
|
||||
title = fmt.Sprintf("[%s] Pull request unassigned: #%d %s", p.Repository.FullName, p.Index, p.PullRequest.Title)
|
||||
|
|
|
@ -191,8 +191,12 @@ func getDiscordPullRequestPayload(p *api.PullRequestPayload, meta *DiscordMeta)
|
|||
text = p.PullRequest.Body
|
||||
color = warnColor
|
||||
case api.HookIssueAssigned:
|
||||
list, err := MakeAssigneeList(&Issue{ID: p.PullRequest.ID})
|
||||
if err != nil {
|
||||
return &DiscordPayload{}, err
|
||||
}
|
||||
title = fmt.Sprintf("[%s] Pull request assigned to %s: #%d %s", p.Repository.FullName,
|
||||
p.PullRequest.Assignee.UserName, p.Index, p.PullRequest.Title)
|
||||
list, p.Index, p.PullRequest.Title)
|
||||
text = p.PullRequest.Body
|
||||
color = successColor
|
||||
case api.HookIssueUnassigned:
|
||||
|
|
|
@ -172,8 +172,12 @@ func getSlackPullRequestPayload(p *api.PullRequestPayload, slack *SlackMeta) (*S
|
|||
text = fmt.Sprintf("[%s] Pull request edited: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||
attachmentText = SlackTextFormatter(p.PullRequest.Body)
|
||||
case api.HookIssueAssigned:
|
||||
list, err := MakeAssigneeList(&Issue{ID: p.PullRequest.ID})
|
||||
if err != nil {
|
||||
return &SlackPayload{}, err
|
||||
}
|
||||
text = fmt.Sprintf("[%s] Pull request assigned to %s: %s by %s", p.Repository.FullName,
|
||||
SlackLinkFormatter(setting.AppURL+p.PullRequest.Assignee.UserName, p.PullRequest.Assignee.UserName),
|
||||
SlackLinkFormatter(setting.AppURL+list, list),
|
||||
titleLink, senderLink)
|
||||
case api.HookIssueUnassigned:
|
||||
text = fmt.Sprintf("[%s] Pull request unassigned: %s by %s", p.Repository.FullName, titleLink, senderLink)
|
||||
|
|
|
@ -254,6 +254,7 @@ func (f *NewDingtalkHookForm) Validate(ctx *macaron.Context, errs binding.Errors
|
|||
type CreateIssueForm struct {
|
||||
Title string `binding:"Required;MaxSize(255)"`
|
||||
LabelIDs string `form:"label_ids"`
|
||||
AssigneeIDs string `form:"assignee_ids"`
|
||||
Ref string `form:"ref"`
|
||||
MilestoneID int64
|
||||
AssigneeID int64
|
||||
|
|
|
@ -44,6 +44,7 @@ type InstallForm struct {
|
|||
EnableOpenIDSignIn bool
|
||||
EnableOpenIDSignUp bool
|
||||
DisableRegistration bool
|
||||
AllowOnlyExternalRegistration bool
|
||||
EnableCaptcha bool
|
||||
RequireSignInView bool
|
||||
DefaultKeepEmailPrivate bool
|
||||
|
|
|
@ -99,8 +99,9 @@ func (r *Repository) CanUseTimetracker(issue *models.Issue, user *models.User) b
|
|||
// Checking for following:
|
||||
// 1. Is timetracker enabled
|
||||
// 2. Is the user a contributor, admin, poster or assignee and do the repository policies require this?
|
||||
isAssigned, _ := models.IsUserAssignedToIssue(issue, user)
|
||||
return r.Repository.IsTimetrackerEnabled() && (!r.Repository.AllowOnlyContributorsToTrackTime() ||
|
||||
r.IsWriter() || issue.IsPoster(user.ID) || issue.AssigneeID == user.ID)
|
||||
r.IsWriter() || issue.IsPoster(user.ID) || isAssigned)
|
||||
}
|
||||
|
||||
// GetCommitsCount returns cached commit count for current view
|
||||
|
|
|
@ -1143,6 +1143,7 @@ var Service struct {
|
|||
ResetPwdCodeLives int
|
||||
RegisterEmailConfirm bool
|
||||
DisableRegistration bool
|
||||
AllowOnlyExternalRegistration bool
|
||||
ShowRegistrationButton bool
|
||||
RequireSignInView bool
|
||||
EnableNotifyMail bool
|
||||
|
@ -1168,7 +1169,8 @@ func newService() {
|
|||
Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
|
||||
Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180)
|
||||
Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool()
|
||||
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!Service.DisableRegistration)
|
||||
Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool()
|
||||
Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
|
||||
Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool()
|
||||
Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
|
||||
Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
|
||||
|
|
|
@ -271,9 +271,6 @@ issues.new.no_milestone=Няма етап
|
|||
issues.new.clear_milestone=Изчисти етап
|
||||
issues.new.open_milestone=Отворени етапи
|
||||
issues.new.closed_milestone=Затворени етапи
|
||||
issues.new.assignee=Изпълнител
|
||||
issues.new.clear_assignee=Изчисти изпълнител
|
||||
issues.new.no_assignee=Няма изпълнител
|
||||
issues.create=Създай задача
|
||||
issues.new_label=Нов етикет
|
||||
issues.create_label=Създай етикет
|
||||
|
|
|
@ -270,9 +270,6 @@ issues.new.no_milestone=Bez milníku
|
|||
issues.new.clear_milestone=Smazat milník
|
||||
issues.new.open_milestone=Otevřít milník
|
||||
issues.new.closed_milestone=Zavřené milníky
|
||||
issues.new.assignee=Zpracovatel
|
||||
issues.new.clear_assignee=Smazat zpracovatele
|
||||
issues.new.no_assignee=Bez zpracovatele
|
||||
issues.create=Vytvořit úkol
|
||||
issues.new_label=Nový štítek
|
||||
issues.create_label=Vytvořit štítek
|
||||
|
|
|
@ -81,7 +81,7 @@ err_empty_admin_password=Das Administrator-Passwort darf nicht leer sein.
|
|||
|
||||
general_title=Allgemeine Einstellungen
|
||||
app_name=Seitentitel
|
||||
app_name_helper=Gebe hier den Namen deines Unternehmens ein.
|
||||
app_name_helper=Du kannst hier den Namen deines Unternehmens eingeben.
|
||||
repo_path=Repository-Verzeichnis
|
||||
repo_path_helper=Remote-Git-Repositories werden in diesem Verzeichnis gespeichert.
|
||||
lfs_path=Git LFS-Wurzelpfad
|
||||
|
@ -136,6 +136,7 @@ test_git_failed=Fehler beim Test des 'git' Kommandos: %v
|
|||
sqlite3_not_available=Diese Gitea-Version unterstützt SQLite3 nicht. Bitte lade die offizielle binäre Version von %s herunter (nicht die 'gobuild'-Version).
|
||||
invalid_db_setting=Datenbankeinstellungen sind ungültig: %v
|
||||
invalid_repo_path=Repository-Verzeichnis ist ungültig: %v
|
||||
run_user_not_match=Der "Ausführen als" Benutzer ist nicht der aktuelle Benutzer: %s -> %s
|
||||
save_config_failed=Fehler beim Speichern der Konfiguration: %v
|
||||
invalid_admin_setting=Administrator-Konto Einstellungen sind ungültig: %v
|
||||
install_success=Willkommen! Danke, dass du Gitea gewählt hast. Viel Spaß!
|
||||
|
@ -157,7 +158,7 @@ show_more_repos=Zeige mehr Repositories…
|
|||
collaborative_repos=Gemeinschaftliche Repositories
|
||||
my_orgs=Meine Organisationen
|
||||
my_mirrors=Meine Mirrors
|
||||
view_home=%s betrachten
|
||||
view_home=%s ansehen
|
||||
search_repos=Finde ein Repository…
|
||||
|
||||
issues.in_your_repos=Eigene Repositories
|
||||
|
@ -188,6 +189,7 @@ confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b>
|
|||
reset_password_mail_sent_prompt=Eine E-Mail wurde an <b>%s</b> gesendet. Bitte überprüfe dein Postfach innerhalb der nächsten %s, um das Passwort zurückzusetzen.
|
||||
active_your_account=Aktiviere dein Konto
|
||||
prohibit_login=Anmelden verboten
|
||||
prohibit_login_desc=Dein Account wurde gesperrt, bitte wende dich an den Administrator.
|
||||
resent_limit_prompt=Du hast bereits eine Aktivierungs-E-Mail angefordert. Bitte warte 3 Minuten und probiere es dann nochmal.
|
||||
has_unconfirmed_mail=Hallo %s, du hast eine unbestätigte E-Mail-Adresse (<b>%s</b>). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button.
|
||||
resend_mail=Aktivierungs-E-Mail erneut verschicken
|
||||
|
@ -208,7 +210,9 @@ login_userpass=Anmelden
|
|||
login_openid=OpenID
|
||||
openid_connect_submit=Verbinden
|
||||
openid_connect_title=Mit bestehendem Konto verbinden
|
||||
openid_connect_desc=Die gewählte OpenID URI ist unbekannt. Ordne sie hier einem neuen Account zu.
|
||||
openid_register_title=Neues Konto einrichten
|
||||
openid_register_desc=Die gewählte OpenID URI ist unbekannt. Ordne sie hier einem neuen Account zu.
|
||||
openid_signin_desc=Gib deine OpenID-URI ein. Zum Beispiel: https://anne.me, bob.openid.org.cn oder gnusocial.net/carry.
|
||||
disable_forgot_password_mail=Das Zurücksetzen von Passwörtern wurde deaktiviert. Bitte wende dich an den Administrator.
|
||||
|
||||
|
@ -279,6 +283,7 @@ unable_verify_ssh_key=Dein SSH-Key kann nicht überprüft werden, probiere es er
|
|||
auth_failed=Authentifizierung fehlgeschlagen: %v
|
||||
|
||||
still_own_repo=Dein Konto besitzt ein oder mehrere Repositories. Diese müssen zuerst gelöscht oder übertragen werden.
|
||||
still_has_org=Dein Account ist Mitglied in mindestens einer Organisation. Bitte verlasse diese zuerst.
|
||||
org_still_own_repo=Diese Organisation besitzt noch mindestens ein Repository. Bitte lösche oder übertrage diese zuerst.
|
||||
|
||||
target_branch_not_exist=Die Ziel-Branch existiert nicht.
|
||||
|
@ -370,11 +375,16 @@ openid_desc=Mit OpenID kannst du dich über einen Drittanbieter authentifizieren
|
|||
manage_ssh_keys=SSH-Schlüssel verwalten
|
||||
manage_gpg_keys=GPG-Schlüssel verwalten
|
||||
add_key=Schlüssel hinzufügen
|
||||
ssh_desc=Diese öffentlichen SSH-Keys sind mit deinem Account verbunden. Der dazugehörigen privaten SSH-Keys geben dir vollen Zugriff auf deine Repositories.
|
||||
gpg_desc=Diese öffentlichen GPG-Keys sind mit deinem Account verbunden. Halte die dazugehörigen privaten SSH-Keys geheim, da diese deine Commits signieren.
|
||||
ssh_helper=<strong>Brauchst du Hilfe?</strong> Hier ist Githubs Anleitung zum <a href="%s">Erzeugen von SSH-Schlüsseln</a> oder <a href="%s">Lösen einfacher SSH-Probleme</a>.
|
||||
gpg_helper=<strong>Brauchst du Hilfe?</strong> Hier ist GitHubs Anleitung <a href="%s">über GPG</a>.
|
||||
add_new_key=SSH-Schlüssel hinzufügen
|
||||
add_new_gpg_key=GPG-Schlüssel hinzufügen
|
||||
ssh_key_been_used=Dieser SSH-Key wurde bereits zu deinem Account hinzugefügt.
|
||||
ssh_key_name_used=Ein gleichnamiger SSH-Key existiert bereits in deinem Account.
|
||||
gpg_key_id_used=Ein öffentlicher GPG-Schlüssel mit der gleichen ID existiert bereits.
|
||||
gpg_no_key_email_found=Dieser GPG Schlüssel kann mit keiner E-Mail-Adresse deines Accounts verwendet werden.
|
||||
subkeys=Unterschlüssel
|
||||
key_id=Schlüssel-ID
|
||||
key_name=Schlüsselname
|
||||
|
@ -402,6 +412,7 @@ hide_openid=Nicht im Profil anzeigen
|
|||
ssh_disabled=SSH ist deaktiviert
|
||||
|
||||
manage_social=Verknüpfte soziale Konten verwalten
|
||||
social_desc=Diese Accounts sind mit deinem Gitea-Konto verbunden. Schau dir alle Accounts an, um sicherzustellen dass du alle legitimiert hast, da man sich darüber in deinem Gitea-Konto anmelden kann.
|
||||
unbind=Trennen
|
||||
unbind_success=Das Konto wurde von deinem Gitea-Konto getrennt.
|
||||
|
||||
|
@ -414,7 +425,10 @@ generate_token=Token generieren
|
|||
generate_token_success=Ein neuer Token wurde generiert. Kopiere diesen, da er nicht erneut angezeigt wird.
|
||||
delete_token=Löschen
|
||||
access_token_deletion=Zugriffstoken löschen
|
||||
access_token_deletion_desc=Wenn du ein Token löschst, haben die Anwendungen, die es nutzen keinen Zugriff mehr auf deinen Account. Fortfahren?
|
||||
delete_token_success=Der Zugriffstoken wurde gelöscht. Anwendungen die diesen Token genutzt haben, haben nun keinen Zugriff mehr auf deinen Account.
|
||||
|
||||
twofa_desc=Zwei-Faktor-Authentifizierung trägt zu einer höheren Accountsicherheit bei.
|
||||
twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>.
|
||||
twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet.
|
||||
twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren
|
||||
|
@ -423,6 +437,7 @@ twofa_scratch_token_regenerated=Dein Einmalpasswort ist %s. Bewahre es an einem
|
|||
twofa_enroll=Zwei-Faktor-Authentifizierung aktivieren
|
||||
twofa_disable_note=Du kannst die Zwei-Faktor-Authentifizierung auch wieder deaktivieren.
|
||||
twofa_disable_desc=Wenn du die Zwei-Faktor-Authentifizierung deaktivierst, wird die Sicherheit deines Kontos verringert. Fortfahren?
|
||||
regenerate_scratch_token_desc=Wenn du dein Einmalpasswort verlegt oder es bereits benutzt hast, kannst du es hier zurücksetzen.
|
||||
twofa_disabled=Zwei-Faktor-Authentifizierung wurde deaktiviert.
|
||||
scan_this_image=Scanne diese Grafik mit deiner Authentifizierungs-App:
|
||||
or_enter_secret=Oder gib das Secret ein: %s
|
||||
|
@ -430,21 +445,34 @@ then_enter_passcode=Und gebe dann die angezeigte PIN der Anwendung ein:
|
|||
passcode_invalid=Die PIN ist falsch. Probiere es erneut.
|
||||
twofa_enrolled=Die Zwei-Faktor-Authentifizierung wurde für dein Konto aktiviert. Bewahre dein Einmalpasswort (%s) an einem sicheren Ort auf, da es nicht wieder angezeigt werden wird.
|
||||
|
||||
manage_account_links=Verknüpfte Accounts verwalten
|
||||
manage_account_links_desc=Diese externen Accounts sind mit deinem Gitea-Account verknüpft.
|
||||
account_links_not_available=Es sind keine externen Accounts mit diesem Gitea-Account verknüpft.
|
||||
remove_account_link=Verknüpften Account entfernen
|
||||
remove_account_link_desc=Wenn du den verknüpften Account entfernst, wirst du darüber nicht mehr auf deinen Gitea-Account zugreifen können. Fortfahren?
|
||||
remove_account_link_success=Der verknüpfte Account wurde entfernt.
|
||||
|
||||
orgs_none=Du bist kein Mitglied in einer Organisation.
|
||||
repos_none=Du besitzt keine Repositories
|
||||
|
||||
delete_account=Konto löschen
|
||||
delete_prompt=Wenn du fortfährst wird dein Account permanent gelöscht. Dies <strong>KANN NICHT</strong> rückgängig gemacht werden.
|
||||
confirm_delete_account=Löschen bestätigen
|
||||
delete_account_title=Benutzerkonto löschen
|
||||
delete_account_desc=Bist du sicher, dass du diesen Account dauerhaft löschen möchtest?
|
||||
|
||||
[repo]
|
||||
owner=Besitzer
|
||||
repo_name=Repository-Name
|
||||
repo_name_helper=Ein guter Repository-Name besteht normalerweise aus kurzen, unvergesslichen und einzigartigen Schlagwörtern.
|
||||
visibility=Sichtbarkeit
|
||||
visiblity_helper=privates Repository
|
||||
visiblity_helper_forced=Auf dieser Gitea-Instanz können nur private Repositories angelegt werden.
|
||||
visiblity_fork_helper=(Eine Änderung dieses Wertes wirkt sich auf alle Forks aus)
|
||||
clone_helper=Brauchst du Hilfe beim Klonen? Öffne die <a target="_blank" rel="noopener" href="%s">Hilfe</a>.
|
||||
fork_repo=Repository forken
|
||||
fork_from=Fork von
|
||||
fork_visiblity_helper=Die Sichtbarkeit einer geforkten Repository kann nicht geändert werden.
|
||||
repo_desc=Beschreibung
|
||||
repo_lang=Sprache
|
||||
repo_gitignore_helper=Wähle eine .gitignore-Vorlage aus.
|
||||
|
@ -452,11 +480,16 @@ license=Lizenz
|
|||
license_helper=Wähle eine Lizenz aus.
|
||||
readme=README
|
||||
readme_helper=Wähle eine README-Vorlage aus.
|
||||
auto_init=Repository initialisieren (Fügt .gitignore, License und README-Dateien hinzu)
|
||||
create_repo=Repository erstellen
|
||||
default_branch=Standardbranch
|
||||
mirror_prune=Entfernen
|
||||
mirror_prune_desc=Entferne veraltete remote-tracking Referenzen
|
||||
mirror_interval=Spiegelintervall (gültige Zeiteinheiten sind 'h', 'm', 's')
|
||||
mirror_interval_invalid=Das Spiegel-Intervall ist ungültig.
|
||||
mirror_address=Klonen via URL
|
||||
mirror_address_desc=Bitte gebe alle benötigten Zugangsdaten in der URL an.
|
||||
mirror_last_synced=Zuletzt synchronisiert
|
||||
watchers=Beobachter
|
||||
stargazers=Favorisiert von
|
||||
forks=Forks
|
||||
|
@ -465,16 +498,22 @@ reactions_more=und %d weitere
|
|||
|
||||
form.reach_limit_of_creation=Du hast bereits dein Limit von %d Repositories erreicht.
|
||||
form.name_reserved=Der Repository-Name '%s' ist reserviert.
|
||||
form.name_pattern_not_allowed='%s' ist nicht erlaubt für Repository-Namen.
|
||||
|
||||
migrate_type=Migrationstyp
|
||||
migrate_type_helper=Dieses Repository wird ein <span class="text blue">Mirror</span> sein
|
||||
migrate_repo=Repository migrieren
|
||||
migrate.clone_address=Migrations- / Klon-URL
|
||||
migrate.clone_address_desc=Die HTTP(s) oder Klon-URL eines bereits existierenden Repositories
|
||||
migrate.clone_local_path=oder ein lokaler Serverpfad
|
||||
migrate.permission_denied=Du hast keine Berechtigung zum Importieren lokaler Repositories.
|
||||
migrate.invalid_local_path=Der lokale Pfad ist ungültig, existiert nicht oder ist kein Ordner.
|
||||
migrate.failed=Fehler bei der Migration: %v
|
||||
migrate.lfs_mirror_unsupported=Spiegeln von LFS-Objekten wird nicht unterstützt - nutze stattdessen 'git lfs fetch --all' und 'git lfs push --all'.
|
||||
|
||||
mirror_from=Mirror von
|
||||
forked_from=geforkt von
|
||||
fork_from_self=Du kannst kein Repository forken, das dir bereits gehört.
|
||||
copy_link=Kopieren
|
||||
copy_link_success=Der Link wurde kopiert
|
||||
copy_link_error=Verwende ⌘-C oder Strg-C zum Kopieren
|
||||
|
@ -513,11 +552,13 @@ file_permalink=Permalink
|
|||
file_too_large=Die Datei ist zu groß zum Anzeigen.
|
||||
video_not_supported_in_browser=Dein Browser unterstützt das HTML5 'video'-Tag nicht.
|
||||
stored_lfs=Gespeichert mit Git LFS
|
||||
commit_graph=Commit graph
|
||||
|
||||
editor.new_file=Neue Datei
|
||||
editor.upload_file=Datei hochladen
|
||||
editor.edit_file=Datei bearbeiten
|
||||
editor.preview_changes=Vorschau der Änderungen
|
||||
editor.cannot_edit_non_text_files=Binärdateien können nicht im Webinterface bearbeitet werden.
|
||||
editor.edit_this_file=Datei bearbeiten
|
||||
editor.fork_before_edit=Du musst dieses Repository forken, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
|
||||
editor.delete_this_file=Datei löschen
|
||||
|
@ -542,6 +583,7 @@ editor.directory_is_a_file=Der Verzeichnisname '%s' wird bereits als Dateiname i
|
|||
editor.file_is_a_symlink='%s' ist ein symolischer Link. Symbolische Links können mit dem Web Editor nicht bearbeitet werden.
|
||||
editor.filename_is_a_directory=Der Dateiname '%s' wird bereits als Verzeichnisname in diesem Repository verwendet.
|
||||
editor.file_editing_no_longer_exists=Die bearbeitete Datei '%s' existiert nicht mehr in diesem Repository.
|
||||
editor.file_changed_while_editing=Der Inhalt der Datei hat sich seit dem Beginn der Bearbeitung geändert. <a target="_blank" rel="noopener" href="%s">Hier klicken</a> um die Änderungen anzusehen, oder <strong>Änderungen erneut comitten</strong> um sie zu überschreiben.
|
||||
editor.file_already_exists=Eine Datei mit dem Namen '%s' ist bereits in diesem Repository vorhanden.
|
||||
editor.no_changes_to_show=Keine Änderungen vorhanden.
|
||||
editor.fail_to_update_file=Fehler beim Ändern/Erstellen der Datei '%s'. Fehler: %v
|
||||
|
@ -564,8 +606,9 @@ commits.signed_by=Signiert von
|
|||
commits.gpg_key_id=GPG Schlüssel-ID
|
||||
|
||||
ext_issues=Externe Issues
|
||||
ext_issues.desc=Link zu externem Issuetracker.
|
||||
|
||||
issues.desc=Bearbeite Bug Reports, Aufgaben und Meilensteine.
|
||||
issues.desc=Verwalte Bug-Reports, Aufgaben und Meilensteine.
|
||||
issues.new=Neuer Issue
|
||||
issues.new.labels=Label
|
||||
issues.new.no_label=Kein Label
|
||||
|
@ -575,9 +618,9 @@ issues.new.no_milestone=Kein Meilenstein
|
|||
issues.new.clear_milestone=Meilenstein entfernen
|
||||
issues.new.open_milestone=Offene Meilensteine
|
||||
issues.new.closed_milestone=Geschlossene Meilensteine
|
||||
issues.new.assignee=Zuständig
|
||||
issues.new.clear_assignee=Zuständigkeit entfernen
|
||||
issues.new.no_assignee=Niemand zuständig
|
||||
issues.new.assignees=Zuständig
|
||||
issues.new.clear_assignees=Zuständige entfernen
|
||||
issues.new.no_assignees=Niemand zugewiesen
|
||||
issues.no_ref=Keine Branch/Tag angegeben
|
||||
issues.create=Issue erstellen
|
||||
issues.new_label=Neues Label
|
||||
|
@ -686,12 +729,19 @@ issues.add_time_hours=Stunden
|
|||
issues.add_time_minutes=Minuten
|
||||
issues.cancel_tracking=Abbrechen
|
||||
issues.cancel_tracking_history=hat die Zeiterfassung %s abgebrochen
|
||||
issues.time_spent_from_all_authors=`Aufgewendete Zeit: %s`
|
||||
issues.due_date_form_add=Fälligkeitsdatum hinzufügen
|
||||
issues.due_date_form_update=Fälligkeitsdatum ändern
|
||||
issues.due_date_form_remove=Fälligkeitsdatum löschen
|
||||
issues.due_date_not_set=Kein Fälligkeitsdatum gesetzt.
|
||||
issues.due_date_overdue=Überfällig
|
||||
|
||||
pulls.new=Neuer Pull-Request
|
||||
pulls.compare_changes=Neuer Pull-Request
|
||||
pulls.compare_compare=pull von
|
||||
pulls.filter_branch=Branch filtern
|
||||
pulls.no_results=Keine Ergebnisse verfügbar.
|
||||
pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden.
|
||||
pulls.create=Pull-Request erstellen
|
||||
pulls.title_desc=möchte %[1]d Commits von <code>%[2]s</code> nach <code>%[3]s</code> zusammenführen
|
||||
pulls.merged_title_desc=hat %[1]d Commits von <code>%[2]s</code> nach <code>%[3]s</code> %[4]s zusammengeführt
|
||||
|
@ -838,10 +888,16 @@ settings.convert_confirm=Repository umwandeln
|
|||
settings.convert_succeed=Das Mirror-Repository wurde erfolgreich in ein normales Repository umgewandelt.
|
||||
settings.transfer=Besitz übertragen
|
||||
settings.transfer_desc=Übertrage dieses Repository auf einen anderen Benutzer oder eine Organisation in der Du Admin-Rechte hast.
|
||||
settings.transfer_notices_1=- Du wirst keinen Zugriff mehr haben, wenn der neue Besitzer ein individueller Benutzer ist.
|
||||
settings.transfer_notices_2=- Du wirst weiterhin Zugriff haben, wenn der neue Besitzer eine Organisation ist und du einer der Besitzer bist.
|
||||
settings.transfer_form_title=Gib den Repository-Namen zur Bestätigung ein:
|
||||
settings.wiki_delete=Wiki-Daten löschen
|
||||
settings.wiki_delete_desc=Das Löschen von Wiki-Daten kann nicht rückgängig gemacht werden. Bitte sei vorsichtig.
|
||||
settings.wiki_delete_notices_1=- Dies löscht und deaktiviert das Wiki für %s.
|
||||
settings.confirm_wiki_delete=Wiki-Daten löschen
|
||||
settings.wiki_deletion_success=Repository Wiki-Daten wurden gelöscht.
|
||||
settings.delete=Dieses Repository löschen
|
||||
settings.delete_desc=Wenn dieses Repository gelöscht wurde, gibt es keinen Weg zurück. Bitte sei vorsichtig.
|
||||
settings.delete_notices_1=- Diese Operation kann <strong>NICHT</strong> rückgängig gemacht werden.
|
||||
settings.deletion_success=Das Repository wurde gelöscht.
|
||||
settings.update_settings_success=Repository Einstellungen wurden aktualisiert.
|
||||
|
@ -855,12 +911,16 @@ settings.delete_collaborator=Entfernen
|
|||
settings.collaborator_deletion=Mitarbeiter entfernen
|
||||
settings.remove_collaborator_success=Der Mitarbeiter wurde entfernt.
|
||||
settings.search_user_placeholder=Benutzer suchen…
|
||||
settings.org_not_allowed_to_be_collaborator=Organisationen können nicht als Mitarbeiter hinzugefügt werden.
|
||||
settings.user_is_org_member=Der Benutzer ist ein Organisationsmitglied und kann nicht als Mitarbeiter hinzugefügt werden.
|
||||
settings.add_webhook=Webhook hinzufügen
|
||||
settings.webhook_deletion=Webhook löschen
|
||||
settings.webhook_deletion_success=Webhook wurde entfernt.
|
||||
settings.webhook.test_delivery=Senden testen
|
||||
settings.webhook.request=Anfrage
|
||||
settings.webhook.response=Antwort
|
||||
settings.webhook.headers=Kopfzeilen
|
||||
settings.webhook.payload=Inhalt
|
||||
settings.webhook.body=Inhalt
|
||||
settings.githook_edit_desc=Wenn ein Hook nicht aktiv ist, wird der Standardinhalt benutzt. Lasse den Inhalt leer, um den Hook zu deaktivieren.
|
||||
settings.githook_name=Hook-Name
|
||||
|
@ -873,6 +933,8 @@ settings.slack_icon_url=Icon-URL
|
|||
settings.discord_username=Benutzername
|
||||
settings.discord_icon_url=Icon-URL
|
||||
settings.slack_color=Farbe
|
||||
settings.event_send_everything=Alle Events
|
||||
settings.event_choose=Benutzerdefinierte Events…
|
||||
settings.event_create=Erstellen
|
||||
settings.event_create_desc=Branch oder Tag erstellt.
|
||||
settings.event_pull_request=Pull-Request
|
||||
|
@ -881,7 +943,10 @@ settings.event_push=Push
|
|||
settings.event_push_desc=Git push in ein Repository.
|
||||
settings.event_repository=Repository
|
||||
settings.event_repository_desc=Repository erstellt oder gelöscht.
|
||||
settings.add_hook_success=Webhook wurde hinzugefügt.
|
||||
settings.update_webhook=Webhook aktualisieren
|
||||
settings.update_hook_success=Webhook wurde aktualisiert.
|
||||
settings.delete_webhook=Webhook entfernen
|
||||
settings.recent_deliveries=Letzte Zustellungen
|
||||
settings.hook_type=Hook Typ
|
||||
settings.slack_token=Token
|
||||
|
@ -889,6 +954,7 @@ settings.slack_domain=Domain
|
|||
settings.slack_channel=Kanal
|
||||
settings.deploy_keys=Deploy-Schlüssel
|
||||
settings.add_deploy_key=Deploy-Schlüssel hinzufügen
|
||||
settings.is_writable=Erlaube Schreibzugriff
|
||||
settings.title=Titel
|
||||
settings.deploy_key_content=Inhalt
|
||||
settings.branches=Branches
|
||||
|
@ -896,10 +962,15 @@ settings.protected_branch=Branch-Protection
|
|||
settings.protected_branch_can_push=Push erlauben?
|
||||
settings.protected_branch_can_push_yes=Du kannst pushen
|
||||
settings.protected_branch_can_push_no=Du kannst nicht pushen
|
||||
settings.branch_protection=Branch-Schutz" für Branch '<b>%s</b>'
|
||||
settings.protect_this_branch=Brach-Schutz aktivieren
|
||||
settings.protect_whitelist_search_users=Benutzer suchen…
|
||||
settings.protect_whitelist_search_teams=Suche nach Teams…
|
||||
settings.add_protected_branch=Schutz aktivieren
|
||||
settings.delete_protected_branch=Schutz deaktivieren
|
||||
settings.protected_branch_deletion=Brach-Schutz deaktivieren
|
||||
settings.choose_branch=Wähle eine Branch…
|
||||
settings.no_protected_branch=Es gibt keine geschützten Branches.
|
||||
|
||||
diff.browse_source=Quellcode durchsuchen
|
||||
diff.parent=Ursprung
|
||||
|
@ -955,6 +1026,9 @@ branch.create_from=von '%s'
|
|||
branch.create_success=Branch '%s' wurde erstellt.
|
||||
branch.branch_already_exists=Branch '%s' existiert bereits in diesem Repository.
|
||||
branch.deleted_by=Von %s gelöscht
|
||||
branch.restore_success=Branch '%s' wurde wiederhergestellt.
|
||||
branch.restore_failed=Wiederherstellung der Branch '%s' fehlgeschlagen.
|
||||
branch.protected_deletion_failed=Branch '%s' ist geschützt und kann nicht gelöscht werden.
|
||||
|
||||
topic.manage_topics=Themen verwalten
|
||||
topic.done=Fertig
|
||||
|
@ -962,6 +1036,7 @@ topic.done=Fertig
|
|||
[org]
|
||||
org_name_holder=Name der Organisation
|
||||
org_full_name_holder=Vollständiger Name der Organisation
|
||||
org_name_helper=Organisationsnamen sollten kurz und einprägsam sein.
|
||||
create_org=Organisation erstellen
|
||||
repo_updated=Aktualisiert
|
||||
people=Personen
|
||||
|
@ -973,8 +1048,12 @@ create_team=Team erstellen
|
|||
org_desc=Beschreibung
|
||||
team_name=Teamname
|
||||
team_desc=Beschreibung
|
||||
team_name_helper=Teamnamen sollten kurz und einprägsam sein.
|
||||
team_permission_desc=Berechtigungen
|
||||
team_unit_desc=Zugriff auf Repositorybereiche erlauben
|
||||
|
||||
form.name_reserved=Der Organisationsname '%s' ist reserviert.
|
||||
form.create_org_not_allowed=Du bist nicht berechtigt eine Organisation zu erstellen.
|
||||
|
||||
settings=Einstellungen
|
||||
settings.options=Organisation
|
||||
|
@ -983,12 +1062,17 @@ settings.website=Webseite
|
|||
settings.location=Standort
|
||||
settings.update_settings=Einstellungen speichern
|
||||
settings.update_setting_success=Organisationseinstellungen wurden aktualisiert.
|
||||
settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert.
|
||||
settings.delete=Organisation löschen
|
||||
settings.delete_account=Diese Organisation löschen
|
||||
settings.confirm_delete_account=Löschen
|
||||
settings.delete_org_title=Organisation löschen
|
||||
settings.delete_org_desc=Diese Organisation wird dauerhaft gelöscht. Fortfahren?
|
||||
settings.hooks_desc=Webhooks hinzufügen, die für <strong>alle</strong> Repositories dieser Organisation ausgelöst werden.
|
||||
|
||||
members.membership_visibility=Sichtbarkeit der Mitgliedschaft:
|
||||
members.public=Sichtbar
|
||||
members.private_helper=sichtbar machen
|
||||
members.member_role=Mitgliedsrolle:
|
||||
members.owner=Besitzer
|
||||
members.member=Mitglied
|
||||
|
@ -1000,12 +1084,17 @@ members.invite_now=Jetzt einladen
|
|||
teams.join=Beitreten
|
||||
teams.leave=Verlassen
|
||||
teams.read_access=Lesezugriff
|
||||
teams.read_access_helper=Mitglieder können Teamrepositories ansehen und klonen.
|
||||
teams.write_access=Schreibzugriff
|
||||
teams.admin_access=Administratorzugang
|
||||
teams.admin_access_helper=Mitglieder können auf Team Repositories "pushen", von ihnen "pullen" und Mitarbeiter hinzufügen.
|
||||
teams.no_desc=Dieses Team hat keine Beschreibung
|
||||
teams.settings=Einstellungen
|
||||
teams.members=Teammitglieder
|
||||
teams.update_settings=Einstellungen aktualisieren
|
||||
teams.delete_team=Team löschen
|
||||
teams.add_team_member=Teammitglied hinzufügen
|
||||
teams.delete_team_title=Team löschen
|
||||
teams.delete_team_success=Das Team wurde gelöscht.
|
||||
teams.repositories=Team-Repositories
|
||||
teams.search_repo_placeholder=Repository durchsuchen…
|
||||
|
@ -1015,6 +1104,7 @@ teams.add_nonexistent_repo=Das Repository, das du hinzufügen möchten, existier
|
|||
|
||||
[admin]
|
||||
dashboard=Dashboard
|
||||
users=Benutzerkonten
|
||||
organizations=Organisationen
|
||||
repositories=Repositories
|
||||
authentication=Authentifizierungsquellen
|
||||
|
@ -1043,6 +1133,7 @@ dashboard.git_gc_repos_success=Alle Repositories haben Garbage Collection beende
|
|||
dashboard.reinit_missing_repos=Alle Git-Repositories mit Einträgen neu einlesen
|
||||
dashboard.reinit_missing_repos_success=Alle verlorenen Git-Repositories mit existierenden Einträgen wurden erfolgreich aktualisiert.
|
||||
dashboard.sync_external_users=Externe Benutzerdaten synchronisieren
|
||||
dashboard.sync_external_users_started=Externe Benutzersynchronisation gestartet.
|
||||
dashboard.git_fsck=Healthchecks auf alle Repositories ausführen
|
||||
dashboard.server_uptime=Server-Uptime
|
||||
dashboard.current_goroutine=Aktuelle Goroutinen
|
||||
|
@ -1081,13 +1172,23 @@ users.activated=Aktiviert
|
|||
users.admin=Administrator
|
||||
users.repos=Repositories
|
||||
users.created=Registriert am
|
||||
users.last_login=Letzte Anmeldung
|
||||
users.new_success=Der Account '%s' wurde erstellt.
|
||||
users.edit=Bearbeiten
|
||||
users.auth_source=Authentifizierungsquelle
|
||||
users.local=Lokal
|
||||
users.update_profile_success=Der Account '%s' wurde aktualisiert.
|
||||
users.edit_account=Benutzerkonto bearbeiten
|
||||
users.max_repo_creation=Maximale Anzahl Repositories
|
||||
users.max_repo_creation_desc=(Gib -1 ein, um das globale Standardlimit zu verwenden.)
|
||||
users.is_activated=Account ist aktiviert
|
||||
users.is_admin=Ist Administrator
|
||||
users.allow_git_hook=Darf "Git Hooks" erstellen
|
||||
users.allow_import_local=Darf lokale Repositories importieren
|
||||
users.allow_create_organization=Darf Organisationen erstellen
|
||||
users.update_profile=Benutzerkonto aktualisieren
|
||||
users.delete_account=Benutzerkonto löschen
|
||||
users.deletion_success=Der Account wurde gelöscht.
|
||||
|
||||
orgs.org_manage_panel=Organisationsverwaltung
|
||||
orgs.name=Name
|
||||
|
@ -1104,6 +1205,7 @@ repos.stars=Favoriten
|
|||
repos.issues=Issues
|
||||
repos.size=Größe
|
||||
|
||||
auths.auth_manage_panel=Authentifikationsquellen verwalten
|
||||
auths.new=Authentifizierungsquelle hinzufügen
|
||||
auths.name=Name
|
||||
auths.type=Typ
|
||||
|
@ -1121,6 +1223,9 @@ auths.bind_password=Passwort binden
|
|||
auths.user_base=Basis für Benutzersuche
|
||||
auths.user_dn=Benutzer DN
|
||||
auths.attribute_username=Benutzername Attribut
|
||||
auths.attribute_name=Vornamensattribut
|
||||
auths.attribute_surname=Nachnamensattribut
|
||||
auths.attribute_mail=E-Mail Attribut
|
||||
auths.filter=Benutzerfilter
|
||||
auths.admin_filter=Admin Filter
|
||||
auths.ms_ad_sa=MS AD Suchattribute
|
||||
|
@ -1149,12 +1254,27 @@ auths.tip.facebook=Erstelle eine neue Anwendung auf https://developers.facebook.
|
|||
auths.tip.github=Erstelle unter https://github.com/settings/applications/new eine neue OAuth Anwendung.
|
||||
auths.tip.gitlab=Erstelle unter https://gitlab.com/profile/applications eine neue Anwendung.
|
||||
auths.tip.openid_connect=Benutze die OpenID Connect Discovery URL (<server>/.well-known/openid-configuration) als Endpunkt.
|
||||
auths.edit=Authentifikationsquelle bearbeiten
|
||||
auths.activated=Diese Authentifikationsquelle ist aktiviert
|
||||
auths.new_success=Die Authentifizierung "%s" wurde hinzugefügt.
|
||||
auths.update_success=Diese Authentifizierungsquelle wurde aktualisiert.
|
||||
auths.update=Authentifizierungsquelle aktualisieren
|
||||
auths.delete=Authentifikationsquelle löschen
|
||||
auths.delete_auth_title=Authentifizierungsquelle löschen
|
||||
auths.delete_auth_desc=Das Löschen einer Authentifizierungsquelle verhindert, dass Benutzer sich darüber anmelden können. Fortfahren?
|
||||
auths.still_in_used=Diese Authentifizierungsquelle wird noch verwendet. Bearbeite oder lösche zuerst alle Benutzer, die diese Authentifizierungsquelle benutzen.
|
||||
auths.deletion_success=Die Authentifizierungsquelle '%s' wurde gelöscht.
|
||||
auths.login_source_exist=Die Authentifizierungsquelle '%s' existiert bereits.
|
||||
|
||||
config.server_config=Serverkonfiguration
|
||||
config.app_name=Seitentitel
|
||||
config.app_ver=Gitea Version
|
||||
config.app_url=Gitea Basis-URL
|
||||
config.custom_conf=Konfigurations-Datei-Pfad
|
||||
config.domain=SSH Server-Domain
|
||||
config.offline_mode=Lokaler Modus
|
||||
config.disable_router_log=Router-Log deaktivieren
|
||||
config.run_user=Ausführen als
|
||||
config.run_mode=Laufzeit-Modus
|
||||
config.git_version=Git Version
|
||||
config.repo_root_path=Repository-Verzeichnis
|
||||
|
@ -1187,16 +1307,26 @@ config.db_path=Verzeichnis
|
|||
config.db_path_helper=(für "sqlite3" und "tidb")
|
||||
|
||||
config.service_config=Service-Konfiguration
|
||||
config.register_email_confirm=E-Mail-Bestätigung benötigt zum Registrieren
|
||||
config.disable_register=Selbstegistrierung deaktivieren
|
||||
config.enable_openid_signup=OpenID Selbstregistrierung aktivieren
|
||||
config.enable_openid_signin=OpenID Anmeldung aktivieren
|
||||
config.show_registration_button=Schaltfläche zum Registrieren anzeigen
|
||||
config.require_sign_in_view=Seiten nur für angemeldete Benutzer zugänglich
|
||||
config.mail_notify=E-Mail-Benachrichtigungen aktivieren
|
||||
config.disable_key_size_check=Prüfung der Mindestschlüssellänge deaktiveren
|
||||
config.enable_captcha=CAPTCHA aktivieren
|
||||
config.active_code_lives=Aktivierungscode Lebensdauer
|
||||
config.reset_password_code_lives=Ablaufdatum des Passworts zurücksetzen
|
||||
config.default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
|
||||
config.enable_timetracking=Zeiterfassung aktivieren
|
||||
|
||||
config.webhook_config=Webhook-Konfiguration
|
||||
config.queue_length=Warteschlangenlänge
|
||||
config.deliver_timeout=Zeitlimit für Zustellung
|
||||
config.skip_tls_verify=TLS Verifikation überspringen
|
||||
|
||||
config.mailer_config=SMTP Mailer Konfiguration
|
||||
config.mailer_enabled=Aktiviert
|
||||
config.mailer_disable_helo=HELO Deaktivieren
|
||||
config.mailer_name=Name
|
||||
|
@ -1204,6 +1334,10 @@ config.mailer_host=Host
|
|||
config.mailer_user=Benutzer
|
||||
config.mailer_use_sendmail=Sendmail benutzen
|
||||
config.mailer_sendmail_path=Sendmail-Pfad
|
||||
config.mailer_sendmail_args=Zusätzliche Argumente für Sendmail
|
||||
config.send_test_mail=Test-E-Mail senden
|
||||
config.test_mail_failed=Das Senden der Test-E-Mail an '%s' ist fehlgeschlagen: %v
|
||||
config.test_mail_sent=Eine Test-E-Mail wurde an '%s' gesendet.
|
||||
|
||||
config.oauth_config=OAuth-Konfiguration
|
||||
config.oauth_enabled=Aktiviert
|
||||
|
@ -1307,6 +1441,8 @@ raw_seconds=Sekunden
|
|||
raw_minutes=Minuten
|
||||
|
||||
[dropzone]
|
||||
default_message=Zum Hochladen hier klicken oder Datei ablegen.
|
||||
invalid_input_type=Dateien dieses Dateityps können nicht hochgeladen werden.
|
||||
file_too_big=Dateigröße ({{filesize}} MB) überschreitet die Maximalgröße ({{maxFilesize}} MB).
|
||||
remove_file=Datei entfernen
|
||||
|
||||
|
@ -1314,6 +1450,8 @@ remove_file=Datei entfernen
|
|||
notifications=Nachrichten
|
||||
unread=Ungelesen
|
||||
read=Gelesen
|
||||
no_unread=Keine ungelesenen Benachrichtigungen.
|
||||
no_read=Keine gelesenen Benachrichtigungen.
|
||||
pin=Benachrichtigung pinnen
|
||||
mark_as_read=Als gelesen markieren
|
||||
mark_as_unread=Als ungelesen markieren
|
||||
|
@ -1326,4 +1464,6 @@ error.no_gpg_keys_found=Es konnte kein GPG-Schlüssel zu dieser Signatur gefunde
|
|||
error.not_signed_commit=Kein signierter Commit
|
||||
|
||||
[units]
|
||||
error.no_unit_allowed_repo=Du hast keine Berechtigung auf einen Bereich dieses Repositories zuzugreifen.
|
||||
error.unit_not_allowed=Du hast keine Berechtigung auf diesen Repository-Bereich zuzugreifen.
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ err_empty_admin_password = The administrator password cannot be empty.
|
|||
|
||||
general_title = General Settings
|
||||
app_name = Site Title
|
||||
app_name_helper = Enter your company name here.
|
||||
app_name_helper = You can enter your company name here.
|
||||
repo_path = Repository Root Path
|
||||
repo_path_helper = Remote Git repositories will be saved to this directory.
|
||||
lfs_path = Git LFS Root Path
|
||||
|
@ -121,6 +121,7 @@ federated_avatar_lookup = Enable Federated Avatars
|
|||
federated_avatar_lookup_popup = Enable federated avatar lookup using Libravatar.
|
||||
disable_registration = Disable Self-Registration
|
||||
disable_registration_popup = Disable user self-registration. Only administrators will be able to create new user accounts.
|
||||
allow_only_external_registration_popup=Enable the registration only through external services.
|
||||
openid_signin = Enable OpenID Sign-In
|
||||
openid_signin_popup = Enable user sign-in via OpenID.
|
||||
openid_signup = Enable OpenID Self-Registration
|
||||
|
@ -628,9 +629,9 @@ issues.new.no_milestone = No Milestone
|
|||
issues.new.clear_milestone = Clear milestone
|
||||
issues.new.open_milestone = Open Milestones
|
||||
issues.new.closed_milestone = Closed Milestones
|
||||
issues.new.assignee = Assignee
|
||||
issues.new.clear_assignee = Clear assignee
|
||||
issues.new.no_assignee = No assignee
|
||||
issues.new.assignees = Assignees
|
||||
issues.new.clear_assignees = Clear assignees
|
||||
issues.new.no_assignees = Nobody assigned
|
||||
issues.no_ref = No Branch/Tag Specified
|
||||
issues.create = Create Issue
|
||||
issues.new_label = New Label
|
||||
|
@ -743,15 +744,15 @@ issues.cancel_tracking = Cancel
|
|||
issues.cancel_tracking_history = `cancelled time tracking %s`
|
||||
issues.time_spent_total = Total Time Spent
|
||||
issues.time_spent_from_all_authors = `Total Time Spent: %s`
|
||||
issues.due_date = Due date
|
||||
issues.invalid_due_date_format = "Due date format is invalid, must be 'yyyy-mm-dd'."
|
||||
issues.error_modifying_due_date = "An error occured while modifying the due date."
|
||||
issues.error_removing_due_date = "An error occured while remvoing the due date."
|
||||
issues.due_date_form = "Due date, format yyyy-mm-dd"
|
||||
issues.due_date = Due Date
|
||||
issues.invalid_due_date_format = "Due date format must be 'yyyy-mm-dd'."
|
||||
issues.error_modifying_due_date = "Failed to modify the due date."
|
||||
issues.error_removing_due_date = "Failed to remove the due date."
|
||||
issues.due_date_form = "yyyy-mm-dd"
|
||||
issues.due_date_form_add = "Add due date"
|
||||
issues.due_date_form_update = "Update due date"
|
||||
issues.due_date_form_remove = "Remove due date"
|
||||
issues.due_date_not_writer = "You need to have at least write access to this repository in order to update the due date for this issue."
|
||||
issues.due_date_not_writer = "You need repository write access to update an issue's due date."
|
||||
issues.due_date_not_set = "No due date set."
|
||||
issues.due_date_added = "added the due date %s %s"
|
||||
issues.due_date_modified = "modified the due date to %s from %s %s"
|
||||
|
@ -1369,8 +1370,8 @@ auths.attribute_name = First Name Attribute
|
|||
auths.attribute_surname = Surname Attribute
|
||||
auths.attribute_mail = Email Attribute
|
||||
auths.attributes_in_bind = Fetch Attributes in Bind DN Context
|
||||
auths.use_paged_search = Use paged search
|
||||
auths.search_page_size = Page size
|
||||
auths.use_paged_search = Use Paged Search
|
||||
auths.search_page_size = Page Size
|
||||
auths.filter = User Filter
|
||||
auths.admin_filter = Admin Filter
|
||||
auths.ms_ad_sa = MS AD Search Attributes
|
||||
|
@ -1459,6 +1460,7 @@ config.db_path_helper = (for "sqlite3" and "tidb")
|
|||
config.service_config = Service Configuration
|
||||
config.register_email_confirm = Require Email Confirmation to Register
|
||||
config.disable_register = Disable Self-Registration
|
||||
config.allow_only_external_registration = Enable the registration only through external services
|
||||
config.enable_openid_signup = Enable OpenID Self-Registration
|
||||
config.enable_openid_signin = Enable OpenID Sign-In
|
||||
config.show_registration_button = Show Register Button
|
||||
|
|
|
@ -335,9 +335,6 @@ issues.new.no_milestone=Sin Milestone
|
|||
issues.new.clear_milestone=Limpiar Milestone
|
||||
issues.new.open_milestone=Milestones abiertas
|
||||
issues.new.closed_milestone=Milestones cerradas
|
||||
issues.new.assignee=Asignado a
|
||||
issues.new.clear_assignee=Limpiar asignado
|
||||
issues.new.no_assignee=Sin asignado
|
||||
issues.create=Crear incidencia
|
||||
issues.new_label=Nueva Etiqueta
|
||||
issues.create_label=Crear etiqueta
|
||||
|
|
|
@ -261,9 +261,6 @@ issues.new.no_milestone=Ei merkkipaalua
|
|||
issues.new.clear_milestone=Tyhjennä merkkipaalu
|
||||
issues.new.open_milestone=Avoimet merkkipaalut
|
||||
issues.new.closed_milestone=Suljetut merkkipaalut
|
||||
issues.new.assignee=Osoitettu
|
||||
issues.new.clear_assignee=Tyhjennä osoitettu
|
||||
issues.new.no_assignee=Ei osoitettua
|
||||
issues.create=Ilmoita ongelma
|
||||
issues.new_label=Uusi tunniste
|
||||
issues.create_label=Luo tunniste
|
||||
|
|
|
@ -340,9 +340,6 @@ issues.new.no_milestone=Aucun jalon
|
|||
issues.new.clear_milestone=Effacer le jalon
|
||||
issues.new.open_milestone=Ouvrir un jalon
|
||||
issues.new.closed_milestone=Jalons fermés
|
||||
issues.new.assignee=Affecté à
|
||||
issues.new.clear_assignee=Supprimer les assignataires
|
||||
issues.new.no_assignee=Pas d'assignataire
|
||||
issues.no_ref=Aucune branche/tag spécifiés
|
||||
issues.create=Créer un ticket
|
||||
issues.new_label=Nouvelle étiquette
|
||||
|
|
|
@ -347,9 +347,6 @@ issues.new.no_milestone=Nincs mérföldkő
|
|||
issues.new.clear_milestone=Mérföldkő eltávolítása
|
||||
issues.new.open_milestone=Nyitott mérföldkövek
|
||||
issues.new.closed_milestone=Lezárt mérföldkövek
|
||||
issues.new.assignee=Megbízott
|
||||
issues.new.clear_assignee=Megbízott eltávolítása
|
||||
issues.new.no_assignee=Nincs megbízott
|
||||
issues.no_ref=Nincsen ág/címke megadva
|
||||
issues.create=Hibajegy létrehozása
|
||||
issues.new_label=Új címke
|
||||
|
|
|
@ -340,9 +340,6 @@ issues.new.no_milestone=Tidak Ada Milestone
|
|||
issues.new.clear_milestone=Bersihkan milestone
|
||||
issues.new.open_milestone=Buka Milestone
|
||||
issues.new.closed_milestone=Tutup Milestone
|
||||
issues.new.assignee=Menerima
|
||||
issues.new.clear_assignee=Jelas menerima
|
||||
issues.new.no_assignee=Tidak ada penerima
|
||||
issues.no_ref=Tidak Ada Cabang/Tag Ditentukan
|
||||
issues.create=Buat Masalah
|
||||
issues.new_label=Label Baru
|
||||
|
|
|
@ -323,9 +323,6 @@ issues.new.no_milestone=Nessuna milestone
|
|||
issues.new.clear_milestone=Milestone pulita
|
||||
issues.new.open_milestone=Apri Milestone
|
||||
issues.new.closed_milestone=Milestone chiuse
|
||||
issues.new.assignee=Assegnatario
|
||||
issues.new.clear_assignee=Cancella l'assegnatario
|
||||
issues.new.no_assignee=Nessun assegnatario
|
||||
issues.create=Crea Problema
|
||||
issues.new_label=Nuova etichetta
|
||||
issues.create_label=Crea Etichetta
|
||||
|
|
|
@ -347,9 +347,6 @@ issues.new.no_milestone=マイルストーンなし
|
|||
issues.new.clear_milestone=マイルストーンをクリア
|
||||
issues.new.open_milestone=オープン中のマイルストーン
|
||||
issues.new.closed_milestone=クローズされたマイルストーン
|
||||
issues.new.assignee=担当者
|
||||
issues.new.clear_assignee=担当者をクリア
|
||||
issues.new.no_assignee=担当者なし
|
||||
issues.no_ref=ブランチ/タグが指定されていません
|
||||
issues.create=問題を作成
|
||||
issues.new_label=新しいラベル
|
||||
|
|
|
@ -323,9 +323,6 @@ issues.new.no_milestone=마일스톤 없음
|
|||
issues.new.clear_milestone=마일스톤 초기화
|
||||
issues.new.open_milestone=마일스톤 생성
|
||||
issues.new.closed_milestone=마일스톤 닫기
|
||||
issues.new.assignee=담당자
|
||||
issues.new.clear_assignee=담당자 초기화
|
||||
issues.new.no_assignee=담당자 없음
|
||||
issues.no_ref=Branch/Tag 가 지정되어 있지 않습니다.
|
||||
issues.create=이슈 생성
|
||||
issues.new_label=새로운 레이블
|
||||
|
|
|
@ -347,9 +347,6 @@ issues.new.no_milestone=Nav atskaites punktu
|
|||
issues.new.clear_milestone=Notīrīt atskaites punktus
|
||||
issues.new.open_milestone=Atvērtie atskaites punktus
|
||||
issues.new.closed_milestone=Aizvērtie atskaites punkti
|
||||
issues.new.assignee=Atbildīgais
|
||||
issues.new.clear_assignee=Noņemt atbildīgo
|
||||
issues.new.no_assignee=Nav atbildīgā
|
||||
issues.no_ref=Nav norādīts atzars/tags
|
||||
issues.create=Pieteikt problēmu
|
||||
issues.new_label=Jauna etiķete
|
||||
|
|
|
@ -345,9 +345,6 @@ issues.new.no_milestone=Geen mijlpaal
|
|||
issues.new.clear_milestone=Verwijder mijlpaal
|
||||
issues.new.open_milestone=Open mijlpalen
|
||||
issues.new.closed_milestone=Gesloten mijlpalen
|
||||
issues.new.assignee=Toegewezen aan
|
||||
issues.new.clear_assignee=Verwijder verantwoordelijke
|
||||
issues.new.no_assignee=Geen verantwoordelijke
|
||||
issues.no_ref=Geen Branch/Tag gespecificeerd
|
||||
issues.create=Maak probleem
|
||||
issues.new_label=Nieuw Label
|
||||
|
|
|
@ -340,9 +340,6 @@ issues.new.no_milestone=Brak kamienia milowego
|
|||
issues.new.clear_milestone=Wyczyść kamień milowy
|
||||
issues.new.open_milestone=Otwórz kamienie milowe
|
||||
issues.new.closed_milestone=Zamknięte kamienie milowe
|
||||
issues.new.assignee=Przypisany
|
||||
issues.new.clear_assignee=Usuń przypisanie
|
||||
issues.new.no_assignee=Brak przypisania
|
||||
issues.no_ref=Nie określono gałęzi/etykiety
|
||||
issues.create=Utwórz problem
|
||||
issues.new_label=Nowa etykieta
|
||||
|
|
|
@ -81,7 +81,7 @@ err_empty_admin_password=A senha do administrador não pode ser em branco.
|
|||
|
||||
general_title=Configurações gerais
|
||||
app_name=Título do site
|
||||
app_name_helper=Digite o nome da sua empresa aqui.
|
||||
app_name_helper=Você pode inserir o nome da empresa aqui.
|
||||
repo_path=Caminho raíz do repositório
|
||||
repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório.
|
||||
lfs_path=Caminho raiz do Git LFS
|
||||
|
@ -331,6 +331,7 @@ change_username=Seu nome de usuário foi alterado.
|
|||
change_username_prompt=Nota: as alterações de nome de usuário também mudam sua URL da conta.
|
||||
continue=Continuar
|
||||
cancel=Cancelar
|
||||
language=Idioma
|
||||
|
||||
lookup_avatar_by_mail=Procure o avatar do endereço de e-mail
|
||||
federated_avatar_lookup=Busca de avatar federativo
|
||||
|
@ -623,9 +624,9 @@ issues.new.no_milestone=Sem marco
|
|||
issues.new.clear_milestone=Limpar marco
|
||||
issues.new.open_milestone=Marcos abertos
|
||||
issues.new.closed_milestone=Marcos fechados
|
||||
issues.new.assignee=Responsável
|
||||
issues.new.clear_assignee=Limpar responsável
|
||||
issues.new.no_assignee=Não atribuída
|
||||
issues.new.assignees=Responsáveis
|
||||
issues.new.clear_assignees=Limpar responsáveis
|
||||
issues.new.no_assignees=Nenhum responsável
|
||||
issues.no_ref=Nenhum branch/tag especificado
|
||||
issues.create=Criar issue
|
||||
issues.new_label=Nova etiqueta
|
||||
|
@ -739,14 +740,14 @@ issues.cancel_tracking_history=`cancelou contador de tempo %s`
|
|||
issues.time_spent_total=Tempo total gasto
|
||||
issues.time_spent_from_all_authors=`Tempo total gasto: %s`
|
||||
issues.due_date=Data limite
|
||||
issues.invalid_due_date_format=Formato da data limite inválido, deve ser 'aaaa-mm-dd'.
|
||||
issues.error_modifying_due_date=Ocorreu um erro ao modificar a data limite.
|
||||
issues.error_removing_due_date=Ocorreu um erro ao remover a data limite.
|
||||
issues.due_date_form=Data limite, formato aaaa-mm-dd
|
||||
issues.invalid_due_date_format=Formato da data limite inválido, deve ser 'dd/mm/aaaa'.
|
||||
issues.error_modifying_due_date=Falha ao modificar a data limite.
|
||||
issues.error_removing_due_date=Falha ao remover a data limite.
|
||||
issues.due_date_form=dd/mm/aaaa
|
||||
issues.due_date_form_add=Adicionar data limite
|
||||
issues.due_date_form_update=Modificar data limite
|
||||
issues.due_date_form_remove=Remover data limite
|
||||
issues.due_date_not_writer=Você precisa ter pelo menos permissão de escrita neste repositório para atualizar a data limite desta issue.
|
||||
issues.due_date_not_writer=Você deve ter permissão de escrita no repositório para atualizar a data limite de uma issue.
|
||||
issues.due_date_not_set=Data limite não informada.
|
||||
issues.due_date_added=adicionou a data limite %s à %s
|
||||
issues.due_date_modified=modificou a data limite para %s ao invés de %s à %s
|
||||
|
@ -798,7 +799,7 @@ milestones.title=Título
|
|||
milestones.desc=Descrição
|
||||
milestones.due_date=Prazo (opcional)
|
||||
milestones.clear=Limpar
|
||||
milestones.invalid_due_date_format=Formato da data limite deve ser 'aaaa-mm-dd'.
|
||||
milestones.invalid_due_date_format=Formato da data limite deve ser 'dd/mm/aaaa'.
|
||||
milestones.create_success=O marco '%s' foi criado.
|
||||
milestones.edit=Editar marco
|
||||
milestones.edit_subheader=Marcos organizam as issues e acompanham o progresso.
|
||||
|
@ -1351,6 +1352,8 @@ auths.attribute_name=Atributo primeiro nome
|
|||
auths.attribute_surname=Atributo sobrenome
|
||||
auths.attribute_mail=Atributo e-mail
|
||||
auths.attributes_in_bind=Buscar os atributos no contexto de Bind DN
|
||||
auths.use_paged_search=Use a pesquisa paginada
|
||||
auths.search_page_size=Tamanho da página
|
||||
auths.filter=Filtro de usuário
|
||||
auths.admin_filter=Filtro de administrador
|
||||
auths.ms_ad_sa=Atributos de pesquisa do MS AD
|
||||
|
|
|
@ -475,9 +475,6 @@ issues.new.no_milestone=Нет этапа
|
|||
issues.new.clear_milestone=Очистить этап
|
||||
issues.new.open_milestone=Открыть этап
|
||||
issues.new.closed_milestone=Завершенные этапы
|
||||
issues.new.assignee=Ответственный
|
||||
issues.new.clear_assignee=Убрать ответственного
|
||||
issues.new.no_assignee=Нет ответственного
|
||||
issues.no_ref=Не указана ветка или тэг
|
||||
issues.create=Добавить задачу
|
||||
issues.new_label=Новая метка
|
||||
|
|
|
@ -270,9 +270,6 @@ issues.new.no_milestone=Нема фазе
|
|||
issues.new.clear_milestone=Уклони фазу
|
||||
issues.new.open_milestone=Отворене фазе
|
||||
issues.new.closed_milestone=Затворене фазе
|
||||
issues.new.assignee=Одговорни
|
||||
issues.new.clear_assignee=Уклони одговорног
|
||||
issues.new.no_assignee=Нема одговорних
|
||||
issues.create=Додај задатак
|
||||
issues.new_label=Нова лабела
|
||||
issues.create_label=Креирај лабелу
|
||||
|
|
|
@ -339,9 +339,6 @@ issues.new.no_milestone=Ingen Milsten
|
|||
issues.new.clear_milestone=Rensa milstenar
|
||||
issues.new.open_milestone=Öppna Milstenar
|
||||
issues.new.closed_milestone=Stängda Milstenar
|
||||
issues.new.assignee=Förvärvare
|
||||
issues.new.clear_assignee=Rensa förvärvare
|
||||
issues.new.no_assignee=Ingen förvärvare
|
||||
issues.create=Skapa Ärende
|
||||
issues.new_label=Ny etikett
|
||||
issues.create_label=Skapa Etikett
|
||||
|
|
|
@ -338,9 +338,6 @@ issues.new.no_milestone=Kilometre Taşı Yok
|
|||
issues.new.clear_milestone=Kilometre Taşlarını Temizle
|
||||
issues.new.open_milestone=Kilometre Taşlarını Aç
|
||||
issues.new.closed_milestone=Kapanmış Kilometre Taşları
|
||||
issues.new.assignee=Atanan
|
||||
issues.new.clear_assignee=Atamayı Temizle
|
||||
issues.new.no_assignee=Atanan Kişi Yok
|
||||
issues.no_ref=Bölüm/Etiket Belirtilmedi
|
||||
issues.create=Sorun Oluştur
|
||||
issues.new_label=Yeni Etiket
|
||||
|
|
|
@ -11,7 +11,7 @@ sign_up=Реєстрація
|
|||
link_account=Прив'язати обліковий запис
|
||||
link_account_signin_or_signup=Увійдіть з уже існуючими обліковими даними або зареєструйтеся для зв'язку з цим аккаунтом.
|
||||
register=Реєстрація
|
||||
website=Web-сайт
|
||||
website=Веб-сайт
|
||||
version=Версія
|
||||
page=Сторінка
|
||||
template=Шаблон
|
||||
|
@ -72,20 +72,28 @@ password=Пароль
|
|||
db_name=Ім'я бази даних
|
||||
ssl_mode=SSL
|
||||
path=Шлях
|
||||
sqlite_helper=Шлях до файлу для бази даних SQLite3 або TiDB. <br> Введіть абсолютний шлях, якщо ви запускаєте Gitea як сервіс.
|
||||
err_empty_db_path=Шлях до бази даних SQLite3 або TiDB не може бути порожнім.
|
||||
err_invalid_tidb_name=Ім'я бази даних TiDB не може містити символи '.' або '-'.
|
||||
no_admin_and_disable_registration=Ви не можете вимкнути реєстрацію до створення облікового запису адміністратора.
|
||||
err_empty_admin_password=Пароль адміністратора не може бути порожнім.
|
||||
|
||||
general_title=Загальні налаштування
|
||||
app_name=Назва сайту
|
||||
repo_path=Кореневий шлях репозиторія
|
||||
repo_path_helper=Всі вилучені Git репозиторії будуть збережені в цей каталог.
|
||||
lfs_path=Кореневої шлях Git LFS
|
||||
lfs_path_helper=У цій папці будуть зберігатися файли Git LFS. Залиште порожнім, щоб відключити LFS.
|
||||
lfs_path_helper=У цій папці будуть зберігатися файли Git LFS. Залиште порожнім, щоб вимкнути LFS.
|
||||
run_user=Запуск від імені Користувача
|
||||
run_user_helper=Введіть ім'я користувача операційної системи, під яким працює Gitea. Зверніть увагу, що цей користувач повинен бути доступ до кореневого шляху репозиторія.
|
||||
domain=Домен SSH сервера
|
||||
ssh_port=Порт SSH сервера
|
||||
ssh_port_helper=Номер порту, який використовує SSH сервер. Залиште порожнім, щоб відключити SSH.
|
||||
ssh_port_helper=Номер порту, який використовує SSH сервер. Залиште порожнім, щоб вимкнути SSH.
|
||||
http_port=Gitea HTTP порт
|
||||
http_port_helper=Номер порту, який буде прослуховуватися Giteas веб-сервером.
|
||||
app_url=Базова URL-адреса Gitea
|
||||
log_root_path=Шлях до лог файлу
|
||||
log_root_path_helper=Файли журналу будуть записані в цей каталог.
|
||||
|
||||
optional_title=Додаткові налаштування
|
||||
email_title=Налаштування Email
|
||||
|
@ -93,12 +101,20 @@ smtp_host=SMTP хост
|
|||
smtp_from=Відправляти Email від імені
|
||||
mailer_user=SMTP Ім'я кристувача
|
||||
mailer_password=SMTP Пароль
|
||||
mail_notify=Дозволити поштові повідомлення
|
||||
register_confirm=Потрібно підтвердити електронну пошту для реєстрації
|
||||
mail_notify=Увімкнути сповіщення електронною поштою
|
||||
offline_mode=Увімкнути локальний режим
|
||||
disable_gravatar=Вимкнути Gravatar
|
||||
federated_avatar_lookup=Увімкнути федеративні аватари
|
||||
federated_avatar_lookup_popup=Увімкнути зовнішний Аватар за допомогою Libravatar.
|
||||
disable_registration=Вимкнути самостійну реєстрацію
|
||||
disable_registration_popup=Вимкнути самостійну реєстрацію користувачів, тільки адміністратор може створювати нові облікові записи.
|
||||
openid_signin=Увімкнути реєстрацію за допомогою OpenID
|
||||
openid_signin_popup=Увімкнути вхід за допомогою OpenID.
|
||||
openid_signup=Увімкнути самостійну реєстрацію за допомогою OpenID
|
||||
enable_captcha=Увімкнути CAPTCHA
|
||||
enable_captcha_popup=Вимагати перевірку CAPTCHA при самостійній реєстрації користувача.
|
||||
admin_title=Налаштування облікового запису адміністратора
|
||||
admin_name=Ім'я кристувача Адміністратора
|
||||
admin_password=Пароль
|
||||
confirm_password=Підтвердження пароля
|
||||
|
@ -107,8 +123,14 @@ install_btn_confirm=Встановлення Gitea
|
|||
test_git_failed=Не в змозі перевірити 'git' команду: %v
|
||||
save_config_failed=Не в змозі зберегти конфігурацію: %v
|
||||
install_success=Ласкаво просимо! Дякуємо вам за вибір Gitea. Розважайтеся, і будьте обережні!
|
||||
default_keep_email_private=Приховати адресу електронної пошти за замовчуванням
|
||||
default_keep_email_private_popup=Приховати адресу електронної пошти нових облікових записів за замовчуванням.
|
||||
default_allow_create_organization=Дозволити створення організацій за замовчуванням
|
||||
default_enable_timetracking=Увімкнути відстеження часу за замовчуванням
|
||||
no_reply_address=Прихований поштовий домен
|
||||
|
||||
[home]
|
||||
uname_holder=Ім'я користувача або Ел. пошта
|
||||
password_holder=Пароль
|
||||
switch_dashboard_context=Змінити дошку
|
||||
my_repos=Мої репозиторії
|
||||
|
@ -127,17 +149,20 @@ users=Користувачі
|
|||
organizations=Організації
|
||||
search=Пошук
|
||||
code=Код
|
||||
repo_no_results=Відповідних репозиторіїв не знайдено.
|
||||
code_search_results=Результати пошуку '%s'
|
||||
|
||||
[auth]
|
||||
create_new_account=Реєстрація аккаунта
|
||||
register_helper_msg=Вже зареєстровані? Увійдіть зараз!
|
||||
disable_register_prompt=Вибачте, можливість реєстрації відключена. Будь ласка, зв'яжіться з адміністратором сайту.
|
||||
disable_register_mail=Підтвердження реєстрації електронною поштою вимкнено.
|
||||
remember_me=Запам'ятати мене
|
||||
forgot_password_title=Забув пароль
|
||||
forgot_password=Забули пароль?
|
||||
sign_up_now=Потрібен аккаунт? Зареєструватися.
|
||||
confirmation_mail_sent_prompt=Новий лист для підтвердження було направлено на <b>%s</b>, будь ласка, перевірте вашу поштову скриньку протягом% s для завершення реєстрації.
|
||||
reset_password_mail_sent_prompt=Лист для підтвердження було направлено на <b>%s</b>. Будь ласка, перевірте вашу поштову скриньку протягом% s для скидання пароля.
|
||||
confirmation_mail_sent_prompt=Новий лист для підтвердження було відправлено на <b>%s</b>, будь ласка, перевірте вашу поштову скриньку протягом %s для завершення реєстрації.
|
||||
reset_password_mail_sent_prompt=Лист для підтвердження було відправлено на <b>%s</b>. Будь ласка, перевірте вашу поштову скриньку протягом %s для скидання пароля.
|
||||
active_your_account=Активувати обліковий запис
|
||||
prohibit_login=Вхід заборонений
|
||||
prohibit_login_desc=Вхід для вашого профілю був заборонений, будь ласка, зв'яжіться з адміністратором сайту.
|
||||
|
@ -197,22 +222,33 @@ TreeName=Шлях до файлу
|
|||
Content=Зміст
|
||||
|
||||
require_error=` не може бути пустим.`
|
||||
git_ref_name_error=` має бути правильним посилальним ім'ям Git.`
|
||||
git_ref_name_error=` повинен бути правильним посилальним ім'ям Git.`
|
||||
size_error=` повинен бути розмір %s.`
|
||||
min_size_error=` повинен бути принаймні %s символів.`
|
||||
max_size_error=` повинен бути не більш як %s символів.`
|
||||
email_error=` не є адресою електронної пошти.`
|
||||
url_error=` не є припустимою URL-Адресою.`
|
||||
include_error=`повинен бути текст '%s'`
|
||||
unknown_error=Невідома помилка:
|
||||
captcha_incorrect=Код CAPTCHA неправильний.
|
||||
password_not_match=Паролі не співпадають.
|
||||
|
||||
username_been_taken=Ім'я користувача вже зайнято.
|
||||
repo_name_been_taken=Ім'я репозіторію вже використовується.
|
||||
org_name_been_taken=Назва організації вже зайнято.
|
||||
team_name_been_taken=Назва команди вже зайнято.
|
||||
email_been_used=Ця електронна адреса вже використовується.
|
||||
openid_been_used=OpenID адреса '%s' вже використовується.
|
||||
username_password_incorrect=Неправильне ім'я користувача або пароль.
|
||||
user_not_exist=Даний користувач не існує.
|
||||
|
||||
auth_failed=Помилка автентифікації: %v
|
||||
|
||||
|
||||
target_branch_not_exist=Цільової гілки не існує.
|
||||
|
||||
[user]
|
||||
change_avatar=Змінити свій аватар…
|
||||
join_on=Приєднався
|
||||
repositories=Репозиторії
|
||||
activity=Публічна активність
|
||||
|
@ -241,34 +277,44 @@ uid=Ідентифікатор Uid
|
|||
|
||||
public_profile=Загальнодоступний профіль
|
||||
full_name=Повне ім'я
|
||||
website=Web-сайт
|
||||
website=Веб-сайт
|
||||
location=Місцезнаходження
|
||||
update_profile=Оновити профіль
|
||||
update_profile_success=Профіль успішно оновлено.
|
||||
continue=Продовжити
|
||||
cancel=Відміна
|
||||
language=Мова
|
||||
|
||||
federated_avatar_lookup=Знайти зовнішній аватар
|
||||
enable_custom_avatar=Увімкнути користувацькі аватари
|
||||
choose_new_avatar=Оберіть новий аватар
|
||||
update_avatar=Оновити аватар
|
||||
delete_current_avatar=Видалити поточний аватар
|
||||
update_avatar_success=Ваш аватар був змінений.
|
||||
|
||||
change_password=Оновити пароль
|
||||
old_password=Поточний пароль
|
||||
new_password=Новий пароль
|
||||
retype_new_password=Введіть новий пароль ще раз
|
||||
change_password_success=Ваш пароль був оновлений. Тепер увійдіть в систему, використовуючи новий пароль.
|
||||
password_change_disabled=Нелокальні акаунти не можуть змінити пароль через Gitea.
|
||||
|
||||
emails=Адреса електронної пошти
|
||||
manage_emails=Керування адресами ел. пошти
|
||||
email_desc=Ваша основна адреса електронної пошти використовуватиметься для сповіщення та інших операцій.
|
||||
primary=Основний
|
||||
primary_email=Зробити основним
|
||||
delete_email=Видалити
|
||||
add_new_email=Додати нову адресу електронної пошти
|
||||
add_email=Додати адресу електронної пошти
|
||||
keep_email_private=Приховати адресу електронної пошти
|
||||
keep_email_private_popup=Вашу адресу електронної пошти буде приховано від інших користувачів.
|
||||
|
||||
manage_ssh_keys=Керувати SSH ключами
|
||||
manage_gpg_keys=Керувати GPG ключами
|
||||
add_key=Додати ключ
|
||||
ssh_helper=<strong>Потрібна допомога?</strong> Дивіться гід на GitHub з <a href="%s"> генерації ключів SSH</a> або виправлення <a href="%s">типових неполадок SSH</a>.
|
||||
gpg_helper=<strong> Потрібна допомога? </strong> Перегляньте посібник GitHub <a href="%s"> про GPG </a>.
|
||||
add_new_key=Додати SSH ключ
|
||||
add_new_gpg_key=Додати GPG ключ
|
||||
key_id=ID ключа
|
||||
|
@ -277,6 +323,7 @@ key_content=Зміст
|
|||
delete_key=Видалити
|
||||
ssh_key_deletion=Видалити SSH ключ
|
||||
gpg_key_deletion=Видалити GPG ключ
|
||||
gpg_key_deletion_desc=Видалення GPG ключа скасовує перевірку підписаних ним комітів. Продовжити?
|
||||
add_on=Додано
|
||||
valid_until=Дійсний до
|
||||
valid_forever=Дійсний завжди
|
||||
|
@ -288,14 +335,18 @@ key_state_desc=Цей ключ використовувався в останн
|
|||
token_state_desc=Цей токен використовувався в останні 7 днів
|
||||
show_openid=Показати у профілю
|
||||
hide_openid=Не показувати у профілі
|
||||
ssh_disabled=SSH вимкнено
|
||||
|
||||
manage_social=Керувати зв'язаними аккаунтами соціальних мереж
|
||||
unbind=Від'єднати
|
||||
|
||||
generate_new_token=Згенерувати новий токен
|
||||
token_name=Ім'я токену
|
||||
generate_token=Згенерувати токен
|
||||
delete_token=Видалити
|
||||
|
||||
twofa_disable=Вимкнути двофакторну автентифікацію
|
||||
or_enter_secret=Або введіть секрет: %s
|
||||
|
||||
|
||||
|
||||
|
@ -321,20 +372,28 @@ readme_helper=Виберіть шаблон README.
|
|||
create_repo=Створити репозиторій
|
||||
default_branch=Головна гілка
|
||||
mirror_prune=Очистити
|
||||
mirror_interval=Інтервал дзеркалювання (доступні значення 'h', 'm', 's')
|
||||
mirror_address=Клонування з URL-адреси
|
||||
mirror_last_synced=Остання синхронізація
|
||||
watchers=Спостерігачі
|
||||
forks=Форки
|
||||
pick_reaction=Залиште свою оцінку
|
||||
|
||||
form.reach_limit_of_creation=Ви досягли максимальної кількості %d створених репозиторіїв.
|
||||
|
||||
need_auth=Клонування авторизації
|
||||
migrate_type=Тип міграції
|
||||
migrate_type_helper=Даний репозиторій буде <span class="text blue">дзеркалом</span>
|
||||
migrate_repo=Перенесення репозиторія
|
||||
migrate.clone_address=Міграція / клонувати з URL-адреси
|
||||
migrate.clone_address_desc=URL-адреса HTTP(S) або Git "clone" існуючого репозиторія
|
||||
migrate.failed=Міграція не вдалася: %v
|
||||
migrate.lfs_mirror_unsupported=Дзеркалювання LFS об'єктів не підтримується - використовуйте 'git lfs fetch --all' і 'git lfs push --all' вручну.
|
||||
|
||||
mirror_from=дзеркало
|
||||
forked_from=форк від
|
||||
copy_link=Копіювати
|
||||
copy_link_error=Натисніть ⌘-C або Ctrl-C, щоб скопіювати
|
||||
copied=Скопійовано
|
||||
unwatch=Не стежити
|
||||
watch=Слідкувати
|
||||
|
@ -368,13 +427,16 @@ file_history=Історія
|
|||
file_view_raw=Перегляд Raw
|
||||
file_permalink=Постійне посилання
|
||||
stored_lfs=Збережено з Git LFS
|
||||
commit_graph=Графік комітів
|
||||
|
||||
editor.new_file=Новий файл
|
||||
editor.upload_file=Завантажити файл
|
||||
editor.edit_file=Редагування файлу
|
||||
editor.preview_changes=Попередній перегляд змін
|
||||
editor.edit_this_file=Редагувати файл
|
||||
editor.must_be_on_a_branch=Ви повинні бути у гілці щоб зробити, або запропонувати зміни до цього файлу.
|
||||
editor.delete_this_file=Видалити файл
|
||||
editor.must_have_write_access=Ви повинні мати доступ на запис щоб запропонувати зміни до цього файлу.
|
||||
editor.name_your_file=Дайте назву файлу…
|
||||
editor.or=або
|
||||
editor.cancel_lower=Скасувати
|
||||
|
@ -383,13 +445,17 @@ editor.add_tmpl=Додати '%s/<filename>'
|
|||
editor.add=Додати '%s'
|
||||
editor.update=Оновити '%s'
|
||||
editor.delete=Видалити '%s'
|
||||
editor.commit_message_desc=Додати необов'язковий розширений опис…
|
||||
editor.commit_directly_to_this_branch=Зробіть коміт прямо в гілку <strong class="branch-name">%s</strong>.
|
||||
editor.create_new_branch=Створити <strong>нову гілку</strong> для цього коміту та відкрити запит на злиття.
|
||||
editor.new_branch_name_desc=Нова назва гілки…
|
||||
editor.new_branch_name_desc=Ім'я нової гілки…
|
||||
editor.cancel=Відміна
|
||||
editor.branch_already_exists=Гілка '%s' вже присутня в репозиторії.
|
||||
editor.fail_to_update_file=Не вдалося оновити/створити файл '%s' через помилку: %v
|
||||
editor.upload_files_to_dir=Завантажувати файли до '%s'
|
||||
|
||||
commits.commits=Коміти
|
||||
commits.search=Знайти коміт…
|
||||
commits.find=Пошук
|
||||
commits.search_all=Усі гілки
|
||||
commits.author=Автор
|
||||
|
@ -398,27 +464,32 @@ commits.date=Дата
|
|||
commits.older=Давніше
|
||||
commits.newer=Новіше
|
||||
|
||||
ext_issues=Зов. Проблеми
|
||||
|
||||
issues.new=Нова Проблема
|
||||
issues.new=Нова проблема
|
||||
issues.new.labels=Мітки
|
||||
issues.new.no_label=Без Мітки
|
||||
issues.new.no_label=Без мітки
|
||||
issues.new.clear_labels=Очистити мітки
|
||||
issues.new.milestone=Етап
|
||||
issues.new.no_milestone=Етап відсутній
|
||||
issues.new.clear_milestone=Очистити етап
|
||||
issues.new.open_milestone=Активні етапи
|
||||
issues.new.closed_milestone=Закриті етапи
|
||||
issues.new.assignee=Виконавець
|
||||
issues.new.clear_assignee=Прибрати виконавеця
|
||||
issues.new.no_assignee=Немає виконавеця
|
||||
issues.create=Створити Проблему
|
||||
issues.new.assignees=Виконавеці
|
||||
issues.new.clear_assignees=Прибрати виконавеців
|
||||
issues.no_ref=Не вказана гілка або тег
|
||||
issues.create=Створити проблему
|
||||
issues.new_label=Нова мітка
|
||||
issues.new_label_placeholder=Назва мітки
|
||||
issues.new_label_desc_placeholder=Опис
|
||||
issues.create_label=Створити мітку
|
||||
issues.label_templates.helper=Оберіть набір міток
|
||||
issues.label_templates.fail_to_load_file=Не вдалося завантажити файл шаблона мітки '%s': %v
|
||||
issues.add_label_at=додав(ла) мітку <div class="ui label" style="color: %s\; background-color: %s">%s</div> %s
|
||||
issues.add_milestone_at=`додав(ла) до <b>%s</b> етапу %s`
|
||||
issues.deleted_milestone=`(видалено)`
|
||||
issues.add_assignee_at=`був призначений <b>%s</b> %s`
|
||||
issues.remove_assignee_at=`видалили із призначених %s`
|
||||
issues.open_tab=%d відкрито
|
||||
issues.close_tab=%d закрито
|
||||
issues.filter_label=Мітка
|
||||
|
@ -453,7 +524,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=Закрити
|
||||
|
@ -493,7 +564,11 @@ issues.add_time_short=Додати час
|
|||
issues.add_time_cancel=Відміна
|
||||
issues.add_time_hours=Години
|
||||
issues.add_time_minutes=Хвилини
|
||||
issues.add_time_sum_to_small=Час не введено.
|
||||
issues.cancel_tracking=Відміна
|
||||
issues.due_date=Термін дії
|
||||
issues.due_date_form_add=Додати дату завершення
|
||||
issues.due_date_form_remove=Видалити дату завершення
|
||||
|
||||
pulls.new=Новий запит на злиття
|
||||
pulls.compare_changes=Новий запит на злиття
|
||||
|
@ -503,7 +578,9 @@ pulls.filter_branch=Фільтр по гілці
|
|||
pulls.no_results=Результатів не знайдено.
|
||||
pulls.create=Створити запит на злиття
|
||||
pulls.title_desc=хоче злити %[1]d комітів з <code>%[2]s</code> до <code>%[3]s</code>
|
||||
pulls.tab_conversation=Обговорення
|
||||
pulls.tab_commits=Коміти
|
||||
pulls.tab_files=Змінені файли
|
||||
pulls.reopen_to_merge=Будь ласка перевідкрийте цей запит щоб здіснити операцію злиття.
|
||||
pulls.merged=Злито
|
||||
pulls.can_auto_merge_desc=Цей запит можна об'єднати автоматично.
|
||||
|
@ -525,6 +602,7 @@ milestones.edit=Редагувати етап
|
|||
milestones.cancel=Відміна
|
||||
milestones.modify=Оновити етап
|
||||
|
||||
ext_wiki=Зов. Wiki
|
||||
|
||||
wiki=Wiki
|
||||
wiki.welcome=Ласкаво просимо до Wiki.
|
||||
|
@ -533,6 +611,7 @@ wiki.page=Сторінка
|
|||
wiki.filter_page=Фільтр сторінок
|
||||
wiki.new_page=Сторінка
|
||||
wiki.save_page=Зберегти сторінку
|
||||
wiki.last_commit_info=%s редагував цю сторінку %s
|
||||
wiki.edit_page_button=Редагувати
|
||||
wiki.new_page_button=Нова сторінка
|
||||
wiki.delete_page_button=Видалити сторінку
|
||||
|
@ -546,15 +625,17 @@ activity.period.halfweekly=3 дні
|
|||
activity.period.weekly=1 тиждень
|
||||
activity.period.monthly=1 місяць
|
||||
activity.overview=Огляд
|
||||
activity.active_prs_count_1=<strong>%d</strong> Активний запити на злиття
|
||||
activity.active_prs_count_n=<strong>%d</strong> Активні запити на злиття
|
||||
activity.merged_prs_count_1=Злитий запит на злиття
|
||||
activity.merged_prs_count_n=Злиті запити на злиття
|
||||
activity.opened_prs_count_1=Запропонований запит на злиття
|
||||
activity.opened_prs_count_n=Запропонованих запитів на злиття
|
||||
activity.title.user_1=%d користувач
|
||||
activity.title.user_n=%d користувачів
|
||||
activity.title.user_1=%d користувачем
|
||||
activity.title.user_n=%d користувачами
|
||||
activity.title.prs_1=%d Запит на злиття
|
||||
activity.title.prs_n=%d Запитів на злиття
|
||||
activity.title.prs_merged_by=%s злито %s
|
||||
activity.title.prs_opened_by=%s запропоновано %s
|
||||
activity.merged_prs_label=Злито
|
||||
activity.opened_prs_label=Запропоновано
|
||||
|
@ -564,8 +645,8 @@ activity.closed_issues_count_1=Закрита проблема
|
|||
activity.closed_issues_count_n=Закриті проблеми
|
||||
activity.title.issues_1=%d Проблема
|
||||
activity.title.issues_n=%d Проблеми
|
||||
activity.title.issues_closed_by=%s закрито %s
|
||||
activity.title.issues_created_by=%s створено %s
|
||||
activity.title.issues_closed_by=%s закрита(і) %s
|
||||
activity.title.issues_created_by=%s створена(і) %s
|
||||
activity.closed_issue_label=Закриті
|
||||
activity.new_issues_count_1=Нова Проблема
|
||||
activity.new_issues_count_n=%d Проблем
|
||||
|
@ -573,7 +654,7 @@ activity.new_issue_label=Відкриті
|
|||
activity.unresolved_conv_label=Відкрити
|
||||
activity.title.releases_1=%d Реліз
|
||||
activity.title.releases_n=%d Релізів
|
||||
activity.title.releases_published_by=%s Опубліковано %s
|
||||
activity.title.releases_published_by=%s опубліковано %s
|
||||
activity.published_release_label=Опубліковано
|
||||
|
||||
search=Пошук
|
||||
|
@ -582,7 +663,7 @@ search.search_repo=Пошук репозиторію
|
|||
settings=Налаштування
|
||||
settings.options=Репозиторій
|
||||
settings.collaboration.admin=Адміністратор
|
||||
settings.collaboration.write=Написати
|
||||
settings.collaboration.write=Запис
|
||||
settings.collaboration.read=Читати
|
||||
settings.collaboration.undefined=Не визначено
|
||||
settings.hooks=Веб-хуки
|
||||
|
@ -590,7 +671,7 @@ settings.githooks=Git хуки
|
|||
settings.basic_settings=Базові налаштування
|
||||
settings.mirror_settings=Налаштування дзеркала
|
||||
settings.sync_mirror=Синхронізувати зараз
|
||||
settings.site=Web-сайт
|
||||
settings.site=Веб-сайт
|
||||
settings.update_settings=Оновити налаштування
|
||||
settings.advanced_settings=Додаткові налаштування
|
||||
settings.wiki_desc=Увімкнути репозиторії Wiki
|
||||
|
@ -598,14 +679,21 @@ settings.use_internal_wiki=Використовувати вбудовані Wik
|
|||
settings.use_external_wiki=Використовувати зовнішні Wiki
|
||||
settings.external_wiki_url=URL зовнішньої wiki
|
||||
settings.external_tracker_url=URL зовнішньої системи відстеження проблем
|
||||
settings.tracker_url_format=Формат URL зовнішнього трекера задач
|
||||
settings.tracker_issue_style.numeric=Цифровий
|
||||
settings.tracker_issue_style.alphanumeric=Буквено-цифровий
|
||||
settings.admin_settings=Налаштування адміністратора
|
||||
settings.danger_zone=Небезпечна зона
|
||||
settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою. Будь ласка, виберіть інше ім'я.
|
||||
settings.transfer=Переказати новому власнику
|
||||
settings.convert=Перетворити на звичайний репозиторій
|
||||
settings.transfer=Передати новому власнику
|
||||
settings.wiki_delete=Видалити Wiki-дані
|
||||
settings.confirm_wiki_delete=Видалити Wiki-дані
|
||||
settings.delete=Видалити цей репозиторій
|
||||
settings.delete_notices_1=- Цю операцію <strong>НЕ МОЖНА</strong> відмінити.
|
||||
settings.update_settings_success=Налаштування репозиторію було оновлено.
|
||||
settings.transfer_owner=Новий власник
|
||||
settings.make_transfer=Здіснити перенесення
|
||||
settings.confirm_delete=Видалити репозиторій
|
||||
settings.delete_collaborator=Видалити
|
||||
settings.search_user_placeholder=Пошук користувача…
|
||||
|
@ -626,6 +714,7 @@ settings.slack_icon_url=URL іконки
|
|||
settings.discord_username=Ім'я кристувача
|
||||
settings.discord_icon_url=URL іконки
|
||||
settings.slack_color=Колір
|
||||
settings.event_send_everything=Всі події
|
||||
settings.event_create=Створити
|
||||
settings.event_create_desc=Гілку або тег створено.
|
||||
settings.event_pull_request=Запити до злиття
|
||||
|
@ -639,7 +728,7 @@ settings.slack_domain=Домен
|
|||
settings.slack_channel=Канал
|
||||
settings.deploy_keys=Ключі для розгортування
|
||||
settings.add_deploy_key=Додати ключ для розгортування
|
||||
settings.is_writable=Включити доступ для запису
|
||||
settings.is_writable=Увімкнути доступ для запису
|
||||
settings.title=Заголовок
|
||||
settings.deploy_key_content=Зміст
|
||||
settings.branches=Гілки
|
||||
|
@ -653,8 +742,11 @@ settings.delete_protected_branch=Вимкнути захист
|
|||
settings.choose_branch=Оберіть гілку…
|
||||
|
||||
diff.browse_source=Переглянути джерело
|
||||
diff.parent=джерело
|
||||
diff.commit=коміт
|
||||
diff.show_diff_stats=Показати статистику Diff
|
||||
diff.show_split_view=Розділений перегляд
|
||||
diff.show_unified_view=Об'єднаний перегляд
|
||||
diff.stats_desc=<strong> %d змінених файлів</strong> з <strong>%d додано</strong> та <strong>%d видалено</strong>
|
||||
diff.view_file=Переглянути файл
|
||||
diff.too_many_files=Деякі файли не було показано, через те що забагато файлів було змінено
|
||||
|
@ -668,11 +760,14 @@ release.edit=редагувати
|
|||
release.ahead=<strong>%d</strong> комітів %s після цього релізу
|
||||
release.tag_name=Назва тегу
|
||||
release.target=Ціль
|
||||
release.tag_helper=Виберіть існуючий тег або створіть новий.
|
||||
release.title=Заголовок
|
||||
release.content=Зміст
|
||||
release.write=Запис
|
||||
release.preview=Переглянути
|
||||
release.loading=Завантаження…
|
||||
release.prerelease_desc=Позначити як пре-реліз
|
||||
release.prerelease_helper=Позначте цей випуск непридатним для ПРОД використання.
|
||||
release.cancel=Відміна
|
||||
release.publish=Опублікувати реліз
|
||||
release.save_draft=Зберегти чернетку
|
||||
|
@ -710,13 +805,17 @@ team_permission_desc=Права доступу
|
|||
settings=Налаштування
|
||||
settings.options=Організація
|
||||
settings.full_name=Повне ім'я
|
||||
settings.website=Web-сайт
|
||||
settings.website=Веб-сайт
|
||||
settings.location=Розташування
|
||||
settings.update_settings=Оновити налаштування
|
||||
settings.delete=Видалити організацію
|
||||
settings.delete_account=Видалити цю організацію
|
||||
settings.confirm_delete_account=Підтвердіть видалення
|
||||
|
||||
members.membership_visibility=Видимість учасника:
|
||||
members.public_helper=зробити прихованим
|
||||
members.private=Прихований
|
||||
members.private_helper=зробити видимим
|
||||
members.member_role=Роль учасника:
|
||||
members.owner=Власник
|
||||
members.member=Учасник
|
||||
|
@ -728,6 +827,8 @@ members.invite_now=Запросити зараз
|
|||
teams.join=Приєднатися
|
||||
teams.leave=Покинути
|
||||
teams.read_access=Доступ для читання
|
||||
teams.write_access=Доступ на запис
|
||||
teams.admin_access=Доступ адміністратора
|
||||
teams.settings=Налаштування
|
||||
teams.members=Учасники команди
|
||||
teams.update_settings=Оновити налаштування
|
||||
|
@ -740,6 +841,7 @@ dashboard=Панель управління
|
|||
users=Облікові записи користувачів
|
||||
organizations=Організації
|
||||
repositories=Репозиторії
|
||||
authentication=Джерела автентифікації
|
||||
config=Конфігурація
|
||||
notices=Сповіщення системи
|
||||
monitor=Моніторинг
|
||||
|
@ -755,20 +857,40 @@ dashboard.delete_inactivate_accounts=Видалити всі неактивні
|
|||
dashboard.delete_inactivate_accounts_success=Усі неактивні облікові записи успішно видалено.
|
||||
dashboard.server_uptime=Uptime серверу
|
||||
dashboard.current_memory_usage=Поточне використання пам'яті
|
||||
dashboard.total_memory_allocated=Виділено пам'яті загалом
|
||||
dashboard.memory_obtained=Отримано пам'яті
|
||||
dashboard.stack_memory_obtained=Зайнято пам'яті стеком
|
||||
dashboard.mspan_structures_usage=Використання структур MSpan
|
||||
dashboard.mspan_structures_obtained=Отримано структур MSpan
|
||||
dashboard.mcache_structures_usage=Використання структур MCache
|
||||
dashboard.mcache_structures_obtained=Отримано структур MCache
|
||||
dashboard.profiling_bucket_hash_table_obtained=Отримано хеш-таблиць профілювання
|
||||
dashboard.gc_metadata_obtained=Отримано метаданих GC
|
||||
dashboard.other_system_allocation_obtained=Отримання інших виділень пам'яті
|
||||
dashboard.next_gc_recycle=Наступний цикл GC
|
||||
|
||||
users.user_manage_panel=Керування обліковими записами користувачів
|
||||
users.new_account=Створити обліковий запис
|
||||
users.name=Ім'я кристувача
|
||||
users.activated=Активовано
|
||||
users.admin=Адміністратор
|
||||
users.repos=Репозиторії
|
||||
users.created=Створено
|
||||
users.last_login=Останній вхід
|
||||
users.send_register_notify=Надіслати повідомлення про реєстрацію користувача
|
||||
users.edit=Редагувати
|
||||
users.auth_source=Джерело автентифікації
|
||||
users.local=Локальні
|
||||
users.max_repo_creation=Максимальна кількість репозиторіїв
|
||||
users.max_repo_creation_desc=(Введіть -1, щоб використовувати глобальний ліміт за замовчуванням.)
|
||||
users.is_activated=Обліковий запис користувача увімкнено
|
||||
users.prohibit_login=Вимкнути вхід
|
||||
users.is_admin=Адміністратор
|
||||
users.allow_git_hook=Може створювати Git хуки
|
||||
users.allow_import_local=Може імпортувати локальні репозиторії
|
||||
users.allow_create_organization=Може створювати організацій
|
||||
users.update_profile=Оновити обліковий запис
|
||||
users.delete_account=Видалити цей обліковий запис
|
||||
|
||||
orgs.org_manage_panel=Керування організаціями
|
||||
orgs.name=Назва
|
||||
|
@ -780,9 +902,12 @@ repos.repo_manage_panel=Керування організаціями
|
|||
repos.owner=Власник
|
||||
repos.name=Назва
|
||||
repos.private=Приватний
|
||||
repos.stars=В обраному
|
||||
repos.issues=Проблеми
|
||||
repos.size=Розмір
|
||||
|
||||
auths.auth_manage_panel=Керування джерелом аутентифікації
|
||||
auths.new=Додати джерело автентифікації
|
||||
auths.name=Ім'я
|
||||
auths.type=Тип
|
||||
auths.enabled=Увімкнено
|
||||
|
@ -807,11 +932,27 @@ auths.oauth2_profileURL=URL профілю
|
|||
auths.oauth2_emailURL=URL електронної пошти
|
||||
auths.enable_auto_register=Увімкнути автоматичну реєстрацію
|
||||
auths.tips=Поради
|
||||
auths.tips.oauth2.general=OAuth2 аутентифікація
|
||||
auths.tips.oauth2.general.tip=При додаванні нового OAuth2 провайдера, URL адреса переадресації по завершенні аутентифікації повинена виглядати так:<host>/user/oauth2/<Authentication Name>/callback
|
||||
auths.tip.oauth2_provider=Постачальник OAuth2
|
||||
auths.tip.dropbox=Додайте новий додаток на https://www.dropbox.com/developers/apps
|
||||
auths.tip.facebook=Створіть новий додаток на https://developers.facebook.com/apps і додайте модуль "Facebook Login
|
||||
auths.tip.github=Додайте OAuth додаток на https://github.com/settings/applications/new
|
||||
auths.tip.gitlab=Додайте новий додаток на https://gitlab.com/profile/applications
|
||||
auths.tip.openid_connect=Використовуйте OpenID Connect Discovery URL (<server>/.well-known/openid-configuration) для автоматичної настройки входу OAuth
|
||||
auths.edit=Редагувати джерело автентифікації
|
||||
auths.update=Оновити джерело автентифікації
|
||||
auths.delete=Видалити джерело автентифікації
|
||||
auths.delete_auth_title=Видалити джерело автентифікації
|
||||
|
||||
config.server_config=Конфігурація сервера
|
||||
config.app_name=Назва сайту
|
||||
config.app_ver=Версія Gitea
|
||||
config.app_url=Базова URL-адреса Gitea
|
||||
config.custom_conf=Шлях до файлу конфігурації
|
||||
config.domain=Домен SSH сервера
|
||||
config.disable_router_log=Вимкнути логування роутеру
|
||||
config.run_user=Запуск від імені Користувача
|
||||
config.run_mode=Режим виконання
|
||||
config.git_version=Версія Git
|
||||
config.repo_root_path=Кореневий шлях репозиторія
|
||||
|
@ -822,7 +963,14 @@ config.script_type=Тип скрипта
|
|||
|
||||
config.ssh_config=Конфігурація SSH
|
||||
config.ssh_enabled=Увімкнено
|
||||
config.ssh_domain=Домен сервера
|
||||
config.ssh_port=Порт
|
||||
config.ssh_listen_port=Порт що прослуховується
|
||||
config.ssh_root_path=Шлях до кореню
|
||||
config.ssh_key_test_path=Шлях до тестового ключа
|
||||
config.ssh_keygen_path=Шлях до генератора ключів ('ssh-keygen')
|
||||
config.ssh_minimum_key_size_check=Мінімальний розмір ключа перевірки
|
||||
config.ssh_minimum_key_sizes=Мінімальні розміри ключів
|
||||
|
||||
config.db_config=Конфігурація бази даних
|
||||
config.db_type=Тип
|
||||
|
@ -835,16 +983,32 @@ config.db_path=Шлях
|
|||
config.db_path_helper=(для "sqlite3" і "tidb")
|
||||
|
||||
config.service_config=Конфігурація сервісу
|
||||
config.register_email_confirm=Потрібно підтвердити електронну пошту для реєстрації
|
||||
config.disable_register=Вимкнути самостійну реєстрацію
|
||||
config.enable_openid_signup=Увімкнути самостійну реєстрацію за допомогою OpenID
|
||||
config.enable_openid_signin=Увімкнути реєстрацію за допомогою OpenID
|
||||
config.show_registration_button=Показувати кнопку "Реєстрація
|
||||
config.mail_notify=Увімкнути сповіщення електронною поштою
|
||||
config.disable_key_size_check=Вимкнути перевірку мінімального розміру ключа
|
||||
config.enable_captcha=Увімкнути CAPTCHA
|
||||
config.active_code_lives=Час актуальності кода підтвердження
|
||||
config.default_keep_email_private=Приховати адресу електронної пошти за замовчуванням
|
||||
config.default_allow_create_organization=Дозволити створення організацій за замовчуванням
|
||||
config.default_enable_timetracking=Увімкнути відстеження часу за замовчуванням
|
||||
|
||||
config.webhook_config=Конфігурація web-хуків
|
||||
config.queue_length=Довжина черги
|
||||
config.deliver_timeout=Затримка доставлення
|
||||
config.skip_tls_verify=Пропустити перевірку TLS
|
||||
|
||||
config.mailer_enabled=Увімкнено
|
||||
config.mailer_disable_helo=Вимкнути HELO
|
||||
config.mailer_name=Ім'я
|
||||
config.mailer_host=Хост
|
||||
config.mailer_user=Користувач
|
||||
config.mailer_use_sendmail=Використовувати Sendmail
|
||||
config.mailer_sendmail_path=Шлях до Sendmail
|
||||
config.send_test_mail=Відправити тестового листа
|
||||
|
||||
config.oauth_config=Конфігурація OAuth
|
||||
config.oauth_enabled=Увімкнено
|
||||
|
@ -856,7 +1020,10 @@ config.cache_conn=Підключення до кешу
|
|||
|
||||
config.session_config=Конфігурація сесії
|
||||
config.session_provider=Провайдер сесії
|
||||
config.provider_config=Конфігурація постачальника
|
||||
config.cookie_name=Ім'я файлу cookie
|
||||
config.enable_set_cookie=Увімкнути встановлення cookie
|
||||
config.gc_interval_time=Інтервал запуску GC
|
||||
config.session_life_time=Час життя сесії
|
||||
config.https_only=Тільки HTTPS
|
||||
config.cookie_life_time=Час життя cookie-файлу
|
||||
|
@ -867,6 +1034,9 @@ config.enable_federated_avatar=Увімкнути зовнішні аватар
|
|||
|
||||
config.git_config=Конфігурація git
|
||||
config.git_disable_diff_highlight=Вимкнути підсвітку синтаксису diff
|
||||
config.git_max_diff_lines=Максимум рядків на diff (на один файл)
|
||||
config.git_max_diff_line_characters=Максимум символів на diff (на одну строку)
|
||||
config.git_max_diff_files=Максимум diff-файлів (для показу)
|
||||
config.git_gc_args=Аргументи GC
|
||||
config.git_migrate_timeout=Тайм-аут міграції
|
||||
config.git_mirror_timeout=Тайм-аут оновлення дзеркала
|
||||
|
@ -875,6 +1045,7 @@ config.git_pull_timeout=Тайм-аут операції Pull
|
|||
config.git_gc_timeout=Тайм-аут операції GC
|
||||
|
||||
config.log_config=Конфігурація журналу
|
||||
config.log_mode=Режим журналювання
|
||||
|
||||
monitor.cron=Завдання cron
|
||||
monitor.name=Ім'я
|
||||
|
@ -889,6 +1060,8 @@ monitor.execute_time=Час виконання
|
|||
notices.system_notice_list=Сповіщення системи
|
||||
notices.actions=Дії
|
||||
notices.select_all=Вибрати все
|
||||
notices.deselect_all=Скасувати виділення
|
||||
notices.inverse_selection=Інвертувати виділене
|
||||
notices.delete_selected=Видалити обране
|
||||
notices.delete_all=Видалити усі cповіщення
|
||||
notices.type=Тип
|
||||
|
@ -899,21 +1072,26 @@ notices.op=Оп.
|
|||
[action]
|
||||
create_repo=створено репозиторій <a href="%s">%s</a>
|
||||
rename_repo=репозиторій перейменовано з <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=запушено до <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`відкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
commit_repo=виконав(ла) push в <a href="%[1]s/src/%[2]s">%[3]s</a> у <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`відкрив(ла) проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
close_issue=`закрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
reopen_issue=`повторно відкрито проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
reopen_issue=`повторно відкрив(ла) проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
create_pull_request=`створено запити на злиття <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
close_pull_request=`закрито запит на злиття <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
reopen_pull_request=`повторно відкрито запит на злиття <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
comment_issue=`відкоментовано проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
comment_issue=`прокоментував(ла) проблему <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`запит на злиття злито <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
|
||||
push_tag=створив(ла) тег <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
|
||||
delete_tag=видалено мітку %[2]s з <a href="%[1]s">%[3]s</a>
|
||||
delete_branch=видалено гілку %[2]s з <a href="%[1]s">%[3]s</a>
|
||||
compare_commits=Порівняти %d комітів
|
||||
|
||||
[tool]
|
||||
ago=%s тому
|
||||
from_now=%s з цього моменту
|
||||
now=зараз
|
||||
future=в майбутньому
|
||||
1s=1 секунда
|
||||
1m=1 хвилина
|
||||
1h=1 година
|
||||
|
@ -932,6 +1110,7 @@ raw_seconds=секунди
|
|||
raw_minutes=хвилини
|
||||
|
||||
[dropzone]
|
||||
default_message=Перетягніть файли або натисніть тут, щоб завантажити.
|
||||
file_too_big=Розмір файлу ({{filesize}} MB), що більше ніж максимальний розмір: ({{maxFilesize}} MB).
|
||||
remove_file=Видалити файл
|
||||
|
||||
|
@ -939,11 +1118,15 @@ remove_file=Видалити файл
|
|||
notifications=Сповіщення
|
||||
unread=Непрочитані
|
||||
read=Прочитані
|
||||
no_unread=Немає непрочитаних сповіщень.
|
||||
no_read=Немає прочитаних сповіщень.
|
||||
pin=Прикріпити сповіщення
|
||||
mark_as_read=Позначити як прочитане
|
||||
mark_as_unread=Позначити як непрочитане
|
||||
mark_all_as_read=Позначити всі як прочитані
|
||||
|
||||
[gpg]
|
||||
error.not_signed_commit=Непідписаний коміт
|
||||
|
||||
[units]
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -329,9 +329,6 @@ issues.new.no_milestone=未選擇里程碑
|
|||
issues.new.clear_milestone=清除已選取里程碑
|
||||
issues.new.open_milestone=開啟中的里程碑
|
||||
issues.new.closed_milestone=已關閉的里程碑
|
||||
issues.new.assignee=指派成員
|
||||
issues.new.clear_assignee=取消指派成員
|
||||
issues.new.no_assignee=未指派成員
|
||||
issues.create=建立問題
|
||||
issues.new_label=建立標籤
|
||||
issues.create_label=建立標籤
|
||||
|
|
|
@ -339,9 +339,6 @@ issues.new.no_milestone=未選擇里程碑
|
|||
issues.new.clear_milestone=清除已選取里程碑
|
||||
issues.new.open_milestone=開啟中的里程碑
|
||||
issues.new.closed_milestone=已關閉的里程碑
|
||||
issues.new.assignee=指派成員
|
||||
issues.new.clear_assignee=取消指派成員
|
||||
issues.new.no_assignee=未指派成員
|
||||
issues.no_ref=未指定分支或標籤
|
||||
issues.create=建立問題
|
||||
issues.new_label=建立標籤
|
||||
|
|
665
package-lock.json
generated
Normal file
665
package-lock.json
generated
Normal file
|
@ -0,0 +1,665 @@
|
|||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"amdefine": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
||||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
|
||||
"dev": true
|
||||
},
|
||||
"asap": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
|
||||
"integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
|
||||
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "3.4.28",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
|
||||
"integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.8.1",
|
||||
"source-map": "0.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"amdefine": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-readlink": "1.0.1"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "0.1.1"
|
||||
}
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
|
||||
"integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"prr": "1.0.1"
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"graceful-readlink": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
|
||||
"integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
|
||||
"dev": true
|
||||
},
|
||||
"image-size": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
|
||||
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"less": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz",
|
||||
"integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"errno": "0.1.7",
|
||||
"graceful-fs": "4.1.11",
|
||||
"image-size": "0.5.5",
|
||||
"mime": "1.6.0",
|
||||
"mkdirp": "0.5.1",
|
||||
"promise": "7.3.1",
|
||||
"request": "2.85.0",
|
||||
"source-map": "0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"co": "4.6.0",
|
||||
"fast-deep-equal": "1.1.0",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.3.1"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"boom": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
|
||||
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
}
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
|
||||
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boom": "5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
||||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asynckit": "0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"mime-types": "2.1.18"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ajv": "5.5.2",
|
||||
"har-schema": "2.0.0"
|
||||
}
|
||||
},
|
||||
"hawk": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
|
||||
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"boom": "4.3.1",
|
||||
"cryptiles": "3.1.2",
|
||||
"hoek": "4.2.1",
|
||||
"sntp": "2.1.0"
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
|
||||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==",
|
||||
"dev": true
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"jsprim": "1.4.1",
|
||||
"sshpk": "1.14.1"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"request": {
|
||||
"version": "2.85.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz",
|
||||
"integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"aws-sign2": "0.7.0",
|
||||
"aws4": "1.7.0",
|
||||
"caseless": "0.12.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"extend": "3.0.1",
|
||||
"forever-agent": "0.6.1",
|
||||
"form-data": "2.3.2",
|
||||
"har-validator": "5.0.3",
|
||||
"hawk": "6.0.2",
|
||||
"http-signature": "1.2.0",
|
||||
"is-typedarray": "1.0.0",
|
||||
"isstream": "0.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"mime-types": "2.1.18",
|
||||
"oauth-sign": "0.8.2",
|
||||
"performance-now": "2.1.0",
|
||||
"qs": "6.5.2",
|
||||
"safe-buffer": "5.1.2",
|
||||
"stringstream": "0.0.5",
|
||||
"tough-cookie": "2.3.4",
|
||||
"tunnel-agent": "0.6.0",
|
||||
"uuid": "3.2.1"
|
||||
}
|
||||
},
|
||||
"sntp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
|
||||
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"less-plugin-clean-css": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/less-plugin-clean-css/-/less-plugin-clean-css-1.5.1.tgz",
|
||||
"integrity": "sha1-zFeveqM5iVflbezr5jy2DCNClwM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clean-css": "3.4.28"
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.33.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"promise": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asap": "2.0.6"
|
||||
}
|
||||
},
|
||||
"prr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
|
||||
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"asn1": "0.2.3",
|
||||
"assert-plus": "1.0.0",
|
||||
"bcrypt-pbkdf": "1.0.1",
|
||||
"dashdash": "1.14.1",
|
||||
"ecc-jsbn": "0.1.1",
|
||||
"getpass": "0.1.7",
|
||||
"jsbn": "0.1.1",
|
||||
"tweetnacl": "0.14.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"punycode": "1.4.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
|
||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "1.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"less": "^2.7.2",
|
||||
"less": "^3.0.4",
|
||||
"less-plugin-clean-css": "^1.5.1"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -179,81 +179,115 @@ function initCommentForm() {
|
|||
initBranchSelector();
|
||||
initCommentPreviewTab($('.comment.form'));
|
||||
|
||||
// Labels
|
||||
var $list = $('.ui.labels.list');
|
||||
var $noSelect = $list.find('.no-select');
|
||||
var $labelMenu = $('.select-label .menu');
|
||||
var hasLabelUpdateAction = $labelMenu.data('action') == 'update';
|
||||
// Listsubmit
|
||||
function initListSubmits(selector, outerSelector) {
|
||||
var $list = $('.ui.' + outerSelector + '.list');
|
||||
var $noSelect = $list.find('.no-select');
|
||||
var $listMenu = $('.' + selector + ' .menu');
|
||||
var hasLabelUpdateAction = $listMenu.data('action') == 'update';
|
||||
|
||||
$('.select-label').dropdown('setting', 'onHide', function(){
|
||||
if (hasLabelUpdateAction) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
$labelMenu.find('.item:not(.no-select)').click(function () {
|
||||
if ($(this).hasClass('checked')) {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon').removeClass('octicon-check');
|
||||
$('.' + selector).dropdown('setting', 'onHide', function(){
|
||||
hasLabelUpdateAction = $listMenu.data('action') == 'update'; // Update the var
|
||||
if (hasLabelUpdateAction) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
$listMenu.find('.item:not(.no-select)').click(function () {
|
||||
|
||||
// we don't need the action attribute when updating assignees
|
||||
if (selector == 'select-assignees-modify') {
|
||||
|
||||
// UI magic. We need to do this here, otherwise it would destroy the functionality of
|
||||
// adding/removing labels
|
||||
if ($(this).hasClass('checked')) {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon').removeClass('octicon-check');
|
||||
} else {
|
||||
$(this).addClass('checked');
|
||||
$(this).find('.octicon').addClass('octicon-check');
|
||||
}
|
||||
|
||||
updateIssuesMeta(
|
||||
$labelMenu.data('update-url'),
|
||||
"detach",
|
||||
$labelMenu.data('issue-id'),
|
||||
$listMenu.data('update-url'),
|
||||
"",
|
||||
$listMenu.data('issue-id'),
|
||||
$(this).data('id')
|
||||
);
|
||||
$listMenu.data('action', 'update'); // Update to reload the page when we updated items
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$(this).addClass('checked');
|
||||
$(this).find('.octicon').addClass('octicon-check');
|
||||
if (hasLabelUpdateAction) {
|
||||
updateIssuesMeta(
|
||||
$labelMenu.data('update-url'),
|
||||
"attach",
|
||||
$labelMenu.data('issue-id'),
|
||||
$(this).data('id')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var labelIds = [];
|
||||
$(this).parent().find('.item').each(function () {
|
||||
if ($(this).hasClass('checked')) {
|
||||
labelIds.push($(this).data('id'));
|
||||
$($(this).data('id-selector')).removeClass('hide');
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon').removeClass('octicon-check');
|
||||
if (hasLabelUpdateAction) {
|
||||
updateIssuesMeta(
|
||||
$listMenu.data('update-url'),
|
||||
"detach",
|
||||
$listMenu.data('issue-id'),
|
||||
$(this).data('id')
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$($(this).data('id-selector')).addClass('hide');
|
||||
$(this).addClass('checked');
|
||||
$(this).find('.octicon').addClass('octicon-check');
|
||||
if (hasLabelUpdateAction) {
|
||||
updateIssuesMeta(
|
||||
$listMenu.data('update-url'),
|
||||
"attach",
|
||||
$listMenu.data('issue-id'),
|
||||
$(this).data('id')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var listIds = [];
|
||||
$(this).parent().find('.item').each(function () {
|
||||
if ($(this).hasClass('checked')) {
|
||||
listIds.push($(this).data('id'));
|
||||
$($(this).data('id-selector')).removeClass('hide');
|
||||
} else {
|
||||
$($(this).data('id-selector')).addClass('hide');
|
||||
}
|
||||
});
|
||||
if (listIds.length == 0) {
|
||||
$noSelect.removeClass('hide');
|
||||
} else {
|
||||
$noSelect.addClass('hide');
|
||||
}
|
||||
$($(this).parent().data('id')).val(listIds.join(","));
|
||||
return false;
|
||||
});
|
||||
if (labelIds.length == 0) {
|
||||
$listMenu.find('.no-select.item').click(function () {
|
||||
if (hasLabelUpdateAction || selector == 'select-assignees-modify') {
|
||||
updateIssuesMeta(
|
||||
$listMenu.data('update-url'),
|
||||
"clear",
|
||||
$listMenu.data('issue-id'),
|
||||
""
|
||||
);
|
||||
$listMenu.data('action', 'update'); // Update to reload the page when we updated items
|
||||
}
|
||||
|
||||
$(this).parent().find('.item').each(function () {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon').removeClass('octicon-check');
|
||||
});
|
||||
|
||||
$list.find('.item').each(function () {
|
||||
$(this).addClass('hide');
|
||||
});
|
||||
$noSelect.removeClass('hide');
|
||||
} else {
|
||||
$noSelect.addClass('hide');
|
||||
}
|
||||
$($(this).parent().data('id')).val(labelIds.join(","));
|
||||
return false;
|
||||
});
|
||||
$labelMenu.find('.no-select.item').click(function () {
|
||||
if (hasLabelUpdateAction) {
|
||||
updateIssuesMeta(
|
||||
$labelMenu.data('update-url'),
|
||||
"clear",
|
||||
$labelMenu.data('issue-id'),
|
||||
""
|
||||
);
|
||||
}
|
||||
$($(this).parent().data('id')).val('');
|
||||
|
||||
$(this).parent().find('.item').each(function () {
|
||||
$(this).removeClass('checked');
|
||||
$(this).find('.octicon').removeClass('octicon-check');
|
||||
});
|
||||
}
|
||||
|
||||
$list.find('.item').each(function () {
|
||||
$(this).addClass('hide');
|
||||
});
|
||||
$noSelect.removeClass('hide');
|
||||
$($(this).parent().data('id')).val('');
|
||||
});
|
||||
// Init labels and assignees
|
||||
initListSubmits('select-label', 'labels');
|
||||
initListSubmits('select-assignees', 'assignees');
|
||||
initListSubmits('select-assignees-modify', 'assignees');
|
||||
|
||||
function selectItem(select_id, input_id) {
|
||||
var $menu = $(select_id + ' .menu');
|
||||
|
@ -2227,7 +2261,11 @@ function initTopicbar() {
|
|||
alert(res.message);
|
||||
} else {
|
||||
viewDiv.children(".topic").remove();
|
||||
if (topics.length == 0) {
|
||||
return
|
||||
}
|
||||
var topicArray = topics.split(",");
|
||||
|
||||
var last = viewDiv.children("a").last();
|
||||
for (var i=0;i < topicArray.length; i++) {
|
||||
$('<div class="ui green basic label topic" style="cursor:pointer;">'+topicArray[i]+'</div>').insertBefore(last)
|
||||
|
|
|
@ -152,6 +152,10 @@ pre, code {
|
|||
}
|
||||
}
|
||||
|
||||
&.floating.label {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&.menu,
|
||||
&.vertical.menu,
|
||||
&.segment {
|
||||
|
@ -167,6 +171,14 @@ pre, code {
|
|||
font-size: .92857143rem;
|
||||
}
|
||||
|
||||
&.dropdown .menu>.item>.floating.label {
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
&.dropdown .menu .menu>.item>.floating.label {
|
||||
z-index: 21;
|
||||
}
|
||||
|
||||
.text {
|
||||
&.red {
|
||||
color: #d95c5c !important;
|
||||
|
|
|
@ -119,8 +119,11 @@
|
|||
}
|
||||
.octicon {
|
||||
float: left;
|
||||
margin-left: -5px;
|
||||
margin-right: -7px;
|
||||
margin: 5px -7px 0 -5px;
|
||||
width: 16px;
|
||||
}
|
||||
.text{
|
||||
margin-left: 0.9em;
|
||||
}
|
||||
.menu {
|
||||
max-height: 300px;
|
||||
|
|
454
public/swagger.v1.json
vendored
454
public/swagger.v1.json
vendored
|
@ -1605,235 +1605,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issue/{index}/comments": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "List all comments on an issue",
|
||||
"operationId": "issueGetComments",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "if provided, only comments updated since the specified time are returned.",
|
||||
"name": "string",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/CommentList"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issue/{index}/labels": {
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Replace an issue's labels",
|
||||
"operationId": "issueReplaceLabels",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/IssueLabelsOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/LabelList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Add a label to an issue",
|
||||
"operationId": "issueAddLabel",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/IssueLabelsOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/LabelList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Remove all labels from an issue",
|
||||
"operationId": "issueClearLabels",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"$ref": "#/responses/empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issue/{index}/labels/{id}": {
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Remove a label from an issue",
|
||||
"operationId": "issueRemoveLabel",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "id of the label to remove",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"$ref": "#/responses/empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issues": {
|
||||
"get": {
|
||||
"produces": [
|
||||
|
@ -2139,6 +1910,50 @@
|
|||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issues/{index}/comments": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "List all comments on an issue",
|
||||
"operationId": "issueGetComments",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "if provided, only comments updated since the specified time are returned.",
|
||||
"name": "string",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/CommentList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
|
@ -2330,6 +2145,187 @@
|
|||
"$ref": "#/responses/notFound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Replace an issue's labels",
|
||||
"operationId": "issueReplaceLabels",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/IssueLabelsOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/LabelList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Add a label to an issue",
|
||||
"operationId": "issueAddLabel",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/IssueLabelsOption"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/LabelList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Remove all labels from an issue",
|
||||
"operationId": "issueClearLabels",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"$ref": "#/responses/empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issues/{index}/labels/{id}": {
|
||||
"delete": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"issue"
|
||||
],
|
||||
"summary": "Remove a label from an issue",
|
||||
"operationId": "issueRemoveLabel",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "owner of the repo",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "name of the repo",
|
||||
"name": "repo",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "index of the issue",
|
||||
"name": "index",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "id of the label to remove",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"$ref": "#/responses/empty"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/issues/{index}/times": {
|
||||
|
|
|
@ -178,25 +178,22 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
|
|||
DeadlineUnix: deadlineUnix,
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() {
|
||||
if len(form.Assignee) > 0 {
|
||||
assignee, err := models.GetUserByName(form.Assignee)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", form.Assignee))
|
||||
} else {
|
||||
ctx.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
issue.AssigneeID = assignee.ID
|
||||
// Get all assignee IDs
|
||||
assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
|
||||
} else {
|
||||
ctx.Error(500, "AddAssigneeByName", err)
|
||||
}
|
||||
issue.MilestoneID = form.Milestone
|
||||
} else {
|
||||
form.Labels = nil
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.NewIssue(ctx.Repo.Repository, issue, form.Labels, nil); err != nil {
|
||||
if err := models.NewIssue(ctx.Repo.Repository, issue, form.Labels, assigneeIDs, nil); err != nil {
|
||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err)
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "NewIssue", err)
|
||||
return
|
||||
}
|
||||
|
@ -209,7 +206,6 @@ func CreateIssue(ctx *context.APIContext, form api.CreateIssueOption) {
|
|||
}
|
||||
|
||||
// Refetch from database to assign some automatic values
|
||||
var err error
|
||||
issue, err = models.GetIssueByID(issue.ID)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetIssueByID", err)
|
||||
|
@ -272,6 +268,7 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||
issue.Content = *form.Body
|
||||
}
|
||||
|
||||
// Update the deadline
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil && !form.Deadline.IsZero() {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
|
@ -282,28 +279,28 @@ func EditIssue(ctx *context.APIContext, form api.EditIssueOption) {
|
|||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && form.Assignee != nil &&
|
||||
(issue.Assignee == nil || issue.Assignee.LowerName != strings.ToLower(*form.Assignee)) {
|
||||
if len(*form.Assignee) == 0 {
|
||||
issue.AssigneeID = 0
|
||||
} else {
|
||||
assignee, err := models.GetUserByName(*form.Assignee)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("assignee does not exist: [name: %s]", *form.Assignee))
|
||||
} else {
|
||||
ctx.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
issue.AssigneeID = assignee.ID
|
||||
// Add/delete assignees
|
||||
|
||||
// Deleting is done the Github way (quote from their api documentation):
|
||||
// https://developer.github.com/v3/issues/#edit-an-issue
|
||||
// "assignees" (array): Logins for Users to assign to this issue.
|
||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
|
||||
if ctx.Repo.IsWriter() && (form.Assignees != nil || form.Assignee != nil) {
|
||||
|
||||
oneAssignee := ""
|
||||
if form.Assignee != nil {
|
||||
oneAssignee = *form.Assignee
|
||||
}
|
||||
|
||||
if err = models.UpdateIssueUserByAssignee(issue); err != nil {
|
||||
ctx.Error(500, "UpdateIssueUserByAssignee", err)
|
||||
err = models.UpdateAPIAssignee(issue, oneAssignee, form.Assignees, ctx.User)
|
||||
if err != nil {
|
||||
ctx.Error(500, "UpdateAPIAssignee", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && form.Milestone != nil &&
|
||||
issue.MilestoneID != *form.Milestone {
|
||||
oldMilestoneID := issue.MilestoneID
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
|
||||
// ListIssueComments list all the comments of an issue
|
||||
func ListIssueComments(ctx *context.APIContext) {
|
||||
// swagger:operation GET /repos/{owner}/{repo}/issue/{index}/comments issue issueGetComments
|
||||
// swagger:operation GET /repos/{owner}/{repo}/issues/{index}/comments issue issueGetComments
|
||||
// ---
|
||||
// summary: List all comments on an issue
|
||||
// produces:
|
||||
|
|
|
@ -58,7 +58,7 @@ func ListIssueLabels(ctx *context.APIContext) {
|
|||
|
||||
// AddIssueLabels add labels for an issue
|
||||
func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) {
|
||||
// swagger:operation POST /repos/{owner}/{repo}/issue/{index}/labels issue issueAddLabel
|
||||
// swagger:operation POST /repos/{owner}/{repo}/issues/{index}/labels issue issueAddLabel
|
||||
// ---
|
||||
// summary: Add a label to an issue
|
||||
// consumes:
|
||||
|
@ -129,7 +129,7 @@ func AddIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) {
|
|||
|
||||
// DeleteIssueLabel delete a label for an issue
|
||||
func DeleteIssueLabel(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/issue/{index}/labels/{id} issue issueRemoveLabel
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/labels/{id} issue issueRemoveLabel
|
||||
// ---
|
||||
// summary: Remove a label from an issue
|
||||
// produces:
|
||||
|
@ -193,7 +193,7 @@ func DeleteIssueLabel(ctx *context.APIContext) {
|
|||
|
||||
// ReplaceIssueLabels replace labels for an issue
|
||||
func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) {
|
||||
// swagger:operation PUT /repos/{owner}/{repo}/issue/{index}/labels issue issueReplaceLabels
|
||||
// swagger:operation PUT /repos/{owner}/{repo}/issues/{index}/labels issue issueReplaceLabels
|
||||
// ---
|
||||
// summary: Replace an issue's labels
|
||||
// consumes:
|
||||
|
@ -264,7 +264,7 @@ func ReplaceIssueLabels(ctx *context.APIContext, form api.IssueLabelsOption) {
|
|||
|
||||
// ClearIssueLabels delete all the labels for an issue
|
||||
func ClearIssueLabels(ctx *context.APIContext) {
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/issue/{index}/labels issue issueClearLabels
|
||||
// swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/labels issue issueClearLabels
|
||||
// ---
|
||||
// summary: Remove all labels from an issue
|
||||
// produces:
|
||||
|
|
|
@ -211,26 +211,6 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption
|
|||
milestoneID = milestone.ID
|
||||
}
|
||||
|
||||
if len(form.Assignee) > 0 {
|
||||
assigneeUser, err := models.GetUserByName(form.Assignee)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("assignee does not exist: [name: %s]", form.Assignee))
|
||||
} else {
|
||||
ctx.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
assignee, err := repo.GetAssigneeByID(assigneeUser.ID)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetAssigneeByID", err)
|
||||
return
|
||||
}
|
||||
|
||||
assigneeID = assignee.ID
|
||||
}
|
||||
|
||||
patch, err := headGitRepo.GetPatch(prInfo.MergeBase, headBranch)
|
||||
if err != nil {
|
||||
ctx.Error(500, "GetPatch", err)
|
||||
|
@ -266,7 +246,22 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption
|
|||
Type: models.PullRequestGitea,
|
||||
}
|
||||
|
||||
if err := models.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, patch); err != nil {
|
||||
// Get all assignee IDs
|
||||
assigneeIDs, err := models.MakeIDsFromAPIAssigneesToAdd(form.Assignee, form.Assignees)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
|
||||
} else {
|
||||
ctx.Error(500, "AddAssigneeByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.NewPullRequest(repo, prIssue, labelIDs, []string{}, pr, patch, assigneeIDs); err != nil {
|
||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err)
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "NewPullRequest", err)
|
||||
return
|
||||
} else if err := pr.PushToBaseRepo(); err != nil {
|
||||
|
@ -335,6 +330,7 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
|
|||
issue.Content = form.Body
|
||||
}
|
||||
|
||||
// Update Deadline
|
||||
var deadlineUnix util.TimeStamp
|
||||
if form.Deadline != nil && !form.Deadline.IsZero() {
|
||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix())
|
||||
|
@ -345,28 +341,27 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) {
|
|||
return
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && len(form.Assignee) > 0 &&
|
||||
(issue.Assignee == nil || issue.Assignee.LowerName != strings.ToLower(form.Assignee)) {
|
||||
if len(form.Assignee) == 0 {
|
||||
issue.AssigneeID = 0
|
||||
} else {
|
||||
assignee, err := models.GetUserByName(form.Assignee)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("assignee does not exist: [name: %s]", form.Assignee))
|
||||
} else {
|
||||
ctx.Error(500, "GetUserByName", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
issue.AssigneeID = assignee.ID
|
||||
}
|
||||
// Add/delete assignees
|
||||
|
||||
if err = models.UpdateIssueUserByAssignee(issue); err != nil {
|
||||
ctx.Error(500, "UpdateIssueUserByAssignee", err)
|
||||
// Deleting is done the Github way (quote from their api documentation):
|
||||
// https://developer.github.com/v3/issues/#edit-an-issue
|
||||
// "assignees" (array): Logins for Users to assign to this issue.
|
||||
// Pass one or more user logins to replace the set of assignees on this Issue.
|
||||
// Send an empty array ([]) to clear all assignees from the Issue.
|
||||
|
||||
if ctx.Repo.IsWriter() && (form.Assignees != nil || len(form.Assignee) > 0) {
|
||||
|
||||
err = models.UpdateAPIAssignee(issue, form.Assignee, form.Assignees, ctx.User)
|
||||
if err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.Error(422, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
|
||||
} else {
|
||||
ctx.Error(500, "UpdateAPIAssignee", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Repo.IsWriter() && form.Milestone != 0 &&
|
||||
issue.MilestoneID != form.Milestone {
|
||||
oldMilestoneID := issue.MilestoneID
|
||||
|
|
|
@ -112,6 +112,7 @@ func Install(ctx *context.Context) {
|
|||
form.EnableOpenIDSignIn = setting.Service.EnableOpenIDSignIn
|
||||
form.EnableOpenIDSignUp = setting.Service.EnableOpenIDSignUp
|
||||
form.DisableRegistration = setting.Service.DisableRegistration
|
||||
form.AllowOnlyExternalRegistration = setting.Service.AllowOnlyExternalRegistration
|
||||
form.EnableCaptcha = setting.Service.EnableCaptcha
|
||||
form.RequireSignInView = setting.Service.RequireSignInView
|
||||
form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate
|
||||
|
@ -304,6 +305,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
|
|||
cfg.Section("openid").Key("ENABLE_OPENID_SIGNIN").SetValue(com.ToStr(form.EnableOpenIDSignIn))
|
||||
cfg.Section("openid").Key("ENABLE_OPENID_SIGNUP").SetValue(com.ToStr(form.EnableOpenIDSignUp))
|
||||
cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration))
|
||||
cfg.Section("service").Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").SetValue(com.ToStr(form.AllowOnlyExternalRegistration))
|
||||
cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha))
|
||||
cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView))
|
||||
cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(com.ToStr(form.DefaultKeepEmailPrivate))
|
||||
|
|
|
@ -364,7 +364,7 @@ func NewIssue(ctx *context.Context) {
|
|||
}
|
||||
|
||||
// ValidateRepoMetas check and returns repository's meta informations
|
||||
func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64, int64, int64) {
|
||||
func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64, []int64, int64) {
|
||||
var (
|
||||
repo = ctx.Repo.Repository
|
||||
err error
|
||||
|
@ -372,11 +372,11 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
|||
|
||||
labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository)
|
||||
if ctx.Written() {
|
||||
return nil, 0, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
|
||||
if !ctx.Repo.IsWriter() {
|
||||
return nil, 0, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
|
||||
var labelIDs []int64
|
||||
|
@ -385,7 +385,7 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
|||
if len(form.LabelIDs) > 0 {
|
||||
labelIDs, err = base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
|
||||
if err != nil {
|
||||
return nil, 0, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
labelIDMark := base.Int64sToMap(labelIDs)
|
||||
|
||||
|
@ -407,23 +407,35 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
|
|||
ctx.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetMilestoneByID", err)
|
||||
return nil, 0, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
ctx.Data["milestone_id"] = milestoneID
|
||||
}
|
||||
|
||||
// Check assignee.
|
||||
assigneeID := form.AssigneeID
|
||||
if assigneeID > 0 {
|
||||
ctx.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
|
||||
// Check assignees
|
||||
var assigneeIDs []int64
|
||||
if len(form.AssigneeIDs) > 0 {
|
||||
assigneeIDs, err = base.StringsToInt64s(strings.Split(form.AssigneeIDs, ","))
|
||||
if err != nil {
|
||||
ctx.ServerError("GetAssigneeByID", err)
|
||||
return nil, 0, 0
|
||||
return nil, nil, 0
|
||||
}
|
||||
|
||||
// Check if the passed assignees actually exists and has write access to the repo
|
||||
for _, aID := range assigneeIDs {
|
||||
_, err = repo.GetUserIfHasWriteAccess(aID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserIfHasWriteAccess", err)
|
||||
return nil, nil, 0
|
||||
}
|
||||
}
|
||||
ctx.Data["assignee_id"] = assigneeID
|
||||
}
|
||||
|
||||
return labelIDs, milestoneID, assigneeID
|
||||
// Keep the old assignee id thingy for compatibility reasons
|
||||
if form.AssigneeID > 0 {
|
||||
assigneeIDs = append(assigneeIDs, form.AssigneeID)
|
||||
}
|
||||
|
||||
return labelIDs, assigneeIDs, milestoneID
|
||||
}
|
||||
|
||||
// NewIssuePost response for creating new issue
|
||||
|
@ -440,7 +452,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
|||
attachments []string
|
||||
)
|
||||
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form)
|
||||
labelIDs, assigneeIDs, milestoneID := ValidateRepoMetas(ctx, form)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
@ -460,11 +472,14 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
|
|||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
Content: form.Content,
|
||||
Ref: form.Ref,
|
||||
}
|
||||
if err := models.NewIssue(repo, issue, labelIDs, attachments); err != nil {
|
||||
if err := models.NewIssue(repo, issue, labelIDs, assigneeIDs, attachments); err != nil {
|
||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error())
|
||||
return
|
||||
}
|
||||
ctx.ServerError("NewIssue", err)
|
||||
return
|
||||
}
|
||||
|
@ -702,8 +717,8 @@ func ViewIssue(ctx *context.Context) {
|
|||
comment.Milestone = ghostMilestone
|
||||
}
|
||||
} else if comment.Type == models.CommentTypeAssignees {
|
||||
if err = comment.LoadAssignees(); err != nil {
|
||||
ctx.ServerError("LoadAssignees", err)
|
||||
if err = comment.LoadAssigneeUser(); err != nil {
|
||||
ctx.ServerError("LoadAssigneeUser", err)
|
||||
return
|
||||
}
|
||||
} else if comment.Type == models.CommentTypeCode || comment.Type == models.CommentTypeReview {
|
||||
|
@ -917,13 +932,20 @@ func UpdateIssueAssignee(ctx *context.Context) {
|
|||
}
|
||||
|
||||
assigneeID := ctx.QueryInt64("id")
|
||||
action := ctx.Query("action")
|
||||
|
||||
for _, issue := range issues {
|
||||
if issue.AssigneeID == assigneeID {
|
||||
continue
|
||||
}
|
||||
if err := issue.ChangeAssignee(ctx.User, assigneeID); err != nil {
|
||||
ctx.ServerError("ChangeAssignee", err)
|
||||
return
|
||||
switch action {
|
||||
case "clear":
|
||||
if err := models.DeleteNotPassedAssignee(issue, ctx.User, []*models.User{}); err != nil {
|
||||
ctx.ServerError("ClearAssignees", err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
if err := issue.ChangeAssignee(ctx.User, assigneeID); err != nil {
|
||||
ctx.ServerError("ChangeAssignee", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
|
|
|
@ -785,7 +785,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
|||
return
|
||||
}
|
||||
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form)
|
||||
labelIDs, assigneeIDs, milestoneID := ValidateRepoMetas(ctx, form)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
@ -821,7 +821,6 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
|||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
MilestoneID: milestoneID,
|
||||
AssigneeID: assigneeID,
|
||||
IsPull: true,
|
||||
Content: form.Content,
|
||||
}
|
||||
|
@ -838,7 +837,12 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
|
|||
}
|
||||
// FIXME: check error in the case two people send pull request at almost same time, give nice error prompt
|
||||
// instead of 500.
|
||||
if err := models.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch); err != nil {
|
||||
|
||||
if err := models.NewPullRequest(repo, pullIssue, labelIDs, attachments, pullRequest, patch, assigneeIDs); err != nil {
|
||||
if models.IsErrUserDoesNotHaveAccessToRepo(err) {
|
||||
ctx.Error(400, "UserDoesNotHaveAccessToRepo", err.Error())
|
||||
return
|
||||
}
|
||||
ctx.ServerError("NewPullRequest", err)
|
||||
return
|
||||
} else if err := pullRequest.PushToBaseRepo(); err != nil {
|
||||
|
|
|
@ -21,7 +21,11 @@ func TopicPost(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
topics := strings.Split(ctx.Query("topics"), ",")
|
||||
var topics = make([]string, 0)
|
||||
var topicsStr = strings.TrimSpace(ctx.Query("topics"))
|
||||
if len(topicsStr) > 0 {
|
||||
topics = strings.Split(topicsStr, ",")
|
||||
}
|
||||
|
||||
err := models.SaveTopics(ctx.Repo.Repository.ID, topics...)
|
||||
if err != nil {
|
||||
|
|
|
@ -741,7 +741,8 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
|
|||
|
||||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
||||
|
||||
if setting.Service.DisableRegistration {
|
||||
//Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
|
||||
if !setting.Service.ShowRegistrationButton {
|
||||
ctx.Error(403)
|
||||
return
|
||||
}
|
||||
|
|
66
snap/helpers/app.ini
Normal file
66
snap/helpers/app.ini
Normal file
|
@ -0,0 +1,66 @@
|
|||
APP_NAME = Gitea: Go Git Service
|
||||
RUN_USER = root
|
||||
RUN_MODE = prod
|
||||
CUSTOM_PATH = SNAP_DIR_DATA/custom
|
||||
|
||||
[server]
|
||||
DOMAIN = localhost
|
||||
PROTOCOL = http
|
||||
HTTP_PORT = 3001
|
||||
ROOT_URL = http://localhost:3001/
|
||||
DISABLE_SSH = false
|
||||
SSH_PORT = 22
|
||||
STATIC_ROOT_PATH = SNAP_DIR_DATA/static
|
||||
APP_DATA_PATH = SNAP_DIR_COMMON/data
|
||||
SSH_ROOT = SNAP_DIR_COMMON/ssh
|
||||
SSH_KEY_TEST_PATH = SNAP_DIR_DATA/sshkeytest
|
||||
|
||||
[database]
|
||||
DB_TYPE = sqlite3
|
||||
PATH = SNAP_DIR_COMMON/gitea.db
|
||||
|
||||
[repository]
|
||||
ROOT = SNAP_DIR_COMMON/repositories/data
|
||||
|
||||
[repository.upload]
|
||||
ENABLED = true
|
||||
ALLOWED_TYPES = "image/jpeg|image/png"
|
||||
FILE_MAX_SIZE = 10
|
||||
MAX_FILES = 5
|
||||
TEMP_PATH = SNAP_DIR_COMMON/repositories/tmp
|
||||
|
||||
[release.attachment]
|
||||
PATH = SNAP_DIR_COMMON/releases/attachments
|
||||
|
||||
[smartypants]
|
||||
ENABLED = true
|
||||
|
||||
[indexer]
|
||||
ISSUE_INDEXER_PATH = SNAP_DIR_COMMON/indexers/issues.bleve
|
||||
|
||||
|
||||
[mailer]
|
||||
ENABLED = false
|
||||
|
||||
[service]
|
||||
REGISTER_EMAIL_CONFIRM = false
|
||||
ENABLE_NOTIFY_MAIL = false
|
||||
DISABLE_REGISTRATION = false
|
||||
ENABLE_CAPTCHA = false
|
||||
REQUIRE_SIGNIN_VIEW = false
|
||||
|
||||
[picture]
|
||||
AVATAR_UPLOAD_PATH = SNAP_DIR_COMMON/pictures/avatars
|
||||
DISABLE_GRAVATAR = true
|
||||
ENABLE_FEDERATED_AVATAR = false
|
||||
|
||||
[attachment]
|
||||
PATH = SNAP_DIR_COMMON/attachments
|
||||
|
||||
[session]
|
||||
PROVIDER = memory
|
||||
|
||||
[log]
|
||||
MODE = file
|
||||
LEVEL = Trace
|
||||
ROOT_PATH = SNAP_DIR_COMMON/log
|
126
snap/helpers/configuration.sh
Executable file
126
snap/helpers/configuration.sh
Executable file
|
@ -0,0 +1,126 @@
|
|||
#!/bin/bash
|
||||
if snapctl get gitea.snap.custom; then
|
||||
cdir=$(snapctl get gitea.snap.custom)
|
||||
else
|
||||
cdir=$SNAP_COMMON
|
||||
fi
|
||||
|
||||
cfg="$cdir/conf/app.ini"
|
||||
bak="$cdir/conf/app.ini.bak-$(date -Ins)"
|
||||
basecfg="$SNAP/snap/helpers/app.ini"
|
||||
smp="$SNAP/gitea/custom/conf/app.ini.sample"
|
||||
|
||||
function toSnap() {
|
||||
OIFS=$IFS
|
||||
IFS='
|
||||
'
|
||||
category="none"
|
||||
src="$cfg"
|
||||
[[ "$1" = "init" ]] && src="$smp"
|
||||
[[ "$1" = "snap" ]] && src="$basecfg"
|
||||
|
||||
for l in $(sed 's_;\([A-Z]*\)_\1_g' $src | grep -v -e '^;' -e '^$'); do
|
||||
if echo $l | grep -q '^[[]'; then
|
||||
category=$(CatToSnap "$l")
|
||||
elif echo $l | grep -q '^[A-Z]'; then
|
||||
option=$(OptToSnap "$l")
|
||||
value=$(ValToSnap "$l")
|
||||
if [[ $category = "none" ]]; then
|
||||
snapctl set "$option=$value"
|
||||
else
|
||||
snapctl set "$category.$option=$value"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS=$OIFS
|
||||
}
|
||||
|
||||
function toIni() {
|
||||
OIFS=$IFS
|
||||
IFS='
|
||||
'
|
||||
category="none"; option="none"; catUnset=true
|
||||
src=$smp
|
||||
[[ -f $cfg ]] && src="$cfg"
|
||||
tmpIni="$cfg.tmp"
|
||||
[[ -f $src ]] && cp "$src" "$tmpIni"
|
||||
cp $tmpIni $bak
|
||||
echo '' > $cfg
|
||||
for l in $(grep -v -e '^;' -e '^$' $tmpIni); do
|
||||
if echo $l | grep -q '^[[]'; then
|
||||
category=$(CatToSnap "$l")
|
||||
catUnset=true
|
||||
elif echo $l | grep -q '^[A-Z]'; then
|
||||
option=$(OptToSnap "$l")
|
||||
if [[ $category = "none" ]]; then
|
||||
value=$(snapctl get $option)
|
||||
echo $(OptToIni "$option") = $value >> $cfg
|
||||
else
|
||||
value=$(snapctl get $category.$option)
|
||||
if $catUnset; then
|
||||
echo "" >> $cfg
|
||||
echo "[$(CatToIni "$category")]" >> $cfg
|
||||
catUnset=false
|
||||
fi
|
||||
echo $(OptToIni "$option") = $value >> $cfg
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
IFS=$OIFS
|
||||
}
|
||||
|
||||
function CatToSnap {
|
||||
ret=$(echo "$1" \
|
||||
| grep -oP '[A-Za-z0-9._]+' \
|
||||
| sed 's|\.|-|g' \
|
||||
| sed 's|_|99|g')
|
||||
echo $ret
|
||||
}
|
||||
function OptToSnap {
|
||||
ret=$(echo "$1" \
|
||||
| grep -oP '^[A-Z_]+' \
|
||||
| tr '[:upper:]' '[:lower:]' \
|
||||
| sed 's|_|-|g')
|
||||
echo $ret
|
||||
}
|
||||
function ValToSnap {
|
||||
ret=$(echo "$1" \
|
||||
| grep -oP '=.*$' \
|
||||
| sed 's_^= __g' \
|
||||
| sed 's_^=__g' \
|
||||
| sed "s|SNAP_DIR_DATA|$SDATA|g" \
|
||||
| sed "s|SNAP_DIR_COMMON|$SCOMMON|g" \
|
||||
| sed 's|{}||g')
|
||||
echo $ret
|
||||
}
|
||||
|
||||
function CatToIni {
|
||||
ret=$(echo "$1" \
|
||||
| sed 's|-|.|g' \
|
||||
| sed 's|\ |_|g' \
|
||||
| sed 's|99|_|g')
|
||||
echo $ret
|
||||
}
|
||||
function OptToIni {
|
||||
ret=$(echo "$1" \
|
||||
| tr '[:lower:]' '[:upper:]' \
|
||||
| sed 's|-|_|g')
|
||||
echo $ret
|
||||
}
|
||||
|
||||
[[ "$1" = "configure" ]] \
|
||||
&& toIni \
|
||||
&& exit 0
|
||||
|
||||
[[ "$1" = "install" ]] \
|
||||
&& echo "Initial Configuration..." \
|
||||
&& mkdir -p $SNAP_COMMON/conf \
|
||||
&& toSnap init \
|
||||
&& toSnap snap \
|
||||
&& toIni sample \
|
||||
&& exit 0
|
||||
|
||||
[[ "$1" = "save" ]] \
|
||||
&& echo "Saving current config..." \
|
||||
&& toSnap \
|
||||
&& exit 0
|
23
snap/helpers/simple_launcher.sh
Executable file
23
snap/helpers/simple_launcher.sh
Executable file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
if ! env | grep -q root; then
|
||||
echo "
|
||||
+----------------------------------------+
|
||||
| You are not running gitea as root. |
|
||||
| This is required for the snap package. |
|
||||
| Please re-run as root. |
|
||||
+----------------------------------------+
|
||||
"
|
||||
$SNAP/gitea/gitea --help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set usernames for gitea
|
||||
export USERNAME=root
|
||||
export USER=root
|
||||
|
||||
export GITEA_WORK_DIR=$(snapctl get gitea.snap.workdir)
|
||||
export GITEA_CUSTOM=$(snapctl get gitea.snap.custom)
|
||||
|
||||
$SNAP/bin/gconfig save
|
||||
cd $SNAP/gitea; ./gitea $@
|
3
snap/hooks/configure
vendored
Executable file
3
snap/hooks/configure
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
$SNAP/bin/gconfig configure
|
45
snap/hooks/install
Executable file
45
snap/hooks/install
Executable file
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
|
||||
export SDATA=$(echo $SNAP_DATA | sed "s|$SNAP_REVISION|current|")
|
||||
export SCOMMON="$SNAP_COMMON"
|
||||
export isRoot=`true`
|
||||
snapctl set gitea.snap.workdir="$SDATA/custom"
|
||||
snapctl set gitea.snap.custom="$SCOMMON"
|
||||
|
||||
function mkDirCommon(){
|
||||
for dir in $@; do
|
||||
mkdir -p "$SCOMMON/$dir"
|
||||
done
|
||||
}
|
||||
|
||||
function mkdirData(){
|
||||
for dir in $@; do
|
||||
mkdir -p "$SDATA/$dir"
|
||||
if [ -d $SNAP/$dir ]; then
|
||||
cp -r --preserve=mode \
|
||||
$SNAP/$dir/* \
|
||||
$SNAP/$dir/.[a-zA-Z0-9-]* \
|
||||
$SDATA/$dir/ 2> $SCOMMON/log/snap-mkdirData.log
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mkDirCommon pictures \
|
||||
repositories \
|
||||
attachments \
|
||||
data \
|
||||
log
|
||||
|
||||
mkdirData certs \
|
||||
sshkeytest \
|
||||
custom/conf \
|
||||
static/templates \
|
||||
static/scripts \
|
||||
static/public
|
||||
|
||||
[[ -f $SNAP_COMMON/conf/app.ini ]] || $SNAP/bin/gconfig install
|
||||
|
||||
# Configure Git to use the right templates
|
||||
mkdir -p $SDATA/git/
|
||||
cp -r --preserve=mode $SNAP/usr/share/git-core/templates $SDATA/git/
|
||||
$SNAP/usr/bin/git config --global init.templateDir $SDATA/git/templates/
|
121
snap/snapcraft.yaml
Normal file
121
snap/snapcraft.yaml
Normal file
|
@ -0,0 +1,121 @@
|
|||
name: gitea
|
||||
summary: Gitea - A painless self-hosted Git service
|
||||
description: |
|
||||
The goal of this project is to make the easiest, fastest, and most painless
|
||||
way of setting up a self-hosted Git service. With Go, this can be done with
|
||||
an independent binary distribution across ALL platforms that Go supports,
|
||||
including Linux, Mac OS X, Windows and ARM.
|
||||
|
||||
type: app
|
||||
icon: public/img/gitea-lg.png
|
||||
confinement: strict
|
||||
grade: stable
|
||||
|
||||
version: 'git'
|
||||
|
||||
apps:
|
||||
gitea:
|
||||
command: bin/gitea
|
||||
plugs: [network, network-bind]
|
||||
web:
|
||||
command: bin/gitea web
|
||||
daemon: simple
|
||||
plugs: [network, network-bind]
|
||||
serv:
|
||||
command: bin/gitea serv
|
||||
plugs: [network, network-bind]
|
||||
admin:
|
||||
command: bin/gitea admin
|
||||
plugs: [network, network-bind]
|
||||
cert:
|
||||
command: bin/gitea cert
|
||||
hook:
|
||||
command: bin/gitea hook
|
||||
plugs: [network, network-bind]
|
||||
dump:
|
||||
command: bin/gitea dump
|
||||
plugs: [home]
|
||||
help:
|
||||
command: bin/gitea --help
|
||||
version:
|
||||
command: bin/gitea --version
|
||||
sqlite:
|
||||
command: usr/bin/sqlite3
|
||||
|
||||
parts:
|
||||
go:
|
||||
source-tag: go1.8.3
|
||||
prime:
|
||||
- -*
|
||||
|
||||
gitea:
|
||||
plugin: nil
|
||||
source: .
|
||||
source-type: git
|
||||
after: [ go ]
|
||||
stage-packages: [ git, sqlite3, openssh-client ]
|
||||
build-packages: [ libpam0g-dev, libsqlite3-dev]
|
||||
prepare: |
|
||||
export PATH=$SNAPCRAFT_PART_INSTALL/../../go/install/bin:$PATH
|
||||
export GOPATH=$SNAPCRAFT_PART_INSTALL/../go
|
||||
export bld=$SNAPCRAFT_PART_INSTALL/../build
|
||||
export src=$SNAPCRAFT_PART_INSTALL/../src
|
||||
mkdir -p $GOPATH/src/code.gitea.io/gitea
|
||||
cp -r $src/* $GOPATH/src/code.gitea.io/gitea
|
||||
build: |
|
||||
export PATH=$SNAPCRAFT_PART_INSTALL/../go/bin/:$SNAPCRAFT_PART_INSTALL/../../go/install/bin:$PATH
|
||||
export GOPATH=$SNAPCRAFT_PART_INSTALL/../go
|
||||
go get -u github.com/jteeuwen/go-bindata/...
|
||||
cd $GOPATH/src/code.gitea.io/gitea
|
||||
TAGS="bindata sqlite pam cert" make generate build
|
||||
install: |
|
||||
# Set Convenience Variables
|
||||
src=$SNAPCRAFT_PART_INSTALL/../go/src/code.gitea.io/gitea
|
||||
giteaBase=$SNAPCRAFT_PART_INSTALL/gitea
|
||||
scurrent=/var/snap/$SNAPCRAFT_PROJECT_NAME/current
|
||||
scommon=/var/snap/$SNAPCRAFT_PROJECT_NAME/common
|
||||
# Copy build artifact and necessary files
|
||||
mkdir -p $giteaBase/conf
|
||||
# Workaround for gitea ignoring APP_DATA_PATH in app.ini after snap update.
|
||||
ln -s $scurrent/custom $giteaBase/custom
|
||||
ln -s $scommon/data $giteaBase/data
|
||||
# Workaround for cmd/certs not knowing how to put files somewhere else
|
||||
ln -s $scurrent/cert.pem $giteaBase/cert.pem
|
||||
ln -s $scurrent/key.pem $giteaBase/key.pem
|
||||
# Copy static content
|
||||
mkdir -p $SNAPCRAFT_PART_INSTALL/static
|
||||
cp $src/gitea $giteaBase/
|
||||
cp -r $src/LICENSE \
|
||||
$src/templates \
|
||||
$src/public \
|
||||
$src/scripts \
|
||||
$SNAPCRAFT_PART_INSTALL/static/
|
||||
cp -r $src/README.md \
|
||||
$src/LICENSE \
|
||||
$src/custom \
|
||||
$SNAPCRAFT_PART_INSTALL/
|
||||
prime:
|
||||
- -etc
|
||||
- -usr/lib/systemd
|
||||
- -usr/lib/gcc
|
||||
- -usr/lib/sasl2
|
||||
- -usr/lib/x86_64-linux-gnu/krb5
|
||||
- -usr/share/apport
|
||||
- -usr/share/bash-completion
|
||||
- -usr/share/doc
|
||||
- -usr/share/git-core/contrib
|
||||
- -usr/share/man
|
||||
- -usr/share/upstart
|
||||
- -var
|
||||
|
||||
helpers:
|
||||
plugin: dump
|
||||
source: snap/helpers
|
||||
organize:
|
||||
simple_launcher.sh: bin/gitea
|
||||
app.ini: gitea/snapApp.ini
|
||||
configuration.sh: bin/gconfig
|
||||
prime:
|
||||
- bin/gitea
|
||||
- bin/gconfig
|
||||
- gitea/snapApp.ini
|
|
@ -114,6 +114,8 @@
|
|||
<dd><i class="fa fa{{if .Service.RegisterEmailConfirm}}-check{{end}}-square-o"></i></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.disable_register"}}</dt>
|
||||
<dd><i class="fa fa{{if .Service.DisableRegistration}}-check{{end}}-square-o"></i></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.allow_only_external_registration"}}</dt>
|
||||
<dd><i class="fa fa{{if .Service.AllowOnlyExternalRegistration}}-check{{end}}-square-o"></i></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.show_registration_button"}}</dt>
|
||||
<dd><i class="fa fa{{if .Service.ShowRegistrationButton}}-check{{end}}-square-o"></i></dd>
|
||||
<dt>{{.i18n.Tr "admin.config.enable_openid_signup"}}</dt>
|
||||
|
|
|
@ -17,9 +17,13 @@
|
|||
</div>
|
||||
</div>
|
||||
{{if .DescriptionHTML}}<p class="has-emoji">{{.DescriptionHTML}}</p>{{end}}
|
||||
<div>
|
||||
{{range .Topics}}<div class="ui green basic label topic">{{.}}</div>{{end}}
|
||||
</div>
|
||||
{{if .Topics }}
|
||||
<div>
|
||||
{{range .Topics}}
|
||||
{{if ne . "" }}<div class="ui green basic label topic">{{.}}</div>{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
<p class="time">{{$.i18n.Tr "org.repo_updated"}} {{TimeSinceUnix .UpdatedUnix $.i18n.Lang}}</p>
|
||||
</div>
|
||||
{{else}}
|
||||
|
|
6
templates/install.tmpl
vendored
6
templates/install.tmpl
vendored
|
@ -200,6 +200,12 @@
|
|||
<input name="disable_registration" type="checkbox" {{if .disable_registration}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="allow-only-external-registration">
|
||||
<label class="poping up" data-content="{{.i18n.Tr "install.allow_only_external_registration_popup"}}"><strong>{{.i18n.Tr "install.allow_only_external_registration_popup"}}</strong></label>
|
||||
<input name="allow_only_external_registration" type="checkbox" {{if .allow_only_external_registration}}checked{{end}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline field">
|
||||
<div class="ui checkbox" id="enable-openid-signup">
|
||||
<label class="poping up" data-content="{{.i18n.Tr "install.openid_signup_popup"}}"><strong>{{.i18n.Tr "install.openid_signup"}}</strong></label>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<div class="ui tabs container">
|
||||
<div class="ui tabular stackable menu navbar">
|
||||
{{if .Repository.UnitEnabled $.UnitTypeCode}}
|
||||
<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/branch/{{.BranchName}}{{end}}">
|
||||
<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
|
||||
<i class="octicon octicon-code"></i> {{.i18n.Tr "repo.code"}}
|
||||
</a>
|
||||
{{end}}
|
||||
|
|
|
@ -156,7 +156,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Assignee -->
|
||||
<!-- Assignees -->
|
||||
<div class="ui {{if not .Assignees}}disabled{{end}} dropdown jump item">
|
||||
<span class="text">
|
||||
{{.i18n.Tr "repo.issues.action_assignee"}}
|
||||
|
@ -220,9 +220,9 @@
|
|||
<span class="octicon octicon-calendar"></span>
|
||||
<span{{if .IsOverdue}} class="overdue"{{end}}>{{.DeadlineUnix.FormatShort}}</span>
|
||||
{{end}}
|
||||
{{if .Assignee}}
|
||||
<a class="ui right assignee poping up" href="{{.Assignee.HomeLink}}" data-content="{{.Assignee.Name}}" data-variation="inverted" data-position="left center">
|
||||
<img class="ui avatar image" src="{{.Assignee.RelAvatarLink}}">
|
||||
{{range .Assignees}}
|
||||
<a class="ui right assignee poping up" href="{{.HomeLink}}" data-content="{{.Name}}" data-variation="inverted" data-position="left center">
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}">
|
||||
</a>
|
||||
{{end}}
|
||||
</p>
|
||||
|
|
|
@ -97,27 +97,56 @@
|
|||
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<input id="assignee_id" name="assignee_id" type="hidden" value="{{.assignee_id}}">
|
||||
<input id="assignee_ids" name="assignee_ids" type="hidden" value="{{.assignee_ids}}">
|
||||
<div class="ui {{if not .Assignees}}disabled{{end}} floating jump select-assignees dropdown">
|
||||
<span class="text">
|
||||
<strong>{{.i18n.Tr "repo.issues.new.assignees"}}</strong>
|
||||
<span class="octicon octicon-gear"></span>
|
||||
</span>
|
||||
<div class="filter menu" data-id="#assignee_ids">
|
||||
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignees"}}</div>
|
||||
{{range .Assignees}}
|
||||
<a class="item" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}">
|
||||
<span class="octicon"></span>
|
||||
<span class="text">
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}"> {{.Name}}
|
||||
</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui assignees list">
|
||||
<span class="no-select item {{if .HasSelectedLabel}}hide{{end}}">
|
||||
{{.i18n.Tr "repo.issues.new.no_assignees"}}
|
||||
</span>
|
||||
{{range .Assignees}}
|
||||
<a style="padding: 5px;color:rgba(0, 0, 0, 0.87);" class="hide item" id="assignee_{{.ID}}" href="{{$.RepoLink}}/issues?assignee={{.ID}}">
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}" style="vertical-align: middle;"> {{.Name}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<!-- input id="assignee_ids" name="assignee_ids" type="hidden" value="{{.assignee_id}}">
|
||||
<div class="ui {{if not .Assignees}}disabled{{end}} floating jump select-assignee dropdown">
|
||||
<span class="text">
|
||||
<strong>{{.i18n.Tr "repo.issues.new.assignee"}}</strong>
|
||||
<strong>{{.i18n.Tr "repo.issues.new.assignees"}}</strong>
|
||||
<span class="octicon octicon-gear"></span>
|
||||
</span>
|
||||
<div class="menu">
|
||||
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignee"}}</div>
|
||||
<div class="filter menu">
|
||||
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignees"}}</div>
|
||||
{{range .Assignees}}
|
||||
<div class="item" data-id="{{.ID}}" data-href="{{$.RepoLink}}/issues?assignee={{.ID}}" data-avatar="{{.RelAvatarLink}}"><img src="{{.RelAvatarLink}}"> {{.Name}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui select-assignee list">
|
||||
<span class="no-select item {{if .Assignee}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_assignee"}}</span>
|
||||
<span class="no-select item {{if .Assignee}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_assignees"}}</span>
|
||||
<div class="selected">
|
||||
{{if .Assignee}}
|
||||
<a class="item" href="{{.RepoLink}}/issues?assignee={{.Assignee.ID}}"><img class="ui avatar image" src="{{.Assignee.RelAvatarLink}}"> {{.Assignee.Name}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -118,15 +118,29 @@
|
|||
{{else if eq .Type 9}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
{{if gt .AssigneeID 0}}{{if eq .Poster.ID .AssigneeID}}<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a> <span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.self_assign_at" $createdStr | Safe}} </span>
|
||||
{{else}}<a class="ui avatar image" href="{{.Assignee.HomeLink}}">
|
||||
<img src="{{.Assignee.RelAvatarLink}}">
|
||||
</a><span class="text grey"><a href="{{.Assignee.HomeLink}}">{{.Assignee.Name}}</a> {{$.i18n.Tr "repo.issues.add_assignee_at" .Poster.Name $createdStr | Safe}} </span>{{end}}{{else if gt .OldAssigneeID 0}}
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a> <span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.remove_assignee_at" $createdStr | Safe}} </span>{{end}}
|
||||
{{if gt .AssigneeID 0}}
|
||||
{{if .RemovedAssignee}}
|
||||
<a class="ui avatar image" href="{{.Assignee.HomeLink}}">
|
||||
<img src="{{.Assignee.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey">
|
||||
<a href="{{.Assignee.HomeLink}}">{{.Assignee.Name}}</a>
|
||||
{{$.i18n.Tr "repo.issues.remove_assignee_at" $createdStr | Safe}}
|
||||
</span>
|
||||
{{else}}
|
||||
<a class="ui avatar image" href="{{.Assignee.HomeLink}}">
|
||||
<img src="{{.Assignee.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey">
|
||||
<a href="{{.Assignee.HomeLink}}">{{.Assignee.Name}}</a>
|
||||
{{if eq .Poster.ID .AssigneeID}}
|
||||
{{$.i18n.Tr "repo.issues.self_assign_at" $createdStr | Safe}}
|
||||
{{else}}
|
||||
{{$.i18n.Tr "repo.issues.add_assignee_at" .Poster.Name $createdStr | Safe}}
|
||||
{{end}}
|
||||
</span>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{else if eq .Type 10}}
|
||||
<div class="event">
|
||||
|
|
|
@ -68,23 +68,40 @@
|
|||
<div class="ui divider"></div>
|
||||
|
||||
<input id="assignee_id" name="assignee_id" type="hidden" value="{{.assignee_id}}">
|
||||
<div class="ui {{if not .IsRepositoryWriter}}disabled{{end}} floating jump select-assignee dropdown">
|
||||
<div class="ui {{if not .IsRepositoryWriter}}disabled{{end}} floating jump select-assignees-modify dropdown">
|
||||
<span class="text">
|
||||
<strong>{{.i18n.Tr "repo.issues.new.assignee"}}</strong>
|
||||
<strong>{{.i18n.Tr "repo.issues.new.assignees"}}</strong>
|
||||
<span class="octicon octicon-gear"></span>
|
||||
</span>
|
||||
<div class="menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/assignee">
|
||||
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignee"}}</div>
|
||||
<div class="filter menu" data-action="" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/assignee">
|
||||
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_assignees"}}</div>
|
||||
{{range .Assignees}}
|
||||
<div class="item" data-id="{{.ID}}" data-href="{{$.RepoLink}}/issues?assignee={{.ID}}" data-avatar="{{.RelAvatarLink}}"><img src="{{.RelAvatarLink}}"> {{.Name}}</div>
|
||||
|
||||
{{$AssigneeID := .ID}}
|
||||
<a class="item{{range $.Issue.Assignees}}
|
||||
{{if eq .ID $AssigneeID}}
|
||||
checked
|
||||
{{end}}
|
||||
{{end}}" href="#" data-id="{{.ID}}" data-id-selector="#assignee_{{.ID}}">
|
||||
<span class="octicon{{range $.Issue.Assignees}}
|
||||
{{if eq .ID $AssigneeID}}
|
||||
octicon-check
|
||||
{{end}}
|
||||
{{end}}"></span>
|
||||
<span class="text">
|
||||
<img class="ui avatar image" src="{{.RelAvatarLink}}"> {{.Name}}
|
||||
</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui select-assignee list">
|
||||
<span class="no-select item {{if .Issue.Assignee}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_assignee"}}</span>
|
||||
<div class="ui assignees list">
|
||||
<span class="no-select item {{if .Issue.Assignees}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_assignees"}}</span>
|
||||
<div class="selected">
|
||||
{{if .Issue.Assignee}}
|
||||
<a class="item" href="{{$.RepoLink}}/issues?assignee={{.Issue.Assignee.ID}}"><img class="ui avatar image" src="{{.Issue.Assignee.RelAvatarLink}}"> {{.Issue.Assignee.Name}}</a>
|
||||
{{range .Issue.Assignees}}
|
||||
<div class="item" style="margin-bottom: 10px;">
|
||||
<a href="{{$.RepoLink}}/issues?assignee={{.ID}}"><img class="ui avatar image" src="{{.RelAvatarLink}}"> {{.Name}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -194,7 +211,7 @@
|
|||
|
||||
<div class="ui divider"></div>
|
||||
<span class="text"><strong>{{.i18n.Tr "repo.issues.due_date"}}</strong></span>
|
||||
{{if gt .Issue.DeadlineUnix 0}}
|
||||
{{if ne .Issue.DeadlineUnix 0}}
|
||||
<p>
|
||||
<span class="octicon octicon-calendar"></span>
|
||||
{{.Issue.DeadlineUnix.FormatShort}}
|
||||
|
@ -212,12 +229,12 @@
|
|||
{{end}}
|
||||
|
||||
{{if and .IsSigned .IsRepositoryWriter}}
|
||||
<form method="POST"{{if gt .Issue.DeadlineUnix 0}}style="display: none;"{{end}}} id="add_deadline_form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/deadline/update" class="ui action input fluid">
|
||||
<form method="POST" {{if ne .Issue.DeadlineUnix 0}}style="display: none;"{{end}} id="add_deadline_form" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/deadline/update" class="ui action input fluid">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<div class="ui fluid action input">
|
||||
<input required placeholder="{{.i18n.Tr "repo.issues.due_date_form"}}" {{if gt .Issue.DeadlineUnix 0}}value="{{.Issue.DeadlineUnix.Format "2006-01-02"}}"{{end}} type="date" name="date" style="min-width: 13.9rem;border-radius: 4px 0 0 4px;border-right: 0;white-space: nowrap;">
|
||||
<input required placeholder="{{.i18n.Tr "repo.issues.due_date_form"}}" {{if ne .Issue.DeadlineUnix 0 }}value="{{.Issue.DeadlineUnix.Format "2006-01-02"}}"{{end}} type="date" name="date" style="min-width: 13.9rem;border-radius: 4px 0 0 4px;border-right: 0;white-space: nowrap;">
|
||||
<button class="ui green icon button">
|
||||
{{if gt .Issue.DeadlineUnix 0}}
|
||||
{{if ne .Issue.DeadlineUnix 0}}
|
||||
<i class="edit icon"></i>
|
||||
{{else}}
|
||||
<i class="plus icon"></i>
|
||||
|
|
2
vendor/github.com/lafriks/xormstore/xormstore.go
generated
vendored
2
vendor/github.com/lafriks/xormstore/xormstore.go
generated
vendored
|
@ -70,7 +70,7 @@ type Store struct {
|
|||
}
|
||||
|
||||
type xormSession struct {
|
||||
ID string `xorm:"VARCHAR(400) PK NAME 'id'"`
|
||||
ID string `xorm:"VARCHAR(100) PK NAME 'id'"`
|
||||
Data string `xorm:"TEXT"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -648,10 +648,10 @@
|
|||
"revisionTime": "2016-10-16T15:41:25Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "/X7eCdN7MX8zgCjA9s0ktzgTPlA=",
|
||||
"checksumSHA1": "1zVWfGXRsQi0EuZydyBHgkhl7tU=",
|
||||
"path": "github.com/lafriks/xormstore",
|
||||
"revision": "3a80a383a04b29ec2e1bf61279dd948aa809335b",
|
||||
"revisionTime": "2018-04-09T10:45:24Z"
|
||||
"revision": "9cab149ea91875cf056211bd6ef82379fce9cb67",
|
||||
"revisionTime": "2018-05-10T21:06:47Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "Vxvfs8mukr9GOLSuGIPU4ODyOZc=",
|
||||
|
|
Loading…
Add table
Reference in a new issue