2014-05-01 13:44:22 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2018-08-15 09:29:37 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
2014-05-01 13:44:22 +04:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
2014-07-26 10:28:04 +04:00
import (
2019-02-23 00:56:05 +03:00
"errors"
2019-05-30 05:22:26 +03:00
"fmt"
2021-09-22 08:38:34 +03:00
"io"
2021-04-05 18:30:52 +03:00
"net/http"
2021-06-14 20:20:43 +03:00
"strconv"
2014-07-26 10:28:04 +04:00
"strings"
"time"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
2021-12-10 11:14:24 +03:00
asymkey_model "code.gitea.io/gitea/models/asymkey"
2021-09-24 14:32:56 +03:00
"code.gitea.io/gitea/models/db"
2021-11-28 14:58:28 +03:00
"code.gitea.io/gitea/models/perm"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-09 22:57:58 +03:00
unit_model "code.gitea.io/gitea/models/unit"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
2019-03-27 12:33:00 +03:00
"code.gitea.io/gitea/modules/git"
2021-12-16 18:55:12 +03:00
"code.gitea.io/gitea/modules/indexer/code"
"code.gitea.io/gitea/modules/indexer/stats"
2021-04-09 01:25:57 +03:00
"code.gitea.io/gitea/modules/lfs"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
2019-12-14 20:30:01 +03:00
"code.gitea.io/gitea/modules/repository"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2020-05-21 16:48:01 +03:00
"code.gitea.io/gitea/modules/structs"
2019-08-15 17:46:21 +03:00
"code.gitea.io/gitea/modules/timeutil"
2021-06-05 15:32:19 +03:00
"code.gitea.io/gitea/modules/typesniffer"
2021-06-14 20:20:43 +03:00
"code.gitea.io/gitea/modules/util"
2018-08-15 09:29:37 +03:00
"code.gitea.io/gitea/modules/validation"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2017-12-07 10:00:09 +03:00
"code.gitea.io/gitea/routers/utils"
2021-12-10 11:14:24 +03:00
asymkey_service "code.gitea.io/gitea/services/asymkey"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2019-09-24 08:02:49 +03:00
"code.gitea.io/gitea/services/mailer"
2021-11-16 18:25:33 +03:00
"code.gitea.io/gitea/services/migrations"
2019-10-01 16:40:17 +03:00
mirror_service "code.gitea.io/gitea/services/mirror"
2019-10-26 09:54:11 +03:00
repo_service "code.gitea.io/gitea/services/repository"
2021-09-08 18:19:30 +03:00
wiki_service "code.gitea.io/gitea/services/wiki"
2014-07-26 10:28:04 +04:00
)
const (
2016-11-07 23:58:22 +03:00
tplSettingsOptions base . TplName = "repo/settings/options"
tplCollaboration base . TplName = "repo/settings/collaboration"
2017-02-21 18:02:10 +03:00
tplBranches base . TplName = "repo/settings/branches"
2021-06-25 17:28:55 +03:00
tplTags base . TplName = "repo/settings/tags"
2016-11-07 23:58:22 +03:00
tplGithooks base . TplName = "repo/settings/githooks"
tplGithookEdit base . TplName = "repo/settings/githook_edit"
tplDeployKeys base . TplName = "repo/settings/deploy_keys"
2017-09-14 11:16:22 +03:00
tplProtectedBranch base . TplName = "repo/settings/protected_branch"
2014-07-26 10:28:04 +04:00
)
2016-11-24 10:04:31 +03:00
// Settings show a repository's settings page
2016-03-11 19:56:52 +03:00
func Settings ( ctx * context . Context ) {
2014-08-02 21:47:33 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings" )
ctx . Data [ "PageIsSettingsOptions" ] = true
2019-02-23 00:56:05 +03:00
ctx . Data [ "ForcePrivate" ] = setting . Repository . ForcePrivate
2021-09-07 18:49:36 +03:00
ctx . Data [ "MirrorsEnabled" ] = setting . Mirror . Enabled
ctx . Data [ "DisableNewPushMirrors" ] = setting . Mirror . DisableNewPush
2021-06-14 20:20:43 +03:00
ctx . Data [ "DefaultMirrorInterval" ] = setting . Mirror . DefaultInterval
2020-09-19 19:44:55 +03:00
2022-01-20 02:26:57 +03:00
signing , _ := asymkey_service . SigningKey ( ctx , ctx . Repo . Repository . RepoPath ( ) )
2020-09-19 19:44:55 +03:00
ctx . Data [ "SigningKeyAvailable" ] = len ( signing ) > 0
ctx . Data [ "SigningSettings" ] = setting . Repository . Signing
2021-12-16 18:55:12 +03:00
ctx . Data [ "CodeIndexerEnabled" ] = setting . Indexer . RepoIndexerEnabled
if ctx . User . IsAdmin {
if setting . Indexer . RepoIndexerEnabled {
status , err := repo_model . GetIndexerStatus ( ctx . Repo . Repository , repo_model . RepoIndexerTypeCode )
if err != nil {
ctx . ServerError ( "repo.indexer_status" , err )
return
}
ctx . Data [ "CodeIndexerStatus" ] = status
}
status , err := repo_model . GetIndexerStatus ( ctx . Repo . Repository , repo_model . RepoIndexerTypeStats )
if err != nil {
ctx . ServerError ( "repo.indexer_status" , err )
return
}
ctx . Data [ "StatsIndexerStatus" ] = status
}
2021-12-10 04:27:50 +03:00
pushMirrors , err := repo_model . GetPushMirrorsByRepoID ( ctx . Repo . Repository . ID )
if err != nil {
ctx . ServerError ( "GetPushMirrorsByRepoID" , err )
return
}
ctx . Data [ "PushMirrors" ] = pushMirrors
2020-09-19 19:44:55 +03:00
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplSettingsOptions )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// SettingsPost response for changes of a repository
2021-01-26 18:36:53 +03:00
func SettingsPost ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . RepoSettingForm )
2014-08-02 21:47:33 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings" )
ctx . Data [ "PageIsSettingsOptions" ] = true
2014-07-26 10:28:04 +04:00
2015-08-31 08:36:31 +03:00
repo := ctx . Repo . Repository
2021-08-11 03:31:13 +03:00
switch ctx . FormString ( "action" ) {
2014-07-26 10:28:04 +04:00
case "update" :
if ctx . HasError ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplSettingsOptions )
2014-07-26 10:28:04 +04:00
return
}
newRepoName := form . RepoName
// Check if repository name has been changed.
2015-08-31 08:36:31 +03:00
if repo . LowerName != strings . ToLower ( newRepoName ) {
2019-11-13 10:01:19 +03:00
// Close the GitRepo if open
if ctx . Repo . GitRepo != nil {
ctx . Repo . GitRepo . Close ( )
ctx . Repo . GitRepo = nil
}
2020-06-07 18:23:13 +03:00
if err := repo_service . ChangeRepositoryName ( ctx . User , repo , newRepoName ) ; err != nil {
2015-08-31 08:36:31 +03:00
ctx . Data [ "Err_RepoName" ] = true
2015-03-27 00:11:47 +03:00
switch {
2021-12-12 18:48:20 +03:00
case repo_model . IsErrRepoAlreadyExist ( err ) :
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.repo_name_been_taken" ) , tplSettingsOptions , & form )
2021-11-24 12:49:20 +03:00
case db . IsErrNameReserved ( err ) :
ctx . RenderWithErr ( ctx . Tr ( "repo.form.name_reserved" , err . ( db . ErrNameReserved ) . Name ) , tplSettingsOptions , & form )
2021-12-12 18:48:20 +03:00
case repo_model . IsErrRepoFilesAlreadyExist ( err ) :
2020-09-25 07:09:23 +03:00
ctx . Data [ "Err_RepoName" ] = true
switch {
case ctx . IsUserSiteAdmin ( ) || ( setting . Repository . AllowAdoptionOfUnadoptedRepositories && setting . Repository . AllowDeleteOfUnadoptedRepositories ) :
ctx . RenderWithErr ( ctx . Tr ( "form.repository_files_already_exist.adopt_or_delete" ) , tplSettingsOptions , form )
case setting . Repository . AllowAdoptionOfUnadoptedRepositories :
ctx . RenderWithErr ( ctx . Tr ( "form.repository_files_already_exist.adopt" ) , tplSettingsOptions , form )
case setting . Repository . AllowDeleteOfUnadoptedRepositories :
ctx . RenderWithErr ( ctx . Tr ( "form.repository_files_already_exist.delete" ) , tplSettingsOptions , form )
default :
ctx . RenderWithErr ( ctx . Tr ( "form.repository_files_already_exist" ) , tplSettingsOptions , form )
}
2021-11-24 12:49:20 +03:00
case db . IsErrNamePatternNotAllowed ( err ) :
ctx . RenderWithErr ( ctx . Tr ( "repo.form.name_pattern_not_allowed" , err . ( db . ErrNamePatternNotAllowed ) . Pattern ) , tplSettingsOptions , & form )
2015-03-27 00:11:47 +03:00
default :
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "ChangeRepositoryName" , err )
2014-08-24 17:09:05 +04:00
}
2014-07-26 10:28:04 +04:00
return
}
2015-09-01 18:43:53 +03:00
2015-08-31 08:36:31 +03:00
log . Trace ( "Repository name changed: %s/%s -> %s" , ctx . Repo . Owner . Name , repo . Name , newRepoName )
2014-07-26 10:28:04 +04:00
}
2015-08-31 08:36:31 +03:00
// In case it's just a case change.
repo . Name = newRepoName
repo . LowerName = strings . ToLower ( newRepoName )
repo . Description = form . Description
repo . Website = form . Website
2019-11-11 18:15:29 +03:00
repo . IsTemplate = form . Template
2015-11-18 23:01:11 +03:00
// Visibility of forked repository is forced sync with base repository.
if repo . IsFork {
2020-06-07 03:45:12 +03:00
form . Private = repo . BaseRepo . IsPrivate || repo . BaseRepo . Owner . Visibility == structs . VisibleTypePrivate
2015-11-18 23:01:11 +03:00
}
2015-08-31 08:36:31 +03:00
visibilityChanged := repo . IsPrivate != form . Private
2019-04-11 11:32:42 +03:00
// when ForcePrivate enabled, you could change public repo to private, but only admin users can change private to public
if visibilityChanged && setting . Repository . ForcePrivate && ! form . Private && ! ctx . User . IsAdmin {
2021-12-14 08:08:09 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.repository_force_private" ) , tplSettingsOptions , form )
2019-02-23 00:56:05 +03:00
return
}
2015-08-31 08:36:31 +03:00
repo . IsPrivate = form . Private
if err := models . UpdateRepository ( repo , visibilityChanged ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "UpdateRepository" , err )
2015-09-01 16:29:52 +03:00
return
2014-07-26 10:28:04 +04:00
}
2015-12-05 05:30:33 +03:00
log . Trace ( "Repository basic settings updated: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
2014-07-26 10:28:04 +04:00
2016-08-31 02:18:33 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
2016-07-17 04:30:43 +03:00
2016-08-31 02:18:33 +03:00
case "mirror" :
2021-09-07 18:49:36 +03:00
if ! setting . Mirror . Enabled || ! repo . IsMirror {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2016-08-31 02:18:33 +03:00
return
}
2019-03-26 00:51:55 +03:00
// This section doesn't require repo_name/RepoName to be set in the form, don't show it
// as an error on the UI for this action
ctx . Data [ "Err_RepoName" ] = nil
2017-04-08 18:27:26 +03:00
interval , err := time . ParseDuration ( form . Interval )
2019-01-26 11:26:23 +03:00
if err != nil || ( interval != 0 && interval < setting . Mirror . MinInterval ) {
2019-03-26 00:51:55 +03:00
ctx . Data [ "Err_Interval" ] = true
2017-04-08 18:27:26 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.mirror_interval_invalid" ) , tplSettingsOptions , & form )
} else {
2016-08-31 02:18:33 +03:00
ctx . Repo . Mirror . EnablePrune = form . EnablePrune
2017-04-08 18:27:26 +03:00
ctx . Repo . Mirror . Interval = interval
2018-11-09 02:58:02 +03:00
if interval != 0 {
2019-08-15 17:46:21 +03:00
ctx . Repo . Mirror . NextUpdateUnix = timeutil . TimeStampNow ( ) . AddDuration ( interval )
2018-11-09 02:58:02 +03:00
} else {
ctx . Repo . Mirror . NextUpdateUnix = 0
}
2021-12-10 04:27:50 +03:00
if err := repo_model . UpdateMirror ( ctx . Repo . Mirror ) ; err != nil {
2019-03-26 00:51:55 +03:00
ctx . Data [ "Err_Interval" ] = true
2017-04-08 18:27:26 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.mirror_interval_invalid" ) , tplSettingsOptions , & form )
2015-12-09 04:06:12 +03:00
return
}
2014-07-26 10:28:04 +04:00
}
2019-04-12 23:52:57 +03:00
2021-11-30 23:06:32 +03:00
u , _ := git . GetRemoteAddress ( ctx , ctx . Repo . Repository . RepoPath ( ) , ctx . Repo . Mirror . GetRemoteName ( ) )
2021-06-14 20:20:43 +03:00
if u . User != nil && form . MirrorPassword == "" && form . MirrorUsername == u . User . Username ( ) {
form . MirrorPassword , _ = u . User . Password ( )
2021-05-31 13:46:20 +03:00
}
2021-04-06 22:44:05 +03:00
address , err := forms . ParseRemoteAddr ( form . MirrorAddress , form . MirrorUsername , form . MirrorPassword )
2021-03-16 00:52:11 +03:00
if err == nil {
err = migrations . IsMigrateURLAllowed ( address , ctx . User )
2019-04-12 23:52:57 +03:00
}
2021-03-16 00:52:11 +03:00
if err != nil {
2019-04-12 23:52:57 +03:00
ctx . Data [ "Err_MirrorAddress" ] = true
2021-04-09 01:25:57 +03:00
handleSettingRemoteAddrError ( ctx , err , form )
2019-04-12 23:52:57 +03:00
return
}
2022-01-20 02:26:57 +03:00
if err := mirror_service . UpdateAddress ( ctx , ctx . Repo . Mirror , address ) ; err != nil {
2020-09-28 22:00:52 +03:00
ctx . ServerError ( "UpdateAddress" , err )
2016-08-31 02:18:33 +03:00
return
}
2014-07-26 10:28:04 +04:00
2021-04-09 01:25:57 +03:00
form . LFS = form . LFS && setting . LFS . StartServer
if len ( form . LFSEndpoint ) > 0 {
ep := lfs . DetermineEndpoint ( "" , form . LFSEndpoint )
if ep == nil {
ctx . Data [ "Err_LFSEndpoint" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.migrate.invalid_lfs_endpoint" ) , tplSettingsOptions , & form )
return
}
err = migrations . IsMigrateURLAllowed ( ep . String ( ) , ctx . User )
if err != nil {
ctx . Data [ "Err_LFSEndpoint" ] = true
handleSettingRemoteAddrError ( ctx , err , form )
return
}
}
ctx . Repo . Mirror . LFS = form . LFS
ctx . Repo . Mirror . LFSEndpoint = form . LFSEndpoint
2021-12-10 04:27:50 +03:00
if err := repo_model . UpdateMirror ( ctx . Repo . Mirror ) ; err != nil {
2021-04-09 01:25:57 +03:00
ctx . ServerError ( "UpdateMirror" , err )
return
}
2014-08-02 21:47:33 +04:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
2016-07-15 16:53:43 +03:00
ctx . Redirect ( repo . Link ( ) + "/settings" )
2015-12-05 05:30:33 +03:00
2016-08-31 02:18:33 +03:00
case "mirror-sync" :
2021-09-07 18:49:36 +03:00
if ! setting . Mirror . Enabled || ! repo . IsMirror {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2016-08-31 02:18:33 +03:00
return
}
2019-10-01 16:40:17 +03:00
mirror_service . StartToMirror ( repo . ID )
2016-08-31 02:18:33 +03:00
ctx . Flash . Info ( ctx . Tr ( "repo.settings.mirror_sync_in_progress" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
2021-06-14 20:20:43 +03:00
case "push-mirror-sync" :
2021-09-07 18:49:36 +03:00
if ! setting . Mirror . Enabled {
ctx . NotFound ( "" , nil )
return
}
2021-06-14 20:20:43 +03:00
m , err := selectPushMirrorByForm ( form , repo )
if err != nil {
ctx . NotFound ( "" , nil )
return
}
mirror_service . AddPushMirrorToQueue ( m . ID )
ctx . Flash . Info ( ctx . Tr ( "repo.settings.mirror_sync_in_progress" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
case "push-mirror-remove" :
2021-09-07 18:49:36 +03:00
if ! setting . Mirror . Enabled {
ctx . NotFound ( "" , nil )
return
}
2021-06-14 20:20:43 +03:00
// This section doesn't require repo_name/RepoName to be set in the form, don't show it
// as an error on the UI for this action
ctx . Data [ "Err_RepoName" ] = nil
m , err := selectPushMirrorByForm ( form , repo )
if err != nil {
ctx . NotFound ( "" , nil )
return
}
2022-01-20 02:26:57 +03:00
if err = mirror_service . RemovePushMirrorRemote ( ctx , m ) ; err != nil {
2021-06-14 20:20:43 +03:00
ctx . ServerError ( "RemovePushMirrorRemote" , err )
return
}
2021-12-10 04:27:50 +03:00
if err = repo_model . DeletePushMirrorByID ( m . ID ) ; err != nil {
2021-06-14 20:20:43 +03:00
ctx . ServerError ( "DeletePushMirrorByID" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
case "push-mirror-add" :
2021-09-07 18:49:36 +03:00
if setting . Mirror . DisableNewPush {
ctx . NotFound ( "" , nil )
return
}
2021-06-14 20:20:43 +03:00
// This section doesn't require repo_name/RepoName to be set in the form, don't show it
// as an error on the UI for this action
ctx . Data [ "Err_RepoName" ] = nil
interval , err := time . ParseDuration ( form . PushMirrorInterval )
if err != nil || ( interval != 0 && interval < setting . Mirror . MinInterval ) {
ctx . Data [ "Err_PushMirrorInterval" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.mirror_interval_invalid" ) , tplSettingsOptions , & form )
return
}
address , err := forms . ParseRemoteAddr ( form . PushMirrorAddress , form . PushMirrorUsername , form . PushMirrorPassword )
if err == nil {
err = migrations . IsMigrateURLAllowed ( address , ctx . User )
}
if err != nil {
ctx . Data [ "Err_PushMirrorAddress" ] = true
handleSettingRemoteAddrError ( ctx , err , form )
return
}
2022-01-26 07:10:10 +03:00
remoteSuffix , err := util . CryptoRandomString ( 10 )
2021-06-14 20:20:43 +03:00
if err != nil {
ctx . ServerError ( "RandomString" , err )
return
}
2021-12-10 04:27:50 +03:00
m := & repo_model . PushMirror {
2021-06-14 20:20:43 +03:00
RepoID : repo . ID ,
Repo : repo ,
RemoteName : fmt . Sprintf ( "remote_mirror_%s" , remoteSuffix ) ,
Interval : interval ,
}
2021-12-10 04:27:50 +03:00
if err := repo_model . InsertPushMirror ( m ) ; err != nil {
2021-06-14 20:20:43 +03:00
ctx . ServerError ( "InsertPushMirror" , err )
return
}
2022-01-20 02:26:57 +03:00
if err := mirror_service . AddPushMirrorRemote ( ctx , m , address ) ; err != nil {
2021-12-10 04:27:50 +03:00
if err := repo_model . DeletePushMirrorByID ( m . ID ) ; err != nil {
2021-06-14 20:20:43 +03:00
log . Error ( "DeletePushMirrorByID %v" , err )
}
ctx . ServerError ( "AddPushMirrorRemote" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
2015-12-05 05:30:33 +03:00
case "advanced" :
2021-03-16 04:00:52 +03:00
var repoChanged bool
2021-12-10 04:27:50 +03:00
var units [ ] repo_model . RepoUnit
2021-11-09 22:57:58 +03:00
var deleteUnitTypes [ ] unit_model . Type
2017-02-04 18:53:46 +03:00
2019-03-26 00:51:55 +03:00
// This section doesn't require repo_name/RepoName to be set in the form, don't show it
// as an error on the UI for this action
ctx . Data [ "Err_RepoName" ] = nil
2021-03-16 04:00:52 +03:00
if repo . CloseIssuesViaCommitInAnyBranch != form . EnableCloseIssuesViaCommitInAnyBranch {
repo . CloseIssuesViaCommitInAnyBranch = form . EnableCloseIssuesViaCommitInAnyBranch
repoChanged = true
}
2021-11-09 22:57:58 +03:00
if form . EnableWiki && form . EnableExternalWiki && ! unit_model . TypeExternalWiki . UnitGlobalDisabled ( ) {
2020-01-17 10:34:37 +03:00
if ! validation . IsValidExternalURL ( form . ExternalWikiURL ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.external_wiki_url_error" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
return
}
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2020-01-17 10:34:37 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypeExternalWiki ,
2021-12-10 04:27:50 +03:00
Config : & repo_model . ExternalWikiConfig {
2020-01-17 10:34:37 +03:00
ExternalWikiURL : form . ExternalWikiURL ,
} ,
} )
2021-11-09 22:57:58 +03:00
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeWiki )
} else if form . EnableWiki && ! form . EnableExternalWiki && ! unit_model . TypeWiki . UnitGlobalDisabled ( ) {
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2017-02-04 18:53:46 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypeWiki ,
2021-12-10 04:27:50 +03:00
Config : new ( repo_model . UnitConfig ) ,
2017-02-04 18:53:46 +03:00
} )
2021-11-09 22:57:58 +03:00
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeExternalWiki )
2020-01-17 10:34:37 +03:00
} else {
2021-11-09 22:57:58 +03:00
if ! unit_model . TypeExternalWiki . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeExternalWiki )
2020-01-17 10:34:37 +03:00
}
2021-11-09 22:57:58 +03:00
if ! unit_model . TypeWiki . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeWiki )
2017-02-04 18:53:46 +03:00
}
}
2021-11-09 22:57:58 +03:00
if form . EnableIssues && form . EnableExternalTracker && ! unit_model . TypeExternalTracker . UnitGlobalDisabled ( ) {
2020-01-17 10:34:37 +03:00
if ! validation . IsValidExternalURL ( form . ExternalTrackerURL ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.external_tracker_url_error" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
return
}
if len ( form . TrackerURLFormat ) != 0 && ! validation . IsValidExternalTrackerURLFormat ( form . TrackerURLFormat ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.tracker_url_format_error" ) )
ctx . Redirect ( repo . Link ( ) + "/settings" )
return
}
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2020-01-17 10:34:37 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypeExternalTracker ,
2021-12-10 04:27:50 +03:00
Config : & repo_model . ExternalTrackerConfig {
2020-01-17 10:34:37 +03:00
ExternalTrackerURL : form . ExternalTrackerURL ,
ExternalTrackerFormat : form . TrackerURLFormat ,
ExternalTrackerStyle : form . TrackerIssueStyle ,
} ,
} )
2021-11-09 22:57:58 +03:00
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeIssues )
} else if form . EnableIssues && ! form . EnableExternalTracker && ! unit_model . TypeIssues . UnitGlobalDisabled ( ) {
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2020-01-17 10:34:37 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypeIssues ,
2021-12-10 04:27:50 +03:00
Config : & repo_model . IssuesConfig {
2020-01-17 10:34:37 +03:00
EnableTimetracker : form . EnableTimetracker ,
AllowOnlyContributorsToTrackTime : form . AllowOnlyContributorsToTrackTime ,
EnableDependencies : form . EnableIssueDependencies ,
} ,
} )
2021-11-09 22:57:58 +03:00
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeExternalTracker )
2020-01-17 10:34:37 +03:00
} else {
2021-11-09 22:57:58 +03:00
if ! unit_model . TypeExternalTracker . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeExternalTracker )
2020-01-17 10:34:37 +03:00
}
2021-11-09 22:57:58 +03:00
if ! unit_model . TypeIssues . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeIssues )
2017-02-04 18:53:46 +03:00
}
}
2021-11-09 22:57:58 +03:00
if form . EnableProjects && ! unit_model . TypeProjects . UnitGlobalDisabled ( ) {
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2020-08-17 06:07:38 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypeProjects ,
2020-08-17 06:07:38 +03:00
} )
2021-11-09 22:57:58 +03:00
} else if ! unit_model . TypeProjects . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypeProjects )
2020-08-17 06:07:38 +03:00
}
2021-11-09 22:57:58 +03:00
if form . EnablePulls && ! unit_model . TypePullRequests . UnitGlobalDisabled ( ) {
2021-12-10 04:27:50 +03:00
units = append ( units , repo_model . RepoUnit {
2017-02-04 18:53:46 +03:00
RepoID : repo . ID ,
2021-11-09 22:57:58 +03:00
Type : unit_model . TypePullRequests ,
2021-12-10 04:27:50 +03:00
Config : & repo_model . PullRequestsConfig {
2021-07-13 02:26:25 +03:00
IgnoreWhitespaceConflicts : form . PullsIgnoreWhitespace ,
AllowMerge : form . PullsAllowMerge ,
AllowRebase : form . PullsAllowRebase ,
AllowRebaseMerge : form . PullsAllowRebaseMerge ,
AllowSquash : form . PullsAllowSquash ,
AllowManualMerge : form . PullsAllowManualMerge ,
AutodetectManualMerge : form . EnableAutodetectManualMerge ,
DefaultDeleteBranchAfterMerge : form . DefaultDeleteBranchAfterMerge ,
2021-12-10 04:27:50 +03:00
DefaultMergeStyle : repo_model . MergeStyle ( form . PullsDefaultMergeStyle ) ,
2018-01-05 21:56:50 +03:00
} ,
2017-02-04 18:53:46 +03:00
} )
2021-11-09 22:57:58 +03:00
} else if ! unit_model . TypePullRequests . UnitGlobalDisabled ( ) {
deleteUnitTypes = append ( deleteUnitTypes , unit_model . TypePullRequests )
2017-02-04 18:53:46 +03:00
}
2021-12-12 18:48:20 +03:00
if err := repo_model . UpdateRepositoryUnits ( repo , units , deleteUnitTypes ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "UpdateRepositoryUnits" , err )
2015-12-05 05:30:33 +03:00
return
}
2021-03-16 04:00:52 +03:00
if repoChanged {
if err := models . UpdateRepository ( repo , false ) ; err != nil {
ctx . ServerError ( "UpdateRepository" , err )
return
}
}
2015-12-05 05:30:33 +03:00
log . Trace ( "Repository advanced settings updated: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2020-09-19 19:44:55 +03:00
case "signing" :
changed := false
2021-12-10 04:27:50 +03:00
trustModel := repo_model . ToTrustModel ( form . TrustModel )
2020-09-19 19:44:55 +03:00
if trustModel != repo . TrustModel {
repo . TrustModel = trustModel
changed = true
}
if changed {
if err := models . UpdateRepository ( repo , false ) ; err != nil {
ctx . ServerError ( "UpdateRepository" , err )
return
}
}
log . Trace ( "Repository signing settings updated: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2018-03-27 17:13:20 +03:00
case "admin" :
if ! ctx . User . IsAdmin {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusForbidden )
2018-03-27 17:13:20 +03:00
return
}
if repo . IsFsckEnabled != form . EnableHealthCheck {
repo . IsFsckEnabled = form . EnableHealthCheck
}
2019-02-10 22:27:19 +03:00
if err := models . UpdateRepository ( repo , false ) ; err != nil {
ctx . ServerError ( "UpdateRepository" , err )
return
}
log . Trace ( "Repository admin settings updated: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
2018-03-27 17:13:20 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_settings_success" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2021-12-16 18:55:12 +03:00
case "admin_index" :
if ! ctx . User . IsAdmin {
ctx . Error ( http . StatusForbidden )
return
}
switch form . RequestReindexType {
case "stats" :
if err := stats . UpdateRepoIndexer ( ctx . Repo . Repository ) ; err != nil {
ctx . ServerError ( "UpdateStatsRepondexer" , err )
return
}
case "code" :
if ! setting . Indexer . RepoIndexerEnabled {
ctx . Error ( http . StatusForbidden )
return
}
code . UpdateRepoIndexer ( ctx . Repo . Repository )
default :
ctx . NotFound ( "" , nil )
return
}
log . Trace ( "Repository reindex for %s requested: %s/%s" , form . RequestReindexType , ctx . Repo . Owner . Name , repo . Name )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.reindex_requested" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2016-02-14 23:12:00 +03:00
case "convert" :
2016-03-06 04:45:23 +03:00
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2016-03-06 04:45:23 +03:00
return
}
2016-02-14 23:12:00 +03:00
if repo . Name != form . RepoName {
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_repo_name" ) , tplSettingsOptions , nil )
2016-02-14 23:12:00 +03:00
return
}
2016-02-14 23:22:36 +03:00
if ! repo . IsMirror {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2016-02-14 23:22:36 +03:00
return
}
2016-02-14 23:12:00 +03:00
repo . IsMirror = false
2022-01-20 02:26:57 +03:00
if _ , err := repository . CleanUpMigrateInfo ( ctx , repo ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "CleanUpMigrateInfo" , err )
2016-02-14 23:12:00 +03:00
return
2021-12-10 04:27:50 +03:00
} else if err = repo_model . DeleteMirrorByRepoID ( ctx . Repo . Repository . ID ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "DeleteMirrorByRepoID" , err )
2016-02-14 23:12:00 +03:00
return
}
2020-07-02 17:09:09 +03:00
log . Trace ( "Repository converted from mirror to regular: %s" , repo . FullName ( ) )
2016-02-14 23:12:00 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.convert_succeed" ) )
2020-07-02 17:09:09 +03:00
ctx . Redirect ( repo . Link ( ) )
case "convert_fork" :
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2020-07-02 17:09:09 +03:00
return
}
2021-12-10 04:27:50 +03:00
if err := repo . GetOwner ( db . DefaultContext ) ; err != nil {
2020-07-02 17:09:09 +03:00
ctx . ServerError ( "Convert Fork" , err )
return
}
if repo . Name != form . RepoName {
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_repo_name" ) , tplSettingsOptions , nil )
return
}
if ! repo . IsFork {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2020-07-02 17:09:09 +03:00
return
}
if ! ctx . Repo . Owner . CanCreateRepo ( ) {
2022-01-02 05:38:07 +03:00
maxCreationLimit := ctx . Repo . Owner . MaxCreationLimit ( )
2022-01-02 06:33:57 +03:00
msg := ctx . TrN ( maxCreationLimit , "repo.form.reach_limit_of_creation_1" , "repo.form.reach_limit_of_creation_n" , maxCreationLimit )
ctx . Flash . Error ( msg )
2020-07-02 17:09:09 +03:00
ctx . Redirect ( repo . Link ( ) + "/settings" )
return
}
2021-11-16 16:30:11 +03:00
if err := repo_service . ConvertForkToNormalRepository ( repo ) ; err != nil {
2021-09-14 20:07:08 +03:00
log . Error ( "Unable to convert repository %-v from fork. Error: %v" , repo , err )
2020-07-02 17:09:09 +03:00
ctx . ServerError ( "Convert Fork" , err )
return
}
log . Trace ( "Repository converted from fork to regular: %s" , repo . FullName ( ) )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.convert_fork_succeed" ) )
ctx . Redirect ( repo . Link ( ) )
2016-02-14 23:12:00 +03:00
2014-07-26 10:28:04 +04:00
case "transfer" :
2016-03-06 04:45:23 +03:00
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2016-03-06 04:45:23 +03:00
return
}
2015-08-31 08:36:31 +03:00
if repo . Name != form . RepoName {
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_repo_name" ) , tplSettingsOptions , nil )
2014-07-26 10:28:04 +04:00
return
}
2021-11-24 12:49:20 +03:00
newOwner , err := user_model . GetUserByName ( ctx . FormString ( "new_owner_name" ) )
2014-07-26 10:28:04 +04:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2020-01-31 18:49:04 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_owner_name" ) , tplSettingsOptions , nil )
return
}
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "IsUserExist" , err )
2014-07-26 10:28:04 +04:00
return
2015-03-06 03:20:27 +03:00
}
2021-11-24 12:49:20 +03:00
if newOwner . Type == user_model . UserTypeOrganization {
2021-11-19 14:41:40 +03:00
if ! ctx . User . IsAdmin && newOwner . Visibility == structs . VisibleTypePrivate && ! models . OrgFromUser ( newOwner ) . HasMemberWithUserID ( ctx . User . ID ) {
2020-05-21 16:48:01 +03:00
// The user shouldn't know about this organization
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_owner_name" ) , tplSettingsOptions , nil )
return
}
}
2019-11-13 10:01:19 +03:00
// Close the GitRepo if open
if ctx . Repo . GitRepo != nil {
ctx . Repo . GitRepo . Close ( )
ctx . Repo . GitRepo = nil
}
2021-03-01 03:47:30 +03:00
if err := repo_service . StartRepositoryTransfer ( ctx . User , newOwner , repo , nil ) ; err != nil {
2021-12-12 18:48:20 +03:00
if repo_model . IsErrRepoAlreadyExist ( err ) {
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.settings.new_owner_has_same_repo" ) , tplSettingsOptions , nil )
2021-03-01 03:47:30 +03:00
} else if models . IsErrRepoTransferInProgress ( err ) {
ctx . RenderWithErr ( ctx . Tr ( "repo.settings.transfer_in_progress" ) , tplSettingsOptions , nil )
2014-09-13 02:29:58 +04:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "TransferOwnership" , err )
2014-09-13 02:29:58 +04:00
}
2021-03-01 03:47:30 +03:00
return
}
log . Trace ( "Repository transfer process was started: %s/%s -> %s" , ctx . Repo . Owner . Name , repo . Name , newOwner )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.transfer_started" , newOwner . DisplayName ( ) ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( repo . Link ( ) + "/settings" )
2021-03-01 03:47:30 +03:00
case "cancel_transfer" :
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2021-03-01 03:47:30 +03:00
return
}
repoTransfer , err := models . GetPendingRepositoryTransfer ( ctx . Repo . Repository )
if err != nil {
if models . IsErrNoPendingTransfer ( err ) {
ctx . Flash . Error ( "repo.settings.transfer_abort_invalid" )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( repo . Link ( ) + "/settings" )
2021-03-01 03:47:30 +03:00
} else {
ctx . ServerError ( "GetPendingRepositoryTransfer" , err )
}
return
}
if err := repoTransfer . LoadAttributes ( ) ; err != nil {
ctx . ServerError ( "LoadRecipient" , err )
return
}
if err := models . CancelRepositoryTransfer ( ctx . Repo . Repository ) ; err != nil {
ctx . ServerError ( "CancelRepositoryTransfer" , err )
2014-07-26 10:28:04 +04:00
return
}
2019-02-28 06:51:46 +03:00
2021-03-01 03:47:30 +03:00
log . Trace ( "Repository transfer process was cancelled: %s/%s " , ctx . Repo . Owner . Name , repo . Name )
ctx . Flash . Success ( ctx . Tr ( "repo.settings.transfer_abort_success" , repoTransfer . Recipient . Name ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( repo . Link ( ) + "/settings" )
2016-03-06 04:45:23 +03:00
2014-07-26 10:28:04 +04:00
case "delete" :
2016-03-06 04:45:23 +03:00
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2016-03-06 04:45:23 +03:00
return
}
2015-08-31 08:36:31 +03:00
if repo . Name != form . RepoName {
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_repo_name" ) , tplSettingsOptions , nil )
2014-07-26 10:28:04 +04:00
return
2014-08-27 12:39:36 +04:00
}
2021-05-14 23:19:38 +03:00
// Close the gitrepository before doing this.
if ctx . Repo . GitRepo != nil {
ctx . Repo . GitRepo . Close ( )
}
2022-01-20 02:26:57 +03:00
if err := repo_service . DeleteRepository ( ctx , ctx . User , ctx . Repo . Repository , true ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "DeleteRepository" , err )
2014-07-26 10:28:04 +04:00
return
}
2015-08-31 08:36:31 +03:00
log . Trace ( "Repository deleted: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
2015-12-06 01:39:29 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.deletion_success" ) )
2015-08-31 08:36:31 +03:00
ctx . Redirect ( ctx . Repo . Owner . DashboardLink ( ) )
2016-03-06 04:45:23 +03:00
2016-03-03 23:38:25 +03:00
case "delete-wiki" :
2016-03-06 04:45:23 +03:00
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusNotFound )
2016-03-06 04:45:23 +03:00
return
}
2016-03-03 23:38:25 +03:00
if repo . Name != form . RepoName {
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.enterred_invalid_repo_name" ) , tplSettingsOptions , nil )
2016-03-03 23:38:25 +03:00
return
}
2022-01-20 02:26:57 +03:00
err := wiki_service . DeleteWiki ( ctx , repo )
2019-06-12 22:41:28 +03:00
if err != nil {
log . Error ( "Delete Wiki: %v" , err . Error ( ) )
}
2016-03-03 23:38:25 +03:00
log . Trace ( "Repository wiki deleted: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
2016-03-04 07:24:22 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.wiki_deletion_success" ) )
2016-03-03 23:38:25 +03:00
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2016-08-31 02:18:33 +03:00
2019-01-23 21:58:38 +03:00
case "archive" :
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusForbidden )
2019-01-23 21:58:38 +03:00
return
}
if repo . IsMirror {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.archive.error_ismirror" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
return
}
2021-12-12 18:48:20 +03:00
if err := repo_model . SetArchiveRepoState ( repo , true ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Tried to archive a repo: %s" , err )
2019-01-23 21:58:38 +03:00
ctx . Flash . Error ( ctx . Tr ( "repo.settings.archive.error" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.archive.success" ) )
log . Trace ( "Repository was archived: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2021-09-07 18:49:36 +03:00
2019-01-23 21:58:38 +03:00
case "unarchive" :
if ! ctx . Repo . IsOwner ( ) {
2021-04-05 18:30:52 +03:00
ctx . Error ( http . StatusForbidden )
2019-01-23 21:58:38 +03:00
return
}
2021-12-12 18:48:20 +03:00
if err := repo_model . SetArchiveRepoState ( repo , false ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Tried to unarchive a repo: %s" , err )
2019-01-23 21:58:38 +03:00
ctx . Flash . Error ( ctx . Tr ( "repo.settings.unarchive.error" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.unarchive.success" ) )
log . Trace ( "Repository was un-archived: %s/%s" , ctx . Repo . Owner . Name , repo . Name )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
2016-08-31 02:18:33 +03:00
default :
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "" , nil )
2014-07-26 10:28:04 +04:00
}
}
2021-04-09 01:25:57 +03:00
func handleSettingRemoteAddrError ( ctx * context . Context , err error , form * forms . RepoSettingForm ) {
if models . IsErrInvalidCloneAddr ( err ) {
addrErr := err . ( * models . ErrInvalidCloneAddr )
switch {
case addrErr . IsProtocolInvalid :
ctx . RenderWithErr ( ctx . Tr ( "repo.mirror_address_protocol_invalid" ) , tplSettingsOptions , form )
case addrErr . IsURLError :
ctx . RenderWithErr ( ctx . Tr ( "form.url_error" ) , tplSettingsOptions , form )
case addrErr . IsPermissionDenied :
if addrErr . LocalPath {
ctx . RenderWithErr ( ctx . Tr ( "repo.migrate.permission_denied" ) , tplSettingsOptions , form )
} else {
2021-11-20 12:34:05 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.migrate.permission_denied_blocked" ) , tplSettingsOptions , form )
2021-04-09 01:25:57 +03:00
}
case addrErr . IsInvalidPath :
ctx . RenderWithErr ( ctx . Tr ( "repo.migrate.invalid_local_path" ) , tplSettingsOptions , form )
default :
ctx . ServerError ( "Unknown error" , err )
}
2021-08-24 01:09:25 +03:00
return
2021-04-09 01:25:57 +03:00
}
ctx . RenderWithErr ( ctx . Tr ( "repo.mirror_address_url_invalid" ) , tplSettingsOptions , form )
}
2016-11-24 10:04:31 +03:00
// Collaboration render a repository's collaboration page
2016-03-11 19:56:52 +03:00
func Collaboration ( ctx * context . Context ) {
2014-08-07 14:40:05 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings" )
ctx . Data [ "PageIsSettingsCollaboration" ] = true
2021-12-10 04:27:50 +03:00
users , err := models . GetCollaborators ( ctx . Repo . Repository . ID , db . ListOptions { } )
2014-07-26 10:28:04 +04:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetCollaborators" , err )
2014-07-26 10:28:04 +04:00
return
}
2015-01-23 10:54:16 +03:00
ctx . Data [ "Collaborators" ] = users
2016-03-06 02:08:42 +03:00
2021-12-10 04:27:50 +03:00
teams , err := models . GetRepoTeams ( ctx . Repo . Repository )
2019-09-23 23:08:03 +03:00
if err != nil {
ctx . ServerError ( "GetRepoTeams" , err )
return
}
ctx . Data [ "Teams" ] = teams
ctx . Data [ "Repo" ] = ctx . Repo . Repository
ctx . Data [ "OrgID" ] = ctx . Repo . Repository . OwnerID
ctx . Data [ "OrgName" ] = ctx . Repo . Repository . OwnerName
ctx . Data [ "Org" ] = ctx . Repo . Repository . Owner
2021-11-09 22:57:58 +03:00
ctx . Data [ "Units" ] = unit_model . Units
2019-09-23 23:08:03 +03:00
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplCollaboration )
2014-07-26 10:28:04 +04:00
}
2016-11-24 10:04:31 +03:00
// CollaborationPost response for actions for a collaboration of a repository
2016-03-11 19:56:52 +03:00
func CollaborationPost ( ctx * context . Context ) {
2021-08-11 03:31:13 +03:00
name := utils . RemoveUsernameParameterSuffix ( strings . ToLower ( ctx . FormString ( "collaborator" ) ) )
2016-02-20 23:10:34 +03:00
if len ( name ) == 0 || ctx . Repo . Owner . LowerName == name {
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . EscapedPath ( ) )
2016-02-20 23:10:34 +03:00
return
}
2021-11-24 12:49:20 +03:00
u , err := user_model . GetUserByName ( name )
2016-02-20 23:10:34 +03:00
if err != nil {
2021-11-24 12:49:20 +03:00
if user_model . IsErrUserNotExist ( err ) {
2016-02-20 23:10:34 +03:00
ctx . Flash . Error ( ctx . Tr ( "form.user_not_exist" ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . EscapedPath ( ) )
2016-02-20 23:10:34 +03:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetUserByName" , err )
2016-02-20 23:10:34 +03:00
}
return
}
2018-08-07 13:01:06 +03:00
if ! u . IsActive {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.add_collaborator_inactive_user" ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . EscapedPath ( ) )
2018-08-07 13:01:06 +03:00
return
}
2016-02-20 23:10:34 +03:00
// Organization is not allowed to be added as a collaborator.
if u . IsOrganization ( ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.org_not_allowed_to_be_collaborator" ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . EscapedPath ( ) )
2016-02-20 23:10:34 +03:00
return
}
2021-12-10 04:27:50 +03:00
if got , err := models . IsCollaborator ( ctx . Repo . Repository . ID , u . ID ) ; err == nil && got {
2018-08-07 04:59:42 +03:00
ctx . Flash . Error ( ctx . Tr ( "repo.settings.add_collaborator_duplicate" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
2021-12-10 04:27:50 +03:00
if err = models . AddCollaborator ( ctx . Repo . Repository , u ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "AddCollaborator" , err )
2016-02-20 23:10:34 +03:00
return
}
if setting . Service . EnableNotifyMail {
2019-09-24 08:02:49 +03:00
mailer . SendCollaboratorMail ( u , ctx . User , ctx . Repo . Repository )
2016-02-20 23:10:34 +03:00
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.add_collaborator_success" ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + ctx . Req . URL . EscapedPath ( ) )
2016-02-20 23:10:34 +03:00
}
2016-11-24 10:04:31 +03:00
// ChangeCollaborationAccessMode response for changing access of a collaboration
2016-03-11 19:56:52 +03:00
func ChangeCollaborationAccessMode ( ctx * context . Context ) {
2021-12-10 04:27:50 +03:00
if err := models . ChangeCollaborationAccessMode (
ctx . Repo . Repository ,
2021-07-29 04:42:15 +03:00
ctx . FormInt64 ( "uid" ) ,
2021-11-28 14:58:28 +03:00
perm . AccessMode ( ctx . FormInt ( "mode" ) ) ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "ChangeCollaborationAccessMode: %v" , err )
2016-03-06 02:08:42 +03:00
}
}
2016-11-24 10:04:31 +03:00
// DeleteCollaboration delete a collaboration for a repository
2016-03-11 19:56:52 +03:00
func DeleteCollaboration ( ctx * context . Context ) {
2021-12-10 04:27:50 +03:00
if err := models . DeleteCollaboration ( ctx . Repo . Repository , ctx . FormInt64 ( "id" ) ) ; err != nil {
2016-03-06 02:08:42 +03:00
ctx . Flash . Error ( "DeleteCollaboration: " + err . Error ( ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "repo.settings.remove_collaborator_success" ) )
}
2021-04-05 18:30:52 +03:00
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
2016-03-06 02:08:42 +03:00
"redirect" : ctx . Repo . RepoLink + "/settings/collaboration" ,
} )
}
2019-09-23 23:08:03 +03:00
// AddTeamPost response for adding a team to a repository
func AddTeamPost ( ctx * context . Context ) {
if ! ctx . Repo . Owner . RepoAdminChangeTeamAccess && ! ctx . Repo . IsOwner ( ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.change_team_access_not_allowed" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
2021-08-11 03:31:13 +03:00
name := utils . RemoveUsernameParameterSuffix ( strings . ToLower ( ctx . FormString ( "team" ) ) )
2020-01-15 16:18:02 +03:00
if len ( name ) == 0 {
2019-09-23 23:08:03 +03:00
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
2021-11-19 14:41:40 +03:00
team , err := models . OrgFromUser ( ctx . Repo . Owner ) . GetTeam ( name )
2019-09-23 23:08:03 +03:00
if err != nil {
if models . IsErrTeamNotExist ( err ) {
ctx . Flash . Error ( ctx . Tr ( "form.team_not_exist" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
} else {
ctx . ServerError ( "GetTeam" , err )
}
return
}
if team . OrgID != ctx . Repo . Repository . OwnerID {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.team_not_in_organization" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
if models . HasTeamRepo ( ctx . Repo . Repository . OwnerID , team . ID , ctx . Repo . Repository . ID ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.add_team_duplicate" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
if err = team . AddRepository ( ctx . Repo . Repository ) ; err != nil {
ctx . ServerError ( "team.AddRepository" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.add_team_success" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
}
// DeleteTeam response for deleting a team from a repository
func DeleteTeam ( ctx * context . Context ) {
if ! ctx . Repo . Owner . RepoAdminChangeTeamAccess && ! ctx . Repo . IsOwner ( ) {
ctx . Flash . Error ( ctx . Tr ( "repo.settings.change_team_access_not_allowed" ) )
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/collaboration" )
return
}
2021-07-29 04:42:15 +03:00
team , err := models . GetTeamByID ( ctx . FormInt64 ( "id" ) )
2019-09-23 23:08:03 +03:00
if err != nil {
ctx . ServerError ( "GetTeamByID" , err )
return
}
if err = team . RemoveRepository ( ctx . Repo . Repository . ID ) ; err != nil {
ctx . ServerError ( "team.RemoveRepositorys" , err )
return
}
ctx . Flash . Success ( ctx . Tr ( "repo.settings.remove_team_success" ) )
2021-04-05 18:30:52 +03:00
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
2019-09-23 23:08:03 +03:00
"redirect" : ctx . Repo . RepoLink + "/settings/collaboration" ,
} )
}
2016-11-24 10:04:31 +03:00
// GitHooks hooks of a repository
2016-03-11 19:56:52 +03:00
func GitHooks ( ctx * context . Context ) {
2015-08-26 19:30:06 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings.githooks" )
2014-10-07 01:50:00 +04:00
ctx . Data [ "PageIsSettingsGitHooks" ] = true
hooks , err := ctx . Repo . GitRepo . Hooks ( )
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "Hooks" , err )
2014-10-07 01:50:00 +04:00
return
}
ctx . Data [ "Hooks" ] = hooks
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplGithooks )
2014-10-07 01:50:00 +04:00
}
2016-11-24 10:04:31 +03:00
// GitHooksEdit render for editing a hook of repository page
2016-03-11 19:56:52 +03:00
func GitHooksEdit ( ctx * context . Context ) {
2015-08-26 19:30:06 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings.githooks" )
2014-10-07 01:50:00 +04:00
ctx . Data [ "PageIsSettingsGitHooks" ] = true
name := ctx . Params ( ":name" )
hook , err := ctx . Repo . GitRepo . GetHook ( name )
if err != nil {
if err == git . ErrNotValidHook {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "GetHook" , err )
2014-10-07 01:50:00 +04:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetHook" , err )
2014-10-07 01:50:00 +04:00
}
return
}
ctx . Data [ "Hook" ] = hook
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplGithookEdit )
2014-10-07 01:50:00 +04:00
}
2016-11-24 10:04:31 +03:00
// GitHooksEditPost response for editing a git hook of a repository
2016-03-11 19:56:52 +03:00
func GitHooksEditPost ( ctx * context . Context ) {
2014-10-07 01:50:00 +04:00
name := ctx . Params ( ":name" )
hook , err := ctx . Repo . GitRepo . GetHook ( name )
if err != nil {
if err == git . ErrNotValidHook {
2018-01-11 00:34:17 +03:00
ctx . NotFound ( "GetHook" , err )
2014-10-07 01:50:00 +04:00
} else {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetHook" , err )
2014-10-07 01:50:00 +04:00
}
return
}
2021-08-11 03:31:13 +03:00
hook . Content = ctx . FormString ( "content" )
2014-10-07 01:50:00 +04:00
if err = hook . Update ( ) ; err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "hook.Update" , err )
2014-10-07 01:50:00 +04:00
return
}
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/hooks/git" )
}
2015-07-25 16:32:04 +03:00
2016-11-24 10:04:31 +03:00
// DeployKeys render the deploy keys list of a repository page
2016-03-11 19:56:52 +03:00
func DeployKeys ( ctx * context . Context ) {
2015-08-26 19:30:06 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings.deploy_keys" )
2015-08-06 17:48:11 +03:00
ctx . Data [ "PageIsSettingsKeys" ] = true
2017-11-21 06:49:33 +03:00
ctx . Data [ "DisableSSH" ] = setting . SSH . Disabled
2015-08-06 17:48:11 +03:00
2021-12-10 11:14:24 +03:00
keys , err := asymkey_model . ListDeployKeys ( db . DefaultContext , & asymkey_model . ListDeployKeysOptions { RepoID : ctx . Repo . Repository . ID } )
2015-08-06 17:48:11 +03:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "ListDeployKeys" , err )
2015-08-06 17:48:11 +03:00
return
}
ctx . Data [ "Deploykeys" ] = keys
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplDeployKeys )
2015-08-06 17:48:11 +03:00
}
2016-11-24 10:04:31 +03:00
// DeployKeysPost response for adding a deploy key of a repository
2021-01-26 18:36:53 +03:00
func DeployKeysPost ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . AddKeyForm )
2015-08-26 19:30:06 +03:00
ctx . Data [ "Title" ] = ctx . Tr ( "repo.settings.deploy_keys" )
2015-08-06 17:48:11 +03:00
ctx . Data [ "PageIsSettingsKeys" ] = true
2021-12-10 11:14:24 +03:00
keys , err := asymkey_model . ListDeployKeys ( db . DefaultContext , & asymkey_model . ListDeployKeysOptions { RepoID : ctx . Repo . Repository . ID } )
2015-08-20 12:11:29 +03:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "ListDeployKeys" , err )
2015-08-20 12:11:29 +03:00
return
}
ctx . Data [ "Deploykeys" ] = keys
2015-08-06 17:48:11 +03:00
if ctx . HasError ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplDeployKeys )
2015-08-06 17:48:11 +03:00
return
}
2021-12-10 11:14:24 +03:00
content , err := asymkey_model . CheckPublicKeyString ( form . Content )
2015-08-06 17:48:11 +03:00
if err != nil {
2021-12-10 11:14:24 +03:00
if db . IsErrSSHDisabled ( err ) {
2017-11-21 06:49:33 +03:00
ctx . Flash . Info ( ctx . Tr ( "settings.ssh_disabled" ) )
2021-12-10 11:14:24 +03:00
} else if asymkey_model . IsErrKeyUnableVerify ( err ) {
2015-08-06 17:48:11 +03:00
ctx . Flash . Info ( ctx . Tr ( "form.unable_verify_ssh_key" ) )
} else {
ctx . Data [ "HasError" ] = true
ctx . Data [ "Err_Content" ] = true
ctx . Flash . Error ( ctx . Tr ( "form.invalid_ssh_key" , err . Error ( ) ) )
}
2017-11-21 06:49:33 +03:00
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/keys" )
return
2015-08-06 17:48:11 +03:00
}
2021-12-10 11:14:24 +03:00
key , err := asymkey_model . AddDeployKey ( ctx . Repo . Repository . ID , form . Title , content , ! form . IsWritable )
2015-11-19 05:21:47 +03:00
if err != nil {
2015-08-06 17:48:11 +03:00
ctx . Data [ "HasError" ] = true
switch {
2021-12-10 11:14:24 +03:00
case asymkey_model . IsErrDeployKeyAlreadyExist ( err ) :
2015-08-06 17:48:11 +03:00
ctx . Data [ "Err_Content" ] = true
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.settings.key_been_used" ) , tplDeployKeys , & form )
2021-12-10 11:14:24 +03:00
case asymkey_model . IsErrKeyAlreadyExist ( err ) :
2019-02-04 02:56:53 +03:00
ctx . Data [ "Err_Content" ] = true
ctx . RenderWithErr ( ctx . Tr ( "settings.ssh_key_been_used" ) , tplDeployKeys , & form )
2021-12-10 11:14:24 +03:00
case asymkey_model . IsErrKeyNameAlreadyUsed ( err ) :
2015-08-06 17:48:11 +03:00
ctx . Data [ "Err_Title" ] = true
2016-11-07 23:58:22 +03:00
ctx . RenderWithErr ( ctx . Tr ( "repo.settings.key_name_used" ) , tplDeployKeys , & form )
2021-12-10 11:14:24 +03:00
case asymkey_model . IsErrDeployKeyNameAlreadyUsed ( err ) :
2020-10-12 16:44:56 +03:00
ctx . Data [ "Err_Title" ] = true
ctx . RenderWithErr ( ctx . Tr ( "repo.settings.key_name_used" ) , tplDeployKeys , & form )
2015-08-06 17:48:11 +03:00
default :
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "AddDeployKey" , err )
2015-08-06 17:48:11 +03:00
}
return
}
2015-08-08 17:43:14 +03:00
log . Trace ( "Deploy key added: %d" , ctx . Repo . Repository . ID )
2015-11-19 05:21:47 +03:00
ctx . Flash . Success ( ctx . Tr ( "repo.settings.add_key_success" , key . Name ) )
2015-08-06 17:48:11 +03:00
ctx . Redirect ( ctx . Repo . RepoLink + "/settings/keys" )
}
2016-11-24 10:04:31 +03:00
// DeleteDeployKey response for deleting a deploy key
2016-03-11 19:56:52 +03:00
func DeleteDeployKey ( ctx * context . Context ) {
2021-12-10 11:14:24 +03:00
if err := asymkey_service . DeleteDeployKey ( ctx . User , ctx . FormInt64 ( "id" ) ) ; err != nil {
2015-08-06 17:48:11 +03:00
ctx . Flash . Error ( "DeleteDeployKey: " + err . Error ( ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "repo.settings.deploy_key_deletion_success" ) )
}
2021-04-05 18:30:52 +03:00
ctx . JSON ( http . StatusOK , map [ string ] interface { } {
2015-08-06 17:48:11 +03:00
"redirect" : ctx . Repo . RepoLink + "/settings/keys" ,
} )
2015-07-25 16:32:04 +03:00
}
2019-04-12 23:52:57 +03:00
2019-05-30 05:22:26 +03:00
// UpdateAvatarSetting update repo's avatar
2021-04-06 22:44:05 +03:00
func UpdateAvatarSetting ( ctx * context . Context , form forms . AvatarForm ) error {
2019-05-30 05:22:26 +03:00
ctxRepo := ctx . Repo . Repository
if form . Avatar == nil {
// No avatar is uploaded and we not removing it here.
// No random avatar generated here.
// Just exit, no action.
2020-10-14 16:07:51 +03:00
if ctxRepo . CustomAvatarRelativePath ( ) == "" {
2019-05-30 05:22:26 +03:00
log . Trace ( "No avatar was uploaded for repo: %d. Default icon will appear instead." , ctxRepo . ID )
}
return nil
}
r , err := form . Avatar . Open ( )
if err != nil {
return fmt . Errorf ( "Avatar.Open: %v" , err )
}
defer r . Close ( )
2020-10-14 16:07:51 +03:00
if form . Avatar . Size > setting . Avatar . MaxFileSize {
2019-05-30 05:22:26 +03:00
return errors . New ( ctx . Tr ( "settings.uploaded_avatar_is_too_big" ) )
}
2021-09-22 08:38:34 +03:00
data , err := io . ReadAll ( r )
2019-05-30 05:22:26 +03:00
if err != nil {
2021-09-22 08:38:34 +03:00
return fmt . Errorf ( "io.ReadAll: %v" , err )
2019-05-30 05:22:26 +03:00
}
2021-06-05 15:32:19 +03:00
st := typesniffer . DetectContentType ( data )
if ! ( st . IsImage ( ) && ! st . IsSvgImage ( ) ) {
2019-05-30 05:22:26 +03:00
return errors . New ( ctx . Tr ( "settings.uploaded_avatar_not_a_image" ) )
}
2021-12-12 18:48:20 +03:00
if err = repo_service . UploadAvatar ( ctxRepo , data ) ; err != nil {
2019-05-30 05:22:26 +03:00
return fmt . Errorf ( "UploadAvatar: %v" , err )
}
return nil
}
// SettingsAvatar save new POSTed repository avatar
2021-01-26 18:36:53 +03:00
func SettingsAvatar ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . AvatarForm )
form . Source = forms . AvatarLocal
2021-01-26 18:36:53 +03:00
if err := UpdateAvatarSetting ( ctx , * form ) ; err != nil {
2019-05-30 05:22:26 +03:00
ctx . Flash . Error ( err . Error ( ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "repo.settings.update_avatar_success" ) )
}
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
}
// SettingsDeleteAvatar delete repository avatar
func SettingsDeleteAvatar ( ctx * context . Context ) {
2021-12-12 18:48:20 +03:00
if err := repo_service . DeleteAvatar ( ctx . Repo . Repository ) ; err != nil {
2019-05-30 05:22:26 +03:00
ctx . Flash . Error ( fmt . Sprintf ( "DeleteAvatar: %v" , err ) )
}
ctx . Redirect ( ctx . Repo . RepoLink + "/settings" )
}
2021-06-14 20:20:43 +03:00
2021-12-10 04:27:50 +03:00
func selectPushMirrorByForm ( form * forms . RepoSettingForm , repo * repo_model . Repository ) ( * repo_model . PushMirror , error ) {
2021-06-14 20:20:43 +03:00
id , err := strconv . ParseInt ( form . PushMirrorID , 10 , 64 )
if err != nil {
return nil , err
}
2021-12-10 04:27:50 +03:00
pushMirrors , err := repo_model . GetPushMirrorsByRepoID ( repo . ID )
if err != nil {
2021-06-14 20:20:43 +03:00
return nil , err
}
2021-12-10 04:27:50 +03:00
for _ , m := range pushMirrors {
2021-06-14 20:20:43 +03:00
if m . ID == id {
return m , nil
}
}
return nil , fmt . Errorf ( "PushMirror[%v] not associated to repository %v" , id , repo )
}