Skip to content

Commit 197a1cf

Browse files
committed
Close resources left by go-git after request is finished and before actions that touch the repository directory
Especially Windows doesn't like it when there are open handles when a directory is moved or copied.
1 parent 4a08d57 commit 197a1cf

File tree

4 files changed

+38
-0
lines changed

4 files changed

+38
-0
lines changed

modules/context/context.go

+18
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ type Context struct {
4646
Org *Organization
4747
}
4848

49+
// Close Releases resources used by this context, like file descriptors
50+
func (ctx *Context) Close() {
51+
if ctx.Repo != nil && ctx.Repo.GitRepo != nil {
52+
if err := ctx.Repo.GitRepo.Close(); err != nil {
53+
log.Warn("Unable to clean up repository resources %s", err.Error())
54+
}
55+
}
56+
}
57+
4958
// IsUserSiteAdmin returns true if current user is a site admin
5059
func (ctx *Context) IsUserSiteAdmin() bool {
5160
return ctx.IsSigned && ctx.User.IsAdmin
@@ -342,3 +351,12 @@ func Contexter() macaron.Handler {
342351
c.Map(ctx)
343352
}
344353
}
354+
355+
// Cleanup Cleans up used resources like open file descriptors at the end of the request
356+
func Cleanup() macaron.Handler {
357+
return func(ctx *Context) {
358+
defer ctx.Close()
359+
360+
ctx.Next()
361+
}
362+
}

modules/git/repo.go

+5
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ func OpenRepository(repoPath string) (*Repository, error) {
107107
}, nil
108108
}
109109

110+
// Close Release file descriptors that are left open for performance reasons
111+
func (repo *Repository) Close() error {
112+
return repo.gogitStorage.Close()
113+
}
114+
110115
// IsEmpty Check if repository is empty.
111116
func (repo *Repository) IsEmpty() (bool, error) {
112117
var errbuf strings.Builder

routers/repo/setting.go

+13
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
6969
// Check if repository name has been changed.
7070
if repo.LowerName != strings.ToLower(newRepoName) {
7171
isNameChanged = true
72+
73+
// Close any file descriptors, primarily for Windows which refuses to move directories with open descriptors
74+
if err := ctx.Repo.GitRepo.Close(); err != nil {
75+
ctx.ServerError("ChangeRepositoryName", err)
76+
return
77+
}
78+
7279
if err := models.ChangeRepositoryName(ctx.Repo.Owner, repo.Name, newRepoName); err != nil {
7380
ctx.Data["Err_RepoName"] = true
7481
switch {
@@ -370,6 +377,12 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
370377
return
371378
}
372379

380+
// Close any file descriptors, primarily for Windows which refuses to move directories with open descriptors
381+
if err := ctx.Repo.GitRepo.Close(); err != nil {
382+
ctx.ServerError("ChangeRepositoryName", err)
383+
return
384+
}
385+
373386
oldOwnerID := ctx.Repo.Owner.ID
374387
if err = models.TransferOwnership(ctx.User, newOwner, repo); err != nil {
375388
if models.IsErrRepoAlreadyExist(err) {

routers/routes/routes.go

+2
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ func NewMacaron() *macaron.Macaron {
220220
// OK we are now set-up enough to allow us to create a nicer recovery than
221221
// the default macaron recovery
222222
m.Use(context.Recovery())
223+
224+
m.Use(context.Cleanup())
223225
m.SetAutoHead(true)
224226
return m
225227
}

0 commit comments

Comments
 (0)