Merge branch 'master' of github.com:gogits/gogs
This commit is contained in:
		
						commit
						89258e868b
					
				
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							| @ -5,7 +5,7 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### Current version: 0.1.8 Alpha | ||||
| ##### Current version: 0.1.9 Alpha | ||||
| 
 | ||||
| #### Other language version | ||||
| 
 | ||||
| @ -19,7 +19,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o | ||||
| 
 | ||||
| ## Overview | ||||
| 
 | ||||
| - Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, develop specification, change log and road map. | ||||
| - Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, known issues, change log and road map. | ||||
| - See [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. | ||||
| - Try it before anything? Do it [online](http://try.gogits.org/Unknown/gogs) or go down to **Installation -> Install from binary** section! | ||||
| - Having troubles? Get help from [Troubleshooting](https://github.com/gogits/gogs/wiki/Troubleshooting). | ||||
| @ -27,7 +27,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o | ||||
| ## Features | ||||
| 
 | ||||
| - Activity timeline | ||||
| - SSH/HTTPS protocol support. | ||||
| - SSH/HTTPS(Clone only) protocol support. | ||||
| - Register/delete account. | ||||
| - Create/delete/watch public repository. | ||||
| - User profile page. | ||||
| @ -58,3 +58,7 @@ There are two ways to install Gogs: | ||||
| ## Contributors | ||||
| 
 | ||||
| This project was launched by [Unknown](https://github.com/Unknwon) and [lunny](https://github.com/lunny); [fuxiaohei](https://github.com/fuxiaohei) and [slene](https://github.com/slene) joined the team soon after. See [contributors page](https://github.com/gogits/gogs/graphs/contributors) for full list of contributors. | ||||
| 
 | ||||
| ## License | ||||
| 
 | ||||
| Gogs is under the MIT License. See the [LICENSE](https://github.com/gogits/gogs/blob/master/LICENSE) file for the full license text. | ||||
|  | ||||
							
								
								
									
										12
									
								
								README_ZH.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README_ZH.md
									
									
									
									
									
								
							| @ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 当前版本:0.1.8 Alpha | ||||
| ##### 当前版本:0.1.9 Alpha | ||||
| 
 | ||||
| ## 开发目的 | ||||
| 
 | ||||
| @ -15,7 +15,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 | ||||
| 
 | ||||
| ## 项目概览 | ||||
| 
 | ||||
| - 有关项目设计、开发说明、变更日志和路线图,请通过  [Wiki](https://github.com/gogits/gogs/wiki) 查看。 | ||||
| - 有关项目设计、已知问题、变更日志和路线图,请通过  [Wiki](https://github.com/gogits/gogs/wiki) 查看。 | ||||
| - 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。 | ||||
| - 想要先睹为快?通过 [在线体验](http://try.gogits.org/Unknown/gogs) 或查看 **安装部署 -> 二进制安装** 小节。 | ||||
| - 使用过程中遇到问题?尝试从 [故障排查](https://github.com/gogits/gogs/wiki/Troubleshooting) 页面获取帮助。 | ||||
| @ -23,7 +23,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 | ||||
| ## 功能特性 | ||||
| 
 | ||||
| - 活动时间线 | ||||
| - SSH/HTTPS 协议支持 | ||||
| - SSH/HTTPS(仅限 Clone) 协议支持 | ||||
| - 注册/删除用户 | ||||
| - 创建/删除/关注公开仓库 | ||||
| - 用户个人信息页面 | ||||
| @ -53,4 +53,8 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 | ||||
| 
 | ||||
| ## 贡献成员 | ||||
| 
 | ||||
| 本项目最初由 [Unknown](https://github.com/Unknwon) 和 [lunny](https://github.com/lunny) 发起,随后 [fuxiaohei](https://github.com/fuxiaohei) 与 [slene](https://github.com/slene) 加入到开发团队。您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取完整的贡献者列表。 | ||||
| 本项目最初由 [Unknown](https://github.com/Unknwon) 和 [lunny](https://github.com/lunny) 发起,随后 [fuxiaohei](https://github.com/fuxiaohei) 与 [slene](https://github.com/slene) 加入到开发团队。您可以通过查看 [贡献者页面](https://github.com/gogits/gogs/graphs/contributors) 获取完整的贡献者列表。 | ||||
| 
 | ||||
| ## 授权许可 | ||||
| 
 | ||||
| Gogs 采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/gogits/gogs/blob/master/LICENSE) 文件中。 | ||||
| @ -32,6 +32,7 @@ PATH = data/gogs.db | ||||
| [admin] | ||||
| 
 | ||||
| [security] | ||||
| INSTALL_LOCK = false | ||||
| ; Use HTTPS to clone repository, otherwise use HTTP. | ||||
| ENABLE_HTTPS_CLONE = false | ||||
| ; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!! | ||||
|  | ||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							| @ -19,7 +19,7 @@ import ( | ||||
| // Test that go1.2 tag above is included in builds. main.go refers to this definition.
 | ||||
| const go12tag = true | ||||
| 
 | ||||
| const APP_VER = "0.1.8.0326 Alpha" | ||||
| const APP_VER = "0.1.9.0327 Alpha" | ||||
| 
 | ||||
| func init() { | ||||
| 	base.AppVer = APP_VER | ||||
|  | ||||
| @ -15,7 +15,7 @@ const ( | ||||
| 	AU_WRITABLE | ||||
| ) | ||||
| 
 | ||||
| // Access represents the accessibility of user and repository.
 | ||||
| // Access represents the accessibility of user to repository.
 | ||||
| type Access struct { | ||||
| 	Id       int64 | ||||
| 	UserName string    `xorm:"unique(s)"` | ||||
| @ -30,7 +30,7 @@ func AddAccess(access *Access) error { | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // HasAccess returns true if someone can read or write given repository.
 | ||||
| // HasAccess returns true if someone can read or write to given repository.
 | ||||
| func HasAccess(userName, repoName string, mode int) (bool, error) { | ||||
| 	return orm.Get(&Access{ | ||||
| 		Id:       0, | ||||
|  | ||||
| @ -23,7 +23,8 @@ const ( | ||||
| 	OP_PULL_REQUEST | ||||
| ) | ||||
| 
 | ||||
| // Action represents user operation type and information to the repository.
 | ||||
| // Action represents user operation type and other information to repository.,
 | ||||
| // it implemented interface base.Actioner so that can be used in template render.
 | ||||
| type Action struct { | ||||
| 	Id          int64 | ||||
| 	UserId      int64  // Receiver user id.
 | ||||
| @ -57,23 +58,24 @@ func (a Action) GetContent() string { | ||||
| 	return a.Content | ||||
| } | ||||
| 
 | ||||
| // CommitRepoAction records action for commit repository.
 | ||||
| // CommitRepoAction adds new action for committing repository.
 | ||||
| func CommitRepoAction(userId int64, userName string, | ||||
| 	repoId int64, repoName string, refName string, commits *base.PushCommits) error { | ||||
| 	repoId int64, repoName string, refName string, commit *base.PushCommits) error { | ||||
| 	log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName) | ||||
| 
 | ||||
| 	bs, err := json.Marshal(commits) | ||||
| 	bs, err := json.Marshal(commit) | ||||
| 	if err != nil { | ||||
| 		log.Error("action.CommitRepoAction(json): %d/%s", userId, repoName) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if err = NotifyWatchers(userId, repoId, OP_COMMIT_REPO, userName, repoName, refName, string(bs)); err != nil { | ||||
| 	if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, OpType: OP_COMMIT_REPO, | ||||
| 		Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil { | ||||
| 		log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Update repository last update time.
 | ||||
| 	// Change repository bare status and update last updated time.
 | ||||
| 	repo, err := GetRepositoryByName(userId, repoName) | ||||
| 	if err != nil { | ||||
| 		log.Error("action.CommitRepoAction(GetRepositoryByName): %d/%s", userId, repoName) | ||||
| @ -89,16 +91,13 @@ func CommitRepoAction(userId int64, userName string, | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // NewRepoAction records action for create repository.
 | ||||
| func NewRepoAction(user *User, repo *Repository) error { | ||||
| 	_, err := orm.InsertOne(&Action{ | ||||
| 		UserId:      user.Id, | ||||
| 		ActUserId:   user.Id, | ||||
| 		ActUserName: user.Name, | ||||
| 		OpType:      OP_CREATE_REPO, | ||||
| 		RepoId:      repo.Id, | ||||
| 		RepoName:    repo.Name, | ||||
| 	}) | ||||
| // NewRepoAction adds new action for creating repository.
 | ||||
| func NewRepoAction(user *User, repo *Repository) (err error) { | ||||
| 	if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, OpType: OP_CREATE_REPO, | ||||
| 		RepoId: repo.Id, RepoName: repo.Name}); err != nil { | ||||
| 		log.Error("action.NewRepoAction(notify watchers): %d/%s", user.Id, repo.Name) | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	log.Trace("action.NewRepoAction: %s/%s", user.LowerName, repo.LowerName) | ||||
| 	return err | ||||
|  | ||||
| @ -38,8 +38,8 @@ func (file *RepoFile) LookupBlob() (*git.Blob, error) { | ||||
| } | ||||
| 
 | ||||
| // GetBranches returns all branches of given repository.
 | ||||
| func GetBranches(userName, reposName string) ([]string, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, reposName)) | ||||
| func GetBranches(userName, repoName string) ([]string, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -56,8 +56,16 @@ func GetBranches(userName, reposName string) ([]string, error) { | ||||
| 	return brs, nil | ||||
| } | ||||
| 
 | ||||
| func GetTargetFile(userName, reposName, branchName, commitId, rpath string) (*RepoFile, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, reposName)) | ||||
| func IsBranchExist(userName, repoName, branchName string) bool { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return repo.IsBranchExist(branchName) | ||||
| } | ||||
| 
 | ||||
| func GetTargetFile(userName, repoName, branchName, commitId, rpath string) (*RepoFile, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -102,8 +110,8 @@ func GetTargetFile(userName, reposName, branchName, commitId, rpath string) (*Re | ||||
| } | ||||
| 
 | ||||
| // GetReposFiles returns a list of file object in given directory of repository.
 | ||||
| func GetReposFiles(userName, reposName, branchName, commitId, rpath string) ([]*RepoFile, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, reposName)) | ||||
| func GetReposFiles(userName, repoName, branchName, commitId, rpath string) ([]*RepoFile, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -217,13 +225,26 @@ func GetCommit(userName, repoName, branchname, commitid string) (*git.Commit, er | ||||
| 	return repo.GetCommit(branchname, commitid) | ||||
| } | ||||
| 
 | ||||
| // GetCommits returns all commits of given branch of repository.
 | ||||
| func GetCommits(userName, reposName, branchname string) (*list.List, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, reposName)) | ||||
| // GetCommitsByBranch returns all commits of given branch of repository.
 | ||||
| func GetCommitsByBranch(userName, repoName, branchName string) (*list.List, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchname)) | ||||
| 	r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return r.AllCommits() | ||||
| } | ||||
| 
 | ||||
| // GetCommitsByCommitId returns all commits of given commitId of repository.
 | ||||
| func GetCommitsByCommitId(userName, repoName, commitId string) (*list.List, error) { | ||||
| 	repo, err := git.OpenRepository(RepoPath(userName, repoName)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r, err := repo.LookupReference(commitId) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| @ -21,7 +21,8 @@ type Issue struct { | ||||
| 	Id          int64 | ||||
| 	Index       int64 // Index in one repository.
 | ||||
| 	Name        string | ||||
| 	RepoId      int64 `xorm:"index"` | ||||
| 	RepoId      int64       `xorm:"index"` | ||||
| 	Repo        *Repository `xorm:"-"` | ||||
| 	PosterId    int64 | ||||
| 	Poster      *User `xorm:"-"` | ||||
| 	MilestoneId int64 | ||||
| @ -37,17 +38,16 @@ type Issue struct { | ||||
| } | ||||
| 
 | ||||
| // CreateIssue creates new issue for repository.
 | ||||
| func CreateIssue(userId, repoId, milestoneId, assigneeId int64, name, labels, content string, isPull bool) (*Issue, error) { | ||||
| 	count, err := GetIssueCount(repoId) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| func CreateIssue(userId, repoId, milestoneId, assigneeId int64, issueCount int, name, labels, content string, isPull bool) (issue *Issue, err error) { | ||||
| 	// TODO: find out mentions
 | ||||
| 	mentions := "" | ||||
| 
 | ||||
| 	issue := &Issue{ | ||||
| 		Index:       count + 1, | ||||
| 	sess := orm.NewSession() | ||||
| 	defer sess.Close() | ||||
| 	sess.Begin() | ||||
| 
 | ||||
| 	issue = &Issue{ | ||||
| 		Index:       int64(issueCount) + 1, | ||||
| 		Name:        name, | ||||
| 		RepoId:      repoId, | ||||
| 		PosterId:    userId, | ||||
| @ -58,13 +58,23 @@ func CreateIssue(userId, repoId, milestoneId, assigneeId int64, name, labels, co | ||||
| 		Mentions:    mentions, | ||||
| 		Content:     content, | ||||
| 	} | ||||
| 	_, err = orm.Insert(issue) | ||||
| 	return issue, err | ||||
| } | ||||
| 	if _, err = sess.Insert(issue); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| // GetIssueCount returns count of issues in the repository.
 | ||||
| func GetIssueCount(repoId int64) (int64, error) { | ||||
| 	return orm.Count(&Issue{RepoId: repoId}) | ||||
| 	rawSql := "UPDATE `repository` SET num_issues = num_issues + 1 WHERE id = ?" | ||||
| 	if _, err = sess.Exec(rawSql, repoId); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if err = sess.Commit(); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return issue, nil | ||||
| } | ||||
| 
 | ||||
| // GetIssueById returns issue object by given id.
 | ||||
| @ -127,18 +137,18 @@ func GetIssues(userId, repoId, posterId, milestoneId int64, page int, isClosed, | ||||
| 	return issues, err | ||||
| } | ||||
| 
 | ||||
| // GetUserIssueCount returns the number of issues that were created by given user in repository.
 | ||||
| func GetUserIssueCount(userId, repoId int64) int64 { | ||||
| 	count, _ := orm.Where("poster_id=?", userId).And("repo_id=?", repoId).Count(new(Issue)) | ||||
| 	return count | ||||
| } | ||||
| 
 | ||||
| // UpdateIssue updates information of issue.
 | ||||
| func UpdateIssue(issue *Issue) error { | ||||
| 	_, err := orm.Update(issue, &Issue{RepoId: issue.RepoId, Index: issue.Index}) | ||||
| 	_, err := orm.Id(issue.Id).AllCols().Update(issue) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func CloseIssue() { | ||||
| } | ||||
| 
 | ||||
| func ReopenIssue() { | ||||
| } | ||||
| 
 | ||||
| // Label represents a list of labels of repository for issues.
 | ||||
| type Label struct { | ||||
| 	Id     int64 | ||||
| @ -178,8 +188,7 @@ func CreateComment(userId, issueId, commitId, line int64, content string) error | ||||
| 	sess.Begin() | ||||
| 
 | ||||
| 	if _, err := orm.Insert(&Comment{PosterId: userId, IssueId: issueId, | ||||
| 		CommitId: commitId, Line: line, Content: content, | ||||
| 	}); err != nil { | ||||
| 		CommitId: commitId, Line: line, Content: content}); err != nil { | ||||
| 		sess.Rollback() | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @ -10,12 +10,12 @@ import ( | ||||
| 
 | ||||
| 	"github.com/lunny/xorm" | ||||
| 	_ "github.com/mattn/go-sqlite3" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	LoadModelsConfig() | ||||
| 	NewEngine() | ||||
| 
 | ||||
| 	var err error | ||||
| 	orm, err = xorm.NewEngine("sqlite3", "./test.db") | ||||
| 	if err != nil { | ||||
| @ -25,26 +25,31 @@ func init() { | ||||
| 	orm.ShowSQL = true | ||||
| 	orm.ShowDebug = true | ||||
| 
 | ||||
| 	err = orm.Sync(&User{}, &Repo{}) | ||||
| 	err = orm.Sync(&User{}, &Repository{}) | ||||
| 	if err != nil { | ||||
| 		fmt.Println(err) | ||||
| 	} | ||||
| 
 | ||||
| 	root = "test" | ||||
| 	base.RepoRootPath = "test" | ||||
| } | ||||
| 
 | ||||
| func TestCreateRepository(t *testing.T) { | ||||
| 	user := User{Id: 1, Type: Individual} | ||||
| 	_, err := CreateRepository(&user, "test") | ||||
| 	user := User{Id: 1, Name: "foobar", Type: UT_INDIVIDUAL} | ||||
| 	_, err := CreateRepository(&user, "test", "", "", "test repo desc", false, false) | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestDeleteRepository(t *testing.T) { | ||||
| 	user := User{Id: 1, Type: Individual} | ||||
| 	err := DeleteRepository(&user, "test") | ||||
| 	err := DeleteRepository(1, 1, "foobar") | ||||
| 	if err != nil { | ||||
| 		t.Error(err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestCommitRepoAction(t *testing.T) { | ||||
| 	Convey("Create a commit repository action", t, func() { | ||||
| 
 | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @ -72,20 +72,23 @@ func NewRepoContext() { | ||||
| 
 | ||||
| // Repository represents a git repository.
 | ||||
| type Repository struct { | ||||
| 	Id          int64 | ||||
| 	OwnerId     int64 `xorm:"unique(s)"` | ||||
| 	ForkId      int64 | ||||
| 	LowerName   string `xorm:"unique(s) index not null"` | ||||
| 	Name        string `xorm:"index not null"` | ||||
| 	Description string | ||||
| 	Website     string | ||||
| 	NumWatches  int | ||||
| 	NumStars    int | ||||
| 	NumForks    int | ||||
| 	IsPrivate   bool | ||||
| 	IsBare      bool | ||||
| 	Created     time.Time `xorm:"created"` | ||||
| 	Updated     time.Time `xorm:"updated"` | ||||
| 	Id              int64 | ||||
| 	OwnerId         int64 `xorm:"unique(s)"` | ||||
| 	ForkId          int64 | ||||
| 	LowerName       string `xorm:"unique(s) index not null"` | ||||
| 	Name            string `xorm:"index not null"` | ||||
| 	Description     string | ||||
| 	Website         string | ||||
| 	NumWatches      int | ||||
| 	NumStars        int | ||||
| 	NumForks        int | ||||
| 	NumIssues       int | ||||
| 	NumClosedIssues int | ||||
| 	NumOpenIssues   int `xorm:"-"` | ||||
| 	IsPrivate       bool | ||||
| 	IsBare          bool | ||||
| 	Created         time.Time `xorm:"created"` | ||||
| 	Updated         time.Time `xorm:"updated"` | ||||
| } | ||||
| 
 | ||||
| // IsRepositoryExist returns true if the repository with given name under user has already existed.
 | ||||
| @ -94,17 +97,16 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) { | ||||
| 	has, err := orm.Where("lower_name = ?", strings.ToLower(repoName)).Get(&repo) | ||||
| 	if err != nil { | ||||
| 		return has, err | ||||
| 	} else if !has { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	s, err := os.Stat(RepoPath(user.Name, repoName)) | ||||
| 	if err != nil { | ||||
| 		return false, nil // Error simply means does not exist, but we don't want to show up.
 | ||||
| 	} | ||||
| 	return s.IsDir(), nil | ||||
| 
 | ||||
| 	return com.IsDir(RepoPath(user.Name, repoName)), nil | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	// Define as all lower case!!
 | ||||
| 	illegalPatterns = []string{"[.][Gg][Ii][Tt]", "raw", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template", "admin"} | ||||
| 	illegalPatterns = []string{"[.][Gg][Ii][Tt]", "raw", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"} | ||||
| ) | ||||
| 
 | ||||
| // IsLegalName returns false if name contains illegal characters.
 | ||||
| @ -222,16 +224,24 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { | ||||
| 	if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	log.Trace("stderr(1): %s", stderr) | ||||
| 	if len(stderr) > 0 { | ||||
| 		log.Trace("stderr(1): %s", stderr) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), | ||||
| 		"-m", "Init commit"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	log.Trace("stderr(2): %s", stderr) | ||||
| 	if len(stderr) > 0 { | ||||
| 		log.Trace("stderr(2): %s", stderr) | ||||
| 	} | ||||
| 
 | ||||
| 	if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	log.Trace("stderr(3): %s", stderr) | ||||
| 	if len(stderr) > 0 { | ||||
| 		log.Trace("stderr(3): %s", stderr) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| @ -241,10 +251,9 @@ func createHookUpdate(hookPath, content string) error { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer pu.Close() | ||||
| 	if _, err = pu.WriteString(content); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 
 | ||||
| 	_, err = pu.WriteString(content) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // InitRepository initializes README and .gitignore if needed.
 | ||||
| @ -320,10 +329,7 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep | ||||
| 	} | ||||
| 
 | ||||
| 	// Apply changes and commit.
 | ||||
| 	if err := initRepoCommit(tmpDir, user.NewGitSig()); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 	return initRepoCommit(tmpDir, user.NewGitSig()) | ||||
| } | ||||
| 
 | ||||
| // UserRepo reporesents a repository with user name.
 | ||||
| @ -430,7 +436,8 @@ func GetRepositoryByName(userId int64, repoName string) (*Repository, error) { | ||||
| } | ||||
| 
 | ||||
| // GetRepositoryById returns the repository by given id if exists.
 | ||||
| func GetRepositoryById(id int64) (repo *Repository, err error) { | ||||
| func GetRepositoryById(id int64) (*Repository, error) { | ||||
| 	repo := &Repository{} | ||||
| 	has, err := orm.Id(id).Get(repo) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @ -485,30 +492,26 @@ func GetWatches(repoId int64) ([]Watch, error) { | ||||
| } | ||||
| 
 | ||||
| // NotifyWatchers creates batch of actions for every watcher.
 | ||||
| func NotifyWatchers(userId, repoId int64, opType int, userName, repoName, refName, content string) error { | ||||
| func NotifyWatchers(act *Action) error { | ||||
| 	// Add feeds for user self and all watchers.
 | ||||
| 	watches, err := GetWatches(repoId) | ||||
| 	watches, err := GetWatches(act.RepoId) | ||||
| 	if err != nil { | ||||
| 		return errors.New("repo.NotifyWatchers(get watches): " + err.Error()) | ||||
| 	} | ||||
| 	watches = append(watches, Watch{UserId: userId}) | ||||
| 
 | ||||
| 	// Add feed for actioner.
 | ||||
| 	act.UserId = act.ActUserId | ||||
| 	if _, err = orm.InsertOne(act); err != nil { | ||||
| 		return errors.New("repo.NotifyWatchers(create action): " + err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	for i := range watches { | ||||
| 		if userId == watches[i].UserId && i > 0 { | ||||
| 			continue // Do not add twice in case author watches his/her repository.
 | ||||
| 		if act.ActUserId == watches[i].UserId { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		_, err = orm.InsertOne(&Action{ | ||||
| 			UserId:      watches[i].UserId, | ||||
| 			ActUserId:   userId, | ||||
| 			ActUserName: userName, | ||||
| 			OpType:      opType, | ||||
| 			Content:     content, | ||||
| 			RepoId:      repoId, | ||||
| 			RepoName:    repoName, | ||||
| 			RefName:     refName, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 		act.UserId = watches[i].UserId | ||||
| 		if _, err = orm.InsertOne(act); err != nil { | ||||
| 			return errors.New("repo.NotifyWatchers(create action): " + err.Error()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -47,6 +47,7 @@ func HashEmail(email string) string { | ||||
| 	return hex.EncodeToString(h.Sum(nil)) | ||||
| } | ||||
| 
 | ||||
| // Avatar represents the avatar object.
 | ||||
| type Avatar struct { | ||||
| 	Hash           string | ||||
| 	AlterImage     string // image path
 | ||||
| @ -96,8 +97,8 @@ func (this *Avatar) Encode(wr io.Writer, size int) (err error) { | ||||
| 			return | ||||
| 		} | ||||
| 		defer fd.Close() | ||||
| 		img, err = jpeg.Decode(fd) | ||||
| 		if err != nil { | ||||
| 
 | ||||
| 		if img, err = jpeg.Decode(fd); err != nil { | ||||
| 			fd.Seek(0, os.SEEK_SET) | ||||
| 			img, err = png.Decode(fd) | ||||
| 		} | ||||
| @ -110,8 +111,8 @@ func (this *Avatar) Encode(wr io.Writer, size int) (err error) { | ||||
| 		} | ||||
| 		imgPath = this.AlterImage | ||||
| 	} | ||||
| 	img, err = decodeImageFile(imgPath) | ||||
| 	if err != nil { | ||||
| 
 | ||||
| 	if img, err = decodeImageFile(imgPath); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	m := resize.Resize(uint(size), 0, img, resize.Lanczos3) | ||||
| @ -124,8 +125,7 @@ func (this *Avatar) Update() { | ||||
| 		this.imagePath) | ||||
| } | ||||
| 
 | ||||
| func (this *Avatar) UpdateTimeout(timeout time.Duration) error { | ||||
| 	var err error | ||||
| func (this *Avatar) UpdateTimeout(timeout time.Duration) (err error) { | ||||
| 	select { | ||||
| 	case <-time.After(timeout): | ||||
| 		err = fmt.Errorf("get gravatar image %s timeout", this.Hash) | ||||
| @ -140,8 +140,7 @@ type service struct { | ||||
| 	altImage string | ||||
| } | ||||
| 
 | ||||
| func (this *service) mustInt(r *http.Request, defaultValue int, keys ...string) int { | ||||
| 	var v int | ||||
| func (this *service) mustInt(r *http.Request, defaultValue int, keys ...string) (v int) { | ||||
| 	for _, k := range keys { | ||||
| 		if _, err := fmt.Sscanf(r.FormValue(k), "%d", &v); err == nil { | ||||
| 			defaultValue = v | ||||
| @ -176,8 +175,8 @@ func (this *service) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 		w.Header().Set("ETag", etag) | ||||
| 	} | ||||
| 	w.Header().Set("Content-Type", "image/jpeg") | ||||
| 	err := avatar.Encode(w, size) | ||||
| 	if err != nil { | ||||
| 
 | ||||
| 	if err := avatar.Encode(w, size); err != nil { | ||||
| 		log.Warn("avatar encode error: %v", err) | ||||
| 		w.WriteHeader(500) | ||||
| 	} | ||||
|  | ||||
| @ -51,6 +51,14 @@ func IsTextFile(data []byte) (string, bool) { | ||||
| 	return contentType, false | ||||
| } | ||||
| 
 | ||||
| func IsImageFile(data []byte) (string, bool) { | ||||
| 	contentType := http.DetectContentType(data) | ||||
| 	if strings.Index(contentType, "image/") != -1 { | ||||
| 		return contentType, true | ||||
| 	} | ||||
| 	return contentType, false | ||||
| } | ||||
| 
 | ||||
| func IsReadmeFile(name string) bool { | ||||
| 	name = strings.ToLower(name) | ||||
| 	if len(name) < 6 { | ||||
|  | ||||
| @ -412,6 +412,11 @@ func (f StrTo) Int() (int, error) { | ||||
| 	return int(v), err | ||||
| } | ||||
| 
 | ||||
| func (f StrTo) Int64() (int64, error) { | ||||
| 	v, err := strconv.ParseInt(f.String(), 10, 64) | ||||
| 	return int64(v), err | ||||
| } | ||||
| 
 | ||||
| func (f StrTo) String() string { | ||||
| 	if f.Exist() { | ||||
| 		return string(f) | ||||
| @ -541,16 +546,10 @@ func ActionDesc(act Actioner, avatarLink string) string { | ||||
| } | ||||
| 
 | ||||
| func DiffTypeToStr(diffType int) string { | ||||
| 	switch diffType { | ||||
| 	case 1: | ||||
| 		return "add" | ||||
| 	case 2: | ||||
| 		return "modify" | ||||
| 	case 3: | ||||
| 		return "del" | ||||
| 	default: | ||||
| 		return "unknown" | ||||
| 	diffTypes := map[int]string{ | ||||
| 		1: "add", 2: "modify", 3: "del", | ||||
| 	} | ||||
| 	return diffTypes[diffType] | ||||
| } | ||||
| 
 | ||||
| func DiffLineTypeToStr(diffType int) string { | ||||
|  | ||||
| @ -56,7 +56,9 @@ func RepoAssignment(redirect bool) martini.Handler { | ||||
| 		// get repository
 | ||||
| 		repo, err := models.GetRepositoryByName(user.Id, params["reponame"]) | ||||
| 		if err != nil { | ||||
| 			if redirect { | ||||
| 			if err == models.ErrRepoNotExist { | ||||
| 				ctx.Handle(404, "RepoAssignment", err) | ||||
| 			} else if redirect { | ||||
| 				ctx.Redirect("/") | ||||
| 				return | ||||
| 			} | ||||
|  | ||||
| @ -854,6 +854,10 @@ html, body { | ||||
|     min-width: 180px; | ||||
| } | ||||
| 
 | ||||
| .commit-list .sha a { | ||||
|     font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace; | ||||
| } | ||||
| 
 | ||||
| .guide-box pre, .guide-box .input-group { | ||||
|     margin-top: 20px; | ||||
|     margin-bottom: 30px; | ||||
| @ -1119,7 +1123,7 @@ html, body { | ||||
| #issue .issue-head .info { | ||||
|     width: 99%; | ||||
|     margin-top: 10px; | ||||
|     padding-left: 64px; | ||||
|     padding-left: 74px; | ||||
|     margin-bottom: 16px; | ||||
|     padding-bottom: 20px; | ||||
|     border-bottom: 1px solid #CCC; | ||||
| @ -1169,6 +1173,21 @@ html, body { | ||||
|     border-color: #CCC; | ||||
| } | ||||
| 
 | ||||
| #issue .issue-head .info .btn { | ||||
|     margin-top: -8px; | ||||
|     margin-left: 8px; | ||||
| } | ||||
| 
 | ||||
| #issue .issue-action { | ||||
|     padding-left: 8px; | ||||
|     color: #888; | ||||
|     width: 24px; | ||||
| } | ||||
| 
 | ||||
| #issue-edit-title { | ||||
|     width: 60%; | ||||
| } | ||||
| 
 | ||||
| /* wrapper and footer */ | ||||
| 
 | ||||
| #wrapper { | ||||
|  | ||||
| @ -50,6 +50,14 @@ var Gogits = { | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|     $.fn.extend({ | ||||
|         toggleHide: function () { | ||||
|             $(this).addClass("hidden"); | ||||
|         }, | ||||
|         toggleShow: function () { | ||||
|             $(this).removeClass("hidden"); | ||||
|         } | ||||
|     }) | ||||
| }(jQuery)); | ||||
| 
 | ||||
| (function ($) { | ||||
| @ -352,6 +360,54 @@ function initRepository() { | ||||
|     }()); | ||||
| } | ||||
| 
 | ||||
| function initInstall() { | ||||
|     // database type change
 | ||||
|     $('#install-database').on("change", function () { | ||||
|         var val = $(this).val(); | ||||
|         if (val != "sqlite") { | ||||
|             $('.server-sql').show(); | ||||
|             $('.sqlite-setting').addClass("hide"); | ||||
|             if (val == "pgsql") { | ||||
|                 $('.pgsql-setting').removeClass("hide"); | ||||
|             } else { | ||||
|                 $('.pgsql-setting').addClass("hide"); | ||||
|             } | ||||
|         } else { | ||||
|             $('.server-sql').hide(); | ||||
|             $('.sqlite-setting').removeClass("hide"); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function initIssue() { | ||||
|     // close button
 | ||||
|     (function () { | ||||
|         var $closeBtn = $('#issue-close-btn'); | ||||
|         var $openBtn = $('#issue-open-btn'); | ||||
|         $('#issue-reply-content').on("keyup", function () { | ||||
|             if ($(this).val().length) { | ||||
|                 $closeBtn.text($closeBtn.data("text")); | ||||
|                 $openBtn.text($openBtn.data("text")); | ||||
|             } else { | ||||
|                 $closeBtn.text($closeBtn.data("origin")); | ||||
|                 $openBtn.text($openBtn.data("origin")); | ||||
|             } | ||||
|         }); | ||||
|     }()); | ||||
| 
 | ||||
|     // issue edit mode
 | ||||
|     (function () { | ||||
|         $("#issue-edit-btn").on("click", function () { | ||||
|             $('#issue h1.title,#issue .issue-main > .issue-content .content,#issue-edit-btn').toggleHide(); | ||||
|             $('#issue-edit-title,#issue-edit-content,.issue-edit-cancel,.issue-edit-save').toggleShow(); | ||||
|         }); | ||||
|         $('.issue-edit-cancel').on("click", function () { | ||||
|             $('#issue h1.title,#issue .issue-main > .issue-content .content,#issue-edit-btn').toggleShow(); | ||||
|             $('#issue-edit-title,#issue-edit-content,.issue-edit-cancel,.issue-edit-save').toggleHide(); | ||||
|         }) | ||||
|     }()); | ||||
| } | ||||
| 
 | ||||
| (function ($) { | ||||
|     $(function () { | ||||
|         initCore(); | ||||
| @ -365,5 +421,11 @@ function initRepository() { | ||||
|         if ($('.repo-nav').length) { | ||||
|             initRepository(); | ||||
|         } | ||||
|         if ($('#install-card').length) { | ||||
|             initInstall(); | ||||
|         } | ||||
|         if ($('#issue').length) { | ||||
|             initIssue(); | ||||
|         } | ||||
|     }); | ||||
| })(jQuery); | ||||
|  | ||||
| @ -5,13 +5,22 @@ | ||||
| package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"container/list" | ||||
| 	"path" | ||||
| 
 | ||||
| 	"github.com/codegangsta/martini" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| 	"github.com/gogits/gogs/modules/middleware" | ||||
| ) | ||||
| 
 | ||||
| func Commits(ctx *middleware.Context, params martini.Params) { | ||||
| 	brs, err := models.GetBranches(params["username"], params["reponame"]) | ||||
| 	userName := params["username"] | ||||
| 	repoName := params["reponame"] | ||||
| 	branchName := params["branchname"] | ||||
| 
 | ||||
| 	brs, err := models.GetBranches(userName, repoName) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(200, "repo.Commits", err) | ||||
| 		return | ||||
| @ -20,38 +29,70 @@ func Commits(ctx *middleware.Context, params martini.Params) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	commits, err := models.GetCommits(params["username"], | ||||
| 		params["reponame"], params["branchname"]) | ||||
| 	var commits *list.List | ||||
| 	if models.IsBranchExist(userName, repoName, branchName) { | ||||
| 		commits, err = models.GetCommitsByBranch(userName, repoName, branchName) | ||||
| 	} else { | ||||
| 		commits, err = models.GetCommitsByCommitId(userName, repoName, branchName) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "repo.Commits", nil) | ||||
| 		ctx.Handle(404, "repo.Commits", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Username"] = params["username"] | ||||
| 	ctx.Data["Reponame"] = params["reponame"] | ||||
| 
 | ||||
| 	ctx.Data["Username"] = userName | ||||
| 	ctx.Data["Reponame"] = repoName | ||||
| 	ctx.Data["CommitCount"] = commits.Len() | ||||
| 	ctx.Data["Commits"] = commits | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	ctx.HTML(200, "repo/commits") | ||||
| } | ||||
| 
 | ||||
| func Diff(ctx *middleware.Context, params martini.Params) { | ||||
| 	commit, err := models.GetCommit(params["username"], params["reponame"], params["branchname"], params["commitid"]) | ||||
| 	userName := params["username"] | ||||
| 	repoName := params["reponame"] | ||||
| 	branchName := params["branchname"] | ||||
| 	commitId := params["commitid"] | ||||
| 
 | ||||
| 	commit, err := models.GetCommit(userName, repoName, branchName, commitId) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "repo.Diff", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	diff, err := models.GetDiff(models.RepoPath(params["username"], params["reponame"]), params["commitid"]) | ||||
| 	diff, err := models.GetDiff(models.RepoPath(userName, repoName), commitId) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "repo.Diff", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	shortSha := params["commitid"][:7] | ||||
| 	isImageFile := func(name string) bool { | ||||
| 		repoFile, err := models.GetTargetFile(userName, repoName, | ||||
| 			branchName, commitId, name) | ||||
| 
 | ||||
| 		if err != nil { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		blob, err := repoFile.LookupBlob() | ||||
| 		if err != nil { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		data := blob.Contents() | ||||
| 		_, isImage := base.IsImageFile(data) | ||||
| 		return isImage | ||||
| 	} | ||||
| 
 | ||||
| 	shortSha := params["commitid"][:10] | ||||
| 	ctx.Data["IsImageFile"] = isImageFile | ||||
| 	ctx.Data["Title"] = commit.Message() + " · " + shortSha | ||||
| 	ctx.Data["Commit"] = commit | ||||
| 	ctx.Data["ShortSha"] = shortSha | ||||
| 	ctx.Data["Diff"] = diff | ||||
| 	ctx.Data["IsRepoToolbarCommits"] = true | ||||
| 	ctx.Data["SourcePath"] = "/" + path.Join(userName, repoName, "src", commitId) | ||||
| 	ctx.Data["RawPath"] = "/" + path.Join(userName, repoName, "raw", commitId) | ||||
| 	ctx.HTML(200, "repo/diff") | ||||
| } | ||||
|  | ||||
| @ -6,6 +6,7 @@ package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/url" | ||||
| 
 | ||||
| 	"github.com/codegangsta/martini" | ||||
| 
 | ||||
| @ -17,23 +18,41 @@ import ( | ||||
| 	"github.com/gogits/gogs/modules/middleware" | ||||
| ) | ||||
| 
 | ||||
| func Issues(ctx *middleware.Context, params martini.Params) { | ||||
| func Issues(ctx *middleware.Context) { | ||||
| 	if !ctx.Repo.IsValid { | ||||
| 		ctx.Handle(404, "issue.Issues(invalid repo):", nil) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Title"] = "Issues" | ||||
| 	ctx.Data["IsRepoToolbarIssues"] = true | ||||
| 	ctx.Data["IsRepoToolbarIssuesList"] = true | ||||
| 	ctx.Data["ViewType"] = "all" | ||||
| 
 | ||||
| 	milestoneId, _ := base.StrTo(params["milestone"]).Int() | ||||
| 	page, _ := base.StrTo(params["page"]).Int() | ||||
| 	milestoneId, _ := base.StrTo(ctx.Query("milestone")).Int() | ||||
| 	page, _ := base.StrTo(ctx.Query("page")).Int() | ||||
| 
 | ||||
| 	ctx.Data["IssueCreatedCount"] = 0 | ||||
| 
 | ||||
| 	var posterId int64 = 0 | ||||
| 	if ctx.Query("type") == "created_by" { | ||||
| 		if !ctx.IsSigned { | ||||
| 			ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI)) | ||||
| 			ctx.Redirect("/user/login/", 302) | ||||
| 			return | ||||
| 		} | ||||
| 		posterId = ctx.User.Id | ||||
| 		ctx.Data["ViewType"] = "created_by" | ||||
| 		ctx.Data["IssueCreatedCount"] = models.GetUserIssueCount(posterId, ctx.Repo.Repository.Id) | ||||
| 	} | ||||
| 
 | ||||
| 	// Get issues.
 | ||||
| 	issues, err := models.GetIssues(0, ctx.Repo.Repository.Id, 0, | ||||
| 		int64(milestoneId), page, params["state"] == "closed", false, params["labels"], params["sortType"]) | ||||
| 	issues, err := models.GetIssues(0, ctx.Repo.Repository.Id, posterId, int64(milestoneId), page, | ||||
| 		ctx.Query("state") == "closed", false, ctx.Query("labels"), ctx.Query("sortType")) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(200, "issue.Issues: %v", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	var closedCount int | ||||
| 	// Get posters.
 | ||||
| 	for i := range issues { | ||||
| 		u, err := models.GetUserById(issues[i].PosterId) | ||||
| @ -41,21 +60,22 @@ func Issues(ctx *middleware.Context, params martini.Params) { | ||||
| 			ctx.Handle(200, "issue.Issues(get poster): %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if issues[i].IsClosed { | ||||
| 			closedCount++ | ||||
| 		} | ||||
| 		issues[i].Poster = u | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Issues"] = issues | ||||
| 	ctx.Data["IssueCount"] = len(issues) | ||||
| 	ctx.Data["OpenCount"] = len(issues) - closedCount | ||||
| 	ctx.Data["ClosedCount"] = closedCount | ||||
| 	ctx.Data["IssueCount"] = ctx.Repo.Repository.NumIssues | ||||
| 	ctx.Data["OpenCount"] = ctx.Repo.Repository.NumIssues - ctx.Repo.Repository.NumClosedIssues | ||||
| 	ctx.Data["ClosedCount"] = ctx.Repo.Repository.NumClosedIssues | ||||
| 	ctx.Data["IsShowClosed"] = ctx.Query("state") == "closed" | ||||
| 	ctx.HTML(200, "issue/list") | ||||
| } | ||||
| 
 | ||||
| func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) { | ||||
| 	if !ctx.Repo.IsValid { | ||||
| 		ctx.Handle(404, "issue.CreateIssue(invalid repo):", nil) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Title"] = "Create issue" | ||||
| 	ctx.Data["IsRepoToolbarIssues"] = true | ||||
| 	ctx.Data["IsRepoToolbarIssuesList"] = false | ||||
| @ -71,15 +91,16 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat | ||||
| 	} | ||||
| 
 | ||||
| 	issue, err := models.CreateIssue(ctx.User.Id, ctx.Repo.Repository.Id, form.MilestoneId, form.AssigneeId, | ||||
| 		form.IssueName, form.Labels, form.Content, false) | ||||
| 		ctx.Repo.Repository.NumIssues, form.IssueName, form.Labels, form.Content, false) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(200, "issue.CreateIssue", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Notify watchers.
 | ||||
| 	if err = models.NotifyWatchers(ctx.User.Id, ctx.Repo.Repository.Id, models.OP_CREATE_ISSUE, | ||||
| 		ctx.User.Name, ctx.Repo.Repository.Name, "", fmt.Sprintf("%d|%s", issue.Index, issue.Name)); err != nil { | ||||
| 	if err = models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name, | ||||
| 		OpType: models.OP_CREATE_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name), | ||||
| 		RepoId: ctx.Repo.Repository.Id, RepoName: ctx.Repo.Repository.Name, RefName: ""}); err != nil { | ||||
| 		ctx.Handle(200, "issue.CreateIssue", err) | ||||
| 		return | ||||
| 	} | ||||
| @ -97,6 +118,10 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat | ||||
| } | ||||
| 
 | ||||
| func ViewIssue(ctx *middleware.Context, params martini.Params) { | ||||
| 	if !ctx.Repo.IsValid { | ||||
| 		ctx.Handle(404, "issue.ViewIssue(invalid repo):", nil) | ||||
| 	} | ||||
| 
 | ||||
| 	index, err := base.StrTo(params["index"]).Int() | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "issue.ViewIssue", err) | ||||
| @ -120,6 +145,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { | ||||
| 		return | ||||
| 	} | ||||
| 	issue.Poster = u | ||||
| 	issue.Content = string(base.RenderMarkdown([]byte(issue.Content), "")) | ||||
| 
 | ||||
| 	// Get comments.
 | ||||
| 	comments, err := models.GetIssueComments(issue.Id) | ||||
| @ -136,6 +162,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { | ||||
| 			return | ||||
| 		} | ||||
| 		comments[i].Poster = u | ||||
| 		comments[i].Content = string(base.RenderMarkdown([]byte(comments[i].Content), "")) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Title"] = issue.Name | ||||
| @ -147,6 +174,10 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { | ||||
| } | ||||
| 
 | ||||
| func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) { | ||||
| 	if !ctx.Repo.IsValid { | ||||
| 		ctx.Handle(404, "issue.UpdateIssue(invalid repo):", nil) | ||||
| 	} | ||||
| 
 | ||||
| 	index, err := base.StrTo(params["index"]).Int() | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "issue.UpdateIssue", err) | ||||
| @ -183,6 +214,10 @@ func UpdateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat | ||||
| } | ||||
| 
 | ||||
| func Comment(ctx *middleware.Context, params martini.Params) { | ||||
| 	if !ctx.Repo.IsValid { | ||||
| 		ctx.Handle(404, "issue.Comment(invalid repo):", nil) | ||||
| 	} | ||||
| 
 | ||||
| 	index, err := base.StrTo(ctx.Query("issueIndex")).Int() | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "issue.Comment", err) | ||||
|  | ||||
| @ -57,19 +57,23 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	branchName := params["branchname"] | ||||
| 	userName := params["username"] | ||||
| 	repoName := params["reponame"] | ||||
| 
 | ||||
| 	// Get tree path
 | ||||
| 	treename := params["_1"] | ||||
| 
 | ||||
| 	if len(treename) > 0 && treename[len(treename)-1] == '/' { | ||||
| 		ctx.Redirect("/" + ctx.Repo.Owner.LowerName + "/" + | ||||
| 			ctx.Repo.Repository.Name + "/src/" + params["branchname"] + "/" + treename[:len(treename)-1]) | ||||
| 			ctx.Repo.Repository.Name + "/src/" + branchName + "/" + treename[:len(treename)-1]) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["IsRepoToolbarSource"] = true | ||||
| 
 | ||||
| 	// Branches.
 | ||||
| 	brs, err := models.GetBranches(params["username"], params["reponame"]) | ||||
| 	brs, err := models.GetBranches(userName, repoName) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "repo.Single(GetBranches)", err) | ||||
| 		return | ||||
| @ -80,15 +84,22 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 	} | ||||
| 	ctx.Data["Branches"] = brs | ||||
| 
 | ||||
| 	repoFile, err := models.GetTargetFile(params["username"], params["reponame"], | ||||
| 		params["branchname"], params["commitid"], treename) | ||||
| 	var commitId string | ||||
| 	isViewBranch := models.IsBranchExist(userName, repoName, branchName) | ||||
| 	if !isViewBranch { | ||||
| 		commitId = branchName | ||||
| 	} | ||||
| 	ctx.Data["IsViewBranch"] = isViewBranch | ||||
| 
 | ||||
| 	repoFile, err := models.GetTargetFile(userName, repoName, | ||||
| 		branchName, commitId, treename) | ||||
| 	if err != nil && err != models.ErrRepoFileNotExist { | ||||
| 		ctx.Handle(404, "repo.Single(GetTargetFile)", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"] | ||||
| 	rawLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/raw/" + params["branchname"] | ||||
| 	branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + branchName | ||||
| 	rawLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/raw/" + branchName | ||||
| 
 | ||||
| 	if len(treename) != 0 && repoFile == nil { | ||||
| 		ctx.Handle(404, "repo.Single", nil) | ||||
| @ -111,23 +122,28 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 
 | ||||
| 			data := blob.Contents() | ||||
| 			_, isTextFile := base.IsTextFile(data) | ||||
| 			_, isImageFile := base.IsImageFile(data) | ||||
| 			ctx.Data["FileIsText"] = isTextFile | ||||
| 
 | ||||
| 			readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name) | ||||
| 			ctx.Data["ReadmeExist"] = readmeExist | ||||
| 			if readmeExist { | ||||
| 				ctx.Data["FileContent"] = string(base.RenderMarkdown(data, "")) | ||||
| 			if isImageFile { | ||||
| 				ctx.Data["IsImageFile"] = true | ||||
| 			} else { | ||||
| 				if isTextFile { | ||||
| 					ctx.Data["FileContent"] = string(data) | ||||
| 				readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name) | ||||
| 				ctx.Data["ReadmeExist"] = readmeExist | ||||
| 				if readmeExist { | ||||
| 					ctx.Data["FileContent"] = string(base.RenderMarkdown(data, "")) | ||||
| 				} else { | ||||
| 					if isTextFile { | ||||
| 						ctx.Data["FileContent"] = string(data) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	} else { | ||||
| 		// Directory and file list.
 | ||||
| 		files, err := models.GetReposFiles(params["username"], params["reponame"], | ||||
| 			params["branchname"], params["commitid"], treename) | ||||
| 		files, err := models.GetReposFiles(userName, repoName, | ||||
| 			branchName, commitId, treename) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(404, "repo.Single(GetReposFiles)", err) | ||||
| 			return | ||||
| @ -166,8 +182,8 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Username"] = params["username"] | ||||
| 	ctx.Data["Reponame"] = params["reponame"] | ||||
| 	ctx.Data["Username"] = userName | ||||
| 	ctx.Data["Reponame"] = repoName | ||||
| 
 | ||||
| 	var treenames []string | ||||
| 	Paths := make([]string, 0) | ||||
| @ -185,8 +201,8 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 	} | ||||
| 
 | ||||
| 	// Get latest commit according username and repo name.
 | ||||
| 	commit, err := models.GetCommit(params["username"], params["reponame"], | ||||
| 		params["branchname"], params["commitid"]) | ||||
| 	commit, err := models.GetCommit(userName, repoName, | ||||
| 		branchName, commitId) | ||||
| 	if err != nil { | ||||
| 		log.Error("repo.Single(GetCommit): %v", err) | ||||
| 		ctx.Handle(404, "repo.Single(GetCommit)", err) | ||||
| @ -194,6 +210,8 @@ func Single(ctx *middleware.Context, params martini.Params) { | ||||
| 	} | ||||
| 	ctx.Data["LastCommit"] = commit | ||||
| 
 | ||||
| 	ctx.Data["CommitId"] = commitId | ||||
| 
 | ||||
| 	ctx.Data["Paths"] = Paths | ||||
| 	ctx.Data["Treenames"] = treenames | ||||
| 	ctx.Data["BranchLink"] = branchLink | ||||
| @ -209,8 +227,18 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) { | ||||
| 	// Get tree path
 | ||||
| 	treename := params["_1"] | ||||
| 
 | ||||
| 	repoFile, err := models.GetTargetFile(params["username"], params["reponame"], | ||||
| 		params["branchname"], params["commitid"], treename) | ||||
| 	branchName := params["branchname"] | ||||
| 	userName := params["username"] | ||||
| 	repoName := params["reponame"] | ||||
| 
 | ||||
| 	var commitId string | ||||
| 	if !models.IsBranchExist(userName, repoName, branchName) { | ||||
| 		commitId = branchName | ||||
| 		branchName = "" | ||||
| 	} | ||||
| 
 | ||||
| 	repoFile, err := models.GetTargetFile(userName, repoName, | ||||
| 		branchName, commitId, treename) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(404, "repo.SingleDownload(GetTargetFile)", err) | ||||
| @ -225,9 +253,9 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) { | ||||
| 
 | ||||
| 	data := blob.Contents() | ||||
| 	contentType, isTextFile := base.IsTextFile(data) | ||||
| 	_, isImageFile := base.IsImageFile(data) | ||||
| 	ctx.Res.Header().Set("Content-Type", contentType) | ||||
| 	if !isTextFile { | ||||
| 		ctx.Res.Header().Set("Content-Type", contentType) | ||||
| 	if !isTextFile && !isImageFile { | ||||
| 		ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename)) | ||||
| 		ctx.Res.Header().Set("Content-Transfer-Encoding", "binary") | ||||
| 	} | ||||
|  | ||||
| @ -286,6 +286,85 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) { | ||||
| 
 | ||||
| func Issues(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = "Your Issues" | ||||
| 	ctx.Data["ViewType"] = "all" | ||||
| 
 | ||||
| 	page, _ := base.StrTo(ctx.Query("page")).Int() | ||||
| 	repoId, _ := base.StrTo(ctx.Query("repoid")).Int64() | ||||
| 
 | ||||
| 	ctx.Data["RepoId"] = repoId | ||||
| 
 | ||||
| 	var posterId int64 = 0 | ||||
| 	if ctx.Query("type") == "created_by" { | ||||
| 		posterId = ctx.User.Id | ||||
| 		ctx.Data["ViewType"] = "created_by" | ||||
| 	} | ||||
| 
 | ||||
| 	// Get all repositories.
 | ||||
| 	repos, err := models.GetRepositories(ctx.User) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(200, "user.Issues(get repositories)", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	showRepos := make([]models.Repository, 0, len(repos)) | ||||
| 
 | ||||
| 	var closedIssueCount, createdByCount int | ||||
| 
 | ||||
| 	// Get all issues.
 | ||||
| 	allIssues := make([]models.Issue, 0, 5*len(repos)) | ||||
| 	for i, repo := range repos { | ||||
| 		issues, err := models.GetIssues(0, repo.Id, posterId, 0, page, false, false, "", "") | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(200, "user.Issues(get issues)", err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		closedIssueCount += repo.NumClosedIssues | ||||
| 
 | ||||
| 		// Set repository information to issues.
 | ||||
| 		for j := range issues { | ||||
| 			issues[j].Repo = &repos[i] | ||||
| 		} | ||||
| 		allIssues = append(allIssues, issues...) | ||||
| 
 | ||||
| 		repos[i].NumOpenIssues = repo.NumIssues - repo.NumClosedIssues | ||||
| 		if repos[i].NumOpenIssues > 0 { | ||||
| 			showRepos = append(showRepos, repos[i]) | ||||
| 
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	showIssues := make([]models.Issue, 0, len(allIssues)) | ||||
| 	isShowClosed := ctx.Query("state") == "closed" | ||||
| 	ctx.Data["IsShowClosed"] = isShowClosed | ||||
| 
 | ||||
| 	// Get posters and filter issues.
 | ||||
| 	for i := range allIssues { | ||||
| 		u, err := models.GetUserById(allIssues[i].PosterId) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(200, "user.Issues(get poster): %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 		allIssues[i].Poster = u | ||||
| 		if u.Id == ctx.User.Id { | ||||
| 			createdByCount++ | ||||
| 		} | ||||
| 
 | ||||
| 		if repoId > 0 && repoId != allIssues[i].Repo.Id { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		if isShowClosed == allIssues[i].IsClosed { | ||||
| 			showIssues = append(showIssues, allIssues[i]) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Repos"] = showRepos | ||||
| 	ctx.Data["Issues"] = showIssues | ||||
| 	ctx.Data["AllIssueCount"] = len(allIssues) | ||||
| 	ctx.Data["ClosedIssueCount"] = closedIssueCount | ||||
| 	ctx.Data["OpenIssueCount"] = len(allIssues) - closedIssueCount | ||||
| 	ctx.Data["CreatedByCount"] = createdByCount | ||||
| 	ctx.HTML(200, "issue/user") | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -2,69 +2,198 @@ | ||||
| <div id="body" class="container"> | ||||
|     <form action="/install" method="post" class="form-horizontal card" id="install-card"> | ||||
|         {{.CsrfTokenHtml}} | ||||
|         <h3>Install Steps</h3> | ||||
|         <h3>Install Steps For First-time Run</h3> | ||||
| 
 | ||||
|         <div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div> | ||||
|         <p class="help-block text-center">GoGits need MySQL or PostgreSQL server</p> | ||||
|         <div class="form-group {{if .Err_User}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label"><strong>MySQL </strong>Host: </label> | ||||
|         <p class="help-block text-center">Gogs requires MySQL or PostgreSQL based on your choice</p> | ||||
|         <div class="form-group"> | ||||
|             <label class="col-md-3 control-label">Database Type: </label> | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="host" class="form-control" placeholder="Type mysql server ip or domain" value="localhost" required="required"> | ||||
|                 <select name="database" id="install-database" class="form-control"> | ||||
|                     <option value="mysql">MySQL</option> | ||||
|                     <option value="pgsql">PostgreSQL</option> | ||||
|                     <option value="sqlite">SQLite</option> | ||||
|                 </select> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group {{if .Err_User}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label">Port: </label> | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="port" class="form-control" placeholder="Type mysql server port" value="3306" required="required"> | ||||
|         <div class="server-sql"> | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">Host: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="host" class="form-control" placeholder="Type mysql server ip or domain" value="localhost" required="required"> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">Port: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="port" class="form-control" placeholder="Type mysql server port" value="3306" required="required"> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">User: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="user" class="form-control" placeholder="Type mysql username" required="required"> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">Password: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="passwd" type="password" class="form-control" placeholder="Type mysql password" required="required"> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">Database Name: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="database" type="text" class="form-control" placeholder="Type mysql database name" value="gogs" required="required"> | ||||
|                     <p class="help-block">Recommend use INNODB engine with utf8_general_ci charset.</p> | ||||
|                 </div> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="form-group pgsql-setting hide"> | ||||
|                 <label class="col-md-3 control-label">SSL Mode: </label> | ||||
|                 <div class="col-md-8"> | ||||
|                     <select name="ssl_mode" class="form-control"> | ||||
|                         <option value="disable">Disable</option> | ||||
|                         <option value="require">Require</option> | ||||
|                         <option value="verify-full">Verify Full</option> | ||||
|                     </select> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group {{if .Err_User}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label">User: </label> | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="user" class="form-control" placeholder="Type mysql username" required="required"> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label">Password: </label> | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="passwd" type="password" class="form-control" placeholder="Type mysql password" required="required"> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label">Database: </label> | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="database" type="text" class="form-control" placeholder="Type mysql database name" value="gogs" required="required"> | ||||
|                 <p class="help-block">Recommend use INNODB engine with utf8_general_ci charset.</p> | ||||
|         <div class="sqlite-setting hide"> | ||||
|             <div class="form-group"> | ||||
|                 <label class="col-md-3 control-label">Path: </label> | ||||
| 
 | ||||
|                 <div class="col-md-8"> | ||||
|                     <input name="path" class="form-control" placeholder="Type sqlite file path" value="xxx/file.db"> | ||||
|                     <p class="help-block">The file path of SQLite database.</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="form-group"> | ||||
|         <!-- <div class="form-group"> | ||||
|             <div class="col-md-8 col-md-offset-3"> | ||||
|                    <button class="btn btn-sm btn-info">Test Connection</button> | ||||
|                 <button class="btn btn-sm btn-info">Test Connection</button> | ||||
|             </div> | ||||
|         </div> | ||||
|         </div> --> | ||||
| 
 | ||||
|         <hr/> | ||||
| 
 | ||||
|         <p class="help-block text-center">General settings for GoGits</p> | ||||
|         <p class="help-block text-center">General Settings of Gogs</p> | ||||
| 
 | ||||
|         <div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | ||||
|         <div class="form-group"> | ||||
|             <label class="col-md-3 control-label">Repository Path: </label> | ||||
| 
 | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="repo-path" type="text" class="form-control" placeholder="Type your repository directory" value="/var/gogs/repostiory" required="required"> | ||||
| 
 | ||||
|                 <p class="help-block">The git copy of each repository is saved in this directory.</p> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}"> | ||||
|             <label class="col-md-3 control-label">System User: </label> | ||||
|         <div class="form-group"> | ||||
|             <label class="col-md-3 control-label">Run User: </label> | ||||
| 
 | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="system-user" type="text" class="form-control" placeholder="Type mysql password" value="root" required="required"> | ||||
|                 <p class="help-block">The user has access to visit and run GoGits.</p> | ||||
|                 <p class="help-block">The user has access to visit and run Gogs.</p> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <hr/> | ||||
|         <div class="form-group text-center"> | ||||
|             <a class="btn btn-danger btn-lg">Install GoGits</a> | ||||
| 
 | ||||
|         <p class="help-block text-center">Admin Account Settings</p> | ||||
| 
 | ||||
|         <div class="form-group"> | ||||
|             <label class="col-md-3 control-label">Username: </label> | ||||
| 
 | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="repo-path" type="text" class="form-control" placeholder="Type admin user name" value="admin" required="required"> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="form-group"> | ||||
|             <label class="col-md-3 control-label">Password: </label> | ||||
| 
 | ||||
|             <div class="col-md-8"> | ||||
|                 <input name="system-user" type="password" class="form-control" placeholder="Type admin user password" required="required"> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <hr/> | ||||
| 
 | ||||
|         <div class="form-group text-center"> | ||||
|             <button class="btn btn-danger btn-lg">Install Gogs</button> | ||||
|             <button class="btn btn-default btn-sm" type="button" data-toggle="modal" data-target="#advance-options-modal"> | ||||
|                 Advanced Options | ||||
|             </button> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="modal fade" id="advance-options-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> | ||||
|             <div class="modal-dialog"> | ||||
|                 <div class="modal-content"> | ||||
|                     <div class="modal-header"><h4 class="modal-title">Advanced Options</h4></div> | ||||
|                     <div class="modal-body"> | ||||
|                         <p class="help-block text-center">Email Service Settings</p> | ||||
| 
 | ||||
|                         <div class="form-group"> | ||||
|                             <label class="col-md-3 control-label">SMTP Host: </label> | ||||
| 
 | ||||
|                             <div class="col-md-8"> | ||||
|                                 <input name="repo-path" type="text" class="form-control" placeholder="Type admin user name"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group"> | ||||
|                             <label class="col-md-3 control-label">Email: </label> | ||||
| 
 | ||||
|                             <div class="col-md-8"> | ||||
|                                 <input name="repo-path" type="text" class="form-control" placeholder="Type admin user name"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="form-group"> | ||||
|                             <label class="col-md-3 control-label">Password: </label> | ||||
| 
 | ||||
|                             <div class="col-md-8"> | ||||
|                                 <input name="system-user" type="password" class="form-control" placeholder="Type admin user password"> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <hr/> | ||||
|                         <p class="text-center help-block">Notification Settings</p> | ||||
| 
 | ||||
|                         <div class="form-group"> | ||||
|                             <div class="col-md-offset-3 col-md-7"> | ||||
|                                 <div class="checkbox"> | ||||
|                                     <label> | ||||
|                                         <input name="system-user" type="checkbox"> | ||||
|                                         <strong>Enable Register Confirmation</strong> | ||||
|                                     </label> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
| 
 | ||||
|                         <div class="form-group"> | ||||
|                             <div class="col-md-offset-3 col-md-7"> | ||||
|                                 <div class="checkbox"> | ||||
|                                     <label> | ||||
|                                         <input name="system-user" type="checkbox"> | ||||
|                                         <strong>Enable Mail Notification</strong> | ||||
|                                     </label> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
| 
 | ||||
|                     <div class="modal-footer"> | ||||
|                         <button type="button" class="btn btn-success" data-dismiss="modal">Confirm</button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|     </form> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @ -6,16 +6,17 @@ | ||||
|     <div id="issue"> | ||||
|         <div class="col-md-3 filter-list"> | ||||
|             <ul class="list-unstyled"> | ||||
|                 <li><a href="#" class="active">All Issues <strong class="pull-right">{{.IssueCount}}</strong></a></li> | ||||
|                 <li><a href="#">My Issues</a></li> | ||||
|                 <li><a href="#">Mentioned</a></li> | ||||
|                 <li><a href="/{{.RepositoryLink}}/issues"{{if eq .ViewType "all"}} class="active"{{end}}>All Issues <strong class="pull-right">{{.IssueCount}}</strong></a></li> | ||||
|                 <!-- <li><a href="#">Assigned to you</a></li> --> | ||||
|                 <li><a href="/{{.RepositoryLink}}/issues?type=created_by"{{if eq .ViewType "created_by"}} class="active"{{end}}>Created by you <strong class="pull-right">{{.IssueCreatedCount}}</strong></a></li> | ||||
|                 <!-- <li><a href="#">Mentioned</a></li> --> | ||||
|             </ul> | ||||
|         </div> | ||||
|         <div class="col-md-9"> | ||||
|             <div class="filter-option"> | ||||
|                 <div class="btn-group"> | ||||
|                     <a class="btn btn-default active issue-open" href="#">{{.OpenCount}} Open</a> | ||||
|                     <a class="btn btn-default issue-close" href="#">{{.ClosedCount}} Closed</a> | ||||
|                     <a class="btn btn-default issue-open{{if not .IsShowClosed}} active{{end}}" href="/{{.RepositoryLink}}/issues?type={{.ViewType}}">{{.OpenCount}} Open</a> | ||||
|                     <a class="btn btn-default issue-close{{if .IsShowClosed}} active{{end}}" href="/{{.RepositoryLink}}/issues?state=closed&type={{.ViewType}}">{{.ClosedCount}} Closed</a> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="issues list-group"> | ||||
|  | ||||
| @ -16,53 +16,35 @@ | ||||
|     <div id="issue"> | ||||
|         <div class="col-md-3 filter-list"> | ||||
|             <ul class="list-unstyled"> | ||||
|                 <li><a href="#" class="active">In your repositories <strong class="pull-right">10</strong></a></li> | ||||
|                 <li><a href="#">Created by you</a></li> | ||||
|                 <li><a href="#">Assigned to you</a></li> | ||||
|                 <li><a href="/issues"{{if eq .ViewType "all"}} class="active"{{end}}>In your repositories <strong class="pull-right">{{.AllIssueCount}}</strong></a></li> | ||||
|                 <!-- <li><a href="#">Assigned to you</a></li> --> | ||||
|                 <li><a href="/issues?type=created_by"{{if eq .ViewType "created_by"}} class="active"{{end}}>Created by you <strong class="pull-right">{{.CreatedByCount}}</strong></a></li> | ||||
|                 <li><hr/></li> | ||||
|                 <li><a href="" class="sm">gogits/gogs <strong class="pull-right">12</strong></a></li> | ||||
|                 <li><a href="" class="sm">gogits/session <strong class="pull-right">8</strong></a></li> | ||||
|                 <li><a href="" class="sm">gogits/git <strong class="pull-right">2</strong></a></li> | ||||
|                 {{range .Repos}} | ||||
|                 <li><a href="/issues?type={{$.ViewType}}{{if eq $.RepoId .Id}}{{else}}&repoid={{.Id}}{{end}}" class="sm{{if eq $.RepoId .Id}} active{{end}}">{{$.SignedUser.Name}}/{{.Name}} <strong class="pull-right">{{.NumOpenIssues}}</strong></a></li> | ||||
|                 {{end}} | ||||
|             </ul> | ||||
|         </div> | ||||
|         <div class="col-md-9"> | ||||
|             <div class="filter-option"> | ||||
|                 <div class="btn-group"> | ||||
|                     <a class="btn btn-default active issue-open" href="#">27 Open</a> | ||||
|                     <a class="btn btn-default issue-close" href="#">Close 128</a> | ||||
|                     <a class="btn btn-default issue-open{{if not .IsShowClosed}} active{{end}}" href="/issues?type={{.ViewType}}&repoid={{.RepoId}}">{{.OpenIssueCount}} Open</a> | ||||
|                     <a class="btn btn-default issue-close{{if .IsShowClosed}} active{{end}}" href="/issues?state=closed&type={{.ViewType}}&repoid={{.RepoId}}">{{.ClosedIssueCount}} Close</a> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="issues list-group"> | ||||
|                 <div class="list-group-item unread issue-item" id="issue-id"> | ||||
|                     <span class="number pull-right">#123</span> | ||||
|                     <h5 class="title"><a href="#">Bug: When running tests after generating a beego app, templates do not load.</a></h5> | ||||
|                 {{range .Issues}} | ||||
|                 <div class="list-group-item issue-item" id="issue-{{.Id}}"> | ||||
|                     <span class="number pull-right">#{{.Index}}</span> | ||||
|                     <h5 class="title"><a href="/{{$.SignedUser.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Name}}</a></h5> | ||||
|                     <p class="info"> | ||||
|                         <span class="author"><img class="avatar" src="http://tp2.sinaimg.cn/5068084885/50/40050297589/1" alt="" width="20"/> | ||||
|                         <a href="#">Obama</a></span> | ||||
|                         <span class="time">3 days ago</span> | ||||
|                         <span class="comment"><i class="fa fa-comments"></i> 3</span> | ||||
|                     </p> | ||||
|                 </div> | ||||
|                 <div class="list-group-item issue-item" id="issue-id2"> | ||||
|                     <span class="number pull-right">#123</span> | ||||
|                     <h5 class="title"><a href="#">Bug: When running tests after generating a beego app, templates do not load.</a></h5> | ||||
|                     <p class="info"> | ||||
|                         <span class="author"><img class="avatar" src="http://tp2.sinaimg.cn/5068084885/50/40050297589/1" alt="" width="20"/> | ||||
|                         <a href="#">Obama</a></span> | ||||
|                         <span class="time">3 days ago</span> | ||||
|                         <span class="comment"><i class="fa fa-comments"></i> 3</span> | ||||
|                     </p> | ||||
|                 </div> | ||||
|                 <div class="list-group-item issue-item" id="issue-id3"> | ||||
|                     <span class="number pull-right">#123</span> | ||||
|                     <h5 class="title"><a href="#">Bug: When running tests after generating a beego app, templates do not load.</a></h5> | ||||
|                     <p class="info"> | ||||
|                         <span class="author"><img class="avatar" src="http://tp2.sinaimg.cn/5068084885/50/40050297589/1" alt="" width="20"/> | ||||
|                         <a href="#">Obama</a></span> | ||||
|                         <span class="time">3 days ago</span> | ||||
|                         <span class="comment"><i class="fa fa-comments"></i> 3</span> | ||||
|                         <span class="author"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" width="20"/> | ||||
|                         <a href="/user/{{.Poster.Name}}">{{.Poster.Name}}</a></span> | ||||
|                         <span class="time">{{TimeSince .Created}}</span> | ||||
|                         <span class="comment"><i class="fa fa-comments"></i> {{.NumComments}}</span> | ||||
|                     </p> | ||||
|                 </div> | ||||
|                 {{end}} | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
| @ -4,12 +4,16 @@ | ||||
| {{template "repo/toolbar" .}} | ||||
| <div id="body" class="container"> | ||||
|     <div id="issue"> | ||||
|         <div id="issue-id" class="issue-whole"> | ||||
|         <div id="issue-{issue.id}" class="issue-whole"> | ||||
|             <div class="issue-head clearfix"> | ||||
|                 <div class="number pull-right">#{{.Issue.Index}}</div> | ||||
|                 <a class="author pull-left" href="/user/{{.Issue.Poster.Name}}"><img class="avatar" src="{{.Issue.Poster.AvatarLink}}" alt="" width="30"/></a> | ||||
|                 <h1 class="title pull-left">{{.Issue.Name}}</h1> | ||||
|                 <input id="issue-edit-title" class="form-control input-lg pull-left hidden" type="text" value="{issue.title}" data-ajax-rel="issue-save"/> | ||||
|                 <p class="info pull-left"> | ||||
|                     <a class="btn btn-default pull-right issue-edit" href="#" id="issue-edit-btn">Edit</a> | ||||
|                     <a class="btn btn-danger pull-right issue-edit-cancel hidden" href="#">Cancel</a> | ||||
|                     <a class="btn btn-primary pull-right issue-edit-save hidden" href="#" data-ajax="{issue.save.link}" data-ajax-name="issue-save">Save</a> | ||||
|                     <span class="status label label-{{if .Issue.IsClosed}}danger{{else}}success{{end}}">{{if .Issue.IsClosed}}Closed{{else}}Open{{end}}</span> | ||||
|                     <a href="/user/{{.Issue.Poster.Name}}" class="author"><strong>{{.Issue.Poster.Name}}</strong></a> opened this issue | ||||
|                     <span class="time">{{TimeSince .Issue.Created}}</span> · {{.Issue.NumComments}} comments | ||||
| @ -18,18 +22,24 @@ | ||||
|             <div class="issue-main"> | ||||
|                <div class="panel panel-default issue-content"> | ||||
|                    <div class="panel-body markdown"> | ||||
|                        <p>{{.Issue.Content}}</p> | ||||
|                        <div class="content"> | ||||
|                            {{str2html .Issue.Content}} | ||||
|                        </div> | ||||
|                        <textarea class="form-control hidden" name="content" id="issue-edit-content" rows="10" data-ajax-rel="issue-save">content</textarea> | ||||
|                    </div> | ||||
|                </div> | ||||
|                {{range .Comments}} | ||||
|                <div class="issue-child"> | ||||
|                <div class="issue-child" id="issue-comment-{issue.comment.id}"> | ||||
|                    <a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a> | ||||
|                    <div class="issue-content panel panel-default"> | ||||
|                        <div class="panel-heading"> | ||||
|                            <a href="/user/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created}}</span> | ||||
|                            <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a> | ||||
|                            <a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a> | ||||
|                            <span class="role label label-default pull-right">Owner</span> | ||||
|                        </div> | ||||
|                        <div class="panel-body markdown"> | ||||
|                            <p>{{.Content}}</p> | ||||
|                           {{str2html .Content}} | ||||
|                        </div> | ||||
|                    </div> | ||||
|                 </div> | ||||
| @ -52,7 +62,7 @@ | ||||
|                                     <div class="tab-pane" id="issue-textarea"> | ||||
|                                         <div class="form-group"> | ||||
|                                             <input type="hidden" value="{{.Issue.Index}}" name="issueIndex"/> | ||||
|                                             <textarea class="form-control" name="content" id="issue-content" rows="10" placeholder="Write some content">{{.content}}</textarea> | ||||
|                                             <textarea class="form-control" name="content" id="issue-reply-content" rows="10" placeholder="Write some content">{{.content}}</textarea> | ||||
|                                         </div> | ||||
|                                     </div> | ||||
|                                     <div class="tab-pane" id="issue-preview">preview</div> | ||||
| @ -61,7 +71,9 @@ | ||||
|                             <div class="text-right"> | ||||
|                                 <div class="form-group"> | ||||
|                                     <input type="hidden" value="id" name="repo-id"/> | ||||
|                                     <button class="btn-success btn">Comment</button> | ||||
|                                     <button class="btn-default btn issue-open" id="issue-open-btn" data-origin="Open" data-text="Open & Comment">Open</button>   | ||||
|                                     <button class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment">Close</button>   | ||||
|                                     <button class="btn-success btn" id="issue-reply-btn">Comment</button> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | ||||
| @ -27,7 +27,7 @@ | ||||
|                 {{range $r}} | ||||
|                 <tr> | ||||
|                     <td class="author"><img class="avatar" src="{{AvatarLink .Committer.Email}}" alt=""/><a href="/user/{{.Committer.Name}}">{{.Committer.Name}}</a></td> | ||||
|                     <td class="sha"><a class="label label-success" href="/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 7}} </a></td> | ||||
|                     <td class="sha"><a class="label label-success" href="/{{$username}}/{{$reponame}}/commit/{{.Id}} ">{{SubStr .Id.String 0 10}} </a></td> | ||||
|                     <td class="message">{{.Message}} </td> | ||||
|                     <td class="date">{{TimeSince .Committer.When}}</td> | ||||
|                 </tr> | ||||
| @ -37,4 +37,4 @@ | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|     <div id="source"> | ||||
|         <div class="panel panel-info diff-box diff-head-box"> | ||||
|             <div class="panel-heading"> | ||||
|                 <a class="pull-right btn btn-primary btn-sm" href="#commit-source">Browse Source</a> | ||||
|                 <a class="pull-right btn btn-primary btn-sm" href="{{.SourcePath}}">Browse Source</a> | ||||
|                 <h4>{{.Commit.Message}}</h4> | ||||
|             </div> | ||||
|             <div class="panel-body"> | ||||
| @ -57,10 +57,16 @@ | ||||
|                     </span> | ||||
|                     <span class="del" data-line="{{.Deletion}}">- {{.Deletion}}</span> | ||||
|                 </div> | ||||
|                 <a class="btn btn-default btn-sm pull-right" href="#">View File</a> | ||||
|                 <a class="btn btn-default btn-sm pull-right" href="{{$.SourcePath}}/{{.Name}}">View File</a> | ||||
|                 <span class="file">{{.Name}}</span> | ||||
|             </div> | ||||
|             {{$isImage := (call $.IsImageFile .Name)}} | ||||
|             <div class="panel-body file-body file-code code-view code-diff"> | ||||
|                 {{if $isImage}} | ||||
|                     <div class="text-center"> | ||||
|                         <img src="{{$.RawPath}}/{{.Name}}"> | ||||
|                     </div> | ||||
|                 {{else}} | ||||
|                 <table> | ||||
|                     <tbody> | ||||
|                         {{range .Sections}} | ||||
| @ -201,6 +207,7 @@ | ||||
|                         </tr> --> | ||||
|                     </tbody> | ||||
|                 </table> | ||||
|                 {{end}} | ||||
|             </div> | ||||
|         </div> | ||||
|         {{end}} | ||||
| @ -411,4 +418,4 @@ | ||||
|         </div> --> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
|  | ||||
| @ -11,7 +11,7 @@ | ||||
|             {{ $n := len .Treenames}} | ||||
|             {{if not .IsFile}}<button class="btn btn-default pull-right hidden"><i class="fa fa-plus-square"></i>Add File</button>{{end}} | ||||
|             <div class="dropdown branch-switch"> | ||||
|                 <a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><i class="fa fa-chain"></i>{{.Branchname}}   | ||||
|                 <a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><i class="fa fa-chain"></i>{{if .CommitId}}{{SubStr .CommitId 0 10}}{{else}}{{.Branchname}}{{end}}   | ||||
|                     <b class="caret"></b></a> | ||||
|                 <ul class="dropdown-menu"> | ||||
|                     {{range .Branches}} | ||||
| @ -41,4 +41,4 @@ | ||||
|         {{end}} | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| {{template "base/footer" .}} | ||||
|  | ||||
| @ -23,7 +23,11 @@ | ||||
|     </div> | ||||
|     {{if not .FileIsText}} | ||||
|         <div class="panel-footer text-center"> | ||||
|             <a href="{{.FileLink}}" class="btn btn-default">View Raw</a> | ||||
|             {{if .IsImageFile}} | ||||
|                 <img src="{{.FileLink}}"> | ||||
|             {{else}} | ||||
|                 <a href="{{.FileLink}}" class="btn btn-default">View Raw</a> | ||||
|             {{end}} | ||||
|         </div> | ||||
|     {{else}} | ||||
|         {{if .ReadmeExist}} | ||||
| @ -43,4 +47,4 @@ | ||||
|             </div> | ||||
|         {{end}} | ||||
|     {{end}} | ||||
| </div> | ||||
| </div> | ||||
|  | ||||
| @ -5,7 +5,7 @@ | ||||
|                 <ul class="nav navbar-nav"> | ||||
|                     <li class="{{if .IsRepoToolbarSource}}active{{end}}"><a href="/{{.RepositoryLink}}">Source</a></li> | ||||
|                     {{if not .IsBareRepo}} | ||||
|                     <li class="{{if .IsRepoToolbarCommits}}active{{end}}"><a href="/{{.RepositoryLink}}/commits/{{.Branchname}}">Commits</a></li> | ||||
|                     {{if .IsViewBranch}}<li class="{{if .IsRepoToolbarCommits}}active{{end}}"><a href="/{{.RepositoryLink}}/commits/{{.Branchname}}">Commits</a></li>{{end}} | ||||
|                     <!-- <li class="{{if .IsRepoToolbarBranches}}active{{end}}"><a href="/{{.RepositoryLink}}/branches">Branches</a></li> --> | ||||
|                     <!-- <li class="{{if .IsRepoToolbarPulls}}active{{end}}"><a href="/{{.RepositoryLink}}/pulls">Pull Requests</a></li> --> | ||||
|                     <li class="{{if .IsRepoToolbarIssues}}active{{end}}"><a href="/{{.RepositoryLink}}/issues">Issues <!--<span class="badge">42</span>--></a></li> | ||||
|  | ||||
							
								
								
									
										8
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								web.go
									
									
									
									
									
								
							| @ -138,6 +138,10 @@ func runWeb(*cli.Context) { | ||||
| 		r.Any("/:userid/delete", admin.DeleteUser) | ||||
| 	}, adminReq) | ||||
| 
 | ||||
| 	if martini.Env == martini.Dev { | ||||
| 		m.Get("/template/**", dev.TemplatePreview) | ||||
| 	} | ||||
| 
 | ||||
| 	m.Group("/:username/:reponame", func(r martini.Router) { | ||||
| 		r.Post("/settings", repo.SettingPost) | ||||
| 		r.Get("/settings", repo.Setting) | ||||
| @ -168,10 +172,6 @@ func runWeb(*cli.Context) { | ||||
| 		r.Any("/:reponame/**", repo.Http) | ||||
| 	}, ignSignIn) | ||||
| 
 | ||||
| 	if martini.Env == martini.Dev { | ||||
| 		m.Get("/template/**", dev.TemplatePreview) | ||||
| 	} | ||||
| 
 | ||||
| 	// Not found handler.
 | ||||
| 	m.NotFound(routers.NotFound) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user