diff --git a/server/daemon/daemon.go b/server/daemon/daemon.go index fcd0ae4f9..1a6070abc 100644 --- a/server/daemon/daemon.go +++ b/server/daemon/daemon.go @@ -181,15 +181,12 @@ func (d *GitDaemon) handleClient(conn net.Conn) { return } - var handler git.ServiceHandler var counter *prometheus.CounterVec service := git.Service(split[0]) switch service { case git.UploadPackService: - handler = git.UploadPack counter = uploadPackGitCounter case git.UploadArchiveService: - handler = git.UploadArchive counter = uploadArchiveGitCounter default: d.fatal(c, git.ErrInvalidRequest) @@ -289,7 +286,7 @@ func (d *GitDaemon) handleClient(conn net.Conn) { Dir: filepath.Join(reposDir, repo), } - if err := handler(ctx, cmd); err != nil { + if err := service.Handler(ctx, cmd); err != nil { d.logger.Debugf("git: error handling request: %v", err) d.fatal(c, err) return diff --git a/server/ssh/git.go b/server/ssh/git.go index 02b59e478..52320ed6b 100644 --- a/server/ssh/git.go +++ b/server/ssh/git.go @@ -93,7 +93,7 @@ func handleGit(s ssh.Session) { createRepoCounter.WithLabelValues(name).Inc() } - if err := git.ReceivePack(ctx, cmd); err != nil { + if err := service.Handler(ctx, cmd); err != nil { sshFatal(s, git.ErrSystemMalfunction) } diff --git a/server/web/git.go b/server/web/git.go index 30914fa35..399298e01 100644 --- a/server/web/git.go +++ b/server/web/git.go @@ -222,16 +222,10 @@ func withAccess(next http.Handler) http.HandlerFunc { be := backend.FromContext(ctx) // Store repository in context + // We're not checking for errors here because we want to allow + // repo creation on the fly. repoName := pat.Param(r, "repo") - repo, err := be.Repository(ctx, repoName) - if err != nil { - if !errors.Is(err, proto.ErrRepoNotFound) { - logger.Error("failed to get repository", "err", err) - } - renderNotFound(w) - return - } - + repo, _ := be.Repository(ctx, repoName) ctx = proto.WithRepositoryContext(ctx, repo) r = r.WithContext(ctx) @@ -285,6 +279,16 @@ func withAccess(next http.Handler) http.HandlerFunc { renderUnauthorized(w) return } + + // Create the repo if it doesn't exist. + if repo == nil { + repo, err = be.CreateRepository(ctx, repoName, proto.RepositoryOptions{}) + if err != nil { + logger.Error("failed to create repository", "repo", repoName, "err", err) + renderInternalServerError(w) + return + } + } case gitLfsService: switch { case strings.HasPrefix(file, "info/lfs/locks"): @@ -330,6 +334,12 @@ func withAccess(next http.Handler) http.HandlerFunc { return } + // If the repo doesn't exist, return 404 + if repo == nil { + renderNotFound(w) + return + } + if accessLevel < access.ReadOnlyAccess { askCredentials(w, r) renderUnauthorized(w) @@ -354,17 +364,6 @@ func serviceRpc(w http.ResponseWriter, r *http.Request) { if service == git.ReceivePackService { gitHttpReceiveCounter.WithLabelValues(repoName) - - // Create the repo if it doesn't exist. - be := backend.FromContext(ctx) - repo := proto.RepositoryFromContext(ctx) - if repo == nil { - if _, err := be.CreateRepository(ctx, repoName, proto.RepositoryOptions{}); err != nil { - logger.Error("failed to create repository", "repo", repoName, "err", err) - renderInternalServerError(w) - return - } - } } w.Header().Set("Content-Type", fmt.Sprintf("application/x-%s-result", service)) @@ -452,6 +451,12 @@ func serviceRpc(w http.ResponseWriter, r *http.Request) { } flusher.Flush() } + + if service == git.ReceivePackService { + if err := git.EnsureDefaultBranch(ctx, cmd); err != nil { + logger.Errorf("failed to ensure default branch: %s", err) + } + } } func getInfoRefs(w http.ResponseWriter, r *http.Request) {