Merge branch 'master' of https://github.com/go-gitea/gitea
# Conflicts: # docs/content/doc/advanced/config-cheat-sheet.en-us.md # models/migrations/migrations.go # models/migrations/v54.go # routers/repo/pull.go
This commit is contained in:
commit
37dc550bc8
|
|
@ -7,6 +7,7 @@ Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
|||
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||
Matthias Loibl <mail@matthiasloibl.com> (@metalmatze)
|
||||
Morgan Bazalgette <the@howl.moe> (@thehowl)
|
||||
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
||||
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
||||
Sandro Santilli <strk@kbt.io> (@strk)
|
||||
|
|
|
|||
|
|
@ -15,219 +15,235 @@ menu:
|
|||
|
||||
# Configuration Cheat Sheet
|
||||
|
||||
This is a cheat sheet for the Gitea configuration file. It is helpful for more fully understanding how it powers Gitea.
|
||||
This is a cheat sheet for the Gitea configuration file. It contains all settings that can configured.
|
||||
|
||||
Before getting started, make sure you know that any change to the configuration should be made in `custom/conf/app.ini` or any corresponding location.
|
||||
Any changes to the Gitea configuration file should be made in `custom/conf/app.ini` or any corresponding location. When installing from a distribution, this will typically be found at `/etc/gitea/conf/app.ini`.
|
||||
|
||||
All default settings can be found in [app.ini.sample](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample) (replace master in URL with name of tag for released versions). If you see anything which looks like `%(X)s`, it is a feature powered by [ini](https://github.com/go-ini/ini/#recursive-values) for reading values recursively.
|
||||
|
||||
Any configuration option that is marked by :exclamation: means that you should keep the default value unless you fully understand what you are doing.
|
||||
The defaults provided here are best-effort (not built automatically). They are accurately recorded in [app.ini.sample](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample) (s/master/<tag|release\>. Any string in the format `%(X)s` is a feature powered by [ini](https://github.com/go-ini/ini/#recursive-values), for reading values recursively.
|
||||
|
||||
Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||
|
||||
**Note** that you have to restart Gitea for changes to take effect.
|
||||
**Note:** A full restart is required for Gitea configuration changes to take effect.
|
||||
|
||||
## Overall (`DEFAULT`)
|
||||
|
||||
- `APP_NAME`: Application name, change to whatever you want.
|
||||
- `RUN_USER`: The user to run Gitea as, we recommend it be `git`; however, change this to whatever your username is if you run Gitea on your personal computer. Gitea may crash if this value is not set properly.
|
||||
- `RUN_MODE`: For performance and other purposes, change this to `prod` when deployed to a production environment. The installation process will set this to `prod` automatically.
|
||||
- `APP_NAME`: **Gitea: Git with a cup of tea**: Application name, used in the page title.
|
||||
- `RUN_USER`: **git**: The user Gitea will run as. This should be a dedicated service (non-user) account. Setting this incorrectly will cause Gitea to not start.
|
||||
- `RUN_MODE`: **dev**: For performance and other purposes, change this to `prod` when deployed to a production environment. The installation process will set this to `prod` automatically. \[prod, dev, test\]
|
||||
|
||||
## Repository (`repository`)
|
||||
|
||||
- `ROOT`: Root path for storing all users' repository data. It must be an absolute path. The default is `~/<username>/gitea-repositories`.
|
||||
- `SCRIPT_TYPE`: The script type your server supports, usually this is `bash`, but some customers report that they only have `sh`.
|
||||
- `ANSI_CHARSET`: The default charset for an unrecognized charset.
|
||||
- `FORCE_PRIVATE`: Force every new repository to be private.
|
||||
- `DEFAULT_PRIVATE`: Default private when create a new repository, could be: `last`, `private` and `public`. Default is last which means last user repo visiblity.
|
||||
- `MAX_CREATION_LIMIT`: Global maximum creation limit of repositories per user, `-1` means no limit.
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`:exclamation:: Length of pull request patch test queue, make it as large as possible.
|
||||
- `MIRROR_QUEUE_LENGTH`: Patch test queue length, increase if pull request patch testing starts hanging. Defaults to 1000.
|
||||
- `PREFERRED_LICENSES`: Preferred Licenses to place at the top of the List. Name must match file name in conf/license or custom/conf/license. Defaults to 'Apache License 2.0,MIT License'
|
||||
- `DISABLE_HTTP_GIT`: Disable ability to interact with repositories by HTTP protocol. Defaults to false
|
||||
- `USE_COMPAT_SSH_URI`: Force ssh:// clone url instead of scp-style uri when default SSH port is used. Defaults to false.
|
||||
- `ROOT`: **~/gitea-repositories/**: Root path for storing all repository data. It must be an absolute path.
|
||||
- `SCRIPT_TYPE`: **bash**: The script type your server supports, usually this is `bash`, but some users report that only `sh` is available.
|
||||
- `ANSI_CHARSET`: **\<empty\>**: The default charset for an unrecognized charset.
|
||||
- `FORCE_PRIVATE`: **false**: Force every new repository to be private.
|
||||
- `DEFAULT_PRIVATE`: **last**: Default private when create a new repository. \[last, private, public\]
|
||||
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user, `-1` means no limit.
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`: **1000**: Length of pull request patch test queue, make it as large as possible. Use caution when editing this value.
|
||||
- `MIRROR_QUEUE_LENGTH`: **1000**: Patch test queue length, increase if pull request patch testing starts hanging.
|
||||
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at the top of the List. Name must match file name in conf/license or custom/conf/license.
|
||||
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the HTTP protocol.
|
||||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when default SSH port is used.
|
||||
|
||||
## UI (`ui`)
|
||||
|
||||
- `EXPLORE_PAGING_NUM`: Number of repositories that are shown in one explore page.
|
||||
- `ISSUE_PAGING_NUM`: Number of issues that are shown in one page (for all pages that list issues).
|
||||
- `FEED_MAX_COMMIT_NUM`: Number of maximum commits shown in one activity feed.
|
||||
- `EXPLORE_PAGING_NUM`: **20**: Number of repositories that are shown in one explore page.
|
||||
- `ISSUE_PAGING_NUM`: **10**: Number of issues that are shown in one page (for all pages that list issues).
|
||||
- `FEED_MAX_COMMIT_NUM`: **5**: Number of maximum commits shown in one activity feed.
|
||||
|
||||
### UI - Admin (`ui.admin`)
|
||||
|
||||
- `USER_PAGING_NUM`: Number of users that are shown in one page.
|
||||
- `REPO_PAGING_NUM`: Number of repos that are shown in one page.
|
||||
- `NOTICE_PAGING_NUM`: Number of notices that are shown in one page.
|
||||
- `ORG_PAGING_NUM`: Number of organizations that are shown in one page.
|
||||
- `USER_PAGING_NUM`: **50**: Number of users that are shown in one page.
|
||||
- `REPO_PAGING_NUM`: **50**: Number of repos that are shown in one page.
|
||||
- `NOTICE_PAGING_NUM`: **25**: Number of notices that are shown in one page.
|
||||
- `ORG_PAGING_NUM`: **50**: Number of organizations that are shown in one page.
|
||||
|
||||
## Markdown (`markdown`)
|
||||
|
||||
- `ENABLE_HARD_LINE_BREAK`: Whether or not to enable hard the line break extension.
|
||||
- `ENABLE_HARD_LINE_BREAK`: **false**: Whether or not to enable hard the line break extension.
|
||||
|
||||
## Server (`server`)
|
||||
|
||||
- `PROTOCOL`: Either `http`, `https`, `fcgi`, or `unix`.
|
||||
- `DOMAIN`: Domain name of your server.
|
||||
- `ROOT_URL`: Full public URL of Gitea server.
|
||||
- `HTTP_ADDR`: HTTP listen address. If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings. If `PROTOCOL` is set to `unix`, this should be the name of the Unix socket file to use.
|
||||
- `HTTP_PORT`: HTTP listen port. If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||
- `UNIX_SOCKET_PERMISSION`: Permisson mode for Unix socket, default is 666.
|
||||
- `DISABLE_SSH`: Disables SSH feature when it's not available.
|
||||
- `START_SSH_SERVER`: Starts built-in SSH server when enabled.
|
||||
- `SSH_DOMAIN`: Domain name of your ssh server.
|
||||
- `SSH_PORT`: SSH port displayed in clone URL, in case yours is not `22`.
|
||||
- `SSH_LISTEN_PORT`: Port for the built-in SSH server. Defaults to `SSH_PORT`.
|
||||
- `OFFLINE_MODE`: Disables use of CDN for static files and Gravatar for profile pictures.
|
||||
- `DISABLE_ROUTER_LOG`: Mutes printing of the router log.
|
||||
- `CERT_FILE`: Cert file path used for HTTPS.
|
||||
- `KEY_FILE`: Key file path used for HTTPS.
|
||||
- `STATIC_ROOT_PATH`: Upper level of template and static files path, default is the path where Gitea is located.
|
||||
- `ENABLE_GZIP`: Enables application-level GZIP support.
|
||||
- `LANDING_PAGE`: Non-logged-in users' landing page, either `home` or `explore`.
|
||||
- `LFS_START_SERVER`: Enables git-lfs support. `true` or `false`, default is `false`.
|
||||
- `LFS_CONTENT_PATH`: Where your lfs files put on, default is `data/lfs`.
|
||||
- `LFS_JWT_SECRET`: LFS authentication secret, changed this to yourself.
|
||||
- `REDIRECT_OTHER_PORT`: If true and `PROTOCOL` is https, redirects http requests on another port to `ROOT_URL`, default is `false`.
|
||||
- `PORT_TO_REDIRECT`: Port used when `REDIRECT_OTHER_PORT` is true, default is `80`.
|
||||
- `PROTOCOL`: **http**: Either `http`, `https`, `fcgi`, or `unix`.
|
||||
- `DOMAIN`: **localhost**: Domain name of your server.
|
||||
- `ROOT_URL`: **%(PROTOCOL)s://%(DOMAIN)s:%(HTTP\_PORT)s/**: Full public URL of Gitea server.
|
||||
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
|
||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||
- If `PROTOCOL` is set to `unix`, this should be the name of the Unix socket file to use.
|
||||
- `HTTP_PORT`: **3000**: HTTP listen port.
|
||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||
- `UNIX_SOCKET_PERMISSION`: **666**: Permisson mode for Unix socket.
|
||||
- `DISABLE_SSH`: **false**: Disables SSH feature when it's not available.
|
||||
- `START_SSH_SERVER`: **false**: When enabled, uses the built-in SSH server.
|
||||
- `SSH_DOMAIN`: **%(DOMAIN)s**: Domain name of your ssh server, used for displayed clone URL.
|
||||
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
|
||||
- `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
|
||||
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
||||
- `DISABLE_ROUTER_LOG`: **false**: Mutes printing of the router log.
|
||||
- `CERT_FILE`: **custom/https/cert.pem**: Cert file path used for HTTPS.
|
||||
- `KEY_FILE`: **custom/https/key.pem**: Key file path used for HTTPS.
|
||||
- `STATIC_ROOT_PATH`: **./**: Upper level of template and static files path.
|
||||
- `ENABLE_GZIP`: **false**: Enables application-level GZIP support.
|
||||
- `LANDING_PAGE`: **home**: Landing page for unauthenticated users, either `home` or `explore`.
|
||||
- `LFS_START_SERVER`: **false**: Enables git-lfs support.
|
||||
- `LFS_CONTENT_PATH`: **./data/lfs**: Where to store lfs files.
|
||||
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, redirects http requests on another (https) port.
|
||||
- `PORT_TO_REDIRECT`: **80**: Port used when `REDIRECT_OTHER_PORT` is true.
|
||||
|
||||
## Database (`database`)
|
||||
|
||||
- `DB_TYPE`: The database type you choose, either `mysql`, `postgres`, `mssql` or `sqlite3`.
|
||||
- `HOST`: Database host address and port.
|
||||
- `NAME`: Database name.
|
||||
- `USER`: Database username.
|
||||
- `PASSWD`: Database user password.
|
||||
- `SSL_MODE`: For PostgreSQL only.
|
||||
- `PATH`: For SQLite3 only, the database file path.
|
||||
- `DB_TYPE`: **mysql**: The database type you choose, either `mysql`, `postgres`, `mssql` or `sqlite3`.
|
||||
- `HOST`: **127.0.0.1:3306**: Database host address and port.
|
||||
- `NAME`: **gitea**: Database name.
|
||||
- `USER`: **root**: Database username.
|
||||
- `PASSWD`: **\<empty\>**: Database user password.
|
||||
- `SSL_MODE`: **disable**: For PostgreSQL only.
|
||||
- `PATH`: **data/gitea.db**: For SQLite3 only, the database file path.
|
||||
|
||||
## Security (`security`)
|
||||
|
||||
- `INSTALL_LOCK`: Indicates whether to allow the open install page (setting admin account is involved, so it's a very important value).
|
||||
- `SECRET_KEY`: Global secret key for your server security, **you'd better change it** (will generate a random string every time you install).
|
||||
- `LOGIN_REMEMBER_DAYS`: Cookie lifetime, in days.
|
||||
- `COOKIE_USERNAME`: Name of the cookie that saves username.
|
||||
- `COOKIE_REMEMBER_NAME`: Name of cookie that saves auto-login information.
|
||||
- `REVERSE_PROXY_AUTHENTICATION_USER`: Header name for reverse proxy authentication username.
|
||||
- `DISABLE_GIT_HOOKS`: Prevent all users (including admin) from creating custom git hooks (defaults to false)
|
||||
- `INSTALL_LOCK`: **false**: Disable to allow accessing the install page.
|
||||
- `SECRET_KEY`: **random at every install**: Global secret key. This should be changed.
|
||||
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
|
||||
- `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username.
|
||||
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication information.
|
||||
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy authentication.
|
||||
- `DISABLE_GIT_HOOKS`: **false**: Prevent all users (including admin) from creating custom git hooks.
|
||||
|
||||
## OpenID (`openid`)
|
||||
|
||||
- `ENABLE_OPENID_SIGNIN`: Whether to allow signin in via OpenID (defaults to false).
|
||||
- `ENABLE_OPENID_SIGNUP`: Whether to allow registering via OpenID (defaults to `!DISABLE_REGISTRATION`).
|
||||
- `WHITELISTED_URIS`: Space separated list of POSIX regexp patterns. If non empty OpenID URIs should match any of these to be granted access.
|
||||
- `BLACKLISTED_URIS`: Space separated list of POSIX regexp pattenrs. OpenID URI matching any of these is refused access.
|
||||
- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID.
|
||||
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
|
||||
- `WHITELISTED_URIS`: **\<empty\>**: If non-empty, list of POSIX regex patterns matching OpenID URI's to permit.
|
||||
- `BLACKLISTED_URIS`: **\<empty\>**: If non-empty, list of POSIX regex patterns matching OpenID URI's to block.
|
||||
|
||||
## Service (`service`)
|
||||
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: The minutes of active code life time.
|
||||
- `RESET_PASSWD_CODE_LIVE_MINUTES`: The minutes of reset password code life time.
|
||||
- `REGISTER_EMAIL_CONFIRM`: Enable this to ask for mail confirmation of registration, requires `Mailer` to be enabled.
|
||||
- `DISABLE_REGISTRATION`: Disable registration, after which only admin can create accounts for users.
|
||||
- `SHOW_REGISTRATION_BUTTON`: Indicate whether to show registration button or not.
|
||||
- `REQUIRE_SIGNIN_VIEW`: Enable this to force users to log in to view any page.
|
||||
- `ENABLE_CACHE_AVATAR`: Enable this to cache avatar from Gravatar.
|
||||
- `ENABLE_NOTIFY_MAIL`: Enable this to send e-mail to watchers of repository when something happens like creating issues, requires `Mailer` to be enabled.
|
||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: Enable this to allow reverse proxy authentication, more detail: https://github.com/gogits/gogs/issues/165
|
||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: Enable this to allow auto-registration for reverse authentication.
|
||||
- `DISABLE_MINIMUM_KEY_SIZE_CHECK`: Do not check minimum key size with corresponding type.
|
||||
- `ENABLE_CAPTCHA`: Enable this to use captcha validation for registration.
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: Enable this to have dependencies enabled by default.
|
||||
- `ACTIVE_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm account/email registration.
|
||||
- `RESET_PASSWD_CODE_LIVE_MINUTES`: **180**: Time limit (min) to confirm forgot password reset process.
|
||||
- `REGISTER_EMAIL_CONFIRM`: **false**: Enable this to ask for mail confirmation of registration. Requires `Mailer` to be enabled.
|
||||
- `DISABLE_REGISTRATION`: **false**: Disable registration, after which only admin can create accounts for users.
|
||||
- `REQUIRE_SIGNIN_VIEW`: **false**: Enable this to force users to log in to view any page.
|
||||
- `ENABLE_NOTIFY_MAIL`: **false**: Enable this to send e-mail to watchers of a repository when something happens, like creating issues. Requires `Mailer` to be enabled.
|
||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: **false**: Enable this to allow reverse proxy authentication.
|
||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: **false**: Enable this to allow auto-registration for reverse authentication.
|
||||
- `ENABLE_CAPTCHA`: **true**: Enable this to use captcha validation for registration.
|
||||
- `DEFAULT_ENABLE_DEPENDENCIES`: **true** Enable this to have dependencies enabled by default.
|
||||
|
||||
## Webhook (`webhook`)
|
||||
|
||||
- `QUEUE_LENGTH`:exclamation:: Hook task queue length.
|
||||
- `DELIVER_TIMEOUT`: Delivery timeout in seconds for shooting webhooks.
|
||||
- `SKIP_TLS_VERIFY`: Indicate whether to allow insecure certification or not.
|
||||
- `PAGING_NUM`: Number of webhook history that are shown in one page.
|
||||
- `QUEUE_LENGTH`: **1000**: Hook task queue length. Use caution when editing this value.
|
||||
- `DELIVER_TIMEOUT`: **5**: Delivery timeout (sec) for shooting webhooks.
|
||||
- `SKIP_TLS_VERIFY`: **false**: Allow insecure certification.
|
||||
- `PAGING_NUM`: **10**: Number of webhook history events that are shown in one page.
|
||||
|
||||
## Mailer (`mailer`)
|
||||
|
||||
- `ENABLED`: Enable this to use a mail service.
|
||||
- `DISABLE_HELO`: Disable HELO operation.
|
||||
- `HELO_HOSTNAME`: Custom hostname for HELO operation.
|
||||
- `HOST`: SMTP mail host address and port (example: smtp.gitea.io:587).
|
||||
- `FROM`: Mail from address, RFC 5322. This can be just an email address, or the "Name" \<email@example.com\> format.
|
||||
- `USER`: Username of mailer (usually just your e-mail address).
|
||||
- `PASSWD`: Password of mailer.
|
||||
- `SKIP_VERIFY`: Do not verify the self-signed certificates.
|
||||
- `USE_SENDMAIL`: Use the operating system's `sendmail` command instead of SMTP. This is common on linux systems. Valid values are `true` to use sendmail and `false` to use SMTP (default). Note that enabling sendmail will ignore all other `mailer` settings except `ENABLED`, `FROM` and `SENDMAIL_PATH`.
|
||||
- `SENDMAIL_PATH`: The location of sendmail on the operating system. This can be an absolute path (eg: `/usr/sbin/sendmail`) or just the name of the command (eg: `sendmail` - default) if it can be found in the `PATH` environment variable.
|
||||
|
||||
Note: Actually, Gitea supports only SMTP with STARTTLS.
|
||||
- `ENABLED`: **false**: Enable to use a mail service.
|
||||
- `DISABLE_HELO`: **\<empty\>**: Disable HELO operation.
|
||||
- `HELO_HOSTNAME`: **\<empty\>**: Custom hostname for HELO operation.
|
||||
- `HOST`: **\<empty\>**: SMTP mail host address and port (example: smtp.gitea.io:587).
|
||||
- `FROM`: **\<empty\>**: Mail from address, RFC 5322. This can be just an email address, or the "Name" \<email@example.com\> format.
|
||||
- `USER`: **\<empty\>**: Username of mailing user (usually the sender's e-mail address).
|
||||
- `PASSWD`: **\<empty\>**: Password of mailing user.
|
||||
- `SKIP_VERIFY`: **\<empty\>**: Do not verify the self-signed certificates.
|
||||
- **Note:** Gitea only supports SMTP with STARTTLS.
|
||||
- `USE_SENDMAIL`: **false** Use the operating system's `sendmail` command instead of SMTP. This is common on linux systems.
|
||||
- Note that enabling sendmail will ignore all other `mailer` settings except `ENABLED`, `FROM` and `SENDMAIL_PATH`.
|
||||
- `SENDMAIL_PATH`: **sendmail**: The location of sendmail on the operating system. (can be command or full path)
|
||||
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ADAPTER`: Cache engine adapter, either `memory`, `redis`, or `memcache`. If you want to use `redis` or `memcache`, be sure to rebuild everything with build tags `redis` or `memcache`: `go build -tags='redis'`.
|
||||
- `INTERVAL`: for memory cache only, GC interval in seconds.
|
||||
- `HOST`: For redis and memcache, the host address and port number.
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, or `memcache`. If you want 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`
|
||||
- Memache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: Session engine provider, either `memory`, `file`, `redis`, or `mysql`.
|
||||
- `PROVIDER_CONFIG`: For file, it's the root path; for others, it's the host address and port number.
|
||||
- `COOKIE_SECURE`: Enable this to force using HTTPS for all session access.
|
||||
- `COOKIE_NAME`: The name of the cookie used for the session ID, defaults to `i_like_gitea`.
|
||||
- `GC_INTERVAL_TIME`: GC interval in seconds.
|
||||
- `PROVIDER`: **memory**: Session engine provider, either `memory`, `file`, `redis`, or `mysql`.
|
||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for others, the connection string.
|
||||
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
||||
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID, defaults to `i_like_gitea`.
|
||||
- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
|
||||
|
||||
## Picture (`picture`)
|
||||
|
||||
- `GRAVATAR_SOURCE`: Can be `gravatar`, `duoshuo` or anything like `http://cn.gravatar.com/avatar/`.
|
||||
- `DISABLE_GRAVATAR`: Enable this to use local avatars only.
|
||||
- `ENABLE_FEDERATED_AVATAR`: Enable support for federated avatars (see http://www.libravatar.org)
|
||||
- `AVATAR_UPLOAD_PATH`: Path to store local and cached files.
|
||||
- `GRAVATAR_SOURCE`: **gravatar**: Can be `gravatar`, `duoshuo` or anything like `http://cn.gravatar.com/avatar/`.
|
||||
- `DISABLE_GRAVATAR`: **false**: Enable this to use local avatars only.
|
||||
- `ENABLE_FEDERATED_AVATAR`: **false**: Enable support for federated avatars (see http://www.libravatar.org)
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store local and cached files.
|
||||
|
||||
## Attachment (`attachment`)
|
||||
|
||||
- `ENABLED`: Enable this to allow users upload attachments.
|
||||
- `PATH`: Path to store attachments.
|
||||
- `ALLOWED_TYPES`: Allowed MIME types, e.g. `image/jpeg|image/png`, use `*/*` for all types.
|
||||
- `MAX_SIZE`: Maximum size in MB, e.g. `4`
|
||||
- `MAX_FILES`: Maximum number of attachments can be uploaded at once, e.g. `5`.
|
||||
- `ENABLED`: **true**: Enable this to allow uploading attachments.
|
||||
- `PATH`: **data/attachments**: Path to store attachments.
|
||||
- `ALLOWED_TYPES`: **see app.ini.sample**: Allowed MIME types, e.g. `image/jpeg|image/png`, use `*/*` for all types.
|
||||
- `MAX_SIZE`: **4**: Maximum size (MB).
|
||||
- `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once.
|
||||
|
||||
## Log (`log`)
|
||||
|
||||
- `ROOT_PATH`: Root path for log files.
|
||||
- `MODE`: Logging mode, default is `console`. For multiple modes, use comma to separate it.
|
||||
- `LEVEL`: General log level, default is `Trace`.
|
||||
- `ROOT_PATH`: **\<empty\>**: Root path for log files.
|
||||
- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values.
|
||||
- `LEVEL`: **Trace**: General log level. \[Trace, Debug, Info, Warn, Error, Critical\]
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
- `ENABLED`: Enable this to run cron tasks periodically.
|
||||
- `RUN_AT_START`: Enable this to run cron tasks at start time.
|
||||
- `ENABLED`: **true**: Run cron tasks periodically.
|
||||
- `RUN_AT_START`: **false**: Run cron tasks at application start-up.
|
||||
|
||||
### Cron - Cleanup old repository archives (`cron.archive_cleanup`)
|
||||
|
||||
- `ENABLED`: Enable service. Defaults to true.
|
||||
- `RUN_AT_START`: Run tasks at start up time (if ENABLED). Defaults to true.
|
||||
- `SCHEDULE`: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`. Defaults to `@every 24h`.
|
||||
- `OLDER_THAN`: Archives created more than `OLDER_THAN` ago are subject to deletion, e.g. `12h`. Defaults to `24h`.
|
||||
- `ENABLED`: **true**: Enable service.
|
||||
- `RUN_AT_START`: **true**: Run tasks at start up time (if ENABLED).
|
||||
- `SCHEDULE`: **@every 24h**: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`.
|
||||
- `OLDER_THAN`: **24h**: Archives created more than `OLDER_THAN` ago are subject to deletion, e.g. `12h`.
|
||||
|
||||
### Cron - Update Mirrors (`cron.update_mirrors`)
|
||||
|
||||
- `SCHEDULE`: Cron syntax for scheduling update mirrors, e.g. `@every 1h`.
|
||||
- `SCHEDULE`: **@every 10m**: Cron syntax for scheduling update mirrors, e.g. `@every 3h`.
|
||||
|
||||
### Cron - Repository Health Check (`cron.repo_health_check`)
|
||||
|
||||
- `SCHEDULE`: Cron syntax for scheduling repository health check, e.g. `@every 24h`.
|
||||
- `TIMEOUT`: Time duration syntax for health check execution timeout, e.g. `60s`.
|
||||
- `ARGS`: Arguments for command `git fsck`, e.g. `--unreachable --tags`.
|
||||
- `SCHEDULE`: **every 24h**: Cron syntax for scheduling repository health check.
|
||||
- `TIMEOUT`: **60s**: Time duration syntax for health check execution timeout.
|
||||
- `ARGS`: **\<empty\>**: Arguments for command `git fsck`, e.g. `--unreachable --tags`.
|
||||
|
||||
### Cron - Repository Statistics Check (`cron.check_repo_stats`)
|
||||
|
||||
- `RUN_AT_START`: Enable this to run repository statistics check at start time.
|
||||
- `SCHEDULE`: Cron syntax for scheduling repository statistics check, e.g. `@every 24h`.
|
||||
- `RUN_AT_START`: **true**: Run repository statistics check at start time.
|
||||
- `SCHEDULE`: **@every 24h**: Cron syntax for scheduling repository statistics check.
|
||||
|
||||
## Git (`git`)
|
||||
|
||||
- `MAX_GIT_DIFF_LINES`: Max number of lines allowed of a single file in diff view.
|
||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: Max number of characters of a line allowed in diff view.
|
||||
- `MAX_GIT_DIFF_FILES`: Max number of files shown in diff view.
|
||||
- `GC_ARGS`: Arguments for command `git gc`, e.g. `--aggressive --auto`.
|
||||
- `MAX_GIT_DIFF_LINES`: **100**: Max number of lines allowed of a single file in diff view.
|
||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
||||
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`.
|
||||
|
||||
## markup (`markup`)
|
||||
|
||||
Gitea supports external markup support, you can integrate all your favorite tool. For example,
|
||||
below will add a markup named `asciidoc` which is followed `markup.` ini section. And there are some config items below.
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = false
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
- ENABLED: Whether enable this tool. default is false.
|
||||
- FILE_EXTENSIONS: List of file extensions that should be rendered by an external command. Multiple extentions needs a comma as splitter.
|
||||
- RENDER_COMMAND: External command to render all matching extensions.
|
||||
- IS_INPUT_FILE: Input is not a standard input but a file param followed `RENDER_COMMAND`, default is false.
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: Enable this to show Gitea branding in the footer.
|
||||
- `SHOW_FOOTER_VERSION`: Enable this to show Gitea version information in the footer.
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: Enable this to show time of template execution in the footer.
|
||||
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
|
||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea version information in the footer.
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
||||
|
|
|
|||
|
|
@ -186,6 +186,25 @@ menu:
|
|||
- `MAX_GIT_DIFF_FILES`: 比较视图中的最大现实文件数目。
|
||||
- `GC_ARGS`: 执行 `git gc` 命令的参数, 比如: `--aggressive --auto`。
|
||||
|
||||
## markup (`markup`)
|
||||
|
||||
外部渲染工具支持,你可以用你熟悉的文档渲染工具. 比如一下将新增一个名字为 `asciidoc` 的渲染工具which is followed `markup.` ini section. And there are some config items below.
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = false
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
- ENABLED: 是否启用,默认为false。
|
||||
- FILE_EXTENSIONS: 关联的文档的扩展名,多个扩展名用都好分隔。
|
||||
- RENDER_COMMAND: 工具的命令行命令及参数。
|
||||
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。
|
||||
|
||||
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
|
||||
|
|
|
|||
|
|
@ -39,8 +39,6 @@ func testPullCreate(t *testing.T, session *TestSession, user, repo, branch strin
|
|||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
//TODO check the redirected URL
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
|
|
@ -49,5 +47,16 @@ func TestPullCreate(t *testing.T) {
|
|||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
testPullCreate(t, session, "user1", "repo1", "master")
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
|
||||
// check the redirected URL
|
||||
url := resp.HeaderMap.Get("Location")
|
||||
assert.Regexp(t, "^/user2/repo1/pulls/[0-9]*$", url)
|
||||
|
||||
// check .diff can be accessed and matches performed change
|
||||
req := NewRequest(t, "GET", url+".diff")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Regexp(t, "\\+Hello, World \\(Edited\\)", resp.Body)
|
||||
assert.Regexp(t, "^diff", resp.Body)
|
||||
assert.NotRegexp(t, "diff.*diff", resp.Body) // not two diffs, just one
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,21 +11,23 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum string) *httptest.ResponseRecorder {
|
||||
func testPullMerge(t *testing.T, session *TestSession, user, repo, pullnum string, mergeStyle models.MergeStyle) *httptest.ResponseRecorder {
|
||||
req := NewRequest(t, "GET", path.Join(user, repo, "pulls", pullnum))
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Click the little green button to create a pull
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
link, exists := htmlDoc.doc.Find("form.ui.form>button.ui.green.button").Parent().Attr("action")
|
||||
link, exists := htmlDoc.doc.Find(".ui.form." + string(mergeStyle) + "-fields > form").Attr("action")
|
||||
assert.True(t, exists, "The template has changed")
|
||||
req = NewRequestWithValues(t, "POST", link, map[string]string{
|
||||
"_csrf": htmlDoc.GetCSRF(),
|
||||
"do": string(mergeStyle),
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
|
|
@ -58,7 +60,34 @@ func TestPullMerge(t *testing.T) {
|
|||
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
|
||||
}
|
||||
|
||||
func TestPullRebase(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleRebase)
|
||||
}
|
||||
|
||||
func TestPullSquash(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
session := loginUser(t, "user1")
|
||||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited!)\n")
|
||||
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleSquash)
|
||||
}
|
||||
|
||||
func TestPullCleanUpAfterMerge(t *testing.T) {
|
||||
|
|
@ -71,7 +100,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
|
|||
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
|
||||
|
||||
// Check PR branch deletion
|
||||
resp = testPullCleanUp(t, session, elem[1], elem[2], elem[4])
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -24,7 +25,7 @@ func TestRepoActivity(t *testing.T) {
|
|||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4], models.MergeStyleMerge)
|
||||
|
||||
testEditFileToNewBranch(t, session, "user1", "repo1", "master", "feat/better_readme", "README.md", "Hello, World (Edited Again)\n")
|
||||
testPullCreate(t, session, "user1", "repo1", "feat/better_readme")
|
||||
|
|
|
|||
|
|
@ -878,6 +878,23 @@ func (err ErrPullRequestAlreadyExists) Error() string {
|
|||
err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
|
||||
}
|
||||
|
||||
// ErrInvalidMergeStyle represents an error if merging with disabled merge strategy
|
||||
type ErrInvalidMergeStyle struct {
|
||||
ID int64
|
||||
Style MergeStyle
|
||||
}
|
||||
|
||||
// IsErrInvalidMergeStyle checks if an error is a ErrInvalidMergeStyle.
|
||||
func IsErrInvalidMergeStyle(err error) bool {
|
||||
_, ok := err.(ErrInvalidMergeStyle)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrInvalidMergeStyle) Error() string {
|
||||
return fmt.Sprintf("merge strategy is not allowed or is invalid [repo_id: %d, strategy: %s]",
|
||||
err.ID, err.Style)
|
||||
}
|
||||
|
||||
// _________ __
|
||||
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
||||
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
id: 5
|
||||
repo_id: 1
|
||||
type: 3
|
||||
config: "{}"
|
||||
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowSquash\":true}"
|
||||
created_unix: 946684810
|
||||
|
||||
-
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
id: 8
|
||||
repo_id: 3
|
||||
type: 3
|
||||
config: "{}"
|
||||
config: "{\"IgnoreWhitespaceConflicts\":true,\"AllowMerge\":true,\"AllowRebase\":false,\"AllowSquash\":false}"
|
||||
created_unix: 946684810
|
||||
|
||||
-
|
||||
|
|
|
|||
|
|
@ -160,6 +160,8 @@ var migrations = []Migration{
|
|||
NewMigration("add lfs lock table", addLFSLock),
|
||||
// v53 -> v54
|
||||
NewMigration("add reactions", addReactions),
|
||||
// v54 -> v55
|
||||
NewMigration("add pull request options", addPullRequestOptions),
|
||||
// v51 -> v52
|
||||
NewMigration("add issue_dependencies", addIssueDependencies),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,56 +5,53 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
func addIssueDependencies(x *xorm.Engine) (err error) {
|
||||
|
||||
type IssueDependency struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL"`
|
||||
IssueID int64 `xorm:"NOT NULL"`
|
||||
DependencyID int64 `xorm:"NOT NULL"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
}
|
||||
|
||||
if err = x.Sync(new(IssueDependency)); err != nil {
|
||||
return fmt.Errorf("Error creating issue_dependency_table column definition: %v", err)
|
||||
}
|
||||
|
||||
func addPullRequestOptions(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"`
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//Updating existing issue units
|
||||
units := make([]*RepoUnit, 0, 100)
|
||||
err = x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
|
||||
if err != nil {
|
||||
if err := sess.Where("`type` = ?", V16UnitTypePRs).Find(&units); err != nil {
|
||||
return fmt.Errorf("Query repo units: %v", err)
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
}
|
||||
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
||||
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
||||
if _, ok := unit.Config["IgnoreWhitespaceConflicts"]; !ok {
|
||||
unit.Config["IgnoreWhitespaceConflicts"] = false
|
||||
}
|
||||
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
if _, ok := unit.Config["AllowMerge"]; !ok {
|
||||
unit.Config["AllowMerge"] = true
|
||||
}
|
||||
if _, ok := unit.Config["AllowRebase"]; !ok {
|
||||
unit.Config["AllowRebase"] = true
|
||||
}
|
||||
if _, ok := unit.Config["AllowSquash"]; !ok {
|
||||
unit.Config["AllowSquash"] = true
|
||||
}
|
||||
if _, err := sess.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
|
|||
1
models/migrations/v55.go
Normal file
1
models/migrations/v55.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package migrations
|
||||
138
models/pull.go
138
models/pull.go
|
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
|
@ -109,6 +110,28 @@ func (pr *PullRequest) loadIssue(e Engine) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// GetDefaultMergeMessage returns default message used when merging pull request
|
||||
func (pr *PullRequest) GetDefaultMergeMessage() string {
|
||||
if pr.HeadRepo == nil {
|
||||
var err error
|
||||
pr.HeadRepo, err = GetRepositoryByID(pr.HeadRepoID)
|
||||
if err != nil {
|
||||
log.Error(4, "GetRepositoryById[%d]: %v", pr.HeadRepoID, err)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.HeadUserName, pr.HeadRepo.Name, pr.BaseBranch)
|
||||
}
|
||||
|
||||
// GetDefaultSquashMessage returns default message used when squash and merging pull request
|
||||
func (pr *PullRequest) GetDefaultSquashMessage() string {
|
||||
if err := pr.LoadIssue(); err != nil {
|
||||
log.Error(4, "LoadIssue: %v", err)
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%s (#%d)", pr.Issue.Title, pr.Issue.Index)
|
||||
}
|
||||
|
||||
// APIFormat assumes following fields have been assigned with valid values:
|
||||
// Required - Issue
|
||||
// Optional - Merger
|
||||
|
|
@ -232,15 +255,38 @@ func (pr *PullRequest) CanAutoMerge() bool {
|
|||
return pr.Status == PullRequestStatusMergeable
|
||||
}
|
||||
|
||||
// MergeStyle represents the approach to merge commits into base branch.
|
||||
type MergeStyle string
|
||||
|
||||
const (
|
||||
// MergeStyleMerge create merge commit
|
||||
MergeStyleMerge MergeStyle = "merge"
|
||||
// MergeStyleRebase rebase before merging
|
||||
MergeStyleRebase MergeStyle = "rebase"
|
||||
// MergeStyleSquash squash commits into single commit before merging
|
||||
MergeStyleSquash MergeStyle = "squash"
|
||||
)
|
||||
|
||||
// Merge merges pull request to base repository.
|
||||
// FIXME: add repoWorkingPull make sure two merges does not happen at same time.
|
||||
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
|
||||
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle MergeStyle, message string) (err error) {
|
||||
if err = pr.GetHeadRepo(); err != nil {
|
||||
return fmt.Errorf("GetHeadRepo: %v", err)
|
||||
} else if err = pr.GetBaseRepo(); err != nil {
|
||||
return fmt.Errorf("GetBaseRepo: %v", err)
|
||||
}
|
||||
|
||||
prUnit, err := pr.BaseRepo.GetUnit(UnitTypePullRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prConfig := prUnit.PullRequestsConfig()
|
||||
|
||||
// Check if merge style is correct and allowed
|
||||
if !prConfig.IsMergeStyleAllowed(mergeStyle) {
|
||||
return ErrInvalidMergeStyle{pr.BaseRepo.ID, mergeStyle}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
go HookQueue.Add(pr.BaseRepo.ID)
|
||||
go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
|
||||
|
|
@ -289,18 +335,62 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
|||
return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
|
||||
}
|
||||
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git merge --no-ff --no-commit): %s", tmpBasePath),
|
||||
"git", "merge", "--no-ff", "--no-commit", "head_repo/"+pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("git merge --no-ff --no-commit [%s]: %v - %s", tmpBasePath, err, stderr)
|
||||
}
|
||||
switch mergeStyle {
|
||||
case MergeStyleMerge:
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git merge --no-ff --no-commit): %s", tmpBasePath),
|
||||
"git", "merge", "--no-ff", "--no-commit", "head_repo/"+pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("git merge --no-ff --no-commit [%s]: %v - %s", tmpBasePath, err, stderr)
|
||||
}
|
||||
|
||||
sig := doer.NewGitSig()
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git merge): %s", tmpBasePath),
|
||||
"git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
|
||||
"-m", fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.HeadUserName, pr.HeadRepo.Name, pr.BaseBranch)); err != nil {
|
||||
return fmt.Errorf("git commit [%s]: %v - %s", tmpBasePath, err, stderr)
|
||||
sig := doer.NewGitSig()
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git merge): %s", tmpBasePath),
|
||||
"git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
|
||||
"-m", message); err != nil {
|
||||
return fmt.Errorf("git commit [%s]: %v - %s", tmpBasePath, err, stderr)
|
||||
}
|
||||
case MergeStyleRebase:
|
||||
// Checkout head branch
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
|
||||
"git", "checkout", "-b", "head_repo_"+pr.HeadBranch, "head_repo/"+pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("git checkout: %s", stderr)
|
||||
}
|
||||
// Rebase before merging
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath),
|
||||
"git", "rebase", "-q", pr.BaseBranch); err != nil {
|
||||
return fmt.Errorf("git rebase [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
|
||||
}
|
||||
// Checkout base branch again
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
|
||||
"git", "checkout", pr.BaseBranch); err != nil {
|
||||
return fmt.Errorf("git checkout: %s", stderr)
|
||||
}
|
||||
// Merge fast forward
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git rebase): %s", tmpBasePath),
|
||||
"git", "merge", "--ff-only", "-q", "head_repo_"+pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("git merge --ff-only [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
|
||||
}
|
||||
case MergeStyleSquash:
|
||||
// Merge with squash
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git squash): %s", tmpBasePath),
|
||||
"git", "merge", "-q", "--squash", "head_repo/"+pr.HeadBranch); err != nil {
|
||||
return fmt.Errorf("git merge --squash [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
|
||||
}
|
||||
sig := pr.Issue.Poster.NewGitSig()
|
||||
if _, stderr, err = process.GetManager().ExecDir(-1, tmpBasePath,
|
||||
fmt.Sprintf("PullRequest.Merge (git squash): %s", tmpBasePath),
|
||||
"git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
|
||||
"-m", message); err != nil {
|
||||
return fmt.Errorf("git commit [%s]: %v - %s", tmpBasePath, err, stderr)
|
||||
}
|
||||
default:
|
||||
return ErrInvalidMergeStyle{pr.BaseRepo.ID, mergeStyle}
|
||||
}
|
||||
|
||||
// Push back to upstream.
|
||||
|
|
@ -327,6 +417,9 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
|||
log.Error(4, "MergePullRequestAction [%d]: %v", pr.ID, err)
|
||||
}
|
||||
|
||||
// Reset cached commit count
|
||||
cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true))
|
||||
|
||||
// Reload pull request information.
|
||||
if err = pr.LoadAttributes(); err != nil {
|
||||
log.Error(4, "LoadAttributes: %v", err)
|
||||
|
|
@ -349,7 +442,6 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
|||
return nil
|
||||
}
|
||||
|
||||
// TODO: when squash commits, no need to append merge commit.
|
||||
// It is possible that head branch is not fully sync with base branch for merge commits,
|
||||
// so we need to get latest head commit and append merge commit manually
|
||||
// to avoid strange diff commits produced.
|
||||
|
|
@ -358,12 +450,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
|||
log.Error(4, "GetBranchCommit: %v", err)
|
||||
return nil
|
||||
}
|
||||
l.PushFront(mergeCommit)
|
||||
if mergeStyle == MergeStyleMerge {
|
||||
l.PushFront(mergeCommit)
|
||||
}
|
||||
|
||||
p := &api.PushPayload{
|
||||
Ref: git.BranchPrefix + pr.BaseBranch,
|
||||
Before: pr.MergeBase,
|
||||
After: pr.MergedCommitID,
|
||||
After: mergeCommit.ID.String(),
|
||||
CompareURL: setting.AppURL + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
||||
Commits: ListToPushCommits(l).ToAPIPayloadCommits(pr.BaseRepo.HTMLURL()),
|
||||
Repo: pr.BaseRepo.APIFormat(AccessModeNone),
|
||||
|
|
@ -563,9 +657,21 @@ func (pr *PullRequest) testPatch() (err error) {
|
|||
return fmt.Errorf("git read-tree --index-output=%s %s: %v - %s", indexTmpPath, pr.BaseBranch, err, stderr)
|
||||
}
|
||||
|
||||
prUnit, err := pr.BaseRepo.GetUnit(UnitTypePullRequests)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prConfig := prUnit.PullRequestsConfig()
|
||||
|
||||
args := []string{"apply", "--check", "--cached"}
|
||||
if prConfig.IgnoreWhitespaceConflicts {
|
||||
args = append(args, "--ignore-whitespace")
|
||||
}
|
||||
args = append(args, patchPath)
|
||||
|
||||
_, stderr, err = process.GetManager().ExecDirEnv(-1, "", fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
|
||||
[]string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()},
|
||||
"git", "apply", "--check", "--cached", patchPath)
|
||||
"git", args...)
|
||||
if err != nil {
|
||||
for i := range patchConflicts {
|
||||
if strings.Contains(stderr, patchConflicts[i]) {
|
||||
|
|
|
|||
|
|
@ -427,6 +427,11 @@ func (repo *Repository) MustGetUnit(tp UnitType) *RepoUnit {
|
|||
Type: tp,
|
||||
Config: new(ExternalTrackerConfig),
|
||||
}
|
||||
} else if tp == UnitTypePullRequests {
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
Config: new(PullRequestsConfig),
|
||||
}
|
||||
}
|
||||
return &RepoUnit{
|
||||
Type: tp,
|
||||
|
|
@ -570,7 +575,9 @@ func (repo *Repository) GetMirror() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// GetBaseRepo returns the base repository
|
||||
// GetBaseRepo populates repo.BaseRepo for a fork repository and
|
||||
// returns an error on failure (NOTE: no error is returned for
|
||||
// non-fork repositories, and BaseRepo will be left untouched)
|
||||
func (repo *Repository) GetBaseRepo() (err error) {
|
||||
if !repo.IsFork {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -86,18 +86,44 @@ func (cfg *IssuesConfig) ToDB() ([]byte, error) {
|
|||
return json.Marshal(cfg)
|
||||
}
|
||||
|
||||
// PullRequestsConfig describes pull requests config
|
||||
type PullRequestsConfig struct {
|
||||
IgnoreWhitespaceConflicts bool
|
||||
AllowMerge bool
|
||||
AllowRebase bool
|
||||
AllowSquash bool
|
||||
}
|
||||
|
||||
// FromDB fills up a PullRequestsConfig from serialized format.
|
||||
func (cfg *PullRequestsConfig) FromDB(bs []byte) error {
|
||||
return json.Unmarshal(bs, &cfg)
|
||||
}
|
||||
|
||||
// ToDB exports a PullRequestsConfig to a serialized format.
|
||||
func (cfg *PullRequestsConfig) ToDB() ([]byte, error) {
|
||||
return json.Marshal(cfg)
|
||||
}
|
||||
|
||||
// IsMergeStyleAllowed returns if merge style is allowed
|
||||
func (cfg *PullRequestsConfig) IsMergeStyleAllowed(mergeStyle MergeStyle) bool {
|
||||
return mergeStyle == MergeStyleMerge && cfg.AllowMerge ||
|
||||
mergeStyle == MergeStyleRebase && cfg.AllowRebase ||
|
||||
mergeStyle == MergeStyleSquash && cfg.AllowSquash
|
||||
}
|
||||
|
||||
// BeforeSet is invoked from XORM before setting the value of a field of this object.
|
||||
func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
|
||||
switch colName {
|
||||
case "type":
|
||||
switch UnitType(Cell2Int64(val)) {
|
||||
case UnitTypeCode, UnitTypePullRequests, UnitTypeReleases,
|
||||
UnitTypeWiki:
|
||||
case UnitTypeCode, UnitTypeReleases, UnitTypeWiki:
|
||||
r.Config = new(UnitConfig)
|
||||
case UnitTypeExternalWiki:
|
||||
r.Config = new(ExternalWikiConfig)
|
||||
case UnitTypeExternalTracker:
|
||||
r.Config = new(ExternalTrackerConfig)
|
||||
case UnitTypePullRequests:
|
||||
r.Config = new(PullRequestsConfig)
|
||||
case UnitTypeIssues:
|
||||
r.Config = new(IssuesConfig)
|
||||
default:
|
||||
|
|
@ -117,8 +143,8 @@ func (r *RepoUnit) CodeConfig() *UnitConfig {
|
|||
}
|
||||
|
||||
// PullRequestsConfig returns config for UnitTypePullRequests
|
||||
func (r *RepoUnit) PullRequestsConfig() *UnitConfig {
|
||||
return r.Config.(*UnitConfig)
|
||||
func (r *RepoUnit) PullRequestsConfig() *PullRequestsConfig {
|
||||
return r.Config.(*PullRequestsConfig)
|
||||
}
|
||||
|
||||
// ReleasesConfig returns config for UnitTypeReleases
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ type RepoSettingForm struct {
|
|||
TrackerURLFormat string
|
||||
TrackerIssueStyle string
|
||||
EnablePulls bool
|
||||
PullsIgnoreWhitespace bool
|
||||
PullsAllowMerge bool
|
||||
PullsAllowRebase bool
|
||||
PullsAllowSquash bool
|
||||
EnableTimetracker bool
|
||||
AllowOnlyContributorsToTrackTime bool
|
||||
EnableIssueDependencies bool
|
||||
|
|
@ -327,6 +331,25 @@ func (f *InitializeLabelsForm) Validate(ctx *macaron.Context, errs binding.Error
|
|||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__ .__ __________ __
|
||||
// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
|
||||
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
|
||||
// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
|
||||
// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
|
||||
// \/ \/ |__| \/ \/
|
||||
|
||||
// MergePullRequestForm form for merging Pull Request
|
||||
type MergePullRequestForm struct {
|
||||
Do string `binding:"Required;In(merge,rebase,squash)"`
|
||||
MergeTitleField string
|
||||
MergeMessageField string
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
func (f *MergePullRequestForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \ ____ | | ____ _____ ______ ____
|
||||
// | _// __ \| | _/ __ \\__ \ / ___// __ \
|
||||
|
|
|
|||
|
|
@ -1310,6 +1310,7 @@ auths.attribute_mail=E-Mail-Attribut
|
|||
auths.attributes_in_bind=Hole Attribute im Bind-Kontext
|
||||
auths.filter=Benutzerfilter
|
||||
auths.admin_filter=Admin Filter
|
||||
auths.ms_ad_sa=MS AD Suchattribute
|
||||
auths.smtp_auth=SMTP-Authentifizierungstyp
|
||||
auths.smtphost=SMTP-Host
|
||||
auths.smtpport=SMTP-Port
|
||||
|
|
|
|||
|
|
@ -779,7 +779,12 @@ pulls.is_checking = "The conflict checking is still in progress; please refresh
|
|||
pulls.can_auto_merge_desc = This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc = This pull request cannot be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper = Please merge manually in order to resolve the conflicts.
|
||||
pulls.no_merge_desc = This pull request can not be merged as no merge options are enabled.
|
||||
pulls.no_merge_helper = To merge this pull request enable at least one merge option in repository settings or merge pull request manually.
|
||||
pulls.merge_pull_request = Merge Pull Request
|
||||
pulls.rebase_merge_pull_request = Rebase and Merge
|
||||
pulls.squash_merge_pull_request = Squash and Merge
|
||||
pulls.invalid_merge_option = You can not use this merge option for this pull request
|
||||
pulls.open_unmerged_pull_exists = `You cannot perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
|
||||
milestones.new = New Milestone
|
||||
|
|
@ -918,6 +923,10 @@ settings.tracker_url_format_desc = You can use placeholder <code>{user} {repo} {
|
|||
settings.enable_timetracker = Enable time tracker
|
||||
settings.allow_only_contributors_to_track_time = Allow only contributors to track time
|
||||
settings.pulls_desc = Enable pull requests to accept public contributions
|
||||
settings.pulls.ignore_whitespace = Ignore changes in whitespace when checking conflicts
|
||||
settings.pulls.allow_merge_commits = Allow merge commits
|
||||
settings.pulls.allow_rebase_merge = Allow rebase to merge commits
|
||||
settings.pulls.allow_squash_commits = Allow to squash commits before merging
|
||||
settings.danger_zone = Danger Zone
|
||||
settings.new_owner_has_same_repo = The new owner already has a repository with same name. Please choose another name.
|
||||
settings.convert = Convert To Regular Repository
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ your_settings=Beállításaid
|
|||
|
||||
all=Összes
|
||||
sources=Saját
|
||||
mirrors=Tükrök
|
||||
mirrors=Tükör
|
||||
collaborative=Közreműködő
|
||||
forks=Másolatok
|
||||
forks=Másolat
|
||||
|
||||
activities=Tevékenységek
|
||||
pull_requests=Egyesítési Kérések
|
||||
|
|
@ -755,7 +755,12 @@ pulls.is_checking=Az ütközési ellenőrzés még folyamatban van; kérjük fri
|
|||
pulls.can_auto_merge_desc=Ez az egyesítési kérés automatikusan végrehajtható.
|
||||
pulls.cannot_auto_merge_desc=Ez az egyesítési kérés ütközések miatt nem hajtható végre automatikusan.
|
||||
pulls.cannot_auto_merge_helper=Kérjük, egyesítse kézileg az ütközések megoldásához.
|
||||
pulls.no_merge_desc=Ez az egyesítési kérés nem hajtható végre, mert egyik mód sincs engedélyezve.
|
||||
pulls.no_merge_helper=Az egyesítési kérés végrehajtásához engedélyezzen legalább egy módot a tároló beállításinál.
|
||||
pulls.merge_pull_request=Egyesítési kérés végrehajtása
|
||||
pulls.rebase_merge_pull_request=Rebase és egyesítés
|
||||
pulls.squash_merge_pull_request=Squash és egyesítés
|
||||
pulls.invalid_merge_option=Nem használhatja ezt a módot ehhez az egyesítési kéréshez
|
||||
pulls.open_unmerged_pull_exists=`Nem tudja újranyitni, mert már van egy nyitott egyesítési kérés (#%d) ugyanebben a tárolóban, ugyanezekket az egyesítési információkkal, és végrehajtásra vár.`
|
||||
|
||||
milestones.new=Új mérföldkő
|
||||
|
|
@ -894,6 +899,10 @@ settings.tracker_url_format_desc=Használhat behelyettesítéseket: <code>{user}
|
|||
settings.enable_timetracker=Időzítő engedélyezése
|
||||
settings.allow_only_contributors_to_track_time=Csak együttműködőknek elérhető az időzítő
|
||||
settings.pulls_desc=Nyilvános hozzájárulások engedélyezése egyesítési kérések esetén
|
||||
settings.pulls.ignore_whitespace=A whitespace-ek figyelmen kívül hagyása az ütközések ellenőrzésénél
|
||||
settings.pulls.allow_merge_commits=Egyesítési commit engedélyezése
|
||||
settings.pulls.allow_rebase_merge=Rebase engedélyezése egyesítésnél
|
||||
settings.pulls.allow_squash_commits=Squash engedélyezése egyesítés előtt
|
||||
settings.danger_zone=Veszélyes terület
|
||||
settings.new_owner_has_same_repo=Az új tulajdonos már rendelkezik ilyen nevű tárolóval. Kérjük válasszon egy másik nevet.
|
||||
settings.convert=Hagyományos tárolóvá alakítás
|
||||
|
|
|
|||
|
|
@ -755,7 +755,12 @@ pulls.is_checking=Notiek konfliktu pārbaude, mirkli uzgaidiet un atjaunojiet la
|
|||
pulls.can_auto_merge_desc=Šo izmaiņu pieprasījumu var automātiski sapludināt.
|
||||
pulls.cannot_auto_merge_desc=Šis izmaiņu pieprasījums nevar tikt automātiski sapludināts konfliktu dēļ.
|
||||
pulls.cannot_auto_merge_helper=Lūdzu sapludiniet manuāli, lai atrisinātu konfliktus.
|
||||
pulls.no_merge_desc=Šo izmaiņu pieprasījumu nav iespējams sapludināt, jo nav pieejams neviens sapludināšanas veids.
|
||||
pulls.no_merge_helper=Lai sapludinātu šo izmaiņu pieprasījumu, iespējojiet vismaz vienu sapludināšanas veidu repozitorija iestatījumos vai sapludiniet to manuāli.
|
||||
pulls.merge_pull_request=Izmaiņu pieprasījuma sapludināšana
|
||||
pulls.rebase_merge_pull_request=Pārbāzēt un sapludināt
|
||||
pulls.squash_merge_pull_request=Saspiest un sapludināt
|
||||
pulls.invalid_merge_option=Nav iespējams izmantot šādu sapludināšanas veidu šim izmaiņu pieprasījumam
|
||||
pulls.open_unmerged_pull_exists=`Jūs nevarat veikt atkārtotas atvēršanas darbību, jo jau eksistē izmaiņu pieprasījums (#%d) no šī repozitorija ar tādu pašu sapludināšanas informāciju un gaida sapludināšanu.`
|
||||
|
||||
milestones.new=Jauns atskaites punkts
|
||||
|
|
@ -894,6 +899,10 @@ settings.tracker_url_format_desc=Jūs varat izmantot <code>{user}{repo}{index}</
|
|||
settings.enable_timetracker=Iespējot laika uzskaiti
|
||||
settings.allow_only_contributors_to_track_time=Atļaut tikai dalībniekiem uzskaitīt laiku
|
||||
settings.pulls_desc=Iespējot izmaiņu pieprasījumus lai saņemtu publiskus ieguldījumus
|
||||
settings.pulls.ignore_whitespace=Pārbaudot konfliktus, ignorēt izmaiņas atstarpēs
|
||||
settings.pulls.allow_merge_commits=Atļaut sapludināt revīzijas
|
||||
settings.pulls.allow_rebase_merge=Atļaut pārbāzēt un sapludināt revīzijas
|
||||
settings.pulls.allow_squash_commits=Atļaut saspiest revīzijas pirms sapludināšanas
|
||||
settings.danger_zone=Bīstamā zona
|
||||
settings.new_owner_has_same_repo=Jaunajam īpašniekam jau ir repozitorijs ar šādu nosaukumu.
|
||||
settings.convert=Konvertēt uz parastu repozitoriju
|
||||
|
|
@ -1310,6 +1319,7 @@ auths.attribute_mail=E-pasta atribūts
|
|||
auths.attributes_in_bind=Nolasīt atribūtus no saistīšanas DN konteksta
|
||||
auths.filter=Lietotāju filts
|
||||
auths.admin_filter=Administratoru filtrs
|
||||
auths.ms_ad_sa=MS AD meklēšanas atribūti
|
||||
auths.smtp_auth=SMTP autentifikācijas tips
|
||||
auths.smtphost=SMTP resursdators
|
||||
auths.smtpport=SMTP ports
|
||||
|
|
|
|||
|
|
@ -755,7 +755,12 @@ pulls.is_checking=Продолжается проверка конфликтов
|
|||
pulls.can_auto_merge_desc=Этот Pull Request может быть объединён автоматически.
|
||||
pulls.cannot_auto_merge_desc=Этот Pull Request не может быть объединён автоматически.
|
||||
pulls.cannot_auto_merge_helper=Пожалуйста, совершите слияние вручную для урегулирования конфликтов.
|
||||
pulls.no_merge_desc=Pull Request не может быть принят, так как запрещены все методы организации рабочего потока.
|
||||
pulls.no_merge_helper=Для принятия этого Pull Request'а необходимо включить хотя бы один способ слияния сторонних изменений или выполнить слияние вручную.
|
||||
pulls.merge_pull_request=Принять Pull Request
|
||||
pulls.rebase_merge_pull_request=Выполнить rebase и принять PR
|
||||
pulls.squash_merge_pull_request=Объединить и принять PR
|
||||
pulls.invalid_merge_option=Невозможно использовать данный способ слияния изменений автоматически
|
||||
pulls.open_unmerged_pull_exists=`Вы не можете снова открыть, поскольку уже существует Pull Request (#%d) из того же репозитория с той же информацией о слиянии и ожидающий подтверждения. `
|
||||
|
||||
milestones.new=Новый этап
|
||||
|
|
@ -894,6 +899,10 @@ settings.tracker_url_format_desc=Вы можете использовать ша
|
|||
settings.enable_timetracker=Включить отслеживание времени
|
||||
settings.allow_only_contributors_to_track_time=Учитывать только участников разработки в подсчёте времени
|
||||
settings.pulls_desc=Система Pull Request'ов создана для упрощения совместной работы над репозиторием
|
||||
settings.pulls.ignore_whitespace=Игнорировать незначащие изменения (пробелы, табуляция) при проверке на конфликты слияния
|
||||
settings.pulls.allow_merge_commits=Разрешить коммиты слияния
|
||||
settings.pulls.allow_rebase_merge=Разрешить rebase-слияние
|
||||
settings.pulls.allow_squash_commits=Разрешить объединять коммиты перед слиянием
|
||||
settings.danger_zone=Опасная зона
|
||||
settings.new_owner_has_same_repo=У нового владельца уже есть хранилище с таким названием.
|
||||
settings.convert=Преобразовать в обычный репозиторий
|
||||
|
|
|
|||
|
|
@ -649,6 +649,28 @@ function initRepository() {
|
|||
$('#status').val($statusButton.data('status-val'));
|
||||
$('#comment-form').submit();
|
||||
});
|
||||
|
||||
// Pull Request merge button
|
||||
var $mergeButton = $('.merge-button > button');
|
||||
$mergeButton.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('.' + $(this).data('do') + '-fields').show();
|
||||
$(this).parent().hide();
|
||||
});
|
||||
$('.merge-button > .dropdown').dropdown({
|
||||
onChange: function (text, value, $choice) {
|
||||
if ($choice.data('do')) {
|
||||
$mergeButton.find('.button-text').text($choice.text());
|
||||
$mergeButton.data('do', $choice.data('do'));
|
||||
}
|
||||
}
|
||||
});
|
||||
$('.merge-cancel').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.form').hide();
|
||||
$mergeButton.parent().show();
|
||||
});
|
||||
|
||||
initReactionSelector();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,7 +477,7 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
m.Combo("").Get(repo.GetPullRequest).
|
||||
Patch(reqToken(), reqRepoWriter(), bind(api.EditPullRequestOption{}), repo.EditPullRequest)
|
||||
m.Combo("/merge").Get(repo.IsPullRequestMerged).
|
||||
Post(reqToken(), reqRepoWriter(), repo.MergePullRequest)
|
||||
Post(reqToken(), reqRepoWriter(), bind(auth.MergePullRequestForm{}), repo.MergePullRequest)
|
||||
})
|
||||
|
||||
}, mustAllowPulls, context.ReferencesGitRepo())
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
|
|
@ -434,7 +435,7 @@ func IsPullRequestMerged(ctx *context.APIContext) {
|
|||
}
|
||||
|
||||
// MergePullRequest merges a PR given an index
|
||||
func MergePullRequest(ctx *context.APIContext) {
|
||||
func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) {
|
||||
// swagger:operation POST /repos/{owner}/{repo}/pulls/{index}/merge repository repoMergePullRequest
|
||||
// ---
|
||||
// summary: Merge a pull request
|
||||
|
|
@ -497,7 +498,30 @@ func MergePullRequest(ctx *context.APIContext) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := pr.Merge(ctx.User, ctx.Repo.GitRepo); err != nil {
|
||||
if len(form.Do) == 0 {
|
||||
form.Do = string(models.MergeStyleMerge)
|
||||
}
|
||||
|
||||
message := strings.TrimSpace(form.MergeTitleField)
|
||||
if len(message) == 0 {
|
||||
if models.MergeStyle(form.Do) == models.MergeStyleMerge {
|
||||
message = pr.GetDefaultMergeMessage()
|
||||
}
|
||||
if models.MergeStyle(form.Do) == models.MergeStyleSquash {
|
||||
message = pr.GetDefaultSquashMessage()
|
||||
}
|
||||
}
|
||||
|
||||
form.MergeMessageField = strings.TrimSpace(form.MergeMessageField)
|
||||
if len(form.MergeMessageField) > 0 {
|
||||
message += "\n\n" + form.MergeMessageField
|
||||
}
|
||||
|
||||
if err := pr.Merge(ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil {
|
||||
if models.IsErrInvalidMergeStyle(err) {
|
||||
ctx.Status(405)
|
||||
return
|
||||
}
|
||||
ctx.Error(500, "Merge", err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -736,6 +736,26 @@ func ViewIssue(ctx *context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
prUnit, err := repo.GetUnit(models.UnitTypePullRequests)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetUnit", err)
|
||||
return
|
||||
}
|
||||
prConfig := prUnit.PullRequestsConfig()
|
||||
|
||||
// Check correct values and select default
|
||||
if ms, ok := ctx.Data["MergeStyle"].(models.MergeStyle); !ok ||
|
||||
!prConfig.IsMergeStyleAllowed(ms) {
|
||||
if prConfig.AllowMerge {
|
||||
ctx.Data["MergeStyle"] = models.MergeStyleMerge
|
||||
} else if prConfig.AllowRebase {
|
||||
ctx.Data["MergeStyle"] = models.MergeStyleRebase
|
||||
} else if prConfig.AllowSquash {
|
||||
ctx.Data["MergeStyle"] = models.MergeStyleSquash
|
||||
} else {
|
||||
ctx.Data["MergeStyle"] = ""
|
||||
}
|
||||
}
|
||||
ctx.Data["IsPullBranchDeletable"] = canDelete && pull.HeadRepo != nil && git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2018 The Gitea Authors.
|
||||
// Copyright 2014 The Gogs Authors.
|
||||
// All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
|
|
@ -493,7 +495,7 @@ func ViewPullFiles(ctx *context.Context) {
|
|||
}
|
||||
|
||||
// MergePullRequest response for merging pull request
|
||||
func MergePullRequest(ctx *context.Context) {
|
||||
func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) {
|
||||
issue := checkPullInfo(ctx)
|
||||
if ctx.Written() {
|
||||
return
|
||||
|
|
@ -512,12 +514,34 @@ func MergePullRequest(ctx *context.Context) {
|
|||
}
|
||||
return
|
||||
}
|
||||
pr.Issue = issue
|
||||
|
||||
if !pr.CanAutoMerge() || pr.HasMerged {
|
||||
ctx.Handle(404, "MergePullRequest", nil)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.Flash.Error(ctx.Data["ErrorMsg"].(string))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
||||
return
|
||||
}
|
||||
|
||||
message := strings.TrimSpace(form.MergeTitleField)
|
||||
if len(message) == 0 {
|
||||
if models.MergeStyle(form.Do) == models.MergeStyleMerge {
|
||||
message = pr.GetDefaultMergeMessage()
|
||||
}
|
||||
if models.MergeStyle(form.Do) == models.MergeStyleSquash {
|
||||
message = pr.GetDefaultSquashMessage()
|
||||
}
|
||||
}
|
||||
|
||||
form.MergeMessageField = strings.TrimSpace(form.MergeMessageField)
|
||||
if len(form.MergeMessageField) > 0 {
|
||||
message += "\n\n" + form.MergeMessageField
|
||||
}
|
||||
|
||||
pr.Issue = issue
|
||||
pr.Issue.Repo = ctx.Repo.Repository
|
||||
|
||||
|
|
@ -532,7 +556,12 @@ func MergePullRequest(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = pr.Merge(ctx.User, ctx.Repo.GitRepo); err != nil {
|
||||
if err = pr.Merge(ctx.User, ctx.Repo.GitRepo, models.MergeStyle(form.Do), message); err != nil {
|
||||
if models.IsErrInvalidMergeStyle(err) {
|
||||
ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index))
|
||||
return
|
||||
}
|
||||
ctx.Handle(500, "Merge", err)
|
||||
return
|
||||
}
|
||||
|
|
@ -1003,3 +1032,37 @@ func CleanUpPullRequest(ctx *context.Context) {
|
|||
|
||||
ctx.Flash.Success(ctx.Tr("repo.branch.deletion_success", fullBranchName))
|
||||
}
|
||||
|
||||
// DownloadPullDiff render a pull's raw diff
|
||||
func DownloadPullDiff(ctx *context.Context) {
|
||||
issue, err := models.GetIssueByIndex(ctx.Repo.Repository.ID, ctx.ParamsInt64(":index"))
|
||||
if err != nil {
|
||||
if models.IsErrIssueNotExist(err) {
|
||||
ctx.Handle(404, "GetIssueByIndex", err)
|
||||
} else {
|
||||
ctx.Handle(500, "GetIssueByIndex", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Redirect elsewhere if it's not a pull request
|
||||
if !issue.IsPull {
|
||||
ctx.Handle(404, "DownloadPullDiff",
|
||||
fmt.Errorf("Issue is not a pull request"))
|
||||
return
|
||||
}
|
||||
|
||||
pr := issue.PullRequest
|
||||
|
||||
if err = pr.GetBaseRepo(); err != nil {
|
||||
ctx.Handle(500, "GetBaseRepo", err)
|
||||
return
|
||||
}
|
||||
patch, err := pr.BaseRepo.PatchPath(pr.Index)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "PatchPath", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.ServeFileContent(patch)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,7 +212,12 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
|||
units = append(units, models.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: models.UnitTypePullRequests,
|
||||
Config: new(models.UnitConfig),
|
||||
Config: &models.PullRequestsConfig{
|
||||
IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace,
|
||||
AllowMerge: form.PullsAllowMerge,
|
||||
AllowRebase: form.PullsAllowRebase,
|
||||
AllowSquash: form.PullsAllowSquash,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -628,9 +628,10 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
}, repo.MustBeNotBare, context.RepoRef(), context.CheckUnit(models.UnitTypeCode))
|
||||
|
||||
m.Group("/pulls/:index", func() {
|
||||
m.Get(".diff", repo.DownloadPullDiff)
|
||||
m.Get("/commits", context.RepoRef(), repo.ViewPullCommits)
|
||||
m.Get("/files", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ViewPullFiles)
|
||||
m.Post("/merge", reqRepoWriter, repo.MergePullRequest)
|
||||
m.Post("/merge", reqRepoWriter, bindIgnErr(auth.MergePullRequestForm{}), repo.MergePullRequest)
|
||||
m.Post("/cleanup", context.RepoRef(), repo.CleanUpPullRequest)
|
||||
}, repo.MustAllowPulls)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{{with .Repository}}
|
||||
<div class="ui container">
|
||||
<div class="ui stackable grid header-grid">
|
||||
<div class="ten wide column">
|
||||
<div class="eight wide column">
|
||||
<div class="ui huge breadcrumb">
|
||||
<i class="mega-octicon octicon-{{if .IsPrivate}}lock{{else if .IsMirror}}repo-clone{{else if .IsFork}}repo-forked{{else}}repo{{end}}"></i>
|
||||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui six wide right aligned column">
|
||||
<div class="ui eight wide right aligned column">
|
||||
<div class="ui compact labeled button" tabindex="0">
|
||||
<a class="ui compact button" href="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}">
|
||||
<i class="icon fa-eye{{if not $.IsWatchingRepo}}-slash{{end}}"></i>{{if $.IsWatchingRepo}}{{$.i18n.Tr "repo.unwatch"}}{{else}}{{$.i18n.Tr "repo.watch"}}{{end}}
|
||||
|
|
|
|||
|
|
@ -38,15 +38,100 @@
|
|||
{{$.i18n.Tr "repo.pulls.can_auto_merge_desc"}}
|
||||
</div>
|
||||
{{if .IsRepositoryWriter}}
|
||||
<div class="ui divider"></div>
|
||||
<div>
|
||||
<form class="ui form" action="{{.Link}}/merge" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button class="ui green button">
|
||||
<span class="octicon octicon-git-merge"></span> {{$.i18n.Tr "repo.pulls.merge_pull_request"}}
|
||||
{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
|
||||
{{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowSquash}}
|
||||
<div class="ui divider"></div>
|
||||
{{if $prUnit.PullRequestsConfig.AllowMerge}}
|
||||
<div class="ui form merge-fields" style="display: none">
|
||||
<form action="{{.Link}}/merge" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field">
|
||||
<input type="text" name="merge_title_field" value="{{.Issue.PullRequest.GetDefaultMergeMessage}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea name="merge_message_field" rows="5" placeholder="{{$.i18n.Tr "repo.editor.commit_message_desc"}}"></textarea>
|
||||
</div>
|
||||
<button class="ui green button" type="submit" name="do" value="merge">
|
||||
{{$.i18n.Tr "repo.pulls.merge_pull_request"}}
|
||||
</button>
|
||||
<button class="ui button merge-cancel">
|
||||
{{$.i18n.Tr "cancel"}}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if $prUnit.PullRequestsConfig.AllowRebase}}
|
||||
<div class="ui form rebase-fields" style="display: none">
|
||||
<form action="{{.Link}}/merge" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<button class="ui green button" type="submit" name="do" value="rebase">
|
||||
{{$.i18n.Tr "repo.pulls.rebase_merge_pull_request"}}
|
||||
</button>
|
||||
<button class="ui button merge-cancel">
|
||||
{{$.i18n.Tr "cancel"}}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if $prUnit.PullRequestsConfig.AllowSquash}}
|
||||
<div class="ui form squash-fields" style="display: none">
|
||||
<form action="{{.Link}}/merge" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<div class="field">
|
||||
<input type="text" name="merge_title_field" value="{{.Issue.PullRequest.GetDefaultSquashMessage}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea name="merge_message_field" rows="5" placeholder="{{$.i18n.Tr "repo.editor.commit_message_desc"}}"></textarea>
|
||||
</div>
|
||||
<button class="ui green button" type="submit" name="do" value="squash">
|
||||
{{$.i18n.Tr "repo.pulls.squash_merge_pull_request"}}
|
||||
</button>
|
||||
<button class="ui button merge-cancel">
|
||||
{{$.i18n.Tr "cancel"}}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ui green buttons merge-button">
|
||||
<button class="ui button" data-do="{{.MergeStyle}}">
|
||||
<span class="octicon octicon-git-merge"></span>
|
||||
<span class="button-text">
|
||||
{{if eq .MergeStyle "merge"}}
|
||||
{{$.i18n.Tr "repo.pulls.merge_pull_request"}}
|
||||
{{end}}
|
||||
{{if eq .MergeStyle "rebase"}}
|
||||
{{$.i18n.Tr "repo.pulls.rebase_merge_pull_request"}}
|
||||
{{end}}
|
||||
{{if eq .MergeStyle "squash"}}
|
||||
{{$.i18n.Tr "repo.pulls.squash_merge_pull_request"}}
|
||||
{{end}}
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="ui dropdown icon button">
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
{{if $prUnit.PullRequestsConfig.AllowMerge}}
|
||||
<div class="item{{if eq .MergeStyle "merge"}} active selected{{end}}" data-do="merge">{{$.i18n.Tr "repo.pulls.merge_pull_request"}}</div>
|
||||
{{end}}
|
||||
{{if $prUnit.PullRequestsConfig.AllowRebase}}
|
||||
<div class="item{{if eq .MergeStyle "rebase"}} active selected{{end}}" data-do="rebase">{{$.i18n.Tr "repo.pulls.rebase_merge_pull_request"}}</div>
|
||||
{{end}}
|
||||
{{if $prUnit.PullRequestsConfig.AllowSquash}}
|
||||
<div class="item{{if eq .MergeStyle "squash"}} active selected{{end}}" data-do="squash">{{$.i18n.Tr "repo.pulls.squash_merge_pull_request"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="item text red">
|
||||
<span class="octicon octicon-x"></span>
|
||||
{{$.i18n.Tr "repo.pulls.no_merge_desc"}}
|
||||
</div>
|
||||
<div class="item text grey">
|
||||
<span class="octicon octicon-info"></span>
|
||||
{{$.i18n.Tr "repo.pulls.no_merge_helper"}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
<div class="item text red">
|
||||
|
|
|
|||
|
|
@ -198,14 +198,41 @@
|
|||
|
||||
{{if .Repository.CanEnablePulls}}
|
||||
<div class="ui divider"></div>
|
||||
|
||||
{{$pullRequestEnabled := .Repository.UnitEnabled $.UnitTypePullRequests}}
|
||||
{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
|
||||
<div class="inline field">
|
||||
<label>{{.i18n.Tr "repo.pulls"}}</label>
|
||||
<div class="ui checkbox">
|
||||
<input name="enable_pulls" type="checkbox" {{if .Repository.UnitEnabled $.UnitTypePullRequests}}checked{{end}}>
|
||||
<input class="enable-system" name="enable_pulls" type="checkbox" data-target="#pull_box" {{if $pullRequestEnabled}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.pulls_desc"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field{{if not $pullRequestEnabled}} disabled{{end}}" id="pull_box">
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="pulls_ignore_whitespace" type="checkbox" {{if and $pullRequestEnabled ($prUnit.PullRequestsConfig.IgnoreWhitespaceConflicts)}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.pulls.ignore_whitespace"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="pulls_allow_merge" type="checkbox" {{if or (not $pullRequestEnabled) ($prUnit.PullRequestsConfig.AllowMerge)}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.pulls.allow_merge_commits"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="pulls_allow_rebase" type="checkbox" {{if or (not $pullRequestEnabled) ($prUnit.PullRequestsConfig.AllowRebase)}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.pulls.allow_rebase_merge"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input name="pulls_allow_squash" type="checkbox" {{if or (not $pullRequestEnabled) ($prUnit.PullRequestsConfig.AllowSquash)}}checked{{end}}>
|
||||
<label>{{.i18n.Tr "repo.settings.pulls.allow_squash_commits"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="ui divider"></div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user