Defer closing the gitrepo until the end of the wrapped context functions (#15653)
There was a mistake in #15372 where deferral of gitrepo close occurs before it should. This PR fixes this. Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									e071b53686
								
							
						
					
					
						commit
						eedc0c8324
					
				
					 2 changed files with 41 additions and 8 deletions
				
			
		|  | @ -6,6 +6,7 @@ | ||||||
| package context | package context | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"net/url" | 	"net/url" | ||||||
|  | @ -393,7 +394,7 @@ func RepoIDAssignment() func(ctx *Context) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RepoAssignment returns a middleware to handle repository assignment
 | // RepoAssignment returns a middleware to handle repository assignment
 | ||||||
| func RepoAssignment(ctx *Context) { | func RepoAssignment(ctx *Context) (cancel context.CancelFunc) { | ||||||
| 	var ( | 	var ( | ||||||
| 		owner *models.User | 		owner *models.User | ||||||
| 		err   error | 		err   error | ||||||
|  | @ -529,12 +530,12 @@ func RepoAssignment(ctx *Context) { | ||||||
| 	ctx.Repo.GitRepo = gitRepo | 	ctx.Repo.GitRepo = gitRepo | ||||||
| 
 | 
 | ||||||
| 	// We opened it, we should close it
 | 	// We opened it, we should close it
 | ||||||
| 	defer func() { | 	cancel = func() { | ||||||
| 		// If it's been set to nil then assume someone else has closed it.
 | 		// If it's been set to nil then assume someone else has closed it.
 | ||||||
| 		if ctx.Repo.GitRepo != nil { | 		if ctx.Repo.GitRepo != nil { | ||||||
| 			ctx.Repo.GitRepo.Close() | 			ctx.Repo.GitRepo.Close() | ||||||
| 		} | 		} | ||||||
| 	}() | 	} | ||||||
| 
 | 
 | ||||||
| 	// Stop at this point when the repo is empty.
 | 	// Stop at this point when the repo is empty.
 | ||||||
| 	if ctx.Repo.Repository.IsEmpty { | 	if ctx.Repo.Repository.IsEmpty { | ||||||
|  | @ -619,6 +620,7 @@ func RepoAssignment(ctx *Context) { | ||||||
| 		ctx.Data["GoDocDirectory"] = prefix + "{/dir}" | 		ctx.Data["GoDocDirectory"] = prefix + "{/dir}" | ||||||
| 		ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}" | 		ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}" | ||||||
| 	} | 	} | ||||||
|  | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // RepoRefType type of repo reference
 | // RepoRefType type of repo reference
 | ||||||
|  | @ -643,7 +645,7 @@ const ( | ||||||
| 
 | 
 | ||||||
| // RepoRef handles repository reference names when the ref name is not
 | // RepoRef handles repository reference names when the ref name is not
 | ||||||
| // explicitly given
 | // explicitly given
 | ||||||
| func RepoRef() func(*Context) { | func RepoRef() func(*Context) context.CancelFunc { | ||||||
| 	// since no ref name is explicitly specified, ok to just use branch
 | 	// since no ref name is explicitly specified, ok to just use branch
 | ||||||
| 	return RepoRefByType(RepoRefBranch) | 	return RepoRefByType(RepoRefBranch) | ||||||
| } | } | ||||||
|  | @ -722,8 +724,8 @@ func getRefName(ctx *Context, pathType RepoRefType) string { | ||||||
| 
 | 
 | ||||||
| // RepoRefByType handles repository reference name for a specific type
 | // RepoRefByType handles repository reference name for a specific type
 | ||||||
| // of repository reference
 | // of repository reference
 | ||||||
| func RepoRefByType(refType RepoRefType) func(*Context) { | func RepoRefByType(refType RepoRefType) func(*Context) context.CancelFunc { | ||||||
| 	return func(ctx *Context) { | 	return func(ctx *Context) (cancel context.CancelFunc) { | ||||||
| 		// Empty repository does not have reference information.
 | 		// Empty repository does not have reference information.
 | ||||||
| 		if ctx.Repo.Repository.IsEmpty { | 		if ctx.Repo.Repository.IsEmpty { | ||||||
| 			return | 			return | ||||||
|  | @ -742,12 +744,12 @@ func RepoRefByType(refType RepoRefType) func(*Context) { | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			// We opened it, we should close it
 | 			// We opened it, we should close it
 | ||||||
| 			defer func() { | 			cancel = func() { | ||||||
| 				// If it's been set to nil then assume someone else has closed it.
 | 				// If it's been set to nil then assume someone else has closed it.
 | ||||||
| 				if ctx.Repo.GitRepo != nil { | 				if ctx.Repo.GitRepo != nil { | ||||||
| 					ctx.Repo.GitRepo.Close() | 					ctx.Repo.GitRepo.Close() | ||||||
| 				} | 				} | ||||||
| 			}() | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Get default branch.
 | 		// Get default branch.
 | ||||||
|  | @ -841,6 +843,7 @@ func RepoRefByType(refType RepoRefType) func(*Context) { | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount | 		ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| package web | package web | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	goctx "context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"reflect" | 	"reflect" | ||||||
|  | @ -27,6 +28,7 @@ func Wrap(handlers ...interface{}) http.HandlerFunc { | ||||||
| 		switch t := handler.(type) { | 		switch t := handler.(type) { | ||||||
| 		case http.HandlerFunc, func(http.ResponseWriter, *http.Request), | 		case http.HandlerFunc, func(http.ResponseWriter, *http.Request), | ||||||
| 			func(ctx *context.Context), | 			func(ctx *context.Context), | ||||||
|  | 			func(ctx *context.Context) goctx.CancelFunc, | ||||||
| 			func(*context.APIContext), | 			func(*context.APIContext), | ||||||
| 			func(*context.PrivateContext), | 			func(*context.PrivateContext), | ||||||
| 			func(http.Handler) http.Handler: | 			func(http.Handler) http.Handler: | ||||||
|  | @ -48,6 +50,15 @@ func Wrap(handlers ...interface{}) http.HandlerFunc { | ||||||
| 				if r, ok := resp.(context.ResponseWriter); ok && r.Status() > 0 { | 				if r, ok := resp.(context.ResponseWriter); ok && r.Status() > 0 { | ||||||
| 					return | 					return | ||||||
| 				} | 				} | ||||||
|  | 			case func(ctx *context.Context) goctx.CancelFunc: | ||||||
|  | 				ctx := context.GetContext(req) | ||||||
|  | 				cancel := t(ctx) | ||||||
|  | 				if cancel != nil { | ||||||
|  | 					defer cancel() | ||||||
|  | 				} | ||||||
|  | 				if ctx.Written() { | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
| 			case func(ctx *context.Context): | 			case func(ctx *context.Context): | ||||||
| 				ctx := context.GetContext(req) | 				ctx := context.GetContext(req) | ||||||
| 				t(ctx) | 				t(ctx) | ||||||
|  | @ -94,6 +105,23 @@ func Middle(f func(ctx *context.Context)) func(netx http.Handler) http.Handler { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // MiddleCancel wrap a context function as a chi middleware
 | ||||||
|  | func MiddleCancel(f func(ctx *context.Context) goctx.CancelFunc) func(netx http.Handler) http.Handler { | ||||||
|  | 	return func(next http.Handler) http.Handler { | ||||||
|  | 		return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { | ||||||
|  | 			ctx := context.GetContext(req) | ||||||
|  | 			cancel := f(ctx) | ||||||
|  | 			if cancel != nil { | ||||||
|  | 				defer cancel() | ||||||
|  | 			} | ||||||
|  | 			if ctx.Written() { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			next.ServeHTTP(ctx.Resp, ctx.Req) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // MiddleAPI wrap a context function as a chi middleware
 | // MiddleAPI wrap a context function as a chi middleware
 | ||||||
| func MiddleAPI(f func(ctx *context.APIContext)) func(netx http.Handler) http.Handler { | func MiddleAPI(f func(ctx *context.APIContext)) func(netx http.Handler) http.Handler { | ||||||
| 	return func(next http.Handler) http.Handler { | 	return func(next http.Handler) http.Handler { | ||||||
|  | @ -163,6 +191,8 @@ func (r *Route) Use(middlewares ...interface{}) { | ||||||
| 				r.R.Use(t) | 				r.R.Use(t) | ||||||
| 			case func(*context.Context): | 			case func(*context.Context): | ||||||
| 				r.R.Use(Middle(t)) | 				r.R.Use(Middle(t)) | ||||||
|  | 			case func(*context.Context) goctx.CancelFunc: | ||||||
|  | 				r.R.Use(MiddleCancel(t)) | ||||||
| 			case func(*context.APIContext): | 			case func(*context.APIContext): | ||||||
| 				r.R.Use(MiddleAPI(t)) | 				r.R.Use(MiddleAPI(t)) | ||||||
| 			default: | 			default: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue