func MergePullRequest(ctx *context.Context) { issue := checkPullInfo(ctx) if ctx.Written() { return } if issue.IsClosed { ctx.Handle(404, "MergePullRequest", nil) return } pr, err := models.GetPullRequestByIssueID(issue.ID) if err != nil { if models.IsErrPullRequestNotExist(err) { ctx.Handle(404, "GetPullRequestByIssueID", nil) } else { ctx.Handle(500, "GetPullRequestByIssueID", err) } return } if !pr.CanAutoMerge() || pr.HasMerged { ctx.Handle(404, "MergePullRequest", nil) return } pr.Issue = issue pr.Issue.Repo = ctx.Repo.Repository if err = pr.Merge(ctx.User, ctx.Repo.GitRepo); err != nil { ctx.Handle(500, "Merge", err) return } log.Trace("Pull request merged: %d", pr.ID) ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index)) }
func UpdateIssueTitle(ctx *context.Context) { issue := getActionIssue(ctx) if ctx.Written() { return } if !ctx.IsSigned || (!issue.IsPoster(ctx.User.Id) && !ctx.Repo.IsWriter()) { ctx.Error(403) return } issue.Name = ctx.QueryTrim("title") if len(issue.Name) == 0 { ctx.Error(204) return } if err := models.UpdateIssue(issue); err != nil { ctx.Handle(500, "UpdateIssue", err) return } ctx.JSON(200, map[string]interface{}{ "title": issue.Name, }) }
func UpdateIssueAssignee(ctx *context.Context) { issue := getActionIssue(ctx) if ctx.Written() { return } aid := ctx.QueryInt64("id") if issue.AssigneeID == aid { ctx.JSON(200, map[string]interface{}{ "ok": true, }) return } // Not check for invalid assignee id and give responsibility to owners. issue.AssigneeID = aid if err := models.UpdateIssueUserByAssignee(issue); err != nil { ctx.Handle(500, "UpdateIssueUserByAssignee: %v", err) return } ctx.JSON(200, map[string]interface{}{ "ok": true, }) }
func Action(ctx *context.Context) { u := GetUserByParams(ctx) if ctx.Written() { return } var err error switch ctx.Params(":action") { case "follow": err = models.FollowUser(ctx.User.Id, u.Id) case "unfollow": err = models.UnfollowUser(ctx.User.Id, u.Id) } if err != nil { ctx.Handle(500, fmt.Sprintf("Action (%s)", ctx.Params(":action")), err) return } redirectTo := ctx.Query("redirect_to") if len(redirectTo) == 0 { redirectTo = u.HomeLink() } ctx.Redirect(redirectTo) }
func SettingsPost(ctx *context.Context, form auth.UpdateProfileForm) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsProfile"] = true if ctx.HasError() { ctx.HTML(200, SETTINGS_PROFILE) return } handleUsernameChange(ctx, form.Name) if ctx.Written() { return } ctx.User.FullName = form.FullName ctx.User.Email = form.Email ctx.User.Website = form.Website ctx.User.Location = form.Location if len(form.Gravatar) > 0 { ctx.User.Avatar = base.EncodeMD5(form.Gravatar) ctx.User.AvatarEmail = form.Gravatar } if err := models.UpdateUser(ctx.User); err != nil { ctx.Handle(500, "UpdateUser", err) return } log.Trace("User settings updated: %s", ctx.User.Name) ctx.Flash.Success(ctx.Tr("settings.update_profile_success")) ctx.Redirect(setting.AppSubUrl + "/user/settings") }
func UpdateIssueMilestone(ctx *context.Context) { issue := getActionIssue(ctx) if ctx.Written() { return } oldMid := issue.MilestoneID mid := ctx.QueryInt64("id") if oldMid == mid { ctx.JSON(200, map[string]interface{}{ "ok": true, }) return } // Not check for invalid milestone id and give responsibility to owners. issue.MilestoneID = mid if err := models.ChangeMilestoneAssign(oldMid, issue); err != nil { ctx.Handle(500, "ChangeMilestoneAssign", err) return } ctx.JSON(200, map[string]interface{}{ "ok": true, }) }
func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true u := prepareUserInfo(ctx) if ctx.Written() { return } if ctx.HasError() { ctx.HTML(200, USER_EDIT) return } fields := strings.Split(form.LoginType, "-") if len(fields) == 2 { loginType := models.LoginType(com.StrTo(fields[0]).MustInt()) loginSource := com.StrTo(fields[1]).MustInt64() if u.LoginSource != loginSource { u.LoginSource = loginSource u.LoginType = loginType } } if len(form.Password) > 0 { u.Passwd = form.Password u.Salt = models.GetUserSalt() u.EncodePasswd() } u.LoginName = form.LoginName u.FullName = form.FullName u.Email = form.Email u.Website = form.Website u.Location = form.Location u.MaxRepoCreation = form.MaxRepoCreation u.IsActive = form.Active u.IsAdmin = form.Admin u.AllowGitHook = form.AllowGitHook u.AllowImportLocal = form.AllowImportLocal if err := models.UpdateUser(u); err != nil { if models.IsErrEmailAlreadyUsed(err) { ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("form.email_been_used"), USER_EDIT, &form) } else { ctx.Handle(500, "UpdateUser", err) } return } log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name) ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) }
func Fork(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_fork") getForkRepository(ctx) if ctx.Written() { return } ctx.Data["ContextUser"] = ctx.User ctx.HTML(200, FORK) }
func Following(ctx *context.Context) { u := GetUserByParams(ctx) if ctx.Written() { return } ctx.Data["Title"] = u.DisplayName() ctx.Data["CardsTitle"] = ctx.Tr("user.following") ctx.Data["PageIsFollowing"] = true ctx.Data["Owner"] = u repo.RenderUserCards(ctx, u.NumFollowing, u.GetFollowing, FOLLOWERS) }
func EditUser(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdminUsers"] = true prepareUserInfo(ctx) if ctx.Written() { return } ctx.HTML(200, USER_EDIT) }
func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64, int64, int64) { var ( repo = ctx.Repo.Repository err error ) labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository) if ctx.Written() { return nil, 0, 0 } if !ctx.Repo.IsWriter() { return nil, 0, 0 } // Check labels. labelIDs := base.StringsToInt64s(strings.Split(form.LabelIDs, ",")) labelIDMark := base.Int64sToMap(labelIDs) hasSelected := false for i := range labels { if labelIDMark[labels[i].ID] { labels[i].IsChecked = true hasSelected = true } } ctx.Data["HasSelectedLabel"] = hasSelected ctx.Data["label_ids"] = form.LabelIDs ctx.Data["Labels"] = labels // Check milestone. milestoneID := form.MilestoneID if milestoneID > 0 { ctx.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID) if err != nil { ctx.Handle(500, "GetMilestoneByID: %v", err) return nil, 0, 0 } ctx.Data["milestone_id"] = milestoneID } // Check assignee. assigneeID := form.AssigneeID if assigneeID > 0 { ctx.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID) if err != nil { ctx.Handle(500, "GetAssigneeByID: %v", err) return nil, 0, 0 } ctx.Data["assignee_id"] = assigneeID } return labelIDs, milestoneID, assigneeID }
func ForkPost(ctx *context.Context, form auth.CreateRepoForm) { ctx.Data["Title"] = ctx.Tr("new_fork") forkRepo := getForkRepository(ctx) if ctx.Written() { return } ctxUser := checkContextUser(ctx, form.Uid) if ctx.Written() { return } ctx.Data["ContextUser"] = ctxUser if ctx.HasError() { ctx.HTML(200, FORK) return } repo, has := models.HasForkedRepo(ctxUser.Id, forkRepo.ID) if has { ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name) return } // Check ownership of organization. if ctxUser.IsOrganization() { if !ctxUser.IsOwnedBy(ctx.User.Id) { ctx.Error(403) return } } repo, err := models.ForkRepository(ctxUser, forkRepo, form.RepoName, form.Description) if err != nil { ctx.Data["Err_RepoName"] = true switch { case models.IsErrRepoAlreadyExist(err): ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), FORK, &form) case models.IsErrNameReserved(err): ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), FORK, &form) case models.IsErrNamePatternNotAllowed(err): ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), FORK, &form) default: ctx.Handle(500, "ForkPost", err) } return } log.Trace("Repository forked[%d]: %s/%s", forkRepo.ID, ctxUser.Name, repo.Name) ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name) }
func WebHooksEdit(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true orCtx, w := checkWebhook(ctx) if ctx.Written() { return } ctx.Data["Webhook"] = w ctx.HTML(200, orCtx.NewTemplate) }
func Migrate(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_migrate") ctx.Data["private"] = ctx.User.LastRepoVisibility ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate ctx.Data["mirror"] = ctx.Query("mirror") == "1" ctxUser := checkContextUser(ctx, ctx.QueryInt64("org")) if ctx.Written() { return } ctx.Data["ContextUser"] = ctxUser ctx.HTML(200, MIGRATE) }
func NewIssue(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true setTemplateIfExists(ctx, ISSUE_TEMPLATE_KEY, IssueTemplateCandidates) renderAttachmentSettings(ctx) RetrieveRepoMetas(ctx, ctx.Repo.Repository) if ctx.Written() { return } ctx.Data["RequireHighlightJS"] = true ctx.HTML(200, ISSUE_NEW) }
func EditWiki(ctx *context.Context) { ctx.Data["PageIsWiki"] = true ctx.Data["PageIsWikiEdit"] = true ctx.Data["RequireSimpleMDE"] = true if !ctx.Repo.Repository.HasWiki() { ctx.Redirect(ctx.Repo.RepoLink + "/wiki") return } renderWikiPage(ctx, false) if ctx.Written() { return } ctx.HTML(200, WIKI_NEW) }
func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { ctx.Data["Title"] = ctx.Tr("repo.issues.new") ctx.Data["PageIsIssueList"] = true renderAttachmentSettings(ctx) var ( repo = ctx.Repo.Repository attachments []string ) labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, form) if ctx.Written() { return } if setting.AttachmentEnabled { attachments = form.Attachments } if ctx.HasError() { ctx.HTML(200, ISSUE_NEW) return } issue := &models.Issue{ RepoID: repo.ID, Name: form.Title, PosterID: ctx.User.Id, Poster: ctx.User, MilestoneID: milestoneID, AssigneeID: assigneeID, Content: form.Content, } if err := models.NewIssue(repo, issue, labelIDs, attachments); err != nil { ctx.Handle(500, "NewIssue", err) return } else if err := MailWatchersAndMentions(ctx, issue); err != nil { ctx.Handle(500, "MailWatchersAndMentions", err) return } log.Trace("Issue created: %d/%d", repo.ID, issue.ID) ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index)) }
func showOrgProfile(ctx *context.Context) { ctx.SetParams(":org", ctx.Params(":username")) context.HandleOrgAssignment(ctx) if ctx.Written() { return } org := ctx.Org.Organization ctx.Data["Title"] = org.FullName if ctx.IsSigned { if ctx.User.IsAdmin { repos, err := models.GetRepositories(org.Id, true) if err != nil { ctx.Handle(500, "GetRepositoriesAsAdmin", err) return } ctx.Data["Repos"] = repos } else { if err := org.GetUserRepositories(ctx.User.Id); err != nil { ctx.Handle(500, "GetUserRepositories", err) return } ctx.Data["Repos"] = org.Repos } } else { repos, err := models.GetRepositories(org.Id, false) if err != nil { ctx.Handle(500, "GetRepositories", err) return } ctx.Data["Repos"] = repos } if err := org.GetMembers(); err != nil { ctx.Handle(500, "GetMembers", err) return } ctx.Data["Members"] = org.Members ctx.Data["Teams"] = org.Teams ctx.HTML(200, ORG_HOME) }
func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository) []*models.Label { if !ctx.Repo.IsWriter() { return nil } labels, err := models.GetLabelsByRepoID(repo.ID) if err != nil { ctx.Handle(500, "GetLabelsByRepoID: %v", err) return nil } ctx.Data["Labels"] = labels RetrieveRepoMilestonesAndAssignees(ctx, repo) if ctx.Written() { return nil } return labels }
func Create(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("new_repo") // Give default value for template to render. ctx.Data["Gitignores"] = models.Gitignores ctx.Data["Licenses"] = models.Licenses ctx.Data["Readmes"] = models.Readmes ctx.Data["readme"] = "Default" ctx.Data["private"] = ctx.User.LastRepoVisibility ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate ctxUser := checkContextUser(ctx, ctx.QueryInt64("org")) if ctx.Written() { return } ctx.Data["ContextUser"] = ctxUser ctx.HTML(200, CREATE) }
func SlackHooksEditPost(ctx *context.Context, form auth.NewSlackHookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true orCtx, w := checkWebhook(ctx) if ctx.Written() { return } ctx.Data["Webhook"] = w if ctx.HasError() { ctx.HTML(200, orCtx.NewTemplate) return } meta, err := json.Marshal(&models.SlackMeta{ Channel: form.Channel, Username: form.Username, IconURL: form.IconURL, Color: form.Color, }) if err != nil { ctx.Handle(500, "Marshal", err) return } w.URL = form.PayloadURL w.Meta = string(meta) w.HookEvent = ParseHookEvent(form.WebhookForm) w.IsActive = form.Active if err := w.UpdateEvent(); err != nil { ctx.Handle(500, "UpdateEvent", err) return } else if err := models.UpdateWebhook(w); err != nil { ctx.Handle(500, "UpdateWebhook", err) return } ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success")) ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID)) }
func WebhooksNew(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} orCtx, err := getOrgRepoCtx(ctx) if err != nil { ctx.Handle(500, "getOrgRepoCtx", err) return } ctx.Data["HookType"] = checkHookType(ctx) if ctx.Written() { return } ctx.Data["BaseLink"] = orCtx.Link ctx.HTML(200, orCtx.NewTemplate) }
func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { ctx.Data["Title"] = ctx.Tr("new_repo") ctx.Data["Gitignores"] = models.Gitignores ctx.Data["Licenses"] = models.Licenses ctx.Data["Readmes"] = models.Readmes ctxUser := checkContextUser(ctx, form.Uid) if ctx.Written() { return } ctx.Data["ContextUser"] = ctxUser if ctx.HasError() { ctx.HTML(200, CREATE) return } repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{ Name: form.RepoName, Description: form.Description, Gitignores: form.Gitignores, License: form.License, Readme: form.Readme, IsPrivate: form.Private || setting.Repository.ForcePrivate, AutoInit: form.AutoInit, }) if err == nil { log.Trace("Repository created[%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + repo.Name) return } if repo != nil { if errDelete := models.DeleteRepository(ctxUser.Id, repo.ID); errDelete != nil { log.Error(4, "DeleteRepository: %v", errDelete) } } handleCreateError(ctx, ctxUser, err, "CreatePost", CREATE, &form) }
func UpdateIssueContent(ctx *context.Context) { issue := getActionIssue(ctx) if ctx.Written() { return } if !ctx.IsSigned || (ctx.User.Id != issue.PosterID && !ctx.Repo.IsWriter()) { ctx.Error(403) return } issue.Content = ctx.Query("content") if err := models.UpdateIssue(issue); err != nil { ctx.Handle(500, "UpdateIssue", err) return } ctx.JSON(200, map[string]interface{}{ "content": string(markdown.Render([]byte(issue.Content), ctx.Query("context"), ctx.Repo.Repository.ComposeMetas())), }) }
func UpdateIssueLabel(ctx *context.Context) { issue := getActionIssue(ctx) if ctx.Written() { return } if ctx.Query("action") == "clear" { if err := issue.ClearLabels(); err != nil { ctx.Handle(500, "ClearLabels", err) return } } else { isAttach := ctx.Query("action") == "attach" label, err := models.GetLabelByID(ctx.QueryInt64("id")) if err != nil { if models.IsErrLabelNotExist(err) { ctx.Error(404, "GetLabelByID") } else { ctx.Handle(500, "GetLabelByID", err) } return } if isAttach && !issue.HasLabel(label.ID) { if err = issue.AddLabel(label); err != nil { ctx.Handle(500, "AddLabel", err) return } } else if !isAttach && issue.HasLabel(label.ID) { if err = issue.RemoveLabel(label); err != nil { ctx.Handle(500, "RemoveLabel", err) return } } } ctx.JSON(200, map[string]interface{}{ "ok": true, }) }
func WebHooksEditPost(ctx *context.Context, form auth.NewWebhookForm) { ctx.Data["Title"] = ctx.Tr("repo.settings.update_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksEdit"] = true orCtx, w := checkWebhook(ctx) if ctx.Written() { return } ctx.Data["Webhook"] = w if ctx.HasError() { ctx.HTML(200, orCtx.NewTemplate) return } contentType := models.JSON if models.HookContentType(form.ContentType) == models.FORM { contentType = models.FORM } w.URL = form.PayloadURL w.ContentType = contentType w.Secret = form.Secret w.HookEvent = ParseHookEvent(form.WebhookForm) w.IsActive = form.Active if err := w.UpdateEvent(); err != nil { ctx.Handle(500, "UpdateEvent", err) return } else if err := models.UpdateWebhook(w); err != nil { ctx.Handle(500, "WebHooksEditPost", err) return } ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success")) ctx.Redirect(fmt.Sprintf("%s/settings/hooks/%d", orCtx.Link, w.ID)) }
func TriggerTask(ctx *context.Context) { branch := ctx.Query("branch") secret := ctx.Query("secret") if len(branch) == 0 || len(secret) == 0 { ctx.Error(404) log.Trace("TriggerTask: branch or secret is empty") return } owner, repo := parseOwnerAndRepo(ctx) if ctx.Written() { return } if secret != base.EncodeMD5(owner.Salt) { ctx.Error(404) log.Trace("TriggerTask [%s/%s]: invalid secret", owner.Name, repo.Name) return } log.Trace("TriggerTask [%d].(new request): %s", repo.ID, branch) go models.HookQueue.Add(repo.ID) go models.AddTestPullRequestTask(repo.ID, branch) ctx.Status(202) }
func Wiki(ctx *context.Context) { ctx.Data["PageIsWiki"] = true if !ctx.Repo.Repository.HasWiki() { ctx.Data["Title"] = ctx.Tr("repo.wiki") ctx.HTML(200, WIKI_START) return } wikiRepo, pageName := renderWikiPage(ctx, true) if ctx.Written() { return } // Get last change information. lastCommit, err := wikiRepo.GetCommitByPath(pageName + ".md") if err != nil { ctx.Handle(500, "GetCommitByPath", err) return } ctx.Data["Author"] = lastCommit.Author ctx.HTML(200, WIKI_VIEW) }
func ViewPullCommits(ctx *context.Context) { ctx.Data["PageIsPullCommits"] = true pull := checkPullInfo(ctx) if ctx.Written() { return } ctx.Data["Username"] = pull.HeadUserName ctx.Data["Reponame"] = pull.HeadRepo.Name var commits *list.List if pull.HasMerged { PrepareMergedViewPullInfo(ctx, pull) if ctx.Written() { return } startCommit, err := ctx.Repo.GitRepo.GetCommit(pull.MergeBase) if err != nil { ctx.Handle(500, "Repo.GitRepo.GetCommit", err) return } endCommit, err := ctx.Repo.GitRepo.GetCommit(pull.MergedCommitID) if err != nil { ctx.Handle(500, "Repo.GitRepo.GetCommit", err) return } commits, err = ctx.Repo.GitRepo.CommitsBetween(endCommit, startCommit) if err != nil { ctx.Handle(500, "Repo.GitRepo.CommitsBetween", err) return } } else { prInfo := PrepareViewPullInfo(ctx, pull) if ctx.Written() { return } else if prInfo == nil { ctx.Handle(404, "ViewPullCommits", nil) return } commits = prInfo.Commits } commits = models.ValidateCommitsWithEmails(commits) ctx.Data["Commits"] = commits ctx.Data["CommitCount"] = commits.Len() ctx.HTML(200, PULL_COMMITS) }
func CompareAndPullRequest(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") ctx.Data["PageIsComparePull"] = true ctx.Data["IsDiffCompare"] = true ctx.Data["RequireHighlightJS"] = true setTemplateIfExists(ctx, PULL_REQUEST_TEMPLATE_KEY, PullRequestTemplateCandidates) renderAttachmentSettings(ctx) headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(ctx) if ctx.Written() { return } pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) if err != nil { if !models.IsErrPullRequestNotExist(err) { ctx.Handle(500, "GetUnmergedPullRequest", err) return } } else { ctx.Data["HasPullRequest"] = true ctx.Data["PullRequest"] = pr ctx.HTML(200, COMPARE_PULL) return } nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch) if ctx.Written() { return } if !nothingToCompare { // Setup information for new form. RetrieveRepoMetas(ctx, ctx.Repo.Repository) if ctx.Written() { return } } ctx.HTML(200, COMPARE_PULL) }