47410dedb9e85039bd9631343ebaa2e31f103131

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix(http): handle nested git repos

Diff

This diff is truncated to protect this page.

  1diff --git a/server/http.go b/server/http.go
  2index 5c7d168840031de3122b15441728c77e4fd11562..f36e041cf0e6aade521aab563c8897811280b3de 100644
  3--- a/server/http.go
  4+++ b/server/http.go
  5@@ -5,8 +5,8 @@ import (
  6 	"fmt"
  7 	"net/http"
  8 	"net/url"
  9-	"os"
 10 	"path/filepath"
 11+	"regexp"
 12 	"strings"
 13 	"text/template"
 14 	"time"
 15@@ -81,8 +81,20 @@ func NewHTTPServer(cfg *config.Config) (*HTTPServer, error) {
 16 	}
 17 
 18 	mux.Use(loggingMiddleware)
 19-	mux.HandleFunc(pat.Get("/:repo"), s.repoIndexHandler)
 20-	mux.HandleFunc(pat.Get("/:repo/*"), s.dumbGitHandler)
 21+	for _, m := range []Matcher{
 22+		getInfoRefs,
 23+		getHead,
 24+		getAlternates,
 25+		getHTTPAlternates,
 26+		getInfoPacks,
 27+		getInfoFile,
 28+		getLooseObject,
 29+		getPackFile,
 30+		getIdxFile,
 31+	} {
 32+		mux.HandleFunc(NewPattern(m), s.handleGit)
 33+	}
 34+	mux.HandleFunc(pat.Get("/*"), s.handleIndex)
 35 	return s, nil
 36 }
 37 
 38@@ -101,6 +113,104 @@ func (s *HTTPServer) Shutdown(ctx context.Context) error {
 39 	return s.server.Shutdown(ctx)
 40 }
 41 
 42+// Pattern is a pattern for matching a URL.
 43+// It matches against GET requests.
 44+type Pattern struct {
 45+	match func(*url.URL) *Match
 46+}
 47+
 48+// NewPattern returns a new Pattern with the given matcher.
 49+func NewPattern(m Matcher) *Pattern {
 50+	return &Pattern{
 51+		match: m,
 52+	}
 53+}
 54+
 55+// Match is a match for a URL.
 56+//
 57+// It implements goji.Pattern.
 58+func (p *Pattern) Match(r *http.Request) *http.Request {
 59+	if r.Method != "GET" {
 60+		return nil
 61+	}
 62+
 63+	if m := p.match(r.URL); m != nil {
 64+		ctx := context.WithValue(r.Context(), pattern.Variable("repo"), m.RepoPath)
 65+		ctx = context.WithValue(ctx, pattern.Variable("file"), m.FilePath)
 66+		return r.WithContext(ctx)
 67+	}
 68+	return nil
 69+}
 70+
 71+// Matcher finds a match in a *url.URL.
 72+type Matcher = func(*url.URL) *Match
 73+
 74+var (
 75+	getInfoRefs = func(u *url.URL) *Match {
 76+		return matchSuffix(u.Path, "/info/refs")
 77+	}
 78+
 79+	getHead = func(u *url.URL) *Match {
 80+		return matchSuffix(u.Path, "/HEAD")
 81+	}
 82+
 83+	getAlternates = func(u *url.URL) *Match {
 84+		return matchSuffix(u.Path, "/objects/info/alternates")
 85+	}
 86+
 87+	getHTTPAlternates = func(u *url.URL) *Match {
 88+		return matchSuffix(u.Path, "/objects/info/http-alternates")
 89+	}
 90+
 91+	getInfoPacks = func(u *url.URL) *Match {
 92+		return matchSuffix(u.Path, "/objects/info/packs")
 93+	}
 94+
 95+	getInfoFileRegexp = regexp.MustCompile(".*?(/objects/info/[^/]*)$")
 96+	getInfoFile       = func(u *url.URL) *Match {
 97+		return findStringSubmatch(u.Path, getInfoFileRegexp)
 98+	}
 99+
100+	getLooseObjectRegexp = regexp.MustCompile(".*?(/objects/[0-9a-f]{2}/[0-9a-f]{38})$")
101+	getLooseObject       = func(u *url.URL) *Match {
102+		return findStringSubmatch(u.Path, getLooseObjectRegexp)
103+	}
104+