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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var changed []byte
|
||||||
var refs []byte
|
original, err := fetchRefs(repo)
|
||||||
refs, repo.AllVersions, err = hackedRefs(repo)
|
if err == nil {
|
||||||
|
changed, repo.AllVersions, err = changeRefs(original, repo.MajorVersion)
|
||||||
|
}
|
||||||
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
// all ok
|
// all ok
|
||||||
@ -199,7 +202,7 @@ func handler(resp http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
if repo.SubPath == "/info/refs" {
|
if repo.SubPath == "/info/refs" {
|
||||||
resp.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
|
resp.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
|
||||||
resp.Write(refs)
|
resp.Write(changed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,10 +234,10 @@ const refsSuffix = ".git/info/refs?service=git-upload-pack"
|
|||||||
var ErrNoRepo = errors.New("repository not found in GitHub")
|
var ErrNoRepo = errors.New("repository not found in GitHub")
|
||||||
var ErrNoVersion = errors.New("version reference 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)
|
resp, err := httpClient.Get("https://" + repo.GitHubRoot() + refsSuffix)
|
||||||
if err != nil {
|
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()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@ -242,16 +245,19 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
|||||||
case 200:
|
case 200:
|
||||||
// ok
|
// ok
|
||||||
case 401, 404:
|
case 401, 404:
|
||||||
return nil, nil, ErrNoRepo
|
return nil, ErrNoRepo
|
||||||
default:
|
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 {
|
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 hlinei, hlinej int // HEAD reference line start/end
|
||||||
var mlinei, mlinej int // master reference line start/end
|
var mlinei, mlinej int // master reference line start/end
|
||||||
var vrefhash string
|
var vrefhash string
|
||||||
@ -310,7 +316,7 @@ func hackedRefs(repo *Repo) (refs []byte, versions []Version, err error) {
|
|||||||
name = name[:len(name)-3]
|
name = name[:len(name)-3]
|
||||||
}
|
}
|
||||||
v, ok := parseVersion(name[strings.IndexByte(name, 'v'):])
|
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
|
vrefv = v
|
||||||
vrefhash = sdata[hashi:hashj]
|
vrefhash = sdata[hashi:hashj]
|
||||||
vrefname = name
|
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 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
|
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.
|
// 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)
|
fmt.Fprintf(&buf, "%04x%s", 4+len(line), line)
|
||||||
|
|
||||||
// Insert the master reference 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