| @@ -1,4 +1,4 @@ | |||||
| Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://drone.io/github.com/gogits/gogs/latest) | |||||
| Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://drone.io/github.com/gogits/gogs/latest) [](https://bitdeli.com/free "Bitdeli Badge") | |||||
| ===================== | ===================== | ||||
| Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language. | Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language. | ||||
| @@ -7,7 +7,9 @@ Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language | |||||
| ##### Current version: 0.1.6 Alpha | ##### Current version: 0.1.6 Alpha | ||||
| [简体中文](README_ZH.md) | |||||
| #### Other language version | |||||
| - [简体中文](README_ZH.md) | |||||
| ## Purpose | ## Purpose | ||||
| @@ -1,4 +1,4 @@ | |||||
| Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://drone.io/github.com/gogits/gogs/latest) | |||||
| Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://drone.io/github.com/gogits/gogs/latest) [](https://bitdeli.com/free "Bitdeli Badge") | |||||
| ===================== | ===================== | ||||
| Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 | Gogs(Go Git Service) 是一个由 Go 语言编写的自助 Git 托管服务。 | ||||
| @@ -8,6 +8,7 @@ import ( | |||||
| "encoding/json" | "encoding/json" | ||||
| "time" | "time" | ||||
| "github.com/gogits/gogs/modules/base" | |||||
| "github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
| ) | ) | ||||
| @@ -47,18 +48,17 @@ func (a Action) GetRepoName() string { | |||||
| return a.RepoName | return a.RepoName | ||||
| } | } | ||||
| func (a Action) GetContent() string { | |||||
| return a.Content | |||||
| func (a Action) GetBranch() string { | |||||
| return a.RefName | |||||
| } | } | ||||
| type PushCommits struct { | |||||
| Len int | |||||
| Commits [][]string | |||||
| func (a Action) GetContent() string { | |||||
| return a.Content | |||||
| } | } | ||||
| // CommitRepoAction records action for commit repository. | // CommitRepoAction records action for commit repository. | ||||
| func CommitRepoAction(userId int64, userName string, | func CommitRepoAction(userId int64, userName string, | ||||
| repoId int64, repoName string, refName string, commits *PushCommits) error { | |||||
| repoId int64, repoName string, refName string, commits *base.PushCommits) error { | |||||
| bs, err := json.Marshal(commits) | bs, err := json.Marshal(commits) | ||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| @@ -83,42 +83,42 @@ func GetIssues(userId, repoId, posterId, milestoneId int64, page int, isClosed, | |||||
| sess := orm.Limit(20, (page-1)*20) | sess := orm.Limit(20, (page-1)*20) | ||||
| if repoId > 0 { | if repoId > 0 { | ||||
| sess = sess.Where("repo_id=?", repoId).And("is_closed=?", isClosed) | |||||
| sess.Where("repo_id=?", repoId).And("is_closed=?", isClosed) | |||||
| } else { | } else { | ||||
| sess = sess.Where("is_closed=?", isClosed) | |||||
| sess.Where("is_closed=?", isClosed) | |||||
| } | } | ||||
| if userId > 0 { | if userId > 0 { | ||||
| sess = sess.And("assignee_id=?", userId) | |||||
| sess.And("assignee_id=?", userId) | |||||
| } else if posterId > 0 { | } else if posterId > 0 { | ||||
| sess = sess.And("poster_id=?", posterId) | |||||
| sess.And("poster_id=?", posterId) | |||||
| } else if isMention { | } else if isMention { | ||||
| sess = sess.And("mentions like '%$" + base.ToStr(userId) + "|%'") | |||||
| sess.And("mentions like '%$" + base.ToStr(userId) + "|%'") | |||||
| } | } | ||||
| if milestoneId > 0 { | if milestoneId > 0 { | ||||
| sess = sess.And("milestone_id=?", milestoneId) | |||||
| sess.And("milestone_id=?", milestoneId) | |||||
| } | } | ||||
| if len(labels) > 0 { | if len(labels) > 0 { | ||||
| for _, label := range strings.Split(labels, ",") { | for _, label := range strings.Split(labels, ",") { | ||||
| sess = sess.And("mentions like '%$" + label + "|%'") | |||||
| sess.And("mentions like '%$" + label + "|%'") | |||||
| } | } | ||||
| } | } | ||||
| switch sortType { | switch sortType { | ||||
| case "oldest": | case "oldest": | ||||
| sess = sess.Asc("created") | |||||
| sess.Asc("created") | |||||
| case "recentupdate": | case "recentupdate": | ||||
| sess = sess.Desc("updated") | |||||
| sess.Desc("updated") | |||||
| case "leastupdate": | case "leastupdate": | ||||
| sess = sess.Asc("updated") | |||||
| sess.Asc("updated") | |||||
| case "mostcomment": | case "mostcomment": | ||||
| sess = sess.Desc("num_comments") | |||||
| sess.Desc("num_comments") | |||||
| case "leastcomment": | case "leastcomment": | ||||
| sess = sess.Asc("num_comments") | |||||
| sess.Asc("num_comments") | |||||
| default: | default: | ||||
| sess = sess.Desc("created") | |||||
| sess.Desc("created") | |||||
| } | } | ||||
| var issues []Issue | var issues []Issue | ||||
| @@ -471,6 +471,7 @@ type Actioner interface { | |||||
| GetOpType() int | GetOpType() int | ||||
| GetActUserName() string | GetActUserName() string | ||||
| GetRepoName() string | GetRepoName() string | ||||
| GetBranch() string | |||||
| GetContent() string | GetContent() string | ||||
| } | } | ||||
| @@ -493,25 +494,39 @@ const ( | |||||
| TPL_COMMIT_REPO_LI = `<div><img id="gogs-user-avatar-commit" src="%s?s=16" alt="user-avatar" title="username"/> <a href="/%s/%s/commit/%s">%s</a> %s</div>` | TPL_COMMIT_REPO_LI = `<div><img id="gogs-user-avatar-commit" src="%s?s=16" alt="user-avatar" title="username"/> <a href="/%s/%s/commit/%s">%s</a> %s</div>` | ||||
| ) | ) | ||||
| type PushCommits struct { | |||||
| Len int | |||||
| Commits [][]string | |||||
| } | |||||
| // ActionDesc accepts int that represents action operation type | // ActionDesc accepts int that represents action operation type | ||||
| // and returns the description. | // and returns the description. | ||||
| func ActionDesc(act Actioner, avatarLink string) string { | func ActionDesc(act Actioner, avatarLink string) string { | ||||
| actUserName := act.GetActUserName() | actUserName := act.GetActUserName() | ||||
| repoName := act.GetRepoName() | repoName := act.GetRepoName() | ||||
| branch := act.GetBranch() | |||||
| content := act.GetContent() | content := act.GetContent() | ||||
| switch act.GetOpType() { | switch act.GetOpType() { | ||||
| case 1: // Create repository. | case 1: // Create repository. | ||||
| return fmt.Sprintf(TPL_CREATE_REPO, actUserName, actUserName, actUserName, repoName, repoName) | return fmt.Sprintf(TPL_CREATE_REPO, actUserName, actUserName, actUserName, repoName, repoName) | ||||
| case 5: // Commit repository. | case 5: // Commit repository. | ||||
| var commits [][]string | |||||
| if err := json.Unmarshal([]byte(content), &commits); err != nil { | |||||
| var push *PushCommits | |||||
| if err := json.Unmarshal([]byte(content), &push); err != nil { | |||||
| return err.Error() | return err.Error() | ||||
| } | } | ||||
| buf := bytes.NewBuffer([]byte("\n")) | buf := bytes.NewBuffer([]byte("\n")) | ||||
| for _, commit := range commits { | |||||
| max := 3 | |||||
| count := len(push.Commits) | |||||
| if count < max { | |||||
| max = count | |||||
| } | |||||
| for _, commit := range push.Commits[:max] { | |||||
| buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, avatarLink, actUserName, repoName, commit[0], commit[0][:7], commit[1]) + "\n") | buf.WriteString(fmt.Sprintf(TPL_COMMIT_REPO_LI, avatarLink, actUserName, repoName, commit[0], commit[0][:7], commit[1]) + "\n") | ||||
| } | } | ||||
| return fmt.Sprintf(TPL_COMMIT_REPO, actUserName, actUserName, actUserName, repoName, "master", "master", actUserName, repoName, actUserName, repoName, | |||||
| if count > max { | |||||
| buf.WriteString(fmt.Sprintf(`<div><a href="/%s/%s/commits">%d other commits >></a></div>`, actUserName, repoName, count-max)) | |||||
| } | |||||
| return fmt.Sprintf(TPL_COMMIT_REPO, actUserName, actUserName, actUserName, repoName, branch, branch, actUserName, repoName, actUserName, repoName, | |||||
| buf.String()) | buf.String()) | ||||
| default: | default: | ||||
| return "invalid type" | return "invalid type" | ||||
| @@ -52,30 +52,6 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) { | |||||
| ctx.Handle(200, "repo.Create", err) | ctx.Handle(200, "repo.Create", err) | ||||
| } | } | ||||
| func SettingPost(ctx *middleware.Context) { | |||||
| if !ctx.Repo.IsOwner { | |||||
| ctx.Error(404) | |||||
| return | |||||
| } | |||||
| switch ctx.Query("action") { | |||||
| case "delete": | |||||
| if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") { | |||||
| ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct." | |||||
| ctx.HTML(200, "repo/setting") | |||||
| return | |||||
| } | |||||
| if err := models.DeleteRepository(ctx.User.Id, ctx.Repo.Repository.Id, ctx.User.LowerName); err != nil { | |||||
| ctx.Handle(200, "repo.Delete", err) | |||||
| return | |||||
| } | |||||
| } | |||||
| log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName) | |||||
| ctx.Redirect("/") | |||||
| } | |||||
| func Branches(ctx *middleware.Context, params martini.Params) { | func Branches(ctx *middleware.Context, params martini.Params) { | ||||
| if !ctx.Repo.IsValid { | if !ctx.Repo.IsValid { | ||||
| return | return | ||||
| @@ -203,7 +179,6 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||||
| if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob { | if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob { | ||||
| ctx.Data["FileIsLarge"] = true | ctx.Data["FileIsLarge"] = true | ||||
| } else if blob, err := readmeFile.LookupBlob(); err != nil { | } else if blob, err := readmeFile.LookupBlob(); err != nil { | ||||
| //log.Error("repo.Single(readmeFile.LookupBlob): %v", err) | |||||
| ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err) | ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err) | ||||
| return | return | ||||
| } else { | } else { | ||||
| @@ -301,6 +276,40 @@ func Setting(ctx *middleware.Context, params martini.Params) { | |||||
| ctx.HTML(200, "repo/setting") | ctx.HTML(200, "repo/setting") | ||||
| } | } | ||||
| func SettingPost(ctx *middleware.Context, params martini.Params) { | |||||
| if !ctx.Repo.IsOwner { | |||||
| ctx.Error(404) | |||||
| return | |||||
| } | |||||
| switch ctx.Query("action") { | |||||
| case "update": | |||||
| ctx.Repo.Repository.Description = ctx.Query("desc") | |||||
| ctx.Repo.Repository.Website = ctx.Query("site") | |||||
| if err := models.UpdateRepository(ctx.Repo.Repository); err != nil { | |||||
| ctx.Handle(404, "repo.SettingPost(update)", err) | |||||
| return | |||||
| } | |||||
| ctx.Data["IsSuccess"] = true | |||||
| ctx.HTML(200, "repo/setting") | |||||
| log.Trace("%s Repository updated: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName) | |||||
| case "delete": | |||||
| if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") { | |||||
| ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct." | |||||
| ctx.HTML(200, "repo/setting") | |||||
| return | |||||
| } | |||||
| if err := models.DeleteRepository(ctx.User.Id, ctx.Repo.Repository.Id, ctx.User.LowerName); err != nil { | |||||
| ctx.Handle(200, "repo.Delete", err) | |||||
| return | |||||
| } | |||||
| log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName) | |||||
| ctx.Redirect("/") | |||||
| } | |||||
| } | |||||
| func Commits(ctx *middleware.Context, params martini.Params) { | func Commits(ctx *middleware.Context, params martini.Params) { | ||||
| brs, err := models.GetBranches(params["username"], params["reponame"]) | brs, err := models.GetBranches(params["username"], params["reponame"]) | ||||
| if err != nil { | if err != nil { | ||||
| @@ -272,7 +272,7 @@ func runServ(k *cli.Context) { | |||||
| } | } | ||||
| if err = models.CommitRepoAction(user.Id, user.Name, | if err = models.CommitRepoAction(user.Id, user.Name, | ||||
| repo.Id, repoName, refname, &models.PushCommits{l.Len(), commits}); err != nil { | |||||
| repo.Id, repoName, refname, &base.PushCommits{l.Len(), commits}); err != nil { | |||||
| log.Error("runUpdate.models.CommitRepoAction: %v", err, commits) | log.Error("runUpdate.models.CommitRepoAction: %v", err, commits) | ||||
| } else { | } else { | ||||
| //log.Info("refname", refname) | //log.Info("refname", refname) | ||||
| @@ -3,7 +3,7 @@ | |||||
| <div class="row"> | <div class="row"> | ||||
| <div class="col-md-7"> | <div class="col-md-7"> | ||||
| <h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / {{.Repository.Name}}</h3> | <h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / {{.Repository.Name}}</h3> | ||||
| <p class="desc">{{.Repository.Description}}{{if .Repository.Website}}<a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p> | |||||
| <p class="desc">{{.Repository.Description}}{{if .Repository.Website}} <a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p> | |||||
| </div> | </div> | ||||
| <div class="col-md-5 actions text-right clone-group-btn"> | <div class="col-md-5 actions text-right clone-group-btn"> | ||||
| {{if not .IsBareRepo}} | {{if not .IsBareRepo}} | ||||
| @@ -12,7 +12,7 @@ | |||||
| </div> | </div> | ||||
| <div id="gogs-repo-setting-container" class="col-md-9"> | <div id="gogs-repo-setting-container" class="col-md-9"> | ||||
| {{if .ErrorMsg}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}} | |||||
| {{if .IsSuccess}}<p class="alert alert-success">Repository option has been successfully updated.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}} | |||||
| <div class="panel panel-default"> | <div class="panel panel-default"> | ||||
| <div class="panel-heading"> | <div class="panel-heading"> | ||||
| Repository Options | Repository Options | ||||
| @@ -22,32 +22,26 @@ | |||||
| <form action="/{{.Owner.Name}}/{{.Repository.Name}}/settings" method="post" class="form-horizontal"> | <form action="/{{.Owner.Name}}/{{.Repository.Name}}/settings" method="post" class="form-horizontal"> | ||||
| {{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
| <input type="hidden" name="action" value="update"> | <input type="hidden" name="action" value="update"> | ||||
| <div class="form-group"> | |||||
| <label class="col-md-3 text-right">Repository Name <strong class="text-danger">*</strong></label> | |||||
| <div class="col-md-9"> | |||||
| <input type="text" class="form-control" name="repo-name" required="required" value="{{.Repository.Name}}"/> | |||||
| </div> | |||||
| </div> | |||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <label class="col-md-3 text-right">Description</label> | <label class="col-md-3 text-right">Description</label> | ||||
| <div class="col-md-9"> | <div class="col-md-9"> | ||||
| <textarea class="form-control" name="desc" id="repo-desc" rows="6"></textarea> | |||||
| <textarea class="form-control" name="desc" id="repo-desc" rows="3">{{.Repository.Description}}</textarea> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <label class="col-md-3 text-right">Official Site</label> | <label class="col-md-3 text-right">Official Site</label> | ||||
| <div class="col-md-9"> | <div class="col-md-9"> | ||||
| <input type="url" class="form-control" name="repo-site"/> | |||||
| <input type="url" class="form-control" name="site" value="{{.Repository.Website}}" /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="form-group"> | |||||
| <!-- <div class="form-group"> | |||||
| <label class="col-md-3 text-right">Default Branch</label> | <label class="col-md-3 text-right">Default Branch</label> | ||||
| <div class="col-md-9"> | <div class="col-md-9"> | ||||
| <select name="branch" id="repo-default-branch" class="form-control"> | <select name="branch" id="repo-default-branch" class="form-control"> | ||||
| <option value="">Branch</option> | <option value="">Branch</option> | ||||
| </select> | </select> | ||||
| </div> | </div> | ||||
| </div> | |||||
| </div> --> | |||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <div class="col-md-9 col-md-offset-3"> | <div class="col-md-9 col-md-offset-3"> | ||||
| <button class="btn btn-primary" type="submit">Save Options</button> | <button class="btn btn-primary" type="submit">Save Options</button> | ||||
| @@ -163,7 +163,7 @@ func runWeb(*cli.Context) { | |||||
| m.Get("/template/**", dev.TemplatePreview) | m.Get("/template/**", dev.TemplatePreview) | ||||
| } | } | ||||
| // not found handler | |||||
| // Not found handler. | |||||
| m.NotFound(routers.NotFound) | m.NotFound(routers.NotFound) | ||||
| listenAddr := fmt.Sprintf("%s:%s", | listenAddr := fmt.Sprintf("%s:%s", | ||||