mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add setting to set default and global disabled repository units. (#8788)
* Add possibility to global disable repo units. * Add Default Repo Unit app.ini setting. * Hide units * Hide disabled repo units * Minor fixes * Indicate disabled units in team settings. Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		
				
					committed by
					
						
						Lauris BH
					
				
			
			
				
	
			
			
			
						parent
						
							36943e56d6
						
					
				
				
					commit
					3c07d03c03
				
			@@ -42,6 +42,13 @@ DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
 | 
				
			|||||||
; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
 | 
					; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
 | 
				
			||||||
ENABLE_PUSH_CREATE_USER = false
 | 
					ENABLE_PUSH_CREATE_USER = false
 | 
				
			||||||
ENABLE_PUSH_CREATE_ORG = false
 | 
					ENABLE_PUSH_CREATE_ORG = false
 | 
				
			||||||
 | 
					; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki
 | 
				
			||||||
 | 
					DISABLED_REPO_UNITS = 
 | 
				
			||||||
 | 
					; Comma separated list of default repo units. Allowed values: repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki.
 | 
				
			||||||
 | 
					; Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility.
 | 
				
			||||||
 | 
					; External wiki and issue tracker can't be enabled by default as it requires additional settings.
 | 
				
			||||||
 | 
					; Disabled repo units will not be added to new repositories regardless if it is in the default list.
 | 
				
			||||||
 | 
					DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[repository.editor]
 | 
					[repository.editor]
 | 
				
			||||||
; List of file extensions for which lines should be wrapped in the CodeMirror editor
 | 
					; List of file extensions for which lines should be wrapped in the CodeMirror editor
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -128,6 +128,7 @@ func loadRepoConfig() {
 | 
				
			|||||||
// NewRepoContext creates a new repository context
 | 
					// NewRepoContext creates a new repository context
 | 
				
			||||||
func NewRepoContext() {
 | 
					func NewRepoContext() {
 | 
				
			||||||
	loadRepoConfig()
 | 
						loadRepoConfig()
 | 
				
			||||||
 | 
						loadUnitConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(setting.AppDataPath, "tmp"))
 | 
						RemoveAllWithNotice("Clean up repository temporary data", filepath.Join(setting.AppDataPath, "tmp"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -393,6 +394,7 @@ func (repo *Repository) getUnits(e Engine) (err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo.Units, err = getUnitsByRepoID(e, repo.ID)
 | 
						repo.Units, err = getUnitsByRepoID(e, repo.ID)
 | 
				
			||||||
 | 
						log.Trace("repo.Units: %-+v", repo.Units)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1442,14 +1444,19 @@ func UpdateRepositoryUpdatedTime(repoID int64, updateTime time.Time) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateRepositoryUnits updates a repository's units
 | 
					// UpdateRepositoryUnits updates a repository's units
 | 
				
			||||||
func UpdateRepositoryUnits(repo *Repository, units []RepoUnit) (err error) {
 | 
					func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []UnitType) (err error) {
 | 
				
			||||||
	sess := x.NewSession()
 | 
						sess := x.NewSession()
 | 
				
			||||||
	defer sess.Close()
 | 
						defer sess.Close()
 | 
				
			||||||
	if err = sess.Begin(); err != nil {
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err = sess.Where("repo_id = ?", repo.ID).Delete(new(RepoUnit)); err != nil {
 | 
						// Delete existing settings of units before adding again
 | 
				
			||||||
 | 
						for _, u := range units {
 | 
				
			||||||
 | 
							deleteUnitTypes = append(deleteUnitTypes, u.Type)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(RepoUnit)); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -170,5 +170,16 @@ func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) {
 | 
					func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) {
 | 
				
			||||||
	return units, e.Where("repo_id = ?", repoID).Find(&units)
 | 
						var tmpUnits []*RepoUnit
 | 
				
			||||||
 | 
						if err := e.Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, u := range tmpUnits {
 | 
				
			||||||
 | 
							if !u.Type.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								units = append(units, u)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return units, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UnitType is Unit's Type
 | 
					// UnitType is Unit's Type
 | 
				
			||||||
@@ -78,13 +79,89 @@ var (
 | 
				
			|||||||
		UnitTypeWiki,
 | 
							UnitTypeWiki,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// NotAllowedDefaultRepoUnits contains units that can't be default
 | 
				
			||||||
 | 
						NotAllowedDefaultRepoUnits = []UnitType{
 | 
				
			||||||
 | 
							UnitTypeExternalWiki,
 | 
				
			||||||
 | 
							UnitTypeExternalTracker,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// MustRepoUnits contains the units could not be disabled currently
 | 
						// MustRepoUnits contains the units could not be disabled currently
 | 
				
			||||||
	MustRepoUnits = []UnitType{
 | 
						MustRepoUnits = []UnitType{
 | 
				
			||||||
		UnitTypeCode,
 | 
							UnitTypeCode,
 | 
				
			||||||
		UnitTypeReleases,
 | 
							UnitTypeReleases,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DisabledRepoUnits contains the units that have been globally disabled
 | 
				
			||||||
 | 
						DisabledRepoUnits = []UnitType{}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadUnitConfig() {
 | 
				
			||||||
 | 
						setDefaultRepoUnits := FindUnitTypes(setting.Repository.DefaultRepoUnits...)
 | 
				
			||||||
 | 
						// Default repo units set if setting is not empty
 | 
				
			||||||
 | 
						if len(setDefaultRepoUnits) > 0 {
 | 
				
			||||||
 | 
							// MustRepoUnits required as default
 | 
				
			||||||
 | 
							DefaultRepoUnits = make([]UnitType, len(MustRepoUnits))
 | 
				
			||||||
 | 
							copy(DefaultRepoUnits, MustRepoUnits)
 | 
				
			||||||
 | 
							for _, defaultU := range setDefaultRepoUnits {
 | 
				
			||||||
 | 
								if !defaultU.CanBeDefault() {
 | 
				
			||||||
 | 
									log.Warn("Not allowed as default unit: %s", defaultU.String())
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// MustRepoUnits already added
 | 
				
			||||||
 | 
								if defaultU.CanDisable() {
 | 
				
			||||||
 | 
									DefaultRepoUnits = append(DefaultRepoUnits, defaultU)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DisabledRepoUnits = FindUnitTypes(setting.Repository.DisabledRepoUnits...)
 | 
				
			||||||
 | 
						// Check that must units are not disabled
 | 
				
			||||||
 | 
						for i, disabledU := range DisabledRepoUnits {
 | 
				
			||||||
 | 
							if !disabledU.CanDisable() {
 | 
				
			||||||
 | 
								log.Warn("Not allowed to global disable unit %s", disabledU.String())
 | 
				
			||||||
 | 
								DisabledRepoUnits = append(DisabledRepoUnits[:i], DisabledRepoUnits[i+1:]...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Remove disabled units from default units
 | 
				
			||||||
 | 
						for _, disabledU := range DisabledRepoUnits {
 | 
				
			||||||
 | 
							for i, defaultU := range DefaultRepoUnits {
 | 
				
			||||||
 | 
								if defaultU == disabledU {
 | 
				
			||||||
 | 
									DefaultRepoUnits = append(DefaultRepoUnits[:i], DefaultRepoUnits[i+1:]...)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnitGlobalDisabled checks if unit type is global disabled
 | 
				
			||||||
 | 
					func (u UnitType) UnitGlobalDisabled() bool {
 | 
				
			||||||
 | 
						for _, ud := range DisabledRepoUnits {
 | 
				
			||||||
 | 
							if u == ud {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanDisable checks if this unit type can be disabled.
 | 
				
			||||||
 | 
					func (u *UnitType) CanDisable() bool {
 | 
				
			||||||
 | 
						for _, mu := range MustRepoUnits {
 | 
				
			||||||
 | 
							if *u == mu {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanBeDefault checks if the unit type can be a default repo unit
 | 
				
			||||||
 | 
					func (u *UnitType) CanBeDefault() bool {
 | 
				
			||||||
 | 
						for _, nadU := range NotAllowedDefaultRepoUnits {
 | 
				
			||||||
 | 
							if *u == nadU {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Unit is a section of one repository
 | 
					// Unit is a section of one repository
 | 
				
			||||||
type Unit struct {
 | 
					type Unit struct {
 | 
				
			||||||
	Type    UnitType
 | 
						Type    UnitType
 | 
				
			||||||
@@ -96,7 +173,7 @@ type Unit struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// CanDisable returns if this unit could be disabled.
 | 
					// CanDisable returns if this unit could be disabled.
 | 
				
			||||||
func (u *Unit) CanDisable() bool {
 | 
					func (u *Unit) CanDisable() bool {
 | 
				
			||||||
	return true
 | 
						return u.Type.CanDisable()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsLessThan compares order of two units
 | 
					// IsLessThan compares order of two units
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -622,6 +622,7 @@ func (u *User) GetRepositories(page, pageSize int) (err error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepositoryIDs returns repositories IDs where user owned and has unittypes
 | 
					// GetRepositoryIDs returns repositories IDs where user owned and has unittypes
 | 
				
			||||||
 | 
					// Caller shall check that units is not globally disabled
 | 
				
			||||||
func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
					func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	var ids []int64
 | 
						var ids []int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -636,6 +637,7 @@ func (u *User) GetRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetOrgRepositoryIDs returns repositories IDs where user's team owned and has unittypes
 | 
					// GetOrgRepositoryIDs returns repositories IDs where user's team owned and has unittypes
 | 
				
			||||||
 | 
					// Caller shall check that units is not globally disabled
 | 
				
			||||||
func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
					func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	var ids []int64
 | 
						var ids []int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -656,6 +658,7 @@ func (u *User) GetOrgRepositoryIDs(units ...UnitType) ([]int64, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
 | 
					// GetAccessRepoIDs returns all repositories IDs where user's or user is a team member organizations
 | 
				
			||||||
 | 
					// Caller shall check that units is not globally disabled
 | 
				
			||||||
func (u *User) GetAccessRepoIDs(units ...UnitType) ([]int64, error) {
 | 
					func (u *User) GetAccessRepoIDs(units ...UnitType) ([]int64, error) {
 | 
				
			||||||
	ids, err := u.GetRepositoryIDs(units...)
 | 
						ids, err := u.GetRepositoryIDs(units...)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,8 @@ var (
 | 
				
			|||||||
		DefaultCloseIssuesViaCommitsInAnyBranch bool
 | 
							DefaultCloseIssuesViaCommitsInAnyBranch bool
 | 
				
			||||||
		EnablePushCreateUser                    bool
 | 
							EnablePushCreateUser                    bool
 | 
				
			||||||
		EnablePushCreateOrg                     bool
 | 
							EnablePushCreateOrg                     bool
 | 
				
			||||||
 | 
							DisabledRepoUnits                       []string
 | 
				
			||||||
 | 
							DefaultRepoUnits                        []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Repository editor settings
 | 
							// Repository editor settings
 | 
				
			||||||
		Editor struct {
 | 
							Editor struct {
 | 
				
			||||||
@@ -98,6 +100,8 @@ var (
 | 
				
			|||||||
		DefaultCloseIssuesViaCommitsInAnyBranch: false,
 | 
							DefaultCloseIssuesViaCommitsInAnyBranch: false,
 | 
				
			||||||
		EnablePushCreateUser:                    false,
 | 
							EnablePushCreateUser:                    false,
 | 
				
			||||||
		EnablePushCreateOrg:                     false,
 | 
							EnablePushCreateOrg:                     false,
 | 
				
			||||||
 | 
							DisabledRepoUnits:                       []string{},
 | 
				
			||||||
 | 
							DefaultRepoUnits:                        []string{},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Repository editor settings
 | 
							// Repository editor settings
 | 
				
			||||||
		Editor: struct {
 | 
							Editor: struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -636,6 +636,7 @@ stargazers = Stargazers
 | 
				
			|||||||
forks = Forks
 | 
					forks = Forks
 | 
				
			||||||
pick_reaction = Pick your reaction
 | 
					pick_reaction = Pick your reaction
 | 
				
			||||||
reactions_more = and %d more
 | 
					reactions_more = and %d more
 | 
				
			||||||
 | 
					unit_disabled = The site administrator has disabled this repository section.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template.items = Template Items
 | 
					template.items = Template Items
 | 
				
			||||||
template.git_content = Git Content (Default Branch)
 | 
					template.git_content = Git Content (Default Branch)
 | 
				
			||||||
@@ -1613,6 +1614,7 @@ team_desc_helper = Describe the purpose or role of the team.
 | 
				
			|||||||
team_access_desc = Repository access
 | 
					team_access_desc = Repository access
 | 
				
			||||||
team_permission_desc = Permission
 | 
					team_permission_desc = Permission
 | 
				
			||||||
team_unit_desc = Allow Access to Repository Sections
 | 
					team_unit_desc = Allow Access to Repository Sections
 | 
				
			||||||
 | 
					team_unit_disabled = (Disabled)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
form.name_reserved = The organization name '%s' is reserved.
 | 
					form.name_reserved = The organization name '%s' is reserved.
 | 
				
			||||||
form.name_pattern_not_allowed = The pattern '%s' is not allowed in an organization name.
 | 
					form.name_pattern_not_allowed = The pattern '%s' is not allowed in an organization name.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -757,25 +757,10 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 | 
				
			|||||||
	repo := ctx.Repo.Repository
 | 
						repo := ctx.Repo.Repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var units []models.RepoUnit
 | 
						var units []models.RepoUnit
 | 
				
			||||||
 | 
						var deleteUnitTypes []models.UnitType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tp := range models.MustRepoUnits {
 | 
						if opts.HasIssues != nil {
 | 
				
			||||||
		units = append(units, models.RepoUnit{
 | 
							if *opts.HasIssues && opts.ExternalTracker != nil && !models.UnitTypeExternalTracker.UnitGlobalDisabled() {
 | 
				
			||||||
			RepoID: repo.ID,
 | 
					 | 
				
			||||||
			Type:   tp,
 | 
					 | 
				
			||||||
			Config: new(models.UnitConfig),
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if opts.HasIssues == nil {
 | 
					 | 
				
			||||||
		// If HasIssues setting not touched, rewrite existing repo unit
 | 
					 | 
				
			||||||
		if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil {
 | 
					 | 
				
			||||||
			units = append(units, *unit)
 | 
					 | 
				
			||||||
		} else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil {
 | 
					 | 
				
			||||||
			units = append(units, *unit)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if *opts.HasIssues {
 | 
					 | 
				
			||||||
		if opts.ExternalTracker != nil {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Check that values are valid
 | 
								// Check that values are valid
 | 
				
			||||||
			if !validation.IsValidExternalURL(opts.ExternalTracker.ExternalTrackerURL) {
 | 
								if !validation.IsValidExternalURL(opts.ExternalTracker.ExternalTrackerURL) {
 | 
				
			||||||
				err := fmt.Errorf("External tracker URL not valid")
 | 
									err := fmt.Errorf("External tracker URL not valid")
 | 
				
			||||||
@@ -797,7 +782,8 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 | 
				
			|||||||
					ExternalTrackerStyle:  opts.ExternalTracker.ExternalTrackerStyle,
 | 
										ExternalTrackerStyle:  opts.ExternalTracker.ExternalTrackerStyle,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		} else {
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeIssues)
 | 
				
			||||||
 | 
							} else if *opts.HasIssues && opts.ExternalTracker == nil && !models.UnitTypeIssues.UnitGlobalDisabled() {
 | 
				
			||||||
			// Default to built-in tracker
 | 
								// Default to built-in tracker
 | 
				
			||||||
			var config *models.IssuesConfig
 | 
								var config *models.IssuesConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -823,19 +809,19 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 | 
				
			|||||||
				Type:   models.UnitTypeIssues,
 | 
									Type:   models.UnitTypeIssues,
 | 
				
			||||||
				Config: config,
 | 
									Config: config,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalTracker)
 | 
				
			||||||
 | 
							} else if !*opts.HasIssues {
 | 
				
			||||||
 | 
								if !models.UnitTypeExternalTracker.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalTracker)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !models.UnitTypeIssues.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeIssues)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if opts.HasWiki == nil {
 | 
						if opts.HasWiki != nil {
 | 
				
			||||||
		// If HasWiki setting not touched, rewrite existing repo unit
 | 
							if *opts.HasWiki && opts.ExternalWiki != nil && !models.UnitTypeExternalWiki.UnitGlobalDisabled() {
 | 
				
			||||||
		if unit, err := repo.GetUnit(models.UnitTypeWiki); err == nil {
 | 
					 | 
				
			||||||
			units = append(units, *unit)
 | 
					 | 
				
			||||||
		} else if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err == nil {
 | 
					 | 
				
			||||||
			units = append(units, *unit)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if *opts.HasWiki {
 | 
					 | 
				
			||||||
		if opts.ExternalWiki != nil {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Check that values are valid
 | 
								// Check that values are valid
 | 
				
			||||||
			if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) {
 | 
								if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) {
 | 
				
			||||||
				err := fmt.Errorf("External wiki URL not valid")
 | 
									err := fmt.Errorf("External wiki URL not valid")
 | 
				
			||||||
@@ -850,64 +836,72 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 | 
				
			|||||||
					ExternalWikiURL: opts.ExternalWiki.ExternalWikiURL,
 | 
										ExternalWikiURL: opts.ExternalWiki.ExternalWikiURL,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		} else {
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeWiki)
 | 
				
			||||||
 | 
							} else if *opts.HasWiki && opts.ExternalWiki == nil && !models.UnitTypeWiki.UnitGlobalDisabled() {
 | 
				
			||||||
			config := &models.UnitConfig{}
 | 
								config := &models.UnitConfig{}
 | 
				
			||||||
			units = append(units, models.RepoUnit{
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
				RepoID: repo.ID,
 | 
									RepoID: repo.ID,
 | 
				
			||||||
				Type:   models.UnitTypeWiki,
 | 
									Type:   models.UnitTypeWiki,
 | 
				
			||||||
				Config: config,
 | 
									Config: config,
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalWiki)
 | 
				
			||||||
	}
 | 
							} else if !*opts.HasWiki {
 | 
				
			||||||
 | 
								if !models.UnitTypeExternalWiki.UnitGlobalDisabled() {
 | 
				
			||||||
	if opts.HasPullRequests == nil {
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalWiki)
 | 
				
			||||||
		// If HasPullRequest setting not touched, rewrite existing repo unit
 | 
								}
 | 
				
			||||||
		if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil {
 | 
								if !models.UnitTypeWiki.UnitGlobalDisabled() {
 | 
				
			||||||
			units = append(units, *unit)
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeWiki)
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else if *opts.HasPullRequests {
 | 
					 | 
				
			||||||
		// We do allow setting individual PR settings through the API, so
 | 
					 | 
				
			||||||
		// we get the config settings and then set them
 | 
					 | 
				
			||||||
		// if those settings were provided in the opts.
 | 
					 | 
				
			||||||
		unit, err := repo.GetUnit(models.UnitTypePullRequests)
 | 
					 | 
				
			||||||
		var config *models.PullRequestsConfig
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			// Unit type doesn't exist so we make a new config file with default values
 | 
					 | 
				
			||||||
			config = &models.PullRequestsConfig{
 | 
					 | 
				
			||||||
				IgnoreWhitespaceConflicts: false,
 | 
					 | 
				
			||||||
				AllowMerge:                true,
 | 
					 | 
				
			||||||
				AllowRebase:               true,
 | 
					 | 
				
			||||||
				AllowRebaseMerge:          true,
 | 
					 | 
				
			||||||
				AllowSquash:               true,
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			config = unit.PullRequestsConfig()
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if opts.IgnoreWhitespaceConflicts != nil {
 | 
					 | 
				
			||||||
			config.IgnoreWhitespaceConflicts = *opts.IgnoreWhitespaceConflicts
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if opts.AllowMerge != nil {
 | 
					 | 
				
			||||||
			config.AllowMerge = *opts.AllowMerge
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if opts.AllowRebase != nil {
 | 
					 | 
				
			||||||
			config.AllowRebase = *opts.AllowRebase
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if opts.AllowRebaseMerge != nil {
 | 
					 | 
				
			||||||
			config.AllowRebaseMerge = *opts.AllowRebaseMerge
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if opts.AllowSquash != nil {
 | 
					 | 
				
			||||||
			config.AllowSquash = *opts.AllowSquash
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		units = append(units, models.RepoUnit{
 | 
					 | 
				
			||||||
			RepoID: repo.ID,
 | 
					 | 
				
			||||||
			Type:   models.UnitTypePullRequests,
 | 
					 | 
				
			||||||
			Config: config,
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := models.UpdateRepositoryUnits(repo, units); err != nil {
 | 
						if opts.HasPullRequests != nil {
 | 
				
			||||||
 | 
							if *opts.HasPullRequests && !models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								// We do allow setting individual PR settings through the API, so
 | 
				
			||||||
 | 
								// we get the config settings and then set them
 | 
				
			||||||
 | 
								// if those settings were provided in the opts.
 | 
				
			||||||
 | 
								unit, err := repo.GetUnit(models.UnitTypePullRequests)
 | 
				
			||||||
 | 
								var config *models.PullRequestsConfig
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									// Unit type doesn't exist so we make a new config file with default values
 | 
				
			||||||
 | 
									config = &models.PullRequestsConfig{
 | 
				
			||||||
 | 
										IgnoreWhitespaceConflicts: false,
 | 
				
			||||||
 | 
										AllowMerge:                true,
 | 
				
			||||||
 | 
										AllowRebase:               true,
 | 
				
			||||||
 | 
										AllowRebaseMerge:          true,
 | 
				
			||||||
 | 
										AllowSquash:               true,
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									config = unit.PullRequestsConfig()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if opts.IgnoreWhitespaceConflicts != nil {
 | 
				
			||||||
 | 
									config.IgnoreWhitespaceConflicts = *opts.IgnoreWhitespaceConflicts
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if opts.AllowMerge != nil {
 | 
				
			||||||
 | 
									config.AllowMerge = *opts.AllowMerge
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if opts.AllowRebase != nil {
 | 
				
			||||||
 | 
									config.AllowRebase = *opts.AllowRebase
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if opts.AllowRebaseMerge != nil {
 | 
				
			||||||
 | 
									config.AllowRebaseMerge = *opts.AllowRebaseMerge
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if opts.AllowSquash != nil {
 | 
				
			||||||
 | 
									config.AllowSquash = *opts.AllowSquash
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
									RepoID: repo.ID,
 | 
				
			||||||
 | 
									Type:   models.UnitTypePullRequests,
 | 
				
			||||||
 | 
									Config: config,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							} else if !*opts.HasPullRequests && !models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypePullRequests)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := models.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil {
 | 
				
			||||||
		ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err)
 | 
							ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err)
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -205,78 +205,85 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	case "advanced":
 | 
						case "advanced":
 | 
				
			||||||
		var units []models.RepoUnit
 | 
							var units []models.RepoUnit
 | 
				
			||||||
 | 
							var deleteUnitTypes []models.UnitType
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// This section doesn't require repo_name/RepoName to be set in the form, don't show it
 | 
							// 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
 | 
							// as an error on the UI for this action
 | 
				
			||||||
		ctx.Data["Err_RepoName"] = nil
 | 
							ctx.Data["Err_RepoName"] = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for _, tp := range models.MustRepoUnits {
 | 
							if form.EnableWiki && form.EnableExternalWiki && !models.UnitTypeExternalWiki.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								if !validation.IsValidExternalURL(form.ExternalWikiURL) {
 | 
				
			||||||
 | 
									ctx.Flash.Error(ctx.Tr("repo.settings.external_wiki_url_error"))
 | 
				
			||||||
 | 
									ctx.Redirect(repo.Link() + "/settings")
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			units = append(units, models.RepoUnit{
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
				RepoID: repo.ID,
 | 
									RepoID: repo.ID,
 | 
				
			||||||
				Type:   tp,
 | 
									Type:   models.UnitTypeExternalWiki,
 | 
				
			||||||
 | 
									Config: &models.ExternalWikiConfig{
 | 
				
			||||||
 | 
										ExternalWikiURL: form.ExternalWikiURL,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeWiki)
 | 
				
			||||||
 | 
							} else if form.EnableWiki && !form.EnableExternalWiki && !models.UnitTypeWiki.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
									RepoID: repo.ID,
 | 
				
			||||||
 | 
									Type:   models.UnitTypeWiki,
 | 
				
			||||||
				Config: new(models.UnitConfig),
 | 
									Config: new(models.UnitConfig),
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalWiki)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
		if form.EnableWiki {
 | 
								if !models.UnitTypeExternalWiki.UnitGlobalDisabled() {
 | 
				
			||||||
			if form.EnableExternalWiki {
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalWiki)
 | 
				
			||||||
				if !validation.IsValidExternalURL(form.ExternalWikiURL) {
 | 
								}
 | 
				
			||||||
					ctx.Flash.Error(ctx.Tr("repo.settings.external_wiki_url_error"))
 | 
								if !models.UnitTypeWiki.UnitGlobalDisabled() {
 | 
				
			||||||
					ctx.Redirect(repo.Link() + "/settings")
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeWiki)
 | 
				
			||||||
					return
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				units = append(units, models.RepoUnit{
 | 
					 | 
				
			||||||
					RepoID: repo.ID,
 | 
					 | 
				
			||||||
					Type:   models.UnitTypeExternalWiki,
 | 
					 | 
				
			||||||
					Config: &models.ExternalWikiConfig{
 | 
					 | 
				
			||||||
						ExternalWikiURL: form.ExternalWikiURL,
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				units = append(units, models.RepoUnit{
 | 
					 | 
				
			||||||
					RepoID: repo.ID,
 | 
					 | 
				
			||||||
					Type:   models.UnitTypeWiki,
 | 
					 | 
				
			||||||
					Config: new(models.UnitConfig),
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if form.EnableIssues {
 | 
							if form.EnableIssues && form.EnableExternalTracker && !models.UnitTypeExternalTracker.UnitGlobalDisabled() {
 | 
				
			||||||
			if form.EnableExternalTracker {
 | 
								if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
 | 
				
			||||||
				if !validation.IsValidExternalURL(form.ExternalTrackerURL) {
 | 
									ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
 | 
				
			||||||
					ctx.Flash.Error(ctx.Tr("repo.settings.external_tracker_url_error"))
 | 
									ctx.Redirect(repo.Link() + "/settings")
 | 
				
			||||||
					ctx.Redirect(repo.Link() + "/settings")
 | 
									return
 | 
				
			||||||
					return
 | 
								}
 | 
				
			||||||
				}
 | 
								if len(form.TrackerURLFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(form.TrackerURLFormat) {
 | 
				
			||||||
				if len(form.TrackerURLFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(form.TrackerURLFormat) {
 | 
									ctx.Flash.Error(ctx.Tr("repo.settings.tracker_url_format_error"))
 | 
				
			||||||
					ctx.Flash.Error(ctx.Tr("repo.settings.tracker_url_format_error"))
 | 
									ctx.Redirect(repo.Link() + "/settings")
 | 
				
			||||||
					ctx.Redirect(repo.Link() + "/settings")
 | 
									return
 | 
				
			||||||
					return
 | 
								}
 | 
				
			||||||
				}
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
				units = append(units, models.RepoUnit{
 | 
									RepoID: repo.ID,
 | 
				
			||||||
					RepoID: repo.ID,
 | 
									Type:   models.UnitTypeExternalTracker,
 | 
				
			||||||
					Type:   models.UnitTypeExternalTracker,
 | 
									Config: &models.ExternalTrackerConfig{
 | 
				
			||||||
					Config: &models.ExternalTrackerConfig{
 | 
										ExternalTrackerURL:    form.ExternalTrackerURL,
 | 
				
			||||||
						ExternalTrackerURL:    form.ExternalTrackerURL,
 | 
										ExternalTrackerFormat: form.TrackerURLFormat,
 | 
				
			||||||
						ExternalTrackerFormat: form.TrackerURLFormat,
 | 
										ExternalTrackerStyle:  form.TrackerIssueStyle,
 | 
				
			||||||
						ExternalTrackerStyle:  form.TrackerIssueStyle,
 | 
									},
 | 
				
			||||||
					},
 | 
								})
 | 
				
			||||||
				})
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeIssues)
 | 
				
			||||||
			} else {
 | 
							} else if form.EnableIssues && !form.EnableExternalTracker && !models.UnitTypeIssues.UnitGlobalDisabled() {
 | 
				
			||||||
				units = append(units, models.RepoUnit{
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
					RepoID: repo.ID,
 | 
									RepoID: repo.ID,
 | 
				
			||||||
					Type:   models.UnitTypeIssues,
 | 
									Type:   models.UnitTypeIssues,
 | 
				
			||||||
					Config: &models.IssuesConfig{
 | 
									Config: &models.IssuesConfig{
 | 
				
			||||||
						EnableTimetracker:                form.EnableTimetracker,
 | 
										EnableTimetracker:                form.EnableTimetracker,
 | 
				
			||||||
						AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
 | 
										AllowOnlyContributorsToTrackTime: form.AllowOnlyContributorsToTrackTime,
 | 
				
			||||||
						EnableDependencies:               form.EnableIssueDependencies,
 | 
										EnableDependencies:               form.EnableIssueDependencies,
 | 
				
			||||||
					},
 | 
									},
 | 
				
			||||||
				})
 | 
								})
 | 
				
			||||||
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalTracker)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if !models.UnitTypeExternalTracker.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeExternalTracker)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !models.UnitTypeIssues.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
									deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeIssues)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if form.EnablePulls {
 | 
							if form.EnablePulls && !models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
			units = append(units, models.RepoUnit{
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
				RepoID: repo.ID,
 | 
									RepoID: repo.ID,
 | 
				
			||||||
				Type:   models.UnitTypePullRequests,
 | 
									Type:   models.UnitTypePullRequests,
 | 
				
			||||||
@@ -288,9 +295,11 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
 | 
				
			|||||||
					AllowSquash:               form.PullsAllowSquash,
 | 
										AllowSquash:               form.PullsAllowSquash,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
							} else if !models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								deleteUnitTypes = append(deleteUnitTypes, models.UnitTypePullRequests)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := models.UpdateRepositoryUnits(repo, units); err != nil {
 | 
							if err := models.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil {
 | 
				
			||||||
			ctx.ServerError("UpdateRepositoryUnits", err)
 | 
								ctx.ServerError("UpdateRepositoryUnits", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -261,6 +261,11 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Use(user.GetNotificationCount)
 | 
						m.Use(user.GetNotificationCount)
 | 
				
			||||||
 | 
						m.Use(func(ctx *context.Context) {
 | 
				
			||||||
 | 
							ctx.Data["UnitWikiGlobalDisabled"] = models.UnitTypeWiki.UnitGlobalDisabled()
 | 
				
			||||||
 | 
							ctx.Data["UnitIssuesGlobalDisabled"] = models.UnitTypeIssues.UnitGlobalDisabled()
 | 
				
			||||||
 | 
							ctx.Data["UnitPullsGlobalDisabled"] = models.UnitTypePullRequests.UnitGlobalDisabled()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FIXME: not all routes need go through same middlewares.
 | 
						// FIXME: not all routes need go through same middlewares.
 | 
				
			||||||
	// Especially some AJAX requests, we can reduce middleware number to improve performance.
 | 
						// Especially some AJAX requests, we can reduce middleware number to improve performance.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -158,6 +158,12 @@ func Dashboard(ctx *context.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Milestones render the user milestones page
 | 
					// Milestones render the user milestones page
 | 
				
			||||||
func Milestones(ctx *context.Context) {
 | 
					func Milestones(ctx *context.Context) {
 | 
				
			||||||
 | 
						if models.UnitTypeIssues.UnitGlobalDisabled() && models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
							log.Debug("Milestones overview page not available as both issues and pull requests are globally disabled")
 | 
				
			||||||
 | 
							ctx.Status(404)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("milestones")
 | 
						ctx.Data["Title"] = ctx.Tr("milestones")
 | 
				
			||||||
	ctx.Data["PageIsMilestonesDashboard"] = true
 | 
						ctx.Data["PageIsMilestonesDashboard"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -335,10 +341,22 @@ func Issues(ctx *context.Context) {
 | 
				
			|||||||
	isPullList := ctx.Params(":type") == "pulls"
 | 
						isPullList := ctx.Params(":type") == "pulls"
 | 
				
			||||||
	unitType := models.UnitTypeIssues
 | 
						unitType := models.UnitTypeIssues
 | 
				
			||||||
	if isPullList {
 | 
						if isPullList {
 | 
				
			||||||
 | 
							if models.UnitTypePullRequests.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								log.Debug("Pull request overview page not available as it is globally disabled.")
 | 
				
			||||||
 | 
								ctx.Status(404)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Data["Title"] = ctx.Tr("pull_requests")
 | 
							ctx.Data["Title"] = ctx.Tr("pull_requests")
 | 
				
			||||||
		ctx.Data["PageIsPulls"] = true
 | 
							ctx.Data["PageIsPulls"] = true
 | 
				
			||||||
		unitType = models.UnitTypePullRequests
 | 
							unitType = models.UnitTypePullRequests
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							if models.UnitTypeIssues.UnitGlobalDisabled() {
 | 
				
			||||||
 | 
								log.Debug("Issues overview page not available as it is globally disabled.")
 | 
				
			||||||
 | 
								ctx.Status(404)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Data["Title"] = ctx.Tr("issues")
 | 
							ctx.Data["Title"] = ctx.Tr("issues")
 | 
				
			||||||
		ctx.Data["PageIsIssues"] = true
 | 
							ctx.Data["PageIsIssues"] = true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,15 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	{{if .IsSigned}}
 | 
						{{if .IsSigned}}
 | 
				
			||||||
		<a class="item {{if .PageIsDashboard}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "dashboard"}}</a>
 | 
							<a class="item {{if .PageIsDashboard}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "dashboard"}}</a>
 | 
				
			||||||
 | 
							{{if not .UnitIssuesGlobalDisabled}}
 | 
				
			||||||
		<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
 | 
							<a class="item {{if .PageIsIssues}}active{{end}}" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
 | 
				
			||||||
 | 
							{{end}}
 | 
				
			||||||
 | 
							{{if not .UnitPullsGlobalDisabled}}
 | 
				
			||||||
		<a class="item {{if .PageIsPulls}}active{{end}}" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
 | 
							<a class="item {{if .PageIsPulls}}active{{end}}" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
 | 
				
			||||||
 | 
							{{end}}
 | 
				
			||||||
 | 
							{{if not (and .UnitIssuesGlobalDisabled .UnitPullsGlobalDisabled)}}
 | 
				
			||||||
		{{if .ShowMilestonesDashboardPage}}<a class="item {{if .PageIsMilestonesDashboard}}active{{end}}" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>{{end}}
 | 
							{{if .ShowMilestonesDashboardPage}}<a class="item {{if .PageIsMilestonesDashboard}}active{{end}}" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>{{end}}
 | 
				
			||||||
 | 
							{{end}}
 | 
				
			||||||
		<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "explore"}}</a>
 | 
							<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "explore"}}</a>
 | 
				
			||||||
	{{else if .IsLandingPageHome}}
 | 
						{{else if .IsLandingPageHome}}
 | 
				
			||||||
		<a class="item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "home"}}</a>
 | 
							<a class="item {{if .PageIsHome}}active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "home"}}</a>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,10 +81,14 @@
 | 
				
			|||||||
							<label>{{.i18n.Tr "org.team_unit_desc"}}</label>
 | 
												<label>{{.i18n.Tr "org.team_unit_desc"}}</label>
 | 
				
			||||||
							<br>
 | 
												<br>
 | 
				
			||||||
							{{range $t, $unit := $.Units}}
 | 
												{{range $t, $unit := $.Units}}
 | 
				
			||||||
 | 
												{{if $unit.Type.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
												<div class="field poping up" data-content="{{$.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
												{{else}}
 | 
				
			||||||
							<div class="field">
 | 
												<div class="field">
 | 
				
			||||||
 | 
												{{end}}
 | 
				
			||||||
								<div class="ui toggle checkbox">
 | 
													<div class="ui toggle checkbox">
 | 
				
			||||||
									<input type="checkbox" class="hidden" name="units" value="{{$unit.Type.Value}}"{{if or (eq $.Team.ID 0) ($.Team.UnitEnabled $unit.Type)}} checked{{end}}>
 | 
														<input type="checkbox" class="hidden" name="units" value="{{$unit.Type.Value}}"{{if or (eq $.Team.ID 0) ($.Team.UnitEnabled $unit.Type)}} checked{{end}}>
 | 
				
			||||||
									<label>{{$.i18n.Tr $unit.NameKey}}</label>
 | 
														<label>{{$.i18n.Tr $unit.NameKey}}{{if $unit.Type.UnitGlobalDisabled}} {{$.i18n.Tr "org.team_unit_disabled"}}{{end}}</label>
 | 
				
			||||||
									<span class="help">{{$.i18n.Tr $unit.DescKey}}</span>
 | 
														<span class="help">{{$.i18n.Tr $unit.DescKey}}</span>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,20 +144,32 @@
 | 
				
			|||||||
				{{$isWikiEnabled := or (.Repository.UnitEnabled $.UnitTypeWiki) (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}
 | 
									{{$isWikiEnabled := or (.Repository.UnitEnabled $.UnitTypeWiki) (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}
 | 
				
			||||||
				<div class="inline field">
 | 
									<div class="inline field">
 | 
				
			||||||
					<label>{{.i18n.Tr "repo.wiki"}}</label>
 | 
										<label>{{.i18n.Tr "repo.wiki"}}</label>
 | 
				
			||||||
 | 
										{{if and (.UnitTypeWiki.UnitGlobalDisabled) (.UnitTypeExternalWiki.UnitGlobalDisabled)}}
 | 
				
			||||||
 | 
										<div class="ui checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
										{{else}}
 | 
				
			||||||
					<div class="ui checkbox">
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
										{{end}}
 | 
				
			||||||
						<input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if $isWikiEnabled}}checked{{end}}>
 | 
											<input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if $isWikiEnabled}}checked{{end}}>
 | 
				
			||||||
						<label>{{.i18n.Tr "repo.settings.wiki_desc"}}</label>
 | 
											<label>{{.i18n.Tr "repo.settings.wiki_desc"}}</label>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="field {{if not $isWikiEnabled}}disabled{{end}}" id="wiki_box">
 | 
									<div class="field {{if not $isWikiEnabled}}disabled{{end}}" id="wiki_box">
 | 
				
			||||||
					<div class="field">
 | 
										<div class="field">
 | 
				
			||||||
 | 
											{{if .UnitTypeWiki.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
											<div class="ui radio checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
											{{else}}
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
											<div class="ui radio checkbox">
 | 
				
			||||||
 | 
											{{end}}
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}checked{{end}}/>
 | 
												<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalWiki)}}checked{{end}}/>
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.settings.use_internal_wiki"}}</label>
 | 
												<label>{{.i18n.Tr "repo.settings.use_internal_wiki"}}</label>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="field">
 | 
										<div class="field">
 | 
				
			||||||
 | 
											{{if .UnitTypeExternalWiki.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
											<div class="ui radio checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
											{{else}}
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
											<div class="ui radio checkbox">
 | 
				
			||||||
 | 
											{{end}}
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.UnitTypeExternalWiki}}checked{{end}}/>
 | 
												<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.UnitEnabled $.UnitTypeExternalWiki}}checked{{end}}/>
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label>
 | 
												<label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
@@ -174,14 +186,22 @@
 | 
				
			|||||||
				{{$isIssuesEnabled := or (.Repository.UnitEnabled $.UnitTypeIssues) (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}
 | 
									{{$isIssuesEnabled := or (.Repository.UnitEnabled $.UnitTypeIssues) (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}
 | 
				
			||||||
				<div class="inline field">
 | 
									<div class="inline field">
 | 
				
			||||||
					<label>{{.i18n.Tr "repo.issues"}}</label>
 | 
										<label>{{.i18n.Tr "repo.issues"}}</label>
 | 
				
			||||||
 | 
										{{if and (.UnitTypeIssues.UnitGlobalDisabled) (.UnitTypeExternalTracker.UnitGlobalDisabled)}}
 | 
				
			||||||
 | 
										<div class="ui checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
										{{else}}
 | 
				
			||||||
					<div class="ui checkbox">
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
										{{end}}
 | 
				
			||||||
						<input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if $isIssuesEnabled}}checked{{end}}>
 | 
											<input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if $isIssuesEnabled}}checked{{end}}>
 | 
				
			||||||
						<label>{{.i18n.Tr "repo.settings.issues_desc"}}</label>
 | 
											<label>{{.i18n.Tr "repo.settings.issues_desc"}}</label>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="field {{if not $isIssuesEnabled}}disabled{{end}}" id="issue_box">
 | 
									<div class="field {{if not $isIssuesEnabled}}disabled{{end}}" id="issue_box">
 | 
				
			||||||
					<div class="field">
 | 
										<div class="field">
 | 
				
			||||||
 | 
											{{if .UnitTypeIssues.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
											<div class="ui radio checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
											{{else}}
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
											<div class="ui radio checkbox">
 | 
				
			||||||
 | 
											{{end}}
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}checked{{end}}/>
 | 
												<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-context="#internal_issue_box" data-target="#external_issue_box" {{if not (.Repository.UnitEnabled $.UnitTypeExternalTracker)}}checked{{end}}/>
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.settings.use_internal_issue_tracker"}}</label>
 | 
												<label>{{.i18n.Tr "repo.settings.use_internal_issue_tracker"}}</label>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
@@ -209,7 +229,11 @@
 | 
				
			|||||||
							</div>
 | 
												</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="field">
 | 
										<div class="field">
 | 
				
			||||||
 | 
											{{if .UnitTypeExternalTracker.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
											<div class="ui radio checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
											{{else}}
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
											<div class="ui radio checkbox">
 | 
				
			||||||
 | 
											{{end}}
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.UnitTypeExternalTracker}}checked{{end}}/>
 | 
												<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-context="#internal_issue_box" data-target="#external_issue_box" {{if .Repository.UnitEnabled $.UnitTypeExternalTracker}}checked{{end}}/>
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.settings.use_external_issue_tracker"}}</label>
 | 
												<label>{{.i18n.Tr "repo.settings.use_external_issue_tracker"}}</label>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
@@ -251,7 +275,11 @@
 | 
				
			|||||||
					{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
 | 
										{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
 | 
				
			||||||
					<div class="inline field">
 | 
										<div class="inline field">
 | 
				
			||||||
						<label>{{.i18n.Tr "repo.pulls"}}</label>
 | 
											<label>{{.i18n.Tr "repo.pulls"}}</label>
 | 
				
			||||||
 | 
											{{if .UnitTypePullRequests.UnitGlobalDisabled}}
 | 
				
			||||||
 | 
											<div class="ui checkbox poping up disabled" data-content="{{.i18n.Tr "repo.unit_disabled"}}">
 | 
				
			||||||
 | 
											{{else}}
 | 
				
			||||||
						<div class="ui checkbox">
 | 
											<div class="ui checkbox">
 | 
				
			||||||
 | 
											{{end}}
 | 
				
			||||||
							<input class="enable-system" name="enable_pulls" type="checkbox" data-target="#pull_box" {{if $pullRequestEnabled}}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>
 | 
												<label>{{.i18n.Tr "repo.settings.pulls_desc"}}</label>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user