Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More pleasantly handle broken or missing git repositories #17747

Merged
merged 5 commits into from
Nov 22, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const (
RepositoryReady RepositoryStatus = iota // a normal repository
RepositoryBeingMigrated // repository is migrating
RepositoryPendingTransfer // repository pending in ownership transfer state
RepositoryBroken // repository is in a permanently broken state
)

// TrustModelType defines the types of trust model for this repository
Expand Down Expand Up @@ -289,6 +290,11 @@ func (repo *Repository) IsBeingCreated() bool {
return repo.IsBeingMigrated()
}

// IsBroken indicates that repository is broken
func (repo *Repository) IsBroken() bool {
return repo.Status == RepositoryBroken
}

// AfterLoad is invoked from XORM after setting the values of all fields of this object.
func (repo *Repository) AfterLoad() {
// FIXME: use models migration to solve all at once.
Expand Down
34 changes: 33 additions & 1 deletion modules/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -522,14 +522,30 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
}
}

isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || ctx.Link == ctx.Repo.RepoLink+"/settings" || strings.HasPrefix(ctx.Link, ctx.Repo.RepoLink+"/settings/")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified to:

isHomeOrSettings := ctx.Link == ctx.Repo.RepoLink || strings.HasPrefix(ctx.Link+"/", ctx.Repo.RepoLink+"/settings/")

LGTM~~


// Disable everything when the repo is being created
if ctx.Repo.Repository.IsBeingCreated() {
if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
return
}

gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
if err != nil {
if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
ctx.Repo.Repository.Status = models.RepositoryBroken
ctx.Repo.Repository.IsEmpty = true
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
// Only allow access to base of repo or settings
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
return
}
ctx.ServerError("RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
return
}
Expand All @@ -551,6 +567,17 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {

tags, err := ctx.Repo.GitRepo.GetTags(0, 0)
if err != nil {
if strings.Contains(err.Error(), "fatal: not a git repository ") {
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
ctx.Repo.Repository.Status = models.RepositoryBroken
ctx.Repo.Repository.IsEmpty = true
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
// Only allow access to base of repo or settings
if !isHomeOrSettings {
ctx.Redirect(ctx.Repo.RepoLink)
}
return
}
ctx.ServerError("GetTags", err)
return
}
Expand Down Expand Up @@ -918,6 +945,11 @@ func UnitTypes() func(ctx *Context) {
// IssueTemplatesFromDefaultBranch checks for issue templates in the repo's default branch
func (ctx *Context) IssueTemplatesFromDefaultBranch() []api.IssueTemplate {
var issueTemplates []api.IssueTemplate

if ctx.Repo.Repository.IsEmpty {
return issueTemplates
}

if ctx.Repo.Commit == nil {
var err error
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultBranch)
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,7 @@ clone_this_repo = Clone this repository
create_new_repo_command = Creating a new repository on the command line
push_exist_repo = Pushing an existing repository from the command line
empty_message = This repository does not contain any content.
broken_message = `The git data underlying this repository cannot be read. Contact the administrator of this instance or delete this repository.`
zeripath marked this conversation as resolved.
Show resolved Hide resolved

code = Code
code.desc = Access source code, files, commits and branches.
Expand Down
8 changes: 8 additions & 0 deletions routers/private/serv.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ func ServCommand(ctx *context.PrivateContext) {
return
}

if repo.IsBroken() {
ctx.JSON(http.StatusInternalServerError, private.ErrServCommand{
Results: results,
Err: "Repository is in a broken state",
})
return
}

// We can shortcut at this point if the repo is a mirror
if mode > models.AccessModeRead && repo.IsMirror {
ctx.JSON(http.StatusForbidden, private.ErrServCommand{
Expand Down
6 changes: 5 additions & 1 deletion templates/repo/empty.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
{{.i18n.Tr "repo.archive.title"}}
</div>
{{end}}
{{if .CanWriteCode}}
{{if .Repository.IsBroken}}
<div class="ui segment center">
{{.i18n.Tr "repo.broken_message"}}
</div>
{{else if .CanWriteCode}}
<h4 class="ui top attached header">
{{.i18n.Tr "repo.quick_guide"}}
</h4>
Expand Down
12 changes: 10 additions & 2 deletions templates/repo/header.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullName}}</a></div>{{end}}
{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{.TemplateRepo.FullName}}</a></div>{{end}}
</div>
{{if not .IsBeingCreated}}
{{if not (or .IsBeingCreated .IsBroken)}}
<div class="repo-buttons">
{{if $.RepoTransfer}}
<form method="post" action="{{$.RepoLink}}/action/accept_transfer?redirect_to={{$.RepoLink}}">
Expand Down Expand Up @@ -100,7 +100,7 @@
</div><!-- end container -->
{{end}}
<div class="ui tabs container">
{{if not .Repository.IsBeingCreated}}
{{if not (or .Repository.IsBeingCreated .Repository.IsBroken)}}
<div class="ui tabular stackable menu navbar">
{{if .Permission.CanRead $.UnitTypeCode}}
<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{end}}">
Expand Down Expand Up @@ -172,6 +172,14 @@
</div>
{{end}}
</div>
{{else if .Permission.IsAdmin}}
<div class="ui tabular stackable menu navbar">
<div class="right menu">
<a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings">
{{svg "octicon-tools"}} {{.i18n.Tr "repo.settings"}}
</a>
</div>
</div>
{{end}}
</div>
<div class="ui tabs divider"></div>
Expand Down