Add some tests for reference changes.
This commit is contained in:
parent
f99b4a1b2a
commit
224efbc020
45
main.go
45
main.go
@ -166,9 +166,12 @@ func handler(resp http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
var refs []byte
|
||||
refs, repo.AllVersions, err = hackedRefs(repo)
|
||||
var changed []byte
|
||||
original, err := fetchRefs(repo)
|
||||
if err == nil {
|
||||
changed, repo.AllVersions, err = changeRefs(original, repo.MajorVersion)
|
||||
}
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
// all ok
|
||||
@ -199,7 +202,7 @@ func handler(resp http.ResponseWriter, req *http.Request) {
|
||||
|
||||
if repo.SubPath == "/info/refs" {
|
||||
resp.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
|
||||
resp.Write(refs)
|
||||
resp.Write(changed)
|
||||
return
|
||||
}
|
||||
|
||||
@ -231,10 +234,10 @@ const refsSuffix = ".git/info/refs?service=git-upload-pack"
|
||||
var ErrNoRepo = errors.New("repository not found in GitHub")
|
||||
var ErrNoVersion = errors.New("version reference not found in GitHub")
|
||||
|
||||
func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
||||
func fetchRefs(repo *Repo) (data []byte, err error) {
|
||||
resp, err := httpClient.Get("https://" + repo.GitHubRoot() + refsSuffix)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("cannot talk to GitHub: %v", err)
|
||||
return nil, fmt.Errorf("cannot talk to GitHub: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
@ -242,16 +245,19 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
||||
case 200:
|
||||
// ok
|
||||
case 401, 404:
|
||||
return nil, nil, ErrNoRepo
|
||||
return nil, ErrNoRepo
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("error from GitHub: %v", resp.Status)
|
||||
return nil, fmt.Errorf("error from GitHub: %v", resp.Status)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error reading from GitHub: %v", err)
|
||||
return nil, fmt.Errorf("error reading from GitHub: %v", err)
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func changeRefs(data []byte, major Version) (changed []byte, versions VersionList, err error) {
|
||||
var hlinei, hlinej int // HEAD reference line start/end
|
||||
var mlinei, mlinej int // master reference line start/end
|
||||
var vrefhash string
|
||||
@ -310,7 +316,7 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
||||
name = name[:len(name)-3]
|
||||
}
|
||||
v, ok := parseVersion(name[strings.IndexByte(name, 'v'):])
|
||||
if ok && repo.MajorVersion.Contains(v) && (v == vrefv || !vrefv.IsValid() || vrefv.Less(v)) {
|
||||
if ok && major.Contains(v) && (v == vrefv || !vrefv.IsValid() || vrefv.Less(v)) {
|
||||
vrefv = v
|
||||
vrefhash = sdata[hashi:hashj]
|
||||
vrefname = name
|
||||
@ -322,7 +328,7 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
||||
}
|
||||
|
||||
// If there were absolutely no versions, and v0 was requested, accept the master as-is.
|
||||
if len(versions) == 0 && repo.MajorVersion == (Version{0, -1, -1, false}) {
|
||||
if len(versions) == 0 && major == (Version{0, -1, -1, false}) {
|
||||
return data, nil, nil
|
||||
}
|
||||
|
||||
@ -344,7 +350,20 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
||||
}
|
||||
|
||||
// Insert the HEAD reference line with the right hash and a proper symref capability.
|
||||
line := fmt.Sprintf("%s HEAD\x00symref=HEAD:%s %s\n", vrefhash, vrefname, caps)
|
||||
var line string
|
||||
if strings.HasPrefix(vrefname, "refs/heads/") {
|
||||
if caps == "" {
|
||||
line = fmt.Sprintf("%s HEAD\x00symref=HEAD:%s\n", vrefhash, vrefname)
|
||||
} else {
|
||||
line = fmt.Sprintf("%s HEAD\x00symref=HEAD:%s %s\n", vrefhash, vrefname, caps)
|
||||
}
|
||||
} else {
|
||||
if caps == "" {
|
||||
line = fmt.Sprintf("%s HEAD\n", vrefhash)
|
||||
} else {
|
||||
line = fmt.Sprintf("%s HEAD\x00%s\n", vrefhash, caps)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&buf, "%04x%s", 4+len(line), line)
|
||||
|
||||
// Insert the master reference line.
|
||||
|
194
refs_test.go
Normal file
194
refs_test.go
Normal file
@ -0,0 +1,194 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
. "gopkg.in/check.v1"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var _ = Suite(&RefsSuite{})
|
||||
|
||||
type RefsSuite struct{}
|
||||
|
||||
type refsTest struct {
|
||||
summary string
|
||||
original string
|
||||
version string
|
||||
changed string
|
||||
versions []string
|
||||
}
|
||||
|
||||
var refsTests = []refsTest{{
|
||||
"Version v0 works even without any references",
|
||||
reflines(
|
||||
"hash1 HEAD",
|
||||
),
|
||||
"v0",
|
||||
reflines(
|
||||
"hash1 HEAD",
|
||||
),
|
||||
nil,
|
||||
}, {
|
||||
"Preserve original capabilities",
|
||||
reflines(
|
||||
"hash1 HEAD\x00caps",
|
||||
),
|
||||
"v0",
|
||||
reflines(
|
||||
"hash1 HEAD\x00caps",
|
||||
),
|
||||
nil,
|
||||
}, {
|
||||
"Matching major version branch",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v0",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v2",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash3 HEAD\x00symref=HEAD:refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v0",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v2",
|
||||
),
|
||||
[]string{"v0", "v1", "v2"},
|
||||
}, {
|
||||
"Matching minor version branch",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1.1",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1.3",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v1.2",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash3 HEAD\x00symref=HEAD:refs/heads/v1.3",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1.1",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1.3",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v1.2",
|
||||
),
|
||||
[]string{"v1.1", "v1.2", "v1.3"},
|
||||
}, {
|
||||
"Disable original symref capability",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD\x00foo symref=bar baz",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash2 HEAD\x00symref=HEAD:refs/heads/v1 foo oldref=bar baz",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1",
|
||||
),
|
||||
[]string{"v1"},
|
||||
}, {
|
||||
"Replace original master branch",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash1 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash2 HEAD\x00symref=HEAD:refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/v1",
|
||||
),
|
||||
[]string{"v1"},
|
||||
}, {
|
||||
"Matching tag",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash2 refs/tags/v0",
|
||||
"00000000000000000000000000000000000hash3 refs/tags/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/tags/v2",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash3 HEAD",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash2 refs/tags/v0",
|
||||
"00000000000000000000000000000000000hash3 refs/tags/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/tags/v2",
|
||||
),
|
||||
[]string{"v0", "v1", "v2"},
|
||||
}, {
|
||||
"Tag peeling",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash3 refs/tags/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/tags/v1^{}",
|
||||
"00000000000000000000000000000000000hash5 refs/tags/v2",
|
||||
),
|
||||
"v1",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash4 HEAD",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash3 refs/tags/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/tags/v1^{}",
|
||||
"00000000000000000000000000000000000hash5 refs/tags/v2",
|
||||
),
|
||||
[]string{"v1", "v1", "v2"},
|
||||
}, {
|
||||
"Matching unstable versions",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash1 HEAD",
|
||||
"00000000000000000000000000000000000hash2 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v1.1-unstable",
|
||||
"00000000000000000000000000000000000hash5 refs/heads/v1.3-unstable",
|
||||
"00000000000000000000000000000000000hash6 refs/heads/v1.2-unstable",
|
||||
"00000000000000000000000000000000000hash7 refs/heads/v2",
|
||||
),
|
||||
"v1-unstable",
|
||||
reflines(
|
||||
"00000000000000000000000000000000000hash5 HEAD\x00symref=HEAD:refs/heads/v1.3-unstable",
|
||||
"00000000000000000000000000000000000hash5 refs/heads/master",
|
||||
"00000000000000000000000000000000000hash3 refs/heads/v1",
|
||||
"00000000000000000000000000000000000hash4 refs/heads/v1.1-unstable",
|
||||
"00000000000000000000000000000000000hash5 refs/heads/v1.3-unstable",
|
||||
"00000000000000000000000000000000000hash6 refs/heads/v1.2-unstable",
|
||||
"00000000000000000000000000000000000hash7 refs/heads/v2",
|
||||
),
|
||||
[]string{"v1", "v1.1-unstable", "v1.2-unstable", "v1.3-unstable", "v2"},
|
||||
}}
|
||||
|
||||
func reflines(lines ...string) string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("001e# service=git-upload-pack\n0000")
|
||||
for _, l := range lines {
|
||||
buf.WriteString(fmt.Sprintf("%04x%s\n", len(l)+5, l))
|
||||
}
|
||||
buf.WriteString("0000")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (s *RefsSuite) TestChangeRefs(c *C) {
|
||||
for _, test := range refsTests {
|
||||
c.Logf(test.summary)
|
||||
|
||||
v, ok := parseVersion(test.version)
|
||||
if !ok {
|
||||
c.Fatalf("Test has an invalid version: %q", test.version)
|
||||
}
|
||||
|
||||
changed, versions, err := changeRefs([]byte(test.original), v)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(string(changed), Equals, test.changed)
|
||||
|
||||
sort.Sort(versions)
|
||||
|
||||
var vs []string
|
||||
for _, v := range versions {
|
||||
vs = append(vs, v.String())
|
||||
}
|
||||
c.Assert(vs, DeepEquals, test.versions)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user