Add units concept for modulable functions of a repository (#742)
* Add units concept for modulable functions of a repository * remove unused comment codes & fix lints and tests * remove unused comment codes * use struct config instead of map * fix lint * rm wrong files * fix tests
This commit is contained in:
		
							parent
							
								
									49fa03bf42
								
							
						
					
					
						commit
						8a421b1fd7
					
				| 
						 | 
					@ -441,7 +441,7 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}, func(ctx *context.Context) {
 | 
							}, func(ctx *context.Context) {
 | 
				
			||||||
			ctx.Data["PageIsSettings"] = true
 | 
								ctx.Data["PageIsSettings"] = true
 | 
				
			||||||
		})
 | 
							}, context.UnitTypes())
 | 
				
			||||||
	}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
 | 
						}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
 | 
						m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action)
 | 
				
			||||||
| 
						 | 
					@ -535,7 +535,7 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare)
 | 
						}, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Group("/:username/:reponame", func() {
 | 
						m.Group("/:username/:reponame", func() {
 | 
				
			||||||
		m.Group("", func() {
 | 
							m.Group("", func() {
 | 
				
			||||||
| 
						 | 
					@ -581,7 +581,7 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			||||||
		m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff)
 | 
							m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.CompareDiff)
 | 
							m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.CompareDiff)
 | 
				
			||||||
	}, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare)
 | 
						}, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes())
 | 
				
			||||||
	m.Group("/:username/:reponame", func() {
 | 
						m.Group("/:username/:reponame", func() {
 | 
				
			||||||
		m.Get("/stars", repo.Stars)
 | 
							m.Get("/stars", repo.Stars)
 | 
				
			||||||
		m.Get("/watchers", repo.Watchers)
 | 
							m.Get("/watchers", repo.Watchers)
 | 
				
			||||||
| 
						 | 
					@ -591,7 +591,7 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			||||||
		m.Group("/:reponame", func() {
 | 
							m.Group("/:reponame", func() {
 | 
				
			||||||
			m.Get("", repo.SetEditorconfigIfExists, repo.Home)
 | 
								m.Get("", repo.SetEditorconfigIfExists, repo.Home)
 | 
				
			||||||
			m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home)
 | 
								m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home)
 | 
				
			||||||
		}, ignSignIn, context.RepoAssignment(true), context.RepoRef())
 | 
							}, ignSignIn, context.RepoAssignment(true), context.RepoRef(), context.UnitTypes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m.Group("/:reponame", func() {
 | 
							m.Group("/:reponame", func() {
 | 
				
			||||||
			m.Group("/info/lfs", func() {
 | 
								m.Group("/info/lfs", func() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,10 +76,12 @@ var migrations = []Migration{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// v13 -> v14:v0.9.87
 | 
						// v13 -> v14:v0.9.87
 | 
				
			||||||
	NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
 | 
						NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
 | 
				
			||||||
	// v14
 | 
						// v14 -> v15
 | 
				
			||||||
	NewMigration("create user column diff view style", createUserColumnDiffViewStyle),
 | 
						NewMigration("create user column diff view style", createUserColumnDiffViewStyle),
 | 
				
			||||||
	// v15
 | 
						// v15 -> v16
 | 
				
			||||||
	NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn),
 | 
						NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn),
 | 
				
			||||||
 | 
						// V16 -> v17
 | 
				
			||||||
 | 
						NewMigration("create repo unit table and add units for all repos", addUnitsToTables),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Migrate database to current version
 | 
					// Migrate database to current version
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,117 @@
 | 
				
			||||||
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/markdown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RepoUnit describes all units of a repository
 | 
				
			||||||
 | 
					type RepoUnit struct {
 | 
				
			||||||
 | 
						ID          int64
 | 
				
			||||||
 | 
						RepoID      int64 `xorm:"INDEX(s)"`
 | 
				
			||||||
 | 
						Type        int   `xorm:"INDEX(s)"`
 | 
				
			||||||
 | 
						Index       int
 | 
				
			||||||
 | 
						Config      map[string]string `xorm:"JSON"`
 | 
				
			||||||
 | 
						CreatedUnix int64             `xorm:"INDEX CREATED"`
 | 
				
			||||||
 | 
						Created     time.Time         `xorm:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enumerate all the unit types
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						UnitTypeCode            = iota + 1 // 1 code
 | 
				
			||||||
 | 
						UnitTypeIssues                     // 2 issues
 | 
				
			||||||
 | 
						UnitTypePRs                        // 3 PRs
 | 
				
			||||||
 | 
						UnitTypeCommits                    // 4 Commits
 | 
				
			||||||
 | 
						UnitTypeReleases                   // 5 Releases
 | 
				
			||||||
 | 
						UnitTypeWiki                       // 6 Wiki
 | 
				
			||||||
 | 
						UnitTypeSettings                   // 7 Settings
 | 
				
			||||||
 | 
						UnitTypeExternalWiki               // 8 ExternalWiki
 | 
				
			||||||
 | 
						UnitTypeExternalTracker            // 9 ExternalTracker
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Repo describes a repository
 | 
				
			||||||
 | 
					type Repo struct {
 | 
				
			||||||
 | 
						ID                                                                               int64
 | 
				
			||||||
 | 
						EnableWiki, EnableExternalWiki, EnableIssues, EnableExternalTracker, EnablePulls bool
 | 
				
			||||||
 | 
						ExternalWikiURL, ExternalTrackerURL, ExternalTrackerFormat, ExternalTrackerStyle string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addUnitsToTables(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						var repos []Repo
 | 
				
			||||||
 | 
						err := x.Table("repository").Find(&repos)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Query repositories: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sess.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var repoUnit RepoUnit
 | 
				
			||||||
 | 
						if err := sess.CreateTable(&repoUnit); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("CreateTable RepoUnit: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sess.CreateUniques(&repoUnit); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("CreateUniques RepoUnit: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sess.CreateIndexes(&repoUnit); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("CreateIndexes RepoUnit: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, repo := range repos {
 | 
				
			||||||
 | 
							for i := 1; i <= 9; i++ {
 | 
				
			||||||
 | 
								if (i == UnitTypeWiki || i == UnitTypeExternalWiki) && !repo.EnableWiki {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if i == UnitTypeExternalWiki && !repo.EnableExternalWiki {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if i == UnitTypePRs && !repo.EnablePulls {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (i == UnitTypeIssues || i == UnitTypeExternalTracker) && !repo.EnableIssues {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if i == UnitTypeExternalTracker && !repo.EnableExternalTracker {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var config = make(map[string]string)
 | 
				
			||||||
 | 
								switch i {
 | 
				
			||||||
 | 
								case UnitTypeExternalTracker:
 | 
				
			||||||
 | 
									config["ExternalTrackerURL"] = repo.ExternalTrackerURL
 | 
				
			||||||
 | 
									config["ExternalTrackerFormat"] = repo.ExternalTrackerFormat
 | 
				
			||||||
 | 
									if len(repo.ExternalTrackerStyle) == 0 {
 | 
				
			||||||
 | 
										repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									config["ExternalTrackerStyle"] = repo.ExternalTrackerStyle
 | 
				
			||||||
 | 
								case UnitTypeExternalWiki:
 | 
				
			||||||
 | 
									config["ExternalWikiURL"] = repo.ExternalWikiURL
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if _, err = sess.Insert(&RepoUnit{
 | 
				
			||||||
 | 
									RepoID: repo.ID,
 | 
				
			||||||
 | 
									Type:   i,
 | 
				
			||||||
 | 
									Index:  i,
 | 
				
			||||||
 | 
									Config: config,
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									return fmt.Errorf("Insert repo unit: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := sess.Commit(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -106,6 +106,7 @@ func init() {
 | 
				
			||||||
		new(IssueUser),
 | 
							new(IssueUser),
 | 
				
			||||||
		new(LFSMetaObject),
 | 
							new(LFSMetaObject),
 | 
				
			||||||
		new(TwoFactor),
 | 
							new(TwoFactor),
 | 
				
			||||||
 | 
							new(RepoUnit),
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gonicNames := []string{"SSL", "UID"}
 | 
						gonicNames := []string{"SSL", "UID"}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										136
									
								
								models/repo.go
								
								
								
								
							
							
						
						
									
										136
									
								
								models/repo.go
								
								
								
								
							| 
						 | 
					@ -200,17 +200,8 @@ type Repository struct {
 | 
				
			||||||
	IsMirror bool `xorm:"INDEX"`
 | 
						IsMirror bool `xorm:"INDEX"`
 | 
				
			||||||
	*Mirror  `xorm:"-"`
 | 
						*Mirror  `xorm:"-"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Advanced settings
 | 
					 | 
				
			||||||
	EnableWiki            bool `xorm:"NOT NULL DEFAULT true"`
 | 
					 | 
				
			||||||
	EnableExternalWiki    bool
 | 
					 | 
				
			||||||
	ExternalWikiURL       string
 | 
					 | 
				
			||||||
	EnableIssues          bool `xorm:"NOT NULL DEFAULT true"`
 | 
					 | 
				
			||||||
	EnableExternalTracker bool
 | 
					 | 
				
			||||||
	ExternalTrackerURL    string
 | 
					 | 
				
			||||||
	ExternalTrackerFormat string
 | 
					 | 
				
			||||||
	ExternalTrackerStyle  string
 | 
					 | 
				
			||||||
	ExternalMetas map[string]string `xorm:"-"`
 | 
						ExternalMetas map[string]string `xorm:"-"`
 | 
				
			||||||
	EnablePulls           bool              `xorm:"NOT NULL DEFAULT true"`
 | 
						Units         []*RepoUnit       `xorm:"-"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IsFork   bool        `xorm:"INDEX NOT NULL DEFAULT false"`
 | 
						IsFork   bool        `xorm:"INDEX NOT NULL DEFAULT false"`
 | 
				
			||||||
	ForkID   int64       `xorm:"INDEX"`
 | 
						ForkID   int64       `xorm:"INDEX"`
 | 
				
			||||||
| 
						 | 
					@ -247,10 +238,6 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
 | 
				
			||||||
		repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls
 | 
							repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls
 | 
				
			||||||
	case "num_closed_milestones":
 | 
						case "num_closed_milestones":
 | 
				
			||||||
		repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
 | 
							repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
 | 
				
			||||||
	case "external_tracker_style":
 | 
					 | 
				
			||||||
		if len(repo.ExternalTrackerStyle) == 0 {
 | 
					 | 
				
			||||||
			repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case "created_unix":
 | 
						case "created_unix":
 | 
				
			||||||
		repo.Created = time.Unix(repo.CreatedUnix, 0).Local()
 | 
							repo.Created = time.Unix(repo.CreatedUnix, 0).Local()
 | 
				
			||||||
	case "updated_unix":
 | 
						case "updated_unix":
 | 
				
			||||||
| 
						 | 
					@ -307,6 +294,72 @@ func (repo *Repository) APIFormat(mode AccessMode) *api.Repository {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (repo *Repository) getUnits(e Engine) (err error) {
 | 
				
			||||||
 | 
						if repo.Units != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repo.Units, err = getUnitsByRepoID(e, repo.ID)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) {
 | 
				
			||||||
 | 
						return units, e.Where("repo_id = ?", repoID).Find(&units)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EnableUnit if this repository enabled some unit
 | 
				
			||||||
 | 
					func (repo *Repository) EnableUnit(tp UnitType) bool {
 | 
				
			||||||
 | 
						repo.getUnits(x)
 | 
				
			||||||
 | 
						for _, unit := range repo.Units {
 | 
				
			||||||
 | 
							if unit.Type == tp {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// ErrUnitNotExist organization does not exist
 | 
				
			||||||
 | 
						ErrUnitNotExist = errors.New("Unit does not exist")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// MustGetUnit always returns a RepoUnit object
 | 
				
			||||||
 | 
					func (repo *Repository) MustGetUnit(tp UnitType) *RepoUnit {
 | 
				
			||||||
 | 
						ru, err := repo.GetUnit(tp)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return ru
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if tp == UnitTypeExternalWiki {
 | 
				
			||||||
 | 
							return &RepoUnit{
 | 
				
			||||||
 | 
								Type:   tp,
 | 
				
			||||||
 | 
								Config: new(ExternalWikiConfig),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if tp == UnitTypeExternalTracker {
 | 
				
			||||||
 | 
							return &RepoUnit{
 | 
				
			||||||
 | 
								Type:   tp,
 | 
				
			||||||
 | 
								Config: new(ExternalTrackerConfig),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &RepoUnit{
 | 
				
			||||||
 | 
							Type:   tp,
 | 
				
			||||||
 | 
							Config: new(UnitConfig),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUnit returns a RepoUnit object
 | 
				
			||||||
 | 
					func (repo *Repository) GetUnit(tp UnitType) (*RepoUnit, error) {
 | 
				
			||||||
 | 
						if err := repo.getUnits(x); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, unit := range repo.Units {
 | 
				
			||||||
 | 
							if unit.Type == tp {
 | 
				
			||||||
 | 
								return unit, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil, ErrUnitNotExist
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (repo *Repository) getOwner(e Engine) (err error) {
 | 
					func (repo *Repository) getOwner(e Engine) (err error) {
 | 
				
			||||||
	if repo.Owner != nil {
 | 
						if repo.Owner != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
| 
						 | 
					@ -334,15 +387,18 @@ func (repo *Repository) mustOwner(e Engine) *User {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ComposeMetas composes a map of metas for rendering external issue tracker URL.
 | 
					// ComposeMetas composes a map of metas for rendering external issue tracker URL.
 | 
				
			||||||
func (repo *Repository) ComposeMetas() map[string]string {
 | 
					func (repo *Repository) ComposeMetas() map[string]string {
 | 
				
			||||||
	if !repo.EnableExternalTracker {
 | 
						unit, err := repo.GetUnit(UnitTypeExternalTracker)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	} else if repo.ExternalMetas == nil {
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if repo.ExternalMetas == nil {
 | 
				
			||||||
		repo.ExternalMetas = map[string]string{
 | 
							repo.ExternalMetas = map[string]string{
 | 
				
			||||||
			"format": repo.ExternalTrackerFormat,
 | 
								"format": unit.ExternalTrackerConfig().ExternalTrackerFormat,
 | 
				
			||||||
			"user":   repo.MustOwner().Name,
 | 
								"user":   repo.MustOwner().Name,
 | 
				
			||||||
			"repo":   repo.Name,
 | 
								"repo":   repo.Name,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		switch repo.ExternalTrackerStyle {
 | 
							switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
 | 
				
			||||||
		case markdown.IssueNameStyleAlphanumeric:
 | 
							case markdown.IssueNameStyleAlphanumeric:
 | 
				
			||||||
			repo.ExternalMetas["style"] = markdown.IssueNameStyleAlphanumeric
 | 
								repo.ExternalMetas["style"] = markdown.IssueNameStyleAlphanumeric
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
| 
						 | 
					@ -359,6 +415,8 @@ func (repo *Repository) DeleteWiki() {
 | 
				
			||||||
	for _, wikiPath := range wikiPaths {
 | 
						for _, wikiPath := range wikiPaths {
 | 
				
			||||||
		RemoveAllWithNotice("Delete repository wiki", wikiPath)
 | 
							RemoveAllWithNotice("Delete repository wiki", wikiPath)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x.Where("repo_id = ?", repo.ID).And("type = ?", UnitTypeWiki).Delete(new(RepoUnit))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
 | 
					func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) {
 | 
				
			||||||
| 
						 | 
					@ -482,7 +540,7 @@ func (repo *Repository) CanEnablePulls() bool {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
 | 
					// AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
 | 
				
			||||||
func (repo *Repository) AllowsPulls() bool {
 | 
					func (repo *Repository) AllowsPulls() bool {
 | 
				
			||||||
	return repo.CanEnablePulls() && repo.EnablePulls
 | 
						return repo.CanEnablePulls() && repo.EnableUnit(UnitTypePullRequests)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CanEnableEditor returns true if repository meets the requirements of web editor.
 | 
					// CanEnableEditor returns true if repository meets the requirements of web editor.
 | 
				
			||||||
| 
						 | 
					@ -997,6 +1055,20 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// insert units for repo
 | 
				
			||||||
 | 
						var units = make([]RepoUnit, 0, len(defaultRepoUnits))
 | 
				
			||||||
 | 
						for i, tp := range defaultRepoUnits {
 | 
				
			||||||
 | 
							units = append(units, RepoUnit{
 | 
				
			||||||
 | 
								RepoID: repo.ID,
 | 
				
			||||||
 | 
								Type:   tp,
 | 
				
			||||||
 | 
								Index:  i,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = e.Insert(&units); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u.NumRepos++
 | 
						u.NumRepos++
 | 
				
			||||||
	// Remember visibility preference.
 | 
						// Remember visibility preference.
 | 
				
			||||||
	u.LastRepoVisibility = repo.IsPrivate
 | 
						u.LastRepoVisibility = repo.IsPrivate
 | 
				
			||||||
| 
						 | 
					@ -1041,9 +1113,6 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
 | 
				
			||||||
		LowerName:   strings.ToLower(opts.Name),
 | 
							LowerName:   strings.ToLower(opts.Name),
 | 
				
			||||||
		Description: opts.Description,
 | 
							Description: opts.Description,
 | 
				
			||||||
		IsPrivate:   opts.IsPrivate,
 | 
							IsPrivate:   opts.IsPrivate,
 | 
				
			||||||
		EnableWiki:   true,
 | 
					 | 
				
			||||||
		EnableIssues: true,
 | 
					 | 
				
			||||||
		EnablePulls:  true,
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess := x.NewSession()
 | 
						sess := x.NewSession()
 | 
				
			||||||
| 
						 | 
					@ -1380,6 +1449,25 @@ func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) {
 | 
				
			||||||
	return sess.Commit()
 | 
						return sess.Commit()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateRepositoryUnits updates a repository's units
 | 
				
			||||||
 | 
					func UpdateRepositoryUnits(repo *Repository, units []RepoUnit) (err error) {
 | 
				
			||||||
 | 
						sess := x.NewSession()
 | 
				
			||||||
 | 
						defer sess.Close()
 | 
				
			||||||
 | 
						if err = sess.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Where("repo_id = ?", repo.ID).Delete(new(RepoUnit)); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Insert(units); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return sess.Commit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteRepository deletes a repository for a user or organization.
 | 
					// DeleteRepository deletes a repository for a user or organization.
 | 
				
			||||||
func DeleteRepository(uid, repoID int64) error {
 | 
					func DeleteRepository(uid, repoID int64) error {
 | 
				
			||||||
	repo := &Repository{ID: repoID, OwnerID: uid}
 | 
						repo := &Repository{ID: repoID, OwnerID: uid}
 | 
				
			||||||
| 
						 | 
					@ -1467,6 +1555,10 @@ func DeleteRepository(uid, repoID int64) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if repo.IsFork {
 | 
						if repo.IsFork {
 | 
				
			||||||
		if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
 | 
							if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil {
 | 
				
			||||||
			return fmt.Errorf("decrease fork count: %v", err)
 | 
								return fmt.Errorf("decrease fork count: %v", err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,34 +14,42 @@ func TestRepo(t *testing.T) {
 | 
				
			||||||
		repo.Name = "testrepo"
 | 
							repo.Name = "testrepo"
 | 
				
			||||||
		repo.Owner = new(User)
 | 
							repo.Owner = new(User)
 | 
				
			||||||
		repo.Owner.Name = "testuser"
 | 
							repo.Owner.Name = "testuser"
 | 
				
			||||||
		repo.ExternalTrackerFormat = "https://someurl.com/{user}/{repo}/{issue}"
 | 
							externalTracker := RepoUnit{
 | 
				
			||||||
 | 
								Type: UnitTypeExternalTracker,
 | 
				
			||||||
 | 
								Config: &ExternalTrackerConfig{
 | 
				
			||||||
 | 
									ExternalTrackerFormat: "https://someurl.com/{user}/{repo}/{issue}",
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							repo.Units = []*RepoUnit{
 | 
				
			||||||
 | 
								&externalTracker,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Convey("When no external tracker is configured", func() {
 | 
							Convey("When no external tracker is configured", func() {
 | 
				
			||||||
			Convey("It should be nil", func() {
 | 
								Convey("It should be nil", func() {
 | 
				
			||||||
				repo.EnableExternalTracker = false
 | 
									repo.Units = nil
 | 
				
			||||||
				So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil))
 | 
									So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil))
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			Convey("It should be nil even if other settings are present", func() {
 | 
								Convey("It should be nil even if other settings are present", func() {
 | 
				
			||||||
				repo.EnableExternalTracker = false
 | 
									repo.Units = nil
 | 
				
			||||||
				repo.ExternalTrackerFormat = "http://someurl.com/{user}/{repo}/{issue}"
 | 
					 | 
				
			||||||
				repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric
 | 
					 | 
				
			||||||
				So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil))
 | 
									So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil))
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Convey("When an external issue tracker is configured", func() {
 | 
							Convey("When an external issue tracker is configured", func() {
 | 
				
			||||||
			repo.EnableExternalTracker = true
 | 
								repo.Units = []*RepoUnit{
 | 
				
			||||||
 | 
									&externalTracker,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			Convey("It should default to numeric issue style", func() {
 | 
								Convey("It should default to numeric issue style", func() {
 | 
				
			||||||
				metas := repo.ComposeMetas()
 | 
									metas := repo.ComposeMetas()
 | 
				
			||||||
				So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric)
 | 
									So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric)
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			Convey("It should pass through numeric issue style setting", func() {
 | 
								Convey("It should pass through numeric issue style setting", func() {
 | 
				
			||||||
				repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric
 | 
									externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markdown.IssueNameStyleNumeric
 | 
				
			||||||
				metas := repo.ComposeMetas()
 | 
									metas := repo.ComposeMetas()
 | 
				
			||||||
				So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric)
 | 
									So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric)
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			Convey("It should pass through alphanumeric issue style setting", func() {
 | 
								Convey("It should pass through alphanumeric issue style setting", func() {
 | 
				
			||||||
				repo.ExternalTrackerStyle = markdown.IssueNameStyleAlphanumeric
 | 
									externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markdown.IssueNameStyleAlphanumeric
 | 
				
			||||||
				metas := repo.ComposeMetas()
 | 
									metas := repo.ComposeMetas()
 | 
				
			||||||
				So(metas["style"], ShouldEqual, markdown.IssueNameStyleAlphanumeric)
 | 
									So(metas["style"], ShouldEqual, markdown.IssueNameStyleAlphanumeric)
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,137 @@
 | 
				
			||||||
 | 
					// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
 | 
						"github.com/go-xorm/core"
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RepoUnit describes all units of a repository
 | 
				
			||||||
 | 
					type RepoUnit struct {
 | 
				
			||||||
 | 
						ID          int64
 | 
				
			||||||
 | 
						RepoID      int64    `xorm:"INDEX(s)"`
 | 
				
			||||||
 | 
						Type        UnitType `xorm:"INDEX(s)"`
 | 
				
			||||||
 | 
						Index       int
 | 
				
			||||||
 | 
						Config      core.Conversion `xorm:"TEXT"`
 | 
				
			||||||
 | 
						CreatedUnix int64           `xorm:"INDEX CREATED"`
 | 
				
			||||||
 | 
						Created     time.Time       `xorm:"-"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnitConfig describes common unit config
 | 
				
			||||||
 | 
					type UnitConfig struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FromDB fills up a UnitConfig from serialized format.
 | 
				
			||||||
 | 
					func (cfg *UnitConfig) FromDB(bs []byte) error {
 | 
				
			||||||
 | 
						return json.Unmarshal(bs, &cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToDB exports a UnitConfig to a serialized format.
 | 
				
			||||||
 | 
					func (cfg *UnitConfig) ToDB() ([]byte, error) {
 | 
				
			||||||
 | 
						return json.Marshal(cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExternalWikiConfig describes external wiki config
 | 
				
			||||||
 | 
					type ExternalWikiConfig struct {
 | 
				
			||||||
 | 
						ExternalWikiURL string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FromDB fills up a ExternalWikiConfig from serialized format.
 | 
				
			||||||
 | 
					func (cfg *ExternalWikiConfig) FromDB(bs []byte) error {
 | 
				
			||||||
 | 
						return json.Unmarshal(bs, &cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToDB exports a ExternalWikiConfig to a serialized format.
 | 
				
			||||||
 | 
					func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) {
 | 
				
			||||||
 | 
						return json.Marshal(cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExternalTrackerConfig describes external tracker config
 | 
				
			||||||
 | 
					type ExternalTrackerConfig struct {
 | 
				
			||||||
 | 
						ExternalTrackerURL    string
 | 
				
			||||||
 | 
						ExternalTrackerFormat string
 | 
				
			||||||
 | 
						ExternalTrackerStyle  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FromDB fills up a ExternalTrackerConfig from serialized format.
 | 
				
			||||||
 | 
					func (cfg *ExternalTrackerConfig) FromDB(bs []byte) error {
 | 
				
			||||||
 | 
						return json.Unmarshal(bs, &cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToDB exports a ExternalTrackerConfig to a serialized format.
 | 
				
			||||||
 | 
					func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) {
 | 
				
			||||||
 | 
						return json.Marshal(cfg)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// BeforeSet is invoked from XORM before setting the value of a field of this object.
 | 
				
			||||||
 | 
					func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
 | 
				
			||||||
 | 
						switch colName {
 | 
				
			||||||
 | 
						case "type":
 | 
				
			||||||
 | 
							switch UnitType(Cell2Int64(val)) {
 | 
				
			||||||
 | 
							case UnitTypeCode, UnitTypeIssues, UnitTypePullRequests, UnitTypeCommits, UnitTypeReleases,
 | 
				
			||||||
 | 
								UnitTypeWiki, UnitTypeSettings:
 | 
				
			||||||
 | 
								r.Config = new(UnitConfig)
 | 
				
			||||||
 | 
							case UnitTypeExternalWiki:
 | 
				
			||||||
 | 
								r.Config = new(ExternalWikiConfig)
 | 
				
			||||||
 | 
							case UnitTypeExternalTracker:
 | 
				
			||||||
 | 
								r.Config = new(ExternalTrackerConfig)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								panic("unrecognized repo unit type: " + com.ToStr(*val))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AfterSet is invoked from XORM after setting the value of a field of this object.
 | 
				
			||||||
 | 
					func (r *RepoUnit) AfterSet(colName string, _ xorm.Cell) {
 | 
				
			||||||
 | 
						switch colName {
 | 
				
			||||||
 | 
						case "created_unix":
 | 
				
			||||||
 | 
							r.Created = time.Unix(r.CreatedUnix, 0).Local()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unit returns Unit
 | 
				
			||||||
 | 
					func (r *RepoUnit) Unit() Unit {
 | 
				
			||||||
 | 
						return Units[r.Type]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CodeConfig returns config for UnitTypeCode
 | 
				
			||||||
 | 
					func (r *RepoUnit) CodeConfig() *UnitConfig {
 | 
				
			||||||
 | 
						return r.Config.(*UnitConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IssuesConfig returns config for UnitTypeIssues
 | 
				
			||||||
 | 
					func (r *RepoUnit) IssuesConfig() *UnitConfig {
 | 
				
			||||||
 | 
						return r.Config.(*UnitConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PullRequestsConfig returns config for UnitTypePullRequests
 | 
				
			||||||
 | 
					func (r *RepoUnit) PullRequestsConfig() *UnitConfig {
 | 
				
			||||||
 | 
						return r.Config.(*UnitConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CommitsConfig returns config for UnitTypeCommits
 | 
				
			||||||
 | 
					func (r *RepoUnit) CommitsConfig() *UnitConfig {
 | 
				
			||||||
 | 
						return r.Config.(*UnitConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ReleasesConfig returns config for UnitTypeReleases
 | 
				
			||||||
 | 
					func (r *RepoUnit) ReleasesConfig() *UnitConfig {
 | 
				
			||||||
 | 
						return r.Config.(*UnitConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExternalWikiConfig returns config for UnitTypeExternalWiki
 | 
				
			||||||
 | 
					func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig {
 | 
				
			||||||
 | 
						return r.Config.(*ExternalWikiConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExternalTrackerConfig returns config for UnitTypeExternalTracker
 | 
				
			||||||
 | 
					func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig {
 | 
				
			||||||
 | 
						return r.Config.(*ExternalTrackerConfig)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,137 @@
 | 
				
			||||||
 | 
					// Copyright 2017 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnitType is Unit's Type
 | 
				
			||||||
 | 
					type UnitType int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enumerate all the unit types
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						UnitTypeCode            UnitType = iota + 1 // 1 code
 | 
				
			||||||
 | 
						UnitTypeIssues                              // 2 issues
 | 
				
			||||||
 | 
						UnitTypePullRequests                        // 3 PRs
 | 
				
			||||||
 | 
						UnitTypeCommits                             // 4 Commits
 | 
				
			||||||
 | 
						UnitTypeReleases                            // 5 Releases
 | 
				
			||||||
 | 
						UnitTypeWiki                                // 6 Wiki
 | 
				
			||||||
 | 
						UnitTypeSettings                            // 7 Settings
 | 
				
			||||||
 | 
						UnitTypeExternalWiki                        // 8 ExternalWiki
 | 
				
			||||||
 | 
						UnitTypeExternalTracker                     // 9 ExternalTracker
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Unit is a tab page of one repository
 | 
				
			||||||
 | 
					type Unit struct {
 | 
				
			||||||
 | 
						Type    UnitType
 | 
				
			||||||
 | 
						NameKey string
 | 
				
			||||||
 | 
						URI     string
 | 
				
			||||||
 | 
						DescKey string
 | 
				
			||||||
 | 
						Idx     int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Enumerate all the units
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						UnitCode = Unit{
 | 
				
			||||||
 | 
							UnitTypeCode,
 | 
				
			||||||
 | 
							"repo.code",
 | 
				
			||||||
 | 
							"/",
 | 
				
			||||||
 | 
							"repo.code_desc",
 | 
				
			||||||
 | 
							0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitIssues = Unit{
 | 
				
			||||||
 | 
							UnitTypeIssues,
 | 
				
			||||||
 | 
							"repo.issues",
 | 
				
			||||||
 | 
							"/issues",
 | 
				
			||||||
 | 
							"repo.issues_desc",
 | 
				
			||||||
 | 
							1,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitExternalTracker = Unit{
 | 
				
			||||||
 | 
							UnitTypeExternalTracker,
 | 
				
			||||||
 | 
							"repo.issues",
 | 
				
			||||||
 | 
							"/issues",
 | 
				
			||||||
 | 
							"repo.issues_desc",
 | 
				
			||||||
 | 
							1,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitPullRequests = Unit{
 | 
				
			||||||
 | 
							UnitTypePullRequests,
 | 
				
			||||||
 | 
							"repo.pulls",
 | 
				
			||||||
 | 
							"/pulls",
 | 
				
			||||||
 | 
							"repo.pulls_desc",
 | 
				
			||||||
 | 
							2,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitCommits = Unit{
 | 
				
			||||||
 | 
							UnitTypeCommits,
 | 
				
			||||||
 | 
							"repo.commits",
 | 
				
			||||||
 | 
							"/commits/master",
 | 
				
			||||||
 | 
							"repo.commits_desc",
 | 
				
			||||||
 | 
							3,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitReleases = Unit{
 | 
				
			||||||
 | 
							UnitTypeReleases,
 | 
				
			||||||
 | 
							"repo.releases",
 | 
				
			||||||
 | 
							"/releases",
 | 
				
			||||||
 | 
							"repo.releases_desc",
 | 
				
			||||||
 | 
							4,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitWiki = Unit{
 | 
				
			||||||
 | 
							UnitTypeWiki,
 | 
				
			||||||
 | 
							"repo.wiki",
 | 
				
			||||||
 | 
							"/wiki",
 | 
				
			||||||
 | 
							"repo.wiki_desc",
 | 
				
			||||||
 | 
							5,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitExternalWiki = Unit{
 | 
				
			||||||
 | 
							UnitTypeExternalWiki,
 | 
				
			||||||
 | 
							"repo.wiki",
 | 
				
			||||||
 | 
							"/wiki",
 | 
				
			||||||
 | 
							"repo.wiki_desc",
 | 
				
			||||||
 | 
							5,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						UnitSettings = Unit{
 | 
				
			||||||
 | 
							UnitTypeSettings,
 | 
				
			||||||
 | 
							"repo.settings",
 | 
				
			||||||
 | 
							"/settings",
 | 
				
			||||||
 | 
							"repo.settings_desc",
 | 
				
			||||||
 | 
							6,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// defaultRepoUnits contains all the default unit types
 | 
				
			||||||
 | 
						defaultRepoUnits = []UnitType{
 | 
				
			||||||
 | 
							UnitTypeCode,
 | 
				
			||||||
 | 
							UnitTypeIssues,
 | 
				
			||||||
 | 
							UnitTypePullRequests,
 | 
				
			||||||
 | 
							UnitTypeCommits,
 | 
				
			||||||
 | 
							UnitTypeReleases,
 | 
				
			||||||
 | 
							UnitTypeWiki,
 | 
				
			||||||
 | 
							UnitTypeSettings,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// MustRepoUnits contains the units could be disabled currently
 | 
				
			||||||
 | 
						MustRepoUnits = []UnitType{
 | 
				
			||||||
 | 
							UnitTypeCode,
 | 
				
			||||||
 | 
							UnitTypeCommits,
 | 
				
			||||||
 | 
							UnitTypeReleases,
 | 
				
			||||||
 | 
							UnitTypeSettings,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Units contains all the units
 | 
				
			||||||
 | 
						Units = map[UnitType]Unit{
 | 
				
			||||||
 | 
							UnitTypeCode:            UnitCode,
 | 
				
			||||||
 | 
							UnitTypeIssues:          UnitIssues,
 | 
				
			||||||
 | 
							UnitTypeExternalTracker: UnitExternalTracker,
 | 
				
			||||||
 | 
							UnitTypePullRequests:    UnitPullRequests,
 | 
				
			||||||
 | 
							UnitTypeCommits:         UnitCommits,
 | 
				
			||||||
 | 
							UnitTypeReleases:        UnitReleases,
 | 
				
			||||||
 | 
							UnitTypeWiki:            UnitWiki,
 | 
				
			||||||
 | 
							UnitTypeExternalWiki:    UnitExternalWiki,
 | 
				
			||||||
 | 
							UnitTypeSettings:        UnitSettings,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -477,3 +477,18 @@ func GitHookService() macaron.Handler {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UnitTypes returns a macaron middleware to set unit types to context variables.
 | 
				
			||||||
 | 
					func UnitTypes() macaron.Handler {
 | 
				
			||||||
 | 
						return func(ctx *Context) {
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeCode"] = models.UnitTypeCode
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeIssues"] = models.UnitTypeIssues
 | 
				
			||||||
 | 
							ctx.Data["UnitTypePullRequests"] = models.UnitTypePullRequests
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeCommits"] = models.UnitTypeCommits
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeReleases"] = models.UnitTypeReleases
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeWiki"] = models.UnitTypeWiki
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeSettings"] = models.UnitTypeSettings
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeExternalWiki"] = models.UnitTypeExternalWiki
 | 
				
			||||||
 | 
							ctx.Data["UnitTypeExternalTracker"] = models.UnitTypeExternalTracker
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,7 +205,7 @@ func orgAssignment(args ...bool) macaron.Handler {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mustEnableIssues(ctx *context.APIContext) {
 | 
					func mustEnableIssues(ctx *context.APIContext) {
 | 
				
			||||||
	if !ctx.Repo.Repository.EnableIssues || ctx.Repo.Repository.EnableExternalTracker {
 | 
						if !ctx.Repo.Repository.EnableUnit(models.UnitTypeIssues) {
 | 
				
			||||||
		ctx.Status(404)
 | 
							ctx.Status(404)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,13 +59,15 @@ var (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MustEnableIssues check if repository enable internal issues
 | 
					// MustEnableIssues check if repository enable internal issues
 | 
				
			||||||
func MustEnableIssues(ctx *context.Context) {
 | 
					func MustEnableIssues(ctx *context.Context) {
 | 
				
			||||||
	if !ctx.Repo.Repository.EnableIssues {
 | 
						if !ctx.Repo.Repository.EnableUnit(models.UnitTypeIssues) &&
 | 
				
			||||||
 | 
							!ctx.Repo.Repository.EnableUnit(models.UnitTypeExternalTracker) {
 | 
				
			||||||
		ctx.Handle(404, "MustEnableIssues", nil)
 | 
							ctx.Handle(404, "MustEnableIssues", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Repo.Repository.EnableExternalTracker {
 | 
						unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalTracker)
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.Repository.ExternalTrackerURL)
 | 
						if err == nil {
 | 
				
			||||||
 | 
							ctx.Redirect(unit.ExternalTrackerConfig().ExternalTrackerURL)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,18 +143,70 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
 | 
				
			||||||
		ctx.Redirect(repo.Link() + "/settings")
 | 
							ctx.Redirect(repo.Link() + "/settings")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case "advanced":
 | 
						case "advanced":
 | 
				
			||||||
		repo.EnableWiki = form.EnableWiki
 | 
							var units []models.RepoUnit
 | 
				
			||||||
		repo.EnableExternalWiki = form.EnableExternalWiki
 | 
					 | 
				
			||||||
		repo.ExternalWikiURL = form.ExternalWikiURL
 | 
					 | 
				
			||||||
		repo.EnableIssues = form.EnableIssues
 | 
					 | 
				
			||||||
		repo.EnableExternalTracker = form.EnableExternalTracker
 | 
					 | 
				
			||||||
		repo.ExternalTrackerURL = form.ExternalTrackerURL
 | 
					 | 
				
			||||||
		repo.ExternalTrackerFormat = form.TrackerURLFormat
 | 
					 | 
				
			||||||
		repo.ExternalTrackerStyle = form.TrackerIssueStyle
 | 
					 | 
				
			||||||
		repo.EnablePulls = form.EnablePulls
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := models.UpdateRepository(repo, false); err != nil {
 | 
							for _, tp := range models.MustRepoUnits {
 | 
				
			||||||
			ctx.Handle(500, "UpdateRepository", err)
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
									RepoID: repo.ID,
 | 
				
			||||||
 | 
									Type:   tp,
 | 
				
			||||||
 | 
									Index:  int(tp),
 | 
				
			||||||
 | 
									Config: new(models.UnitConfig),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if form.EnableWiki {
 | 
				
			||||||
 | 
								if form.EnableExternalWiki {
 | 
				
			||||||
 | 
									units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
										RepoID: repo.ID,
 | 
				
			||||||
 | 
										Type:   models.UnitTypeExternalWiki,
 | 
				
			||||||
 | 
										Index:  int(models.UnitTypeExternalWiki),
 | 
				
			||||||
 | 
										Config: &models.ExternalWikiConfig{
 | 
				
			||||||
 | 
											ExternalWikiURL: form.ExternalWikiURL,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
										RepoID: repo.ID,
 | 
				
			||||||
 | 
										Type:   models.UnitTypeWiki,
 | 
				
			||||||
 | 
										Index:  int(models.UnitTypeWiki),
 | 
				
			||||||
 | 
										Config: new(models.UnitConfig),
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if form.EnableIssues {
 | 
				
			||||||
 | 
								if form.EnableExternalTracker {
 | 
				
			||||||
 | 
									units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
										RepoID: repo.ID,
 | 
				
			||||||
 | 
										Type:   models.UnitTypeExternalWiki,
 | 
				
			||||||
 | 
										Index:  int(models.UnitTypeExternalWiki),
 | 
				
			||||||
 | 
										Config: &models.ExternalTrackerConfig{
 | 
				
			||||||
 | 
											ExternalTrackerURL:    form.ExternalTrackerURL,
 | 
				
			||||||
 | 
											ExternalTrackerFormat: form.TrackerURLFormat,
 | 
				
			||||||
 | 
											ExternalTrackerStyle:  form.TrackerIssueStyle,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
										RepoID: repo.ID,
 | 
				
			||||||
 | 
										Type:   models.UnitTypeIssues,
 | 
				
			||||||
 | 
										Index:  int(models.UnitTypeIssues),
 | 
				
			||||||
 | 
										Config: new(models.UnitConfig),
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if form.EnablePulls {
 | 
				
			||||||
 | 
								units = append(units, models.RepoUnit{
 | 
				
			||||||
 | 
									RepoID: repo.ID,
 | 
				
			||||||
 | 
									Type:   models.UnitTypePullRequests,
 | 
				
			||||||
 | 
									Index:  int(models.UnitTypePullRequests),
 | 
				
			||||||
 | 
									Config: new(models.UnitConfig),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := models.UpdateRepositoryUnits(repo, units); err != nil {
 | 
				
			||||||
 | 
								ctx.Handle(500, "UpdateRepositoryUnits", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		log.Trace("Repository advanced settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
							log.Trace("Repository advanced settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
				
			||||||
| 
						 | 
					@ -281,12 +333,6 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
 | 
				
			||||||
		repo.DeleteWiki()
 | 
							repo.DeleteWiki()
 | 
				
			||||||
		log.Trace("Repository wiki deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
							log.Trace("Repository wiki deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		repo.EnableWiki = false
 | 
					 | 
				
			||||||
		if err := models.UpdateRepository(repo, false); err != nil {
 | 
					 | 
				
			||||||
			ctx.Handle(500, "UpdateRepository", err)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ctx.Flash.Success(ctx.Tr("repo.settings.wiki_deletion_success"))
 | 
							ctx.Flash.Success(ctx.Tr("repo.settings.wiki_deletion_success"))
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,13 +27,15 @@ const (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MustEnableWiki check if wiki is enabled, if external then redirect
 | 
					// MustEnableWiki check if wiki is enabled, if external then redirect
 | 
				
			||||||
func MustEnableWiki(ctx *context.Context) {
 | 
					func MustEnableWiki(ctx *context.Context) {
 | 
				
			||||||
	if !ctx.Repo.Repository.EnableWiki {
 | 
						if !ctx.Repo.Repository.EnableUnit(models.UnitTypeWiki) &&
 | 
				
			||||||
 | 
							!ctx.Repo.Repository.EnableUnit(models.UnitTypeExternalWiki) {
 | 
				
			||||||
		ctx.Handle(404, "MustEnableWiki", nil)
 | 
							ctx.Handle(404, "MustEnableWiki", nil)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Repo.Repository.EnableExternalWiki {
 | 
						unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki)
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.Repository.ExternalWikiURL)
 | 
						if err == nil {
 | 
				
			||||||
 | 
							ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ func Issues(ctx *context.Context) {
 | 
				
			||||||
	for _, repo := range repos {
 | 
						for _, repo := range repos {
 | 
				
			||||||
		if (isPullList && repo.NumPulls == 0) ||
 | 
							if (isPullList && repo.NumPulls == 0) ||
 | 
				
			||||||
			(!isPullList &&
 | 
								(!isPullList &&
 | 
				
			||||||
				(!repo.EnableIssues || repo.EnableExternalTracker || repo.NumIssues == 0)) {
 | 
									(!repo.EnableUnit(models.UnitTypeIssues) || repo.NumIssues == 0)) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,30 +49,48 @@
 | 
				
			||||||
{{if not (or .IsBareRepo .IsDiffCompare)}}
 | 
					{{if not (or .IsBareRepo .IsDiffCompare)}}
 | 
				
			||||||
	<div class="ui tabs container">
 | 
						<div class="ui tabs container">
 | 
				
			||||||
		<div class="ui tabular menu navbar">
 | 
							<div class="ui tabular menu navbar">
 | 
				
			||||||
 | 
								{{if .Repository.EnableUnit $.UnitTypeCode}}
 | 
				
			||||||
			<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}">
 | 
								<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}">
 | 
				
			||||||
				<i class="octicon octicon-code"></i> {{.i18n.Tr "repo.code"}}
 | 
									<i class="octicon octicon-code"></i> {{.i18n.Tr "repo.code"}}
 | 
				
			||||||
			</a>
 | 
								</a>
 | 
				
			||||||
			{{if .Repository.EnableIssues}}
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{{if .Repository.EnableUnit $.UnitTypeIssues}}
 | 
				
			||||||
				<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
 | 
									<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
 | 
				
			||||||
					<i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} {{if not .Repository.EnableExternalTracker}}<span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}{{end}}</span>
 | 
										<i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} <span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}</span>
 | 
				
			||||||
				</a>
 | 
									</a>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{{if .Repository.EnableUnit $.UnitTypeExternalTracker}}
 | 
				
			||||||
 | 
									<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
 | 
				
			||||||
 | 
										<i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} </span>
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								{{end}}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
			{{if .Repository.AllowsPulls}}
 | 
								{{if .Repository.AllowsPulls}}
 | 
				
			||||||
				<a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls">
 | 
									<a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls">
 | 
				
			||||||
					<i class="octicon octicon-git-pull-request"></i> {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span>
 | 
										<i class="octicon octicon-git-pull-request"></i> {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span>
 | 
				
			||||||
				</a>
 | 
									</a>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{{if .Repository.EnableUnit $.UnitTypeCommits}}
 | 
				
			||||||
			<a class="{{if (or (.PageIsCommits) (.PageIsDiff))}}active{{end}} item" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}">
 | 
								<a class="{{if (or (.PageIsCommits) (.PageIsDiff))}}active{{end}} item" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}">
 | 
				
			||||||
				<i class="octicon octicon-history"></i> {{.i18n.Tr "repo.commits"}} <span class="ui {{if not .CommitsCount}}gray{{else}}blue{{end}} small label">{{.CommitsCount}}</span>
 | 
									<i class="octicon octicon-history"></i> {{.i18n.Tr "repo.commits"}} <span class="ui {{if not .CommitsCount}}gray{{else}}blue{{end}} small label">{{.CommitsCount}}</span>
 | 
				
			||||||
			</a>
 | 
								</a>
 | 
				
			||||||
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{{if .Repository.EnableUnit $.UnitTypeReleases}}
 | 
				
			||||||
			<a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases">
 | 
								<a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases">
 | 
				
			||||||
				<i class="octicon octicon-tag"></i> {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .Repository.NumTags}}gray{{else}}blue{{end}} small label">{{.Repository.NumTags}}</span>
 | 
									<i class="octicon octicon-tag"></i> {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .Repository.NumTags}}gray{{else}}blue{{end}} small label">{{.Repository.NumTags}}</span>
 | 
				
			||||||
			</a>
 | 
								</a>
 | 
				
			||||||
			{{if .Repository.EnableWiki}}
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								{{if or (.Repository.EnableUnit $.UnitTypeWiki) (.Repository.EnableUnit $.UnitTypeExternalWiki)}}
 | 
				
			||||||
				<a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki">
 | 
									<a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki">
 | 
				
			||||||
					<i class="octicon octicon-book"></i> {{.i18n.Tr "repo.wiki"}}
 | 
										<i class="octicon octicon-book"></i> {{.i18n.Tr "repo.wiki"}}
 | 
				
			||||||
				</a>
 | 
									</a>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			{{if .IsRepositoryAdmin}}
 | 
								{{if .IsRepositoryAdmin}}
 | 
				
			||||||
				<div class="right menu">
 | 
									<div class="right menu">
 | 
				
			||||||
					<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings">
 | 
										<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -114,26 +114,26 @@
 | 
				
			||||||
						<div class="inline field">
 | 
											<div class="inline field">
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.wiki"}}</label>
 | 
												<label>{{.i18n.Tr "repo.wiki"}}</label>
 | 
				
			||||||
							<div class="ui checkbox">
 | 
												<div class="ui checkbox">
 | 
				
			||||||
								<input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if .Repository.EnableWiki}}checked{{end}}>
 | 
													<input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if or (.Repository.EnableUnit $.UnitTypeWiki) (.Repository.EnableUnit $.UnitTypeExternalWiki)}}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 .Repository.EnableWiki}}disabled{{end}}" id="wiki_box">
 | 
											<div class="field {{if not (.Repository.EnableUnit $.UnitTypeWiki)}}disabled{{end}}" id="wiki_box">
 | 
				
			||||||
							<div class="field">
 | 
												<div class="field">
 | 
				
			||||||
								<div class="ui radio checkbox">
 | 
													<div class="ui radio checkbox">
 | 
				
			||||||
									<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not .Repository.EnableExternalWiki}}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.EnableUnit $.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">
 | 
				
			||||||
								<div class="ui radio checkbox">
 | 
													<div class="ui radio checkbox">
 | 
				
			||||||
									<input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.EnableExternalWiki}}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.EnableUnit $.UnitTypeExternalWiki}}checked{{end}}/>
 | 
				
			||||||
									<label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label>
 | 
														<label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
							<div class="field {{if not .Repository.EnableExternalWiki}}disabled{{end}}" id="external_wiki_box">
 | 
												<div class="field {{if not (.Repository.EnableUnit $.UnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box">
 | 
				
			||||||
								<label for="external_wiki_url">{{.i18n.Tr "repo.settings.external_wiki_url"}}</label>
 | 
													<label for="external_wiki_url">{{.i18n.Tr "repo.settings.external_wiki_url"}}</label>
 | 
				
			||||||
								<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{.Repository.ExternalWikiURL}}">
 | 
													<input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}">
 | 
				
			||||||
								<p class="help">{{.i18n.Tr "repo.settings.external_wiki_url_desc"}}</p>
 | 
													<p class="help">{{.i18n.Tr "repo.settings.external_wiki_url_desc"}}</p>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
| 
						 | 
					@ -143,45 +143,47 @@
 | 
				
			||||||
						<div class="inline field">
 | 
											<div class="inline field">
 | 
				
			||||||
							<label>{{.i18n.Tr "repo.issues"}}</label>
 | 
												<label>{{.i18n.Tr "repo.issues"}}</label>
 | 
				
			||||||
							<div class="ui checkbox">
 | 
												<div class="ui checkbox">
 | 
				
			||||||
								<input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if .Repository.EnableIssues}}checked{{end}}>
 | 
													<input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if or (.Repository.EnableUnit $.UnitTypeIssues) (.Repository.EnableUnit $.UnitTypeExternalTracker)}}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 .Repository.EnableIssues}}disabled{{end}}" id="issue_box">
 | 
											<div class="field {{if not (.Repository.EnableUnit $.UnitTypeIssues)}}disabled{{end}}" id="issue_box">
 | 
				
			||||||
							<div class="field">
 | 
												<div class="field">
 | 
				
			||||||
								<div class="ui radio checkbox">
 | 
													<div class="ui radio checkbox">
 | 
				
			||||||
									<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-target="#external_issue_box" {{if not .Repository.EnableExternalTracker}}checked{{end}}/>
 | 
														<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-target="#external_issue_box" {{if not (.Repository.EnableUnit $.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>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
							<div class="field">
 | 
												<div class="field">
 | 
				
			||||||
								<div class="ui radio checkbox">
 | 
													<div class="ui radio checkbox">
 | 
				
			||||||
									<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-target="#external_issue_box" {{if .Repository.EnableExternalTracker}}checked{{end}}/>
 | 
														<input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-target="#external_issue_box" {{if .Repository.EnableUnit $.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>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
							<div class="field {{if not .Repository.EnableExternalTracker}}disabled{{end}}" id="external_issue_box">
 | 
												<div class="field {{if not (.Repository.EnableUnit $.UnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box">
 | 
				
			||||||
								<div class="field">
 | 
													<div class="field">
 | 
				
			||||||
									<label for="external_tracker_url">{{.i18n.Tr "repo.settings.external_tracker_url"}}</label>
 | 
														<label for="external_tracker_url">{{.i18n.Tr "repo.settings.external_tracker_url"}}</label>
 | 
				
			||||||
									<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{.Repository.ExternalTrackerURL}}">
 | 
														<input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}">
 | 
				
			||||||
									<p class="help">{{.i18n.Tr "repo.settings.external_tracker_url_desc"}}</p>
 | 
														<p class="help">{{.i18n.Tr "repo.settings.external_tracker_url_desc"}}</p>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
								<div class="field">
 | 
													<div class="field">
 | 
				
			||||||
									<label for="tracker_url_format">{{.i18n.Tr "repo.settings.tracker_url_format"}}</label>
 | 
														<label for="tracker_url_format">{{.i18n.Tr "repo.settings.tracker_url_format"}}</label>
 | 
				
			||||||
									<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{.Repository.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}">
 | 
														<input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}">
 | 
				
			||||||
									<p class="help">{{.i18n.Tr "repo.settings.tracker_url_format_desc" | Str2html}}</p>
 | 
														<p class="help">{{.i18n.Tr "repo.settings.tracker_url_format_desc" | Str2html}}</p>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
								<div class="inline fields">
 | 
													<div class="inline fields">
 | 
				
			||||||
									<label for="issue_style">{{.i18n.Tr "repo.settings.tracker_issue_style"}}</label>
 | 
														<label for="issue_style">{{.i18n.Tr "repo.settings.tracker_issue_style"}}</label>
 | 
				
			||||||
									<div class="field">
 | 
														<div class="field">
 | 
				
			||||||
										<div class="ui radio checkbox">
 | 
															<div class="ui radio checkbox">
 | 
				
			||||||
											<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="numeric"  {{if eq .Repository.ExternalTrackerStyle "numeric"}}checked=""{{end}}/>
 | 
															{{$externalTracker := (.Repository.MustGetUnit $.UnitTypeExternalTracker)}}
 | 
				
			||||||
 | 
															{{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}}
 | 
				
			||||||
 | 
																<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="numeric" {{if $externalTrackerStyle}}{{if eq $externalTrackerStyle "numeric"}}checked=""{{end}}{{end}}/>
 | 
				
			||||||
											<label>{{.i18n.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">(#1234)</span></label>
 | 
																<label>{{.i18n.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">(#1234)</span></label>
 | 
				
			||||||
										</div>
 | 
															</div>
 | 
				
			||||||
									</div>
 | 
														</div>
 | 
				
			||||||
									<div class="field">
 | 
														<div class="field">
 | 
				
			||||||
										<div class="ui radio checkbox">
 | 
															<div class="ui radio checkbox">
 | 
				
			||||||
											<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric"  {{if eq .Repository.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}/>
 | 
																<input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric" {{if $externalTrackerStyle}}{{if eq $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}{{end}} />
 | 
				
			||||||
											<label>{{.i18n.Tr "repo.settings.tracker_issue_style.alphanumeric"}} <span class="ui light grey text">(ABC-123, DEFG-234)</span></label>
 | 
																<label>{{.i18n.Tr "repo.settings.tracker_issue_style.alphanumeric"}} <span class="ui light grey text">(ABC-123, DEFG-234)</span></label>
 | 
				
			||||||
										</div>
 | 
															</div>
 | 
				
			||||||
									</div>
 | 
														</div>
 | 
				
			||||||
| 
						 | 
					@ -195,7 +197,7 @@
 | 
				
			||||||
							<div class="inline field">
 | 
												<div class="inline field">
 | 
				
			||||||
								<label>{{.i18n.Tr "repo.pulls"}}</label>
 | 
													<label>{{.i18n.Tr "repo.pulls"}}</label>
 | 
				
			||||||
								<div class="ui checkbox">
 | 
													<div class="ui checkbox">
 | 
				
			||||||
									<input name="enable_pulls" type="checkbox" {{if .Repository.EnablePulls}}checked{{end}}>
 | 
														<input name="enable_pulls" type="checkbox" {{if .Repository.EnableUnit $.UnitTypePullRequests}}checked{{end}}>
 | 
				
			||||||
									<label>{{.i18n.Tr "repo.settings.pulls_desc"}}</label>
 | 
														<label>{{.i18n.Tr "repo.settings.pulls_desc"}}</label>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
| 
						 | 
					@ -236,7 +238,7 @@
 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					{{if .Repository.EnableWiki}}
 | 
										{{if .Repository.EnableUnit $.UnitTypeWiki}}
 | 
				
			||||||
						<div class="ui divider"></div>
 | 
											<div class="ui divider"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<div class="item">
 | 
											<div class="item">
 | 
				
			||||||
| 
						 | 
					@ -370,7 +372,7 @@
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{{if .Repository.EnableWiki}}
 | 
						{{if .Repository.EnableUnit $.UnitTypeWiki}}
 | 
				
			||||||
	<div class="ui small modal" id="delete-wiki-modal">
 | 
						<div class="ui small modal" id="delete-wiki-modal">
 | 
				
			||||||
		<div class="header">
 | 
							<div class="header">
 | 
				
			||||||
			{{.i18n.Tr "repo.settings.wiki-delete"}}
 | 
								{{.i18n.Tr "repo.settings.wiki-delete"}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue