mirror of
https://github.com/golang/go
synced 2024-11-23 03:40:02 -07:00
cmd/go: redirect vcs-test.golang.org repo URLs to a test-local server
The new server reconstructs the vcs-test repos on the fly using scripts that run the actual version-control binaries. This allows those repos to be code-reviewed using our normal tools — and, crucially, allows contributors to add new vcs-test contents as part of a contributed CL. It also prevents failures due to network errors reaching vcs-test.golang.org (such as when developing offline), and allows us to iterate on the repo contents without dealing with annoying and unpredictable GCS caching behavior. We can't quite turn down vcs-test.golang.org yet — this server doesn't yet handle "go-import" metadata (and related authentication behaviors), and doesn't serve Subversion repos. But we're getting much closer! For #27494. Change-Id: I233fc718617aed287b0f7248bd8cfe1e5cebe96b Reviewed-on: https://go-review.googlesource.com/c/go/+/421455 Run-TryBot: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
55eaae452c
commit
d5155f6192
@ -33,6 +33,8 @@ import (
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/robustio"
|
||||
"cmd/go/internal/search"
|
||||
"cmd/go/internal/vcs"
|
||||
"cmd/go/internal/vcweb/vcstest"
|
||||
"cmd/go/internal/work"
|
||||
"cmd/internal/sys"
|
||||
|
||||
@ -129,6 +131,12 @@ func TestMain(m *testing.M) {
|
||||
return fmt.Errorf("%stestgo must not write to GOROOT (installing to %s)", callerPos, filepath.Join("GOROOT", rel))
|
||||
}
|
||||
}
|
||||
|
||||
if vcsTest := os.Getenv("TESTGO_VCSTEST_URL"); vcsTest != "" {
|
||||
vcs.VCSTestRepoURL = vcsTest
|
||||
vcs.VCSTestHosts = vcstest.Hosts
|
||||
}
|
||||
|
||||
cmdgo.Main()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
@ -495,21 +495,21 @@ func downloadPackage(p *load.Package) error {
|
||||
vcsCmd, repo, rootPath = rr.VCS, rr.Repo, rr.Root
|
||||
}
|
||||
if !blindRepo && !vcsCmd.IsSecure(repo) && security != web.Insecure {
|
||||
return fmt.Errorf("cannot download, %v uses insecure protocol", repo)
|
||||
return fmt.Errorf("cannot download: %v uses insecure protocol", repo)
|
||||
}
|
||||
|
||||
if p.Internal.Build.SrcRoot == "" {
|
||||
// Package not found. Put in first directory of $GOPATH.
|
||||
list := filepath.SplitList(cfg.BuildContext.GOPATH)
|
||||
if len(list) == 0 {
|
||||
return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
|
||||
return fmt.Errorf("cannot download: $GOPATH not set. For more details see: 'go help gopath'")
|
||||
}
|
||||
// Guard against people setting GOPATH=$GOROOT.
|
||||
if filepath.Clean(list[0]) == filepath.Clean(cfg.GOROOT) {
|
||||
return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
|
||||
return fmt.Errorf("cannot download: $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
|
||||
return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
|
||||
return fmt.Errorf("cannot download: %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
|
||||
}
|
||||
p.Internal.Build.Root = list[0]
|
||||
p.Internal.Build.SrcRoot = filepath.Join(list[0], "src")
|
||||
|
@ -7,6 +7,8 @@ package codehost
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/vcweb/vcstest"
|
||||
"flag"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
@ -26,17 +28,18 @@ func TestMain(m *testing.M) {
|
||||
// needed for initializing the test environment variables as testing.Short
|
||||
// and HasExternalNetwork
|
||||
flag.Parse()
|
||||
os.Exit(testMain(m))
|
||||
if err := testMain(m); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
gitrepo1 = "https://vcs-test.golang.org/git/gitrepo1"
|
||||
hgrepo1 = "https://vcs-test.golang.org/hg/hgrepo1"
|
||||
)
|
||||
var gitrepo1, hgrepo1 string
|
||||
|
||||
var altRepos = []string{
|
||||
"localGitRepo",
|
||||
hgrepo1,
|
||||
var altRepos = func() []string {
|
||||
return []string{
|
||||
"localGitRepo",
|
||||
hgrepo1,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Convert gitrepo1 to svn, bzr, fossil and add tests.
|
||||
@ -45,14 +48,38 @@ var altRepos = []string{
|
||||
// localGitRepo is like gitrepo1 but allows archive access.
|
||||
var localGitRepo, localGitURL string
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
func testMain(m *testing.M) (err error) {
|
||||
cfg.BuildX = true
|
||||
|
||||
srv, err := vcstest.NewServer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := srv.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
|
||||
gitrepo1 = srv.HTTP.URL + "/git/gitrepo1"
|
||||
hgrepo1 = srv.HTTP.URL + "/hg/hgrepo1"
|
||||
|
||||
dir, err := os.MkdirTemp("", "gitrepo-test-")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
defer func() {
|
||||
if rmErr := os.RemoveAll(dir); err == nil {
|
||||
err = rmErr
|
||||
}
|
||||
}()
|
||||
|
||||
if testenv.HasExternalNetwork() && testenv.HasExec() {
|
||||
// Redirect the module cache to a fresh directory to avoid crosstalk, and make
|
||||
// it read/write so that the test can still clean it up easily when done.
|
||||
cfg.GOMODCACHE = filepath.Join(dir, "modcache")
|
||||
cfg.ModCacheRW = true
|
||||
|
||||
if !testing.Short() && testenv.HasExec() {
|
||||
if _, err := exec.LookPath("git"); err == nil {
|
||||
// Clone gitrepo1 into a local directory.
|
||||
// If we use a file:// URL to access the local directory,
|
||||
@ -60,10 +87,10 @@ func testMain(m *testing.M) int {
|
||||
// which will let us test remote git archive invocations.
|
||||
localGitRepo = filepath.Join(dir, "gitrepo2")
|
||||
if _, err := Run("", "git", "clone", "--mirror", gitrepo1, localGitRepo); err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if _, err := Run(localGitRepo, "git", "config", "daemon.uploadarch", "true"); err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert absolute path to file URL. LocalGitRepo will not accept
|
||||
@ -77,7 +104,8 @@ func testMain(m *testing.M) int {
|
||||
}
|
||||
}
|
||||
|
||||
return m.Run()
|
||||
m.Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
func testRepo(t *testing.T, remote string) (Repo, error) {
|
||||
@ -85,49 +113,31 @@ func testRepo(t *testing.T, remote string) (Repo, error) {
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
return LocalGitRepo(localGitURL)
|
||||
}
|
||||
vcs := "git"
|
||||
vcsName := "git"
|
||||
for _, k := range []string{"hg"} {
|
||||
if strings.Contains(remote, "/"+k+"/") {
|
||||
vcs = k
|
||||
vcsName = k
|
||||
}
|
||||
}
|
||||
testenv.MustHaveExecPath(t, vcs)
|
||||
return NewRepo(vcs, remote)
|
||||
}
|
||||
|
||||
var tagsTests = []struct {
|
||||
repo string
|
||||
prefix string
|
||||
tags []Tag
|
||||
}{
|
||||
{gitrepo1, "xxx", []Tag{}},
|
||||
{gitrepo1, "", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
{"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
|
||||
{"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
}},
|
||||
{gitrepo1, "v", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
{"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
|
||||
{"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
}},
|
||||
{gitrepo1, "v1", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
}},
|
||||
{gitrepo1, "2", []Tag{}},
|
||||
testenv.MustHaveExecPath(t, vcsName)
|
||||
return NewRepo(vcsName, remote)
|
||||
}
|
||||
|
||||
func TestTags(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExec(t)
|
||||
t.Parallel()
|
||||
|
||||
type tagsTest struct {
|
||||
repo string
|
||||
prefix string
|
||||
tags []Tag
|
||||
}
|
||||
|
||||
runTest := func(tt tagsTest) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range tagsTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -140,7 +150,31 @@ func TestTags(t *testing.T) {
|
||||
t.Errorf("Tags(%q): incorrect tags\nhave %v\nwant %v", tt.prefix, tags, tt.tags)
|
||||
}
|
||||
}
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.prefix, f)
|
||||
}
|
||||
|
||||
for _, tt := range []tagsTest{
|
||||
{gitrepo1, "xxx", []Tag{}},
|
||||
{gitrepo1, "", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
{"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
|
||||
{"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
}},
|
||||
{gitrepo1, "v", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v2.0.1", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
{"v2.0.2", "9d02800338b8a55be062c838d1f02e0c5780b9eb"},
|
||||
{"v2.3", "76a00fb249b7f93091bc2c89a789dab1fc1bc26f"},
|
||||
}},
|
||||
{gitrepo1, "v1", []Tag{
|
||||
{"v1.2.3", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
{"v1.2.4-annotated", "ede458df7cd0fdca520df19a33158086a8a68e81"},
|
||||
}},
|
||||
{gitrepo1, "2", []Tag{}},
|
||||
} {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.prefix, runTest(tt))
|
||||
if tt.repo == gitrepo1 {
|
||||
// Clear hashes.
|
||||
clearTags := []Tag{}
|
||||
@ -148,60 +182,31 @@ func TestTags(t *testing.T) {
|
||||
clearTags = append(clearTags, Tag{tag.Name, ""})
|
||||
}
|
||||
tags := tt.tags
|
||||
for _, tt.repo = range altRepos {
|
||||
for _, tt.repo = range altRepos() {
|
||||
if strings.Contains(tt.repo, "Git") {
|
||||
tt.tags = tags
|
||||
} else {
|
||||
tt.tags = clearTags
|
||||
}
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.prefix, f)
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.prefix, runTest(tt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var latestTests = []struct {
|
||||
repo string
|
||||
info *RevInfo
|
||||
}{
|
||||
{
|
||||
gitrepo1,
|
||||
&RevInfo{
|
||||
Origin: &Origin{
|
||||
VCS: "git",
|
||||
URL: "https://vcs-test.golang.org/git/gitrepo1",
|
||||
Ref: "HEAD",
|
||||
Hash: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
},
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
hgrepo1,
|
||||
&RevInfo{
|
||||
Origin: &Origin{
|
||||
VCS: "hg",
|
||||
URL: "https://vcs-test.golang.org/hg/hgrepo1",
|
||||
Hash: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
},
|
||||
Name: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
Short: "18518c07eb8e",
|
||||
Version: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
Time: time.Date(2018, 6, 27, 16, 16, 30, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestLatest(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExec(t)
|
||||
t.Parallel()
|
||||
|
||||
type latestTest struct {
|
||||
repo string
|
||||
info *RevInfo
|
||||
}
|
||||
runTest := func(tt latestTest) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range latestTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -214,7 +219,41 @@ func TestLatest(t *testing.T) {
|
||||
t.Errorf("Latest: incorrect info\nhave %+v (origin %+v)\nwant %+v (origin %+v)", info, info.Origin, tt.info, tt.info.Origin)
|
||||
}
|
||||
}
|
||||
t.Run(path.Base(tt.repo), f)
|
||||
}
|
||||
|
||||
for _, tt := range []latestTest{
|
||||
{
|
||||
gitrepo1,
|
||||
&RevInfo{
|
||||
Origin: &Origin{
|
||||
VCS: "git",
|
||||
URL: gitrepo1,
|
||||
Ref: "HEAD",
|
||||
Hash: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
},
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
hgrepo1,
|
||||
&RevInfo{
|
||||
Origin: &Origin{
|
||||
VCS: "hg",
|
||||
URL: hgrepo1,
|
||||
Hash: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
},
|
||||
Name: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
Short: "18518c07eb8e",
|
||||
Version: "18518c07eb8ed5c80221e997e518cccaa8c0c287",
|
||||
Time: time.Date(2018, 6, 27, 16, 16, 30, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(path.Base(tt.repo), runTest(tt))
|
||||
if tt.repo == gitrepo1 {
|
||||
tt.repo = "localGitRepo"
|
||||
info := *tt.info
|
||||
@ -222,44 +261,27 @@ func TestLatest(t *testing.T) {
|
||||
o := *info.Origin
|
||||
info.Origin = &o
|
||||
o.URL = localGitURL
|
||||
t.Run(path.Base(tt.repo), f)
|
||||
t.Run(path.Base(tt.repo), runTest(tt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var readFileTests = []struct {
|
||||
repo string
|
||||
rev string
|
||||
file string
|
||||
err string
|
||||
data string
|
||||
}{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "latest",
|
||||
file: "README",
|
||||
data: "",
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2",
|
||||
file: "another.txt",
|
||||
data: "another\n",
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4",
|
||||
file: "another.txt",
|
||||
err: fs.ErrNotExist.Error(),
|
||||
},
|
||||
}
|
||||
|
||||
func TestReadFile(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExec(t)
|
||||
t.Parallel()
|
||||
|
||||
type readFileTest struct {
|
||||
repo string
|
||||
rev string
|
||||
file string
|
||||
err string
|
||||
data string
|
||||
}
|
||||
runTest := func(tt readFileTest) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range readFileTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -284,162 +306,37 @@ func TestReadFile(t *testing.T) {
|
||||
t.Errorf("ReadFile: incorrect data\nhave %q\nwant %q", data, tt.data)
|
||||
}
|
||||
}
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f)
|
||||
}
|
||||
|
||||
for _, tt := range []readFileTest{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "latest",
|
||||
file: "README",
|
||||
data: "",
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2",
|
||||
file: "another.txt",
|
||||
data: "another\n",
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4",
|
||||
file: "another.txt",
|
||||
err: fs.ErrNotExist.Error(),
|
||||
},
|
||||
} {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, runTest(tt))
|
||||
if tt.repo == gitrepo1 {
|
||||
for _, tt.repo = range altRepos {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f)
|
||||
for _, tt.repo = range altRepos() {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, runTest(tt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var readZipTests = []struct {
|
||||
repo string
|
||||
rev string
|
||||
subdir string
|
||||
err string
|
||||
files map[string]uint64
|
||||
}{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v2.3.4",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
"prefix/another.txt": 8,
|
||||
"prefix/foo.txt": 13,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v2",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
"prefix/another.txt": 8,
|
||||
"prefix/foo.txt": 13,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
"prefix/README": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/.hgtags": 405,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
"prefix/README": 0,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub/dir",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub/dir",
|
||||
files: map[string]uint64{
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub",
|
||||
files: map[string]uint64{
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
subdir: "",
|
||||
err: "unknown revision",
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
subdir: "",
|
||||
err: "unknown revision",
|
||||
},
|
||||
|
||||
{
|
||||
repo: "https://github.com/rsc/vgotest1",
|
||||
rev: "submod/v1.0.4",
|
||||
subdir: "submod",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/submod/": 0,
|
||||
"prefix/submod/go.mod": 53,
|
||||
"prefix/submod/pkg/": 0,
|
||||
"prefix/submod/pkg/p.go": 31,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type zipFile struct {
|
||||
name string
|
||||
size int64
|
||||
@ -448,9 +345,19 @@ type zipFile struct {
|
||||
func TestReadZip(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExec(t)
|
||||
t.Parallel()
|
||||
|
||||
type readZipTest struct {
|
||||
repo string
|
||||
rev string
|
||||
subdir string
|
||||
err string
|
||||
files map[string]uint64
|
||||
}
|
||||
runTest := func(tt readZipTest) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range readZipTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -498,10 +405,152 @@ func TestReadZip(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f)
|
||||
}
|
||||
|
||||
for _, tt := range []readZipTest{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v2.3.4",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
"prefix/another.txt": 8,
|
||||
"prefix/foo.txt": 13,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v2",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/README": 0,
|
||||
"prefix/v2": 3,
|
||||
"prefix/another.txt": 8,
|
||||
"prefix/foo.txt": 13,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
"prefix/README": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "",
|
||||
files: map[string]uint64{
|
||||
"prefix/.hg_archival.txt": ^uint64(0),
|
||||
"prefix/.hgtags": 405,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
"prefix/README": 0,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub/dir",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub/dir",
|
||||
files: map[string]uint64{
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/v3/": 0,
|
||||
"prefix/v3/sub/": 0,
|
||||
"prefix/v3/sub/dir/": 0,
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "v3",
|
||||
subdir: "v3/sub",
|
||||
files: map[string]uint64{
|
||||
"prefix/v3/sub/dir/file.txt": 16,
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
subdir: "",
|
||||
err: "unknown revision",
|
||||
},
|
||||
{
|
||||
repo: hgrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
subdir: "",
|
||||
err: "unknown revision",
|
||||
},
|
||||
|
||||
{
|
||||
repo: "https://github.com/rsc/vgotest1",
|
||||
rev: "submod/v1.0.4",
|
||||
subdir: "submod",
|
||||
files: map[string]uint64{
|
||||
"prefix/": 0,
|
||||
"prefix/submod/": 0,
|
||||
"prefix/submod/go.mod": 53,
|
||||
"prefix/submod/pkg/": 0,
|
||||
"prefix/submod/pkg/p.go": 31,
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, runTest(tt))
|
||||
if tt.repo == gitrepo1 {
|
||||
tt.repo = "localGitRepo"
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f)
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, runTest(tt))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -514,112 +563,21 @@ var hgmap = map[string]string{
|
||||
"97f6aa59c81c623494825b43d39e445566e429a4": "c0cbbfb24c7c3c50c35c7b88e7db777da4ff625d",
|
||||
}
|
||||
|
||||
var statTests = []struct {
|
||||
repo string
|
||||
rev string
|
||||
err string
|
||||
info *RevInfo
|
||||
}{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "HEAD",
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2", // branch
|
||||
info: &RevInfo{
|
||||
Name: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
|
||||
Short: "9d02800338b8",
|
||||
Version: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
|
||||
Time: time.Date(2018, 4, 17, 20, 00, 32, 0, time.UTC),
|
||||
Tags: []string{"v2.0.2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4", // badly-named branch (semver should be a tag)
|
||||
info: &RevInfo{
|
||||
Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Short: "76a00fb249b7",
|
||||
Version: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
|
||||
Tags: []string{"v2.0.1", "v2.3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3", // badly-named tag (we only respect full semver v2.3.0)
|
||||
info: &RevInfo{
|
||||
Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Short: "76a00fb249b7",
|
||||
Version: "v2.3",
|
||||
Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
|
||||
Tags: []string{"v2.0.1", "v2.3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v1.2.3", // tag
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "v1.2.3",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "ede458df", // hash prefix in refs
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "97f6aa59", // hash prefix not in refs
|
||||
info: &RevInfo{
|
||||
Name: "97f6aa59c81c623494825b43d39e445566e429a4",
|
||||
Short: "97f6aa59c81c",
|
||||
Version: "97f6aa59c81c623494825b43d39e445566e429a4",
|
||||
Time: time.Date(2018, 4, 17, 20, 0, 19, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v1.2.4-annotated", // annotated tag uses unwrapped commit hash
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "v1.2.4-annotated",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
err: "unknown revision",
|
||||
},
|
||||
}
|
||||
|
||||
func TestStat(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExec(t)
|
||||
t.Parallel()
|
||||
|
||||
type statTest struct {
|
||||
repo string
|
||||
rev string
|
||||
err string
|
||||
info *RevInfo
|
||||
}
|
||||
runTest := func(tt statTest) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tt := range statTests {
|
||||
f := func(t *testing.T) {
|
||||
r, err := testRepo(t, tt.repo)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@ -642,9 +600,105 @@ func TestStat(t *testing.T) {
|
||||
t.Errorf("Stat: incorrect info\nhave %+v\nwant %+v", *info, *tt.info)
|
||||
}
|
||||
}
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev, f)
|
||||
}
|
||||
|
||||
for _, tt := range []statTest{
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "HEAD",
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2", // branch
|
||||
info: &RevInfo{
|
||||
Name: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
|
||||
Short: "9d02800338b8",
|
||||
Version: "9d02800338b8a55be062c838d1f02e0c5780b9eb",
|
||||
Time: time.Date(2018, 4, 17, 20, 00, 32, 0, time.UTC),
|
||||
Tags: []string{"v2.0.2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3.4", // badly-named branch (semver should be a tag)
|
||||
info: &RevInfo{
|
||||
Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Short: "76a00fb249b7",
|
||||
Version: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
|
||||
Tags: []string{"v2.0.1", "v2.3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v2.3", // badly-named tag (we only respect full semver v2.3.0)
|
||||
info: &RevInfo{
|
||||
Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f",
|
||||
Short: "76a00fb249b7",
|
||||
Version: "v2.3",
|
||||
Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC),
|
||||
Tags: []string{"v2.0.1", "v2.3"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v1.2.3", // tag
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "v1.2.3",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "ede458df", // hash prefix in refs
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "97f6aa59", // hash prefix not in refs
|
||||
info: &RevInfo{
|
||||
Name: "97f6aa59c81c623494825b43d39e445566e429a4",
|
||||
Short: "97f6aa59c81c",
|
||||
Version: "97f6aa59c81c623494825b43d39e445566e429a4",
|
||||
Time: time.Date(2018, 4, 17, 20, 0, 19, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "v1.2.4-annotated", // annotated tag uses unwrapped commit hash
|
||||
info: &RevInfo{
|
||||
Name: "ede458df7cd0fdca520df19a33158086a8a68e81",
|
||||
Short: "ede458df7cd0",
|
||||
Version: "v1.2.4-annotated",
|
||||
Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC),
|
||||
Tags: []string{"v1.2.3", "v1.2.4-annotated"},
|
||||
},
|
||||
},
|
||||
{
|
||||
repo: gitrepo1,
|
||||
rev: "aaaaaaaaab",
|
||||
err: "unknown revision",
|
||||
},
|
||||
} {
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev, runTest(tt))
|
||||
if tt.repo == gitrepo1 {
|
||||
for _, tt.repo = range altRepos {
|
||||
for _, tt.repo = range altRepos() {
|
||||
old := tt
|
||||
var m map[string]string
|
||||
if tt.repo == hgrepo1 {
|
||||
@ -658,7 +712,7 @@ func TestStat(t *testing.T) {
|
||||
tt.info.Short = remap(tt.info.Short, m)
|
||||
}
|
||||
tt.rev = remap(tt.rev, m)
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev, f)
|
||||
t.Run(path.Base(tt.repo)+"/"+tt.rev, runTest(tt))
|
||||
tt = old
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ import (
|
||||
"archive/zip"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"hash"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -20,15 +22,20 @@ import (
|
||||
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/modfetch/codehost"
|
||||
"cmd/go/internal/vcweb/vcstest"
|
||||
|
||||
"golang.org/x/mod/sumdb/dirhash"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(testMain(m))
|
||||
flag.Parse()
|
||||
if err := testMain(m); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
func testMain(m *testing.M) (err error) {
|
||||
|
||||
cfg.GOPROXY = "direct"
|
||||
|
||||
// The sum database is populated using a released version of the go command,
|
||||
@ -39,12 +46,31 @@ func testMain(m *testing.M) int {
|
||||
|
||||
dir, err := os.MkdirTemp("", "gitrepo-test-")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
defer func() {
|
||||
if rmErr := os.RemoveAll(dir); err == nil {
|
||||
err = rmErr
|
||||
}
|
||||
}()
|
||||
|
||||
cfg.GOMODCACHE = dir
|
||||
return m.Run()
|
||||
cfg.GOMODCACHE = filepath.Join(dir, "modcache")
|
||||
if err := os.Mkdir(cfg.GOMODCACHE, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srv, err := vcstest.NewServer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := srv.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
|
||||
m.Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -6,6 +6,7 @@ package modload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"internal/testenv"
|
||||
"log"
|
||||
"os"
|
||||
@ -15,27 +16,47 @@ import (
|
||||
"testing"
|
||||
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/vcweb/vcstest"
|
||||
|
||||
"golang.org/x/mod/module"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(testMain(m))
|
||||
flag.Parse()
|
||||
if err := testMain(m); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
func testMain(m *testing.M) (err error) {
|
||||
cfg.GOPROXY = "direct"
|
||||
cfg.ModCacheRW = true
|
||||
|
||||
srv, err := vcstest.NewServer()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if closeErr := srv.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
}()
|
||||
|
||||
dir, err := os.MkdirTemp("", "modload-test-")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
defer func() {
|
||||
if rmErr := os.RemoveAll(dir); err == nil {
|
||||
err = rmErr
|
||||
}
|
||||
}()
|
||||
|
||||
os.Setenv("GOPATH", dir)
|
||||
cfg.BuildContext.GOPATH = dir
|
||||
cfg.GOMODCACHE = filepath.Join(dir, "pkg/mod")
|
||||
return m.Run()
|
||||
m.Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
@ -55,42 +76,6 @@ var queryTests = []struct {
|
||||
vers string
|
||||
err string
|
||||
}{
|
||||
/*
|
||||
git init
|
||||
echo module vcs-test.golang.org/git/querytest.git >go.mod
|
||||
git add go.mod
|
||||
git commit -m v1 go.mod
|
||||
git tag start
|
||||
for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata unversioned; do
|
||||
echo before $i >status
|
||||
git add status
|
||||
git commit -m "before $i" status
|
||||
echo at $i >status
|
||||
git commit -m "at $i" status
|
||||
git tag $i
|
||||
done
|
||||
git tag favorite v0.0.3
|
||||
|
||||
git branch v2 start
|
||||
git checkout v2
|
||||
echo module vcs-test.golang.org/git/querytest.git/v2 >go.mod
|
||||
git commit -m v2 go.mod
|
||||
for i in v2.0.0 v2.1.0 v2.2.0 v2.5.5 v2.6.0-pre1; do
|
||||
echo before $i >status
|
||||
git add status
|
||||
git commit -m "before $i" status
|
||||
echo at $i >status
|
||||
git commit -m "at $i" status
|
||||
git tag $i
|
||||
done
|
||||
git checkout v2.5.5
|
||||
echo after v2.5.5 >status
|
||||
git commit -m 'after v2.5.5' status
|
||||
git checkout master
|
||||
zip -r ../querytest.zip
|
||||
gsutil cp ../querytest.zip gs://vcs-test/git/querytest.zip
|
||||
curl 'https://vcs-test.golang.org/git/querytest?go-get=1'
|
||||
*/
|
||||
{path: queryRepo, query: "<v0.0.0", vers: "v0.0.0-pre1"},
|
||||
{path: queryRepo, query: "<v0.0.0-pre1", err: `no matching versions for query "<v0.0.0-pre1"`},
|
||||
{path: queryRepo, query: "<=v0.0.0", vers: "v0.0.0"},
|
||||
|
@ -60,6 +60,22 @@ type Status struct {
|
||||
Uncommitted bool // Required.
|
||||
}
|
||||
|
||||
var (
|
||||
// VCSTestRepoURL is the URL of the HTTP server that serves the repos for
|
||||
// vcs-test.golang.org.
|
||||
//
|
||||
// In tests, this is set to the URL of an httptest.Server hosting a
|
||||
// cmd/go/internal/vcweb.Server.
|
||||
VCSTestRepoURL string
|
||||
|
||||
// VCSTestHosts is the set of hosts supported by the vcs-test server.
|
||||
VCSTestHosts []string
|
||||
|
||||
// VCSTestIsLocalHost reports whether the given URL refers to a local
|
||||
// (loopback) host, such as "localhost" or "127.0.0.1:8080".
|
||||
VCSTestIsLocalHost func(*urlpkg.URL) bool
|
||||
)
|
||||
|
||||
var defaultSecureScheme = map[string]bool{
|
||||
"https": true,
|
||||
"git+ssh": true,
|
||||
@ -74,6 +90,12 @@ func (v *Cmd) IsSecure(repo string) bool {
|
||||
// If repo is not a URL, it's not secure.
|
||||
return false
|
||||
}
|
||||
if VCSTestRepoURL != "" && web.IsLocalHost(u) {
|
||||
// If the vcstest server is in use, it may redirect to other local ports for
|
||||
// other protocols (such as svn). Assume that all loopback addresses are
|
||||
// secure during testing.
|
||||
return true
|
||||
}
|
||||
return v.isSecureScheme(u.Scheme)
|
||||
}
|
||||
|
||||
@ -1151,21 +1173,25 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
||||
if !srv.schemelessRepo {
|
||||
repoURL = match["repo"]
|
||||
} else {
|
||||
scheme := vcs.Scheme[0] // default to first scheme
|
||||
repo := match["repo"]
|
||||
if vcs.PingCmd != "" {
|
||||
// If we know how to test schemes, scan to find one.
|
||||
for _, s := range vcs.Scheme {
|
||||
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
|
||||
continue
|
||||
}
|
||||
if vcs.Ping(s, repo) == nil {
|
||||
scheme = s
|
||||
break
|
||||
var ok bool
|
||||
repoURL, ok = interceptVCSTest(repo, vcs, security)
|
||||
if !ok {
|
||||
scheme := vcs.Scheme[0] // default to first scheme
|
||||
if vcs.PingCmd != "" {
|
||||
// If we know how to test schemes, scan to find one.
|
||||
for _, s := range vcs.Scheme {
|
||||
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
|
||||
continue
|
||||
}
|
||||
if vcs.Ping(s, repo) == nil {
|
||||
scheme = s
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
repoURL = scheme + "://" + repo
|
||||
}
|
||||
repoURL = scheme + "://" + repo
|
||||
}
|
||||
rr := &RepoRoot{
|
||||
Repo: repoURL,
|
||||
@ -1177,6 +1203,32 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
|
||||
return nil, errUnknownSite
|
||||
}
|
||||
|
||||
func interceptVCSTest(repo string, vcs *Cmd, security web.SecurityMode) (repoURL string, ok bool) {
|
||||
if VCSTestRepoURL == "" {
|
||||
return "", false
|
||||
}
|
||||
if vcs == vcsMod {
|
||||
return "", false // Will be implemented in CL 427254.
|
||||
}
|
||||
if vcs == vcsSvn {
|
||||
return "", false // Will be implemented in CL 427914.
|
||||
}
|
||||
|
||||
if scheme, path, ok := strings.Cut(repo, "://"); ok {
|
||||
if security == web.SecureOnly && !vcs.isSecureScheme(scheme) {
|
||||
return "", false // Let the caller reject the original URL.
|
||||
}
|
||||
repo = path // Remove leading URL scheme if present.
|
||||
}
|
||||
for _, host := range VCSTestHosts {
|
||||
if !str.HasPathPrefix(repo, host) {
|
||||
continue
|
||||
}
|
||||
return VCSTestRepoURL + strings.TrimPrefix(repo, host), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// urlForImportPath returns a partially-populated URL for the given Go import path.
|
||||
//
|
||||
// The URL leaves the Scheme field blank so that web.Get will try any scheme
|
||||
@ -1275,8 +1327,12 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repoURL, ok := interceptVCSTest(mmi.RepoRoot, vcs, security)
|
||||
if !ok {
|
||||
repoURL = mmi.RepoRoot
|
||||
}
|
||||
rr := &RepoRoot{
|
||||
Repo: mmi.RepoRoot,
|
||||
Repo: repoURL,
|
||||
Root: mmi.Prefix,
|
||||
IsCustom: true,
|
||||
VCS: vcs,
|
||||
|
18
src/cmd/go/internal/vcweb/bzr.go
Normal file
18
src/cmd/go/internal/vcweb/bzr.go
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type bzrHandler struct{}
|
||||
|
||||
func (*bzrHandler) Available() bool { return true }
|
||||
|
||||
func (*bzrHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
|
||||
return http.FileServer(http.Dir(dir)), nil
|
||||
}
|
19
src/cmd/go/internal/vcweb/dir.go
Normal file
19
src/cmd/go/internal/vcweb/dir.go
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// dirHandler is a vcsHandler that serves the raw contents of a directory.
|
||||
type dirHandler struct{}
|
||||
|
||||
func (*dirHandler) Available() bool { return true }
|
||||
|
||||
func (*dirHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
|
||||
return http.FileServer(http.Dir(dir)), nil
|
||||
}
|
62
src/cmd/go/internal/vcweb/fossil.go
Normal file
62
src/cmd/go/internal/vcweb/fossil.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type fossilHandler struct {
|
||||
once sync.Once
|
||||
fossilPath string
|
||||
fossilPathErr error
|
||||
}
|
||||
|
||||
func (h *fossilHandler) Available() bool {
|
||||
h.once.Do(func() {
|
||||
h.fossilPath, h.fossilPathErr = exec.LookPath("fossil")
|
||||
})
|
||||
return h.fossilPathErr == nil
|
||||
}
|
||||
|
||||
func (h *fossilHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
|
||||
if !h.Available() {
|
||||
return nil, ServerNotInstalledError{name: "fossil"}
|
||||
}
|
||||
|
||||
name := filepath.Base(dir)
|
||||
db := filepath.Join(dir, name+".fossil")
|
||||
|
||||
cgiPath := db + ".cgi"
|
||||
cgiScript := fmt.Sprintf("#!%s\nrepository: %s\n", h.fossilPath, db)
|
||||
if err := ioutil.WriteFile(cgiPath, []byte(cgiScript), 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
if _, err := os.Stat(db); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
ch := &cgi.Handler{
|
||||
Env: env,
|
||||
Logger: logger,
|
||||
Path: h.fossilPath,
|
||||
Args: []string{cgiPath},
|
||||
Dir: dir,
|
||||
}
|
||||
ch.ServeHTTP(w, req)
|
||||
})
|
||||
|
||||
return handler, nil
|
||||
}
|
51
src/cmd/go/internal/vcweb/git.go
Normal file
51
src/cmd/go/internal/vcweb/git.go
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/cgi"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type gitHandler struct {
|
||||
once sync.Once
|
||||
gitPath string
|
||||
gitPathErr error
|
||||
}
|
||||
|
||||
func (h *gitHandler) Available() bool {
|
||||
if runtime.GOOS == "plan9" {
|
||||
// The Git command is usually not the real Git on Plan 9.
|
||||
// See https://golang.org/issues/29640.
|
||||
return false
|
||||
}
|
||||
h.once.Do(func() {
|
||||
h.gitPath, h.gitPathErr = exec.LookPath("git")
|
||||
})
|
||||
return h.gitPathErr == nil
|
||||
}
|
||||
|
||||
func (h *gitHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
|
||||
if !h.Available() {
|
||||
return nil, ServerNotInstalledError{name: "git"}
|
||||
}
|
||||
|
||||
handler := &cgi.Handler{
|
||||
Path: h.gitPath,
|
||||
Logger: logger,
|
||||
Args: []string{"http-backend"},
|
||||
Dir: dir,
|
||||
Env: append(env[:len(env):len(env)],
|
||||
"GIT_PROJECT_ROOT="+dir,
|
||||
"GIT_HTTP_EXPORT_ALL=1",
|
||||
),
|
||||
}
|
||||
|
||||
return handler, nil
|
||||
}
|
121
src/cmd/go/internal/vcweb/hg.go
Normal file
121
src/cmd/go/internal/vcweb/hg.go
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type hgHandler struct {
|
||||
once sync.Once
|
||||
hgPath string
|
||||
hgPathErr error
|
||||
}
|
||||
|
||||
func (h *hgHandler) Available() bool {
|
||||
h.once.Do(func() {
|
||||
h.hgPath, h.hgPathErr = exec.LookPath("hg")
|
||||
})
|
||||
return h.hgPathErr == nil
|
||||
}
|
||||
|
||||
func (h *hgHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
|
||||
if !h.Available() {
|
||||
return nil, ServerNotInstalledError{name: "hg"}
|
||||
}
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
// Mercurial has a CGI server implementation (called hgweb). In theory we
|
||||
// could use that — however, assuming that hgweb is even installed, the
|
||||
// configuration for hgweb varies by Python version (2 vs 3), and we would
|
||||
// rather not go rooting around trying to find the right Python version to
|
||||
// run.
|
||||
//
|
||||
// Instead, we'll take a somewhat more roundabout approach: we assume that
|
||||
// if "hg" works at all then "hg serve" works too, and we'll execute that as
|
||||
// a subprocess, using a reverse proxy to forward the request and response.
|
||||
|
||||
cmd := exec.Command(h.hgPath, "serve", "--port", "0", "--address", "localhost", "--accesslog", os.DevNull, "--name", "vcweb", "--print-url")
|
||||
cmd.Dir = dir
|
||||
cmd.Env = append(env[:len(env):len(env)], "PWD="+dir)
|
||||
|
||||
stderr := new(strings.Builder)
|
||||
cmd.Stderr = stderr
|
||||
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
readDone := make(chan struct{})
|
||||
defer func() {
|
||||
stdout.Close()
|
||||
<-readDone
|
||||
}()
|
||||
|
||||
hgURL := make(chan *url.URL, 1)
|
||||
hgURLError := make(chan error, 1)
|
||||
go func() {
|
||||
defer close(readDone)
|
||||
r := bufio.NewReader(stdout)
|
||||
for {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
u, err := url.Parse(strings.TrimSpace(line))
|
||||
if err == nil {
|
||||
hgURL <- u
|
||||
} else {
|
||||
hgURLError <- err
|
||||
}
|
||||
break
|
||||
}
|
||||
io.Copy(io.Discard, r)
|
||||
}()
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := cmd.Process.Signal(os.Interrupt); err != nil && !errors.Is(err, os.ErrProcessDone) {
|
||||
cmd.Process.Kill()
|
||||
}
|
||||
err := cmd.Wait()
|
||||
if out := strings.TrimSuffix(stderr.String(), "interrupted!\n"); out != "" {
|
||||
logger.Printf("%v: %v\n%s", cmd, err, out)
|
||||
} else {
|
||||
logger.Printf("%v", cmd)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-req.Context().Done():
|
||||
logger.Printf("%v: %v", req.Context().Err(), cmd)
|
||||
http.Error(w, req.Context().Err().Error(), http.StatusBadGateway)
|
||||
return
|
||||
case err := <-hgURLError:
|
||||
logger.Printf("%v: %v", cmd, err)
|
||||
http.Error(w, err.Error(), http.StatusBadGateway)
|
||||
return
|
||||
case url := <-hgURL:
|
||||
logger.Printf("proxying hg request to %s", url)
|
||||
httputil.NewSingleHostReverseProxy(url).ServeHTTP(w, req)
|
||||
}
|
||||
})
|
||||
|
||||
return handler, nil
|
||||
}
|
304
src/cmd/go/internal/vcweb/script.go
Normal file
304
src/cmd/go/internal/vcweb/script.go
Normal file
@ -0,0 +1,304 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"cmd/go/internal/script"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/txtar"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// newScriptEngine returns a script engine augmented with commands for
|
||||
// reproducing version-control repositories by replaying commits.
|
||||
func newScriptEngine() *script.Engine {
|
||||
conds := script.DefaultConds()
|
||||
|
||||
interrupt := os.Interrupt
|
||||
gracePeriod := 1 * time.Second // arbitrary
|
||||
|
||||
cmds := script.DefaultCmds()
|
||||
cmds["at"] = scriptAt()
|
||||
cmds["bzr"] = script.Program("bzr", interrupt, gracePeriod)
|
||||
cmds["fossil"] = script.Program("fossil", interrupt, gracePeriod)
|
||||
cmds["git"] = script.Program("git", interrupt, gracePeriod)
|
||||
cmds["hg"] = script.Program("hg", interrupt, gracePeriod)
|
||||
cmds["handle"] = scriptHandle()
|
||||
cmds["svn"] = script.Program("svn", interrupt, gracePeriod)
|
||||
cmds["unquote"] = scriptUnquote()
|
||||
|
||||
return &script.Engine{
|
||||
Cmds: cmds,
|
||||
Conds: conds,
|
||||
}
|
||||
}
|
||||
|
||||
// loadScript interprets the given script content using the vcweb script engine.
|
||||
// loadScript always returns either a non-nil handler or a non-nil error.
|
||||
//
|
||||
// The script content must be a txtar archive with a comment containing a script
|
||||
// with exactly one "handle" command and zero or more VCS commands to prepare
|
||||
// the repository to be served.
|
||||
func (s *Server) loadScript(ctx context.Context, logger *log.Logger, scriptPath string, scriptContent []byte, workDir string) (http.Handler, error) {
|
||||
ar := txtar.Parse(scriptContent)
|
||||
|
||||
if err := os.MkdirAll(workDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st, err := s.newState(ctx, workDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := st.ExtractFiles(ar); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scriptName := filepath.Base(scriptPath)
|
||||
scriptLog := new(strings.Builder)
|
||||
err = s.engine.Execute(st, scriptName, bufio.NewReader(bytes.NewReader(ar.Comment)), scriptLog)
|
||||
closeErr := st.CloseAndWait(scriptLog)
|
||||
logger.Printf("%s:", scriptName)
|
||||
io.WriteString(logger.Writer(), scriptLog.String())
|
||||
io.WriteString(logger.Writer(), "\n")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if closeErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sc, err := getScriptCtx(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if sc.handler == nil {
|
||||
return nil, errors.New("script completed without setting handler")
|
||||
}
|
||||
return sc.handler, nil
|
||||
}
|
||||
|
||||
// newState returns a new script.State for executing scripts in workDir.
|
||||
func (s *Server) newState(ctx context.Context, workDir string) (*script.State, error) {
|
||||
ctx = &scriptCtx{
|
||||
Context: ctx,
|
||||
server: s,
|
||||
}
|
||||
|
||||
st, err := script.NewState(ctx, workDir, s.env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// scriptEnviron returns a new environment that attempts to provide predictable
|
||||
// behavior for the supported version-control tools.
|
||||
func scriptEnviron(homeDir string) []string {
|
||||
env := []string{
|
||||
"USER=gopher",
|
||||
homeEnvName() + "=" + homeDir,
|
||||
"GIT_CONFIG_NOSYSTEM=1",
|
||||
"HGRCPATH=" + filepath.Join(homeDir, ".hgrc"),
|
||||
"HGENCODING=utf-8",
|
||||
}
|
||||
// Preserve additional environment variables that may be needed by VCS tools.
|
||||
for _, k := range []string{
|
||||
pathEnvName(),
|
||||
tempEnvName(),
|
||||
"SYSTEMROOT", // must be preserved on Windows to find DLLs; golang.org/issue/25210
|
||||
"WINDIR", // must be preserved on Windows to be able to run PowerShell command; golang.org/issue/30711
|
||||
"DYLD_LIBRARY_PATH", // must be preserved on macOS systems to find shared libraries
|
||||
"LD_LIBRARY_PATH", // must be preserved on Unix systems to find shared libraries
|
||||
"LIBRARY_PATH", // allow override of non-standard static library paths
|
||||
"PYTHONPATH", // may be needed by hg to find imported modules
|
||||
} {
|
||||
if v, ok := os.LookupEnv(k); ok {
|
||||
env = append(env, k+"="+v)
|
||||
}
|
||||
}
|
||||
|
||||
if os.Getenv("GO_BUILDER_NAME") != "" || os.Getenv("GIT_TRACE_CURL") == "1" {
|
||||
// To help diagnose https://go.dev/issue/52545,
|
||||
// enable tracing for Git HTTPS requests.
|
||||
env = append(env,
|
||||
"GIT_TRACE_CURL=1",
|
||||
"GIT_TRACE_CURL_NO_DATA=1",
|
||||
"GIT_REDACT_COOKIES=o,SSO,GSSO_Uberproxy")
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
// homeEnvName returns the environment variable used by os.UserHomeDir
|
||||
// to locate the user's home directory.
|
||||
func homeEnvName() string {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return "USERPROFILE"
|
||||
case "plan9":
|
||||
return "home"
|
||||
default:
|
||||
return "HOME"
|
||||
}
|
||||
}
|
||||
|
||||
// tempEnvName returns the environment variable used by os.TempDir
|
||||
// to locate the default directory for temporary files.
|
||||
func tempEnvName() string {
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return "TMP"
|
||||
case "plan9":
|
||||
return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine
|
||||
default:
|
||||
return "TMPDIR"
|
||||
}
|
||||
}
|
||||
|
||||
// pathEnvName returns the environment variable used by exec.LookPath to
|
||||
// identify directories to search for executables.
|
||||
func pathEnvName() string {
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
return "path"
|
||||
default:
|
||||
return "PATH"
|
||||
}
|
||||
}
|
||||
|
||||
// A scriptCtx is a context.Context that stores additional state for script
|
||||
// commands.
|
||||
type scriptCtx struct {
|
||||
context.Context
|
||||
server *Server
|
||||
commitTime time.Time
|
||||
handlerName string
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
// scriptCtxKey is the key associating the *scriptCtx in a script's Context..
|
||||
type scriptCtxKey struct{}
|
||||
|
||||
func (sc *scriptCtx) Value(key any) any {
|
||||
if key == (scriptCtxKey{}) {
|
||||
return sc
|
||||
}
|
||||
return sc.Context.Value(key)
|
||||
}
|
||||
|
||||
func getScriptCtx(st *script.State) (*scriptCtx, error) {
|
||||
sc, ok := st.Context().Value(scriptCtxKey{}).(*scriptCtx)
|
||||
if !ok {
|
||||
return nil, errors.New("scriptCtx not found in State.Context")
|
||||
}
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
func scriptAt() script.Cmd {
|
||||
return script.Command(
|
||||
script.CmdUsage{
|
||||
Summary: "set the current commit time for all version control systems",
|
||||
Args: "time",
|
||||
Detail: []string{
|
||||
"The argument must be an absolute timestamp in RFC3339 format.",
|
||||
},
|
||||
},
|
||||
func(st *script.State, args ...string) (script.WaitFunc, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, script.ErrUsage
|
||||
}
|
||||
|
||||
sc, err := getScriptCtx(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sc.commitTime, err = time.ParseInLocation(time.RFC3339, args[0], time.UTC)
|
||||
if err == nil {
|
||||
st.Setenv("GIT_COMMITTER_DATE", args[0])
|
||||
st.Setenv("GIT_AUTHOR_DATE", args[0])
|
||||
}
|
||||
return nil, err
|
||||
})
|
||||
}
|
||||
|
||||
func scriptHandle() script.Cmd {
|
||||
return script.Command(
|
||||
script.CmdUsage{
|
||||
Summary: "set the HTTP handler that will serve the script's output",
|
||||
Args: "handler [dir]",
|
||||
Detail: []string{
|
||||
"The handler will be passed the script's current working directory and environment as arguments.",
|
||||
"Valid handlers include 'dir' (for general http.Dir serving), 'bzr', 'fossil', 'git', and 'hg'",
|
||||
},
|
||||
},
|
||||
func(st *script.State, args ...string) (script.WaitFunc, error) {
|
||||
if len(args) == 0 || len(args) > 2 {
|
||||
return nil, script.ErrUsage
|
||||
}
|
||||
|
||||
sc, err := getScriptCtx(st)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sc.handler != nil {
|
||||
return nil, fmt.Errorf("server handler already set to %s", sc.handlerName)
|
||||
}
|
||||
|
||||
name := args[0]
|
||||
h, ok := sc.server.vcsHandlers[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unrecognized VCS %q", name)
|
||||
}
|
||||
sc.handlerName = name
|
||||
if !h.Available() {
|
||||
return nil, ServerNotInstalledError{name}
|
||||
}
|
||||
|
||||
dir := st.Getwd()
|
||||
if len(args) >= 2 {
|
||||
dir = st.Path(args[1])
|
||||
}
|
||||
sc.handler, err = h.Handler(dir, st.Environ(), sc.server.logger)
|
||||
return nil, err
|
||||
})
|
||||
}
|
||||
|
||||
func scriptUnquote() script.Cmd {
|
||||
return script.Command(
|
||||
script.CmdUsage{
|
||||
Summary: "unquote the argument as a Go string",
|
||||
Args: "string",
|
||||
},
|
||||
func(st *script.State, args ...string) (script.WaitFunc, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, script.ErrUsage
|
||||
}
|
||||
|
||||
s, err := strconv.Unquote(`"` + args[0] + `"`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wait := func(*script.State) (stdout, stderr string, err error) {
|
||||
return s, "", nil
|
||||
}
|
||||
return wait, nil
|
||||
})
|
||||
}
|
83
src/cmd/go/internal/vcweb/vcstest/vcstest.go
Normal file
83
src/cmd/go/internal/vcweb/vcstest/vcstest.go
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package vcstest serves the repository scripts in cmd/go/testdata/vcstest
|
||||
// using the [vcweb] script engine.
|
||||
package vcstest
|
||||
|
||||
import (
|
||||
"cmd/go/internal/vcs"
|
||||
"cmd/go/internal/vcweb"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"log"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var Hosts = []string{
|
||||
"vcs-test.golang.org",
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
workDir string
|
||||
HTTP *httptest.Server
|
||||
}
|
||||
|
||||
// NewServer returns a new test-local vcweb server that serves VCS requests
|
||||
// for modules with paths that begin with "vcs-test.golang.org" using the
|
||||
// scripts in cmd/go/testdata/vcstest.
|
||||
func NewServer() (srv *Server, err error) {
|
||||
if vcs.VCSTestRepoURL != "" {
|
||||
panic("vcs URL hooks already set")
|
||||
}
|
||||
|
||||
scriptDir := filepath.Join(testenv.GOROOT(nil), "src/cmd/go/testdata/vcstest")
|
||||
|
||||
workDir, err := os.MkdirTemp("", "vcstest")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
os.RemoveAll(workDir)
|
||||
}
|
||||
}()
|
||||
|
||||
logger := log.Default()
|
||||
if !testing.Verbose() {
|
||||
logger = log.New(io.Discard, "", log.LstdFlags)
|
||||
}
|
||||
handler, err := vcweb.NewServer(scriptDir, workDir, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
srvHTTP := httptest.NewServer(handler)
|
||||
|
||||
srv = &Server{
|
||||
workDir: workDir,
|
||||
HTTP: srvHTTP,
|
||||
}
|
||||
vcs.VCSTestRepoURL = srv.HTTP.URL
|
||||
vcs.VCSTestHosts = Hosts
|
||||
|
||||
fmt.Fprintln(os.Stderr, "vcs-test.golang.org rerouted to "+srv.HTTP.URL)
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
func (srv *Server) Close() error {
|
||||
if vcs.VCSTestRepoURL != srv.HTTP.URL {
|
||||
panic("vcs URL hooks modified before Close")
|
||||
}
|
||||
vcs.VCSTestRepoURL = ""
|
||||
vcs.VCSTestHosts = nil
|
||||
|
||||
srv.HTTP.Close()
|
||||
return os.RemoveAll(srv.workDir)
|
||||
}
|
151
src/cmd/go/internal/vcweb/vcstest/vcstest_test.go
Normal file
151
src/cmd/go/internal/vcweb/vcstest/vcstest_test.go
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcstest_test
|
||||
|
||||
import (
|
||||
"cmd/go/internal/vcweb"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
dir = flag.String("dir", "../../../testdata/vcstest", "directory containing scripts to serve")
|
||||
host = flag.String("host", "localhost", "hostname on which to serve HTTP")
|
||||
port = flag.Int("port", -1, "port on which to serve HTTP; if nonnegative, skips running tests")
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
|
||||
if *port >= 0 {
|
||||
err := serveStandalone(*host, *port)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
m.Run()
|
||||
}
|
||||
|
||||
// serveStandalone serves the vcweb testdata in a standalone HTTP server.
|
||||
func serveStandalone(host string, port int) (err error) {
|
||||
scriptDir, err := filepath.Abs(*dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
work, err := os.MkdirTemp("", "vcweb")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if rmErr := os.RemoveAll(work); err == nil {
|
||||
err = rmErr
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("running scripts in %s", work)
|
||||
|
||||
v, err := vcweb.NewServer(scriptDir, work, log.Default())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("serving on http://%s:%d/", host, l.Addr().(*net.TCPAddr).Port)
|
||||
|
||||
return http.Serve(l, v)
|
||||
}
|
||||
|
||||
// TestScripts verifies that the VCS setup scripts in cmd/go/testdata/vcstest
|
||||
// run successfully.
|
||||
func TestScripts(t *testing.T) {
|
||||
scriptDir, err := filepath.Abs(*dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
s, err := vcweb.NewServer(scriptDir, t.TempDir(), log.Default())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
srv := httptest.NewServer(s)
|
||||
|
||||
t.Cleanup(func() {
|
||||
// The subtests spawned by WalkDir run in parallel. When they complete, this
|
||||
// Cleanup callback will run. At that point we fetch the root URL (which
|
||||
// contains a status page), both to test that the root handler runs without
|
||||
// crashing and to display a nice summary of the server's view of the test
|
||||
// coverage.
|
||||
resp, err := http.Get(srv.URL)
|
||||
if err == nil {
|
||||
var body []byte
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
if err == nil && testing.Verbose() {
|
||||
t.Logf("GET %s:\n%s", srv.URL, body)
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
srv.Close()
|
||||
})
|
||||
|
||||
err = filepath.WalkDir(scriptDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil || d.IsDir() {
|
||||
return err
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(scriptDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rel == "README" {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Run(filepath.ToSlash(rel), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
buf := new(strings.Builder)
|
||||
logger := log.New(buf, "", log.LstdFlags)
|
||||
// Load the script but don't try to serve the results:
|
||||
// different VCS tools have different handler protocols,
|
||||
// and the tests that actually use these repos will ensure
|
||||
// that they are served correctly as a side effect anyway.
|
||||
err := s.HandleScript(rel, logger, func(http.Handler) {})
|
||||
if buf.Len() > 0 {
|
||||
t.Log(buf)
|
||||
}
|
||||
if err != nil {
|
||||
if notInstalled := (vcweb.ServerNotInstalledError{}); errors.As(err, ¬Installed) || errors.Is(err, exec.ErrNotFound) {
|
||||
t.Skip(err)
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
407
src/cmd/go/internal/vcweb/vcweb.go
Normal file
407
src/cmd/go/internal/vcweb/vcweb.go
Normal file
@ -0,0 +1,407 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package vcweb serves version control repos for testing the go command.
|
||||
//
|
||||
// It is loosely derived from golang.org/x/build/vcs-test/vcweb,
|
||||
// which ran as a service hosted at vcs-test.golang.org.
|
||||
//
|
||||
// When a repository URL is first requested, the vcweb [Server] dynamically
|
||||
// regenerates the repository using a script interpreted by a [script.Engine].
|
||||
// The script produces the server's contents for a corresponding root URL and
|
||||
// all subdirectories of that URL, which are then cached: subsequent requests
|
||||
// for any URL generated by the script will serve the script's previous output
|
||||
// until the script is modified.
|
||||
//
|
||||
// The script engine includes all of the engine's default commands and
|
||||
// conditions, as well as commands for each supported VCS binary (bzr, fossil,
|
||||
// git, hg, and svn), a "handle" command that informs the script which protocol
|
||||
// or handler to use to serve the request, and utilities "at" (which sets
|
||||
// environment variables for Git timestamps) and "unquote" (which unquotes its
|
||||
// argument as if it were a Go string literal).
|
||||
//
|
||||
// The server's "/" endpoint provides a summary of the available scripts,
|
||||
// and "/help" provides documentation for the script environment.
|
||||
//
|
||||
// To run a standalone server based on the vcweb engine, use:
|
||||
//
|
||||
// go test cmd/go/internal/vcweb/vcstest -v --port=0
|
||||
package vcweb
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmd/go/internal/script"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
)
|
||||
|
||||
// A Server serves cached, dynamically-generated version control repositories.
|
||||
type Server struct {
|
||||
env []string
|
||||
logger *log.Logger
|
||||
|
||||
scriptDir string
|
||||
workDir string
|
||||
homeDir string // $workdir/home
|
||||
engine *script.Engine
|
||||
|
||||
scriptCache sync.Map // script path → *scriptResult
|
||||
|
||||
vcsHandlers map[string]vcsHandler
|
||||
}
|
||||
|
||||
// A vcsHandler serves repositories over HTTP for a known version-control tool.
|
||||
type vcsHandler interface {
|
||||
Available() bool
|
||||
Handler(dir string, env []string, logger *log.Logger) (http.Handler, error)
|
||||
}
|
||||
|
||||
// A scriptResult describes the cached result of executing a vcweb script.
|
||||
type scriptResult struct {
|
||||
mu sync.RWMutex
|
||||
|
||||
hash [sha256.Size]byte // hash of the script file, for cache invalidation
|
||||
hashTime time.Time // timestamp at which the script was run, for diagnostics
|
||||
|
||||
handler http.Handler // HTTP handler configured by the script
|
||||
err error // error from executing the script, if any
|
||||
}
|
||||
|
||||
// NewServer returns a Server that generates and serves repositories in workDir
|
||||
// using the scripts found in scriptDir and its subdirectories.
|
||||
//
|
||||
// A request for the path /foo/bar/baz will be handled by the first script along
|
||||
// that path that exists: $scriptDir/foo.txt, $scriptDir/foo/bar.txt, or
|
||||
// $scriptDir/foo/bar/baz.txt.
|
||||
func NewServer(scriptDir, workDir string, logger *log.Logger) (*Server, error) {
|
||||
if scriptDir == "" {
|
||||
panic("vcweb.NewServer: scriptDir is required")
|
||||
}
|
||||
var err error
|
||||
scriptDir, err = filepath.Abs(scriptDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if workDir == "" {
|
||||
workDir, err = os.MkdirTemp("", "vcweb-*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Printf("vcweb work directory: %s", workDir)
|
||||
} else {
|
||||
workDir, err = filepath.Abs(workDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
homeDir := filepath.Join(workDir, "home")
|
||||
if err := os.MkdirAll(homeDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
env := scriptEnviron(homeDir)
|
||||
|
||||
s := &Server{
|
||||
env: env,
|
||||
logger: logger,
|
||||
scriptDir: scriptDir,
|
||||
workDir: workDir,
|
||||
homeDir: homeDir,
|
||||
engine: newScriptEngine(),
|
||||
vcsHandlers: map[string]vcsHandler{
|
||||
"dir": new(dirHandler),
|
||||
"bzr": new(bzrHandler),
|
||||
"fossil": new(fossilHandler),
|
||||
"git": new(gitHandler),
|
||||
"hg": new(hgHandler),
|
||||
},
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(s.homeDir, ".gitconfig"), []byte(gitConfig), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gitConfigDir := filepath.Join(s.homeDir, ".config", "git")
|
||||
if err := os.MkdirAll(gitConfigDir, 0755); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(gitConfigDir, "ignore"), []byte(""), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filepath.Join(s.homeDir, ".hgrc"), []byte(hgrc), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// gitConfig contains a ~/.gitconfg file that attempts to provide
|
||||
// deterministic, platform-agnostic behavior for the 'git' command.
|
||||
var gitConfig = `
|
||||
[user]
|
||||
name = Go Gopher
|
||||
email = gopher@golang.org
|
||||
[init]
|
||||
defaultBranch = main
|
||||
[core]
|
||||
eol = lf
|
||||
[gui]
|
||||
encoding = utf-8
|
||||
`[1:]
|
||||
|
||||
// hgrc contains a ~/.hgrc file that attempts to provide
|
||||
// deterministic, platform-agnostic behavior for the 'hg' command.
|
||||
var hgrc = `
|
||||
[ui]
|
||||
username=Go Gopher <gopher@golang.org>
|
||||
[phases]
|
||||
new-commit=public
|
||||
[extensions]
|
||||
convert=
|
||||
`[1:]
|
||||
|
||||
// ServeHTTP implements [http.Handler] for version-control repositories.
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s.logger.Printf("serving %s", req.URL)
|
||||
|
||||
defer func() {
|
||||
if v := recover(); v != nil {
|
||||
debug.PrintStack()
|
||||
s.logger.Fatal(v)
|
||||
}
|
||||
}()
|
||||
|
||||
urlPath := req.URL.Path
|
||||
if !strings.HasPrefix(urlPath, "/") {
|
||||
urlPath = "/" + urlPath
|
||||
}
|
||||
clean := path.Clean(urlPath)[1:]
|
||||
if clean == "" {
|
||||
s.overview(w, req)
|
||||
return
|
||||
}
|
||||
if clean == "help" {
|
||||
s.help(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Locate the script that generates the requested path.
|
||||
// We follow directories all the way to the end, then look for a ".txt" file
|
||||
// matching the first component that doesn't exist. That guarantees
|
||||
// uniqueness: if a path exists as a directory, then it cannot exist as a
|
||||
// ".txt" script (because the search would ignore that file).
|
||||
scriptPath := "."
|
||||
for _, part := range strings.Split(clean, "/") {
|
||||
scriptPath = filepath.Join(scriptPath, part)
|
||||
dir := filepath.Join(s.scriptDir, scriptPath)
|
||||
if _, err := os.Stat(dir); err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// scriptPath does not exist as a directory, so it either is the script
|
||||
// location or the script doesn't exist.
|
||||
break
|
||||
}
|
||||
}
|
||||
scriptPath += ".txt"
|
||||
|
||||
err := s.HandleScript(scriptPath, s.logger, func(handler http.Handler) {
|
||||
handler.ServeHTTP(w, req)
|
||||
})
|
||||
if err != nil {
|
||||
s.logger.Print(err)
|
||||
if notFound := (ScriptNotFoundError{}); errors.As(err, ¬Found) {
|
||||
http.NotFound(w, req)
|
||||
} else if notInstalled := (ServerNotInstalledError{}); errors.As(err, ¬Installed) || errors.Is(err, exec.ErrNotFound) {
|
||||
http.Error(w, err.Error(), http.StatusNotImplemented)
|
||||
} else {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A ScriptNotFoundError indicates that the requested script file does not exist.
|
||||
// (It typically wraps a "stat" error for the script file.)
|
||||
type ScriptNotFoundError struct{ err error }
|
||||
|
||||
func (e ScriptNotFoundError) Error() string { return e.err.Error() }
|
||||
func (e ScriptNotFoundError) Unwrap() error { return e.err }
|
||||
|
||||
// A ServerNotInstalledError indicates that the server binary required for the
|
||||
// indicated VCS does not exist.
|
||||
type ServerNotInstalledError struct{ name string }
|
||||
|
||||
func (v ServerNotInstalledError) Error() string {
|
||||
return fmt.Sprintf("server for %#q VCS is not installed", v.name)
|
||||
}
|
||||
|
||||
// HandleScript ensures that the script at scriptRelPath has been evaluated
|
||||
// with its current contents.
|
||||
//
|
||||
// If the script completed successfully, HandleScript invokes f on the handler
|
||||
// with the script's result still read-locked, and waits for it to return. (That
|
||||
// ensures that cache invalidation does not race with an in-flight handler.)
|
||||
//
|
||||
// Otherwise, HandleScript returns the (cached) error from executing the script.
|
||||
func (s *Server) HandleScript(scriptRelPath string, logger *log.Logger, f func(http.Handler)) error {
|
||||
ri, ok := s.scriptCache.Load(scriptRelPath)
|
||||
if !ok {
|
||||
ri, _ = s.scriptCache.LoadOrStore(scriptRelPath, new(scriptResult))
|
||||
}
|
||||
r := ri.(*scriptResult)
|
||||
|
||||
relDir := strings.TrimSuffix(scriptRelPath, filepath.Ext(scriptRelPath))
|
||||
workDir := filepath.Join(s.workDir, relDir)
|
||||
prefix := path.Join("/", filepath.ToSlash(relDir))
|
||||
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
for {
|
||||
// For efficiency, we cache the script's output (in the work directory)
|
||||
// across invocations. However, to allow for rapid iteration, we hash the
|
||||
// script's contents and regenerate its output if the contents change.
|
||||
//
|
||||
// That way, one can use 'go run main.go' in this directory to stand up a
|
||||
// server and see the output of the test script in order to fine-tune it.
|
||||
content, err := os.ReadFile(filepath.Join(s.scriptDir, scriptRelPath))
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return ScriptNotFoundError{err}
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(content)
|
||||
if prevHash := r.hash; prevHash != hash {
|
||||
// The script's hash has changed, so regenerate its output.
|
||||
func() {
|
||||
r.mu.RUnlock()
|
||||
r.mu.Lock()
|
||||
defer func() {
|
||||
r.mu.Unlock()
|
||||
r.mu.RLock()
|
||||
}()
|
||||
if r.hash != prevHash {
|
||||
// The cached result changed while we were waiting on the lock.
|
||||
// It may have been updated to our hash or something even newer,
|
||||
// so don't overwrite it.
|
||||
return
|
||||
}
|
||||
|
||||
r.hash = hash
|
||||
r.hashTime = time.Now()
|
||||
r.handler, r.err = nil, nil
|
||||
|
||||
if err := os.RemoveAll(workDir); err != nil {
|
||||
r.err = err
|
||||
return
|
||||
}
|
||||
|
||||
// Note: we use context.Background here instead of req.Context() so that we
|
||||
// don't cache a spurious error (and lose work) if the request is canceled
|
||||
// while the script is still running.
|
||||
scriptHandler, err := s.loadScript(context.Background(), logger, scriptRelPath, content, workDir)
|
||||
if err != nil {
|
||||
r.err = err
|
||||
return
|
||||
}
|
||||
r.handler = http.StripPrefix(prefix, scriptHandler)
|
||||
}()
|
||||
}
|
||||
|
||||
if r.hash != hash {
|
||||
continue // Raced with an update from another handler; try again.
|
||||
}
|
||||
|
||||
if r.err != nil {
|
||||
return r.err
|
||||
}
|
||||
f(r.handler)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// overview serves an HTML summary of the status of the scripts in the server's
|
||||
// script directory.
|
||||
func (s *Server) overview(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "<html>\n")
|
||||
fmt.Fprintf(w, "<title>vcweb</title>\n<pre>\n")
|
||||
fmt.Fprintf(w, "<b>vcweb</b>\n\n")
|
||||
fmt.Fprintf(w, "This server serves various version control repos for testing the go command.\n\n")
|
||||
fmt.Fprintf(w, "For an overview of the script lanugage, see <a href=\"/help\">/help</a>.\n\n")
|
||||
|
||||
fmt.Fprintf(w, "<b>cache</b>\n")
|
||||
|
||||
tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
|
||||
err := filepath.WalkDir(s.scriptDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if filepath.Ext(path) != ".txt" {
|
||||
return nil
|
||||
}
|
||||
|
||||
rel, err := filepath.Rel(s.scriptDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hashTime := "(not loaded)"
|
||||
status := ""
|
||||
if ri, ok := s.scriptCache.Load(rel); ok {
|
||||
r := ri.(*scriptResult)
|
||||
if !r.hashTime.IsZero() {
|
||||
hashTime = r.hashTime.Format(time.RFC3339)
|
||||
}
|
||||
if r.err == nil {
|
||||
status = "ok"
|
||||
} else {
|
||||
status = r.err.Error()
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%s\t%s\n", rel, hashTime, status)
|
||||
return nil
|
||||
})
|
||||
tw.Flush()
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintln(w, err)
|
||||
}
|
||||
}
|
||||
|
||||
// help serves a plain-text summary of the server's supported script language.
|
||||
func (s *Server) help(w http.ResponseWriter, req *http.Request) {
|
||||
st, err := s.newState(req.Context(), s.workDir)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
scriptLog := new(strings.Builder)
|
||||
err = s.engine.Execute(st, "help", bufio.NewReader(strings.NewReader("help")), scriptLog)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain; charset=UTF-8")
|
||||
io.WriteString(w, scriptLog.String())
|
||||
}
|
63
src/cmd/go/internal/vcweb/vcweb_test.go
Normal file
63
src/cmd/go/internal/vcweb/vcweb_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package vcweb_test
|
||||
|
||||
import (
|
||||
"cmd/go/internal/vcweb"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHelp(t *testing.T) {
|
||||
s, err := vcweb.NewServer(os.DevNull, t.TempDir(), log.Default())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
srv := httptest.NewServer(s)
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL + "/help")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatal(resp.Status)
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%s", body)
|
||||
}
|
||||
|
||||
func TestOverview(t *testing.T) {
|
||||
s, err := vcweb.NewServer(os.DevNull, t.TempDir(), log.Default())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
srv := httptest.NewServer(s)
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatal(resp.Status)
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("%s", body)
|
||||
}
|
@ -238,3 +238,9 @@ func (b *errorDetailBuffer) Read(p []byte) (n int, err error) {
|
||||
|
||||
return n, err
|
||||
}
|
||||
|
||||
// IsLocalHost reports whether the given URL refers to a local
|
||||
// (loopback) host, such as "localhost" or "127.0.0.1:8080".
|
||||
func IsLocalHost(u *url.URL) bool {
|
||||
return isLocalHost(u)
|
||||
}
|
||||
|
@ -21,3 +21,5 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) {
|
||||
}
|
||||
|
||||
func openBrowser(url string) bool { return false }
|
||||
|
||||
func isLocalHost(u *urlpkg.URL) bool { return false }
|
||||
|
@ -255,3 +255,20 @@ func getFile(u *urlpkg.URL) (*Response, error) {
|
||||
}
|
||||
|
||||
func openBrowser(url string) bool { return browser.Open(url) }
|
||||
|
||||
func isLocalHost(u *urlpkg.URL) bool {
|
||||
// VCSTestRepoURL itself is secure, and it may redirect requests to other
|
||||
// ports (such as a port serving the "svn" protocol) which should also be
|
||||
// considered secure.
|
||||
host, _, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
host = u.Host
|
||||
}
|
||||
if host == "localhost" {
|
||||
return true
|
||||
}
|
||||
if ip := net.ParseIP(host); ip != nil && ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ import (
|
||||
"cmd/go/internal/cfg"
|
||||
"cmd/go/internal/script"
|
||||
"cmd/go/internal/script/scripttest"
|
||||
"cmd/go/internal/vcs"
|
||||
"cmd/go/internal/vcweb/vcstest"
|
||||
)
|
||||
|
||||
var testSum = flag.String("testsum", "", `may be tidy, listm, or listall. If set, TestScript generates a go.sum file at the beginning of each test and updates test files if they pass.`)
|
||||
@ -38,6 +40,16 @@ func TestScript(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
testenv.SkipIfShortAndSlow(t)
|
||||
|
||||
srv, err := vcstest.NewServer()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := srv.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
StartProxy()
|
||||
|
||||
var (
|
||||
@ -187,6 +199,7 @@ func scriptEnv() ([]string, error) {
|
||||
"GOROOT_FINAL=" + testGOROOT_FINAL, // causes spurious rebuilds and breaks the "stale" built-in if not propagated
|
||||
"GOTRACEBACK=system",
|
||||
"TESTGO_GOROOT=" + testGOROOT,
|
||||
"TESTGO_VCSTEST_URL=" + vcs.VCSTestRepoURL,
|
||||
"GOSUMDB=" + testSumDBVerifierKey,
|
||||
"GONOPROXY=",
|
||||
"GONOSUMDB=",
|
||||
|
40
src/cmd/go/testdata/script/reuse_git.txt
vendored
40
src/cmd/go/testdata/script/reuse_git.txt
vendored
@ -13,7 +13,7 @@ cp stdout hellopseudo.json
|
||||
! stdout '"(Query|TagPrefix|TagSum|Ref)"'
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
|
||||
go clean -modcache
|
||||
|
||||
@ -23,7 +23,7 @@ stderr 'git fetch'
|
||||
cp stdout hello.json
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
stdout '"Query": "latest"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
|
||||
@ -36,7 +36,7 @@ stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
|
||||
go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c
|
||||
! stderr 'git fetch'
|
||||
cp stdout hellopseudo2.json
|
||||
cmp hellopseudo.json hellopseudo2.json
|
||||
cmpenv hellopseudo.json hellopseudo2.json
|
||||
|
||||
# go mod download vcstest/hello@hash needs to check TagSum to find pseudoversion base.
|
||||
go mod download -x -json vcs-test.golang.org/git/hello.git@fc3a09f3dc5c
|
||||
@ -45,7 +45,7 @@ cp stdout hellohash.json
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"Query": "fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
|
||||
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
|
||||
|
||||
@ -100,7 +100,7 @@ cp stdout tagtests.json
|
||||
stdout '"Version": "v0.2.2"'
|
||||
stdout '"Query": "latest"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
|
||||
stdout '"Ref": "refs/tags/v0.2.2"'
|
||||
@ -112,7 +112,7 @@ cp stdout tagtestsv022.json
|
||||
stdout '"Version": "v0.2.2"'
|
||||
! stdout '"Query":'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
! stdout '"TagSum"'
|
||||
stdout '"Ref": "refs/tags/v0.2.2"'
|
||||
@ -124,7 +124,7 @@ cp stdout tagtestsmaster.json
|
||||
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
|
||||
stdout '"Query": "master"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
|
||||
stdout '"Ref": "refs/heads/master"'
|
||||
@ -137,7 +137,7 @@ cp stdout prefixtagtests.json
|
||||
stdout '"Version": "v0.0.10"'
|
||||
stdout '"Query": "latest"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/prefixtagtests"'
|
||||
stdout '"URL": ".*/git/prefixtagtests"'
|
||||
stdout '"Subdir": "sub"'
|
||||
stdout '"TagPrefix": "sub/"'
|
||||
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
|
||||
@ -160,7 +160,7 @@ go mod download -reuse=hello.json -x -json vcs-test.golang.org/git/hello.git@lat
|
||||
stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
|
||||
stdout '"Ref": "HEAD"'
|
||||
@ -176,7 +176,7 @@ go mod download -reuse=hellopseudo.json -x -json vcs-test.golang.org/git/hello.g
|
||||
stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
! stdout '"(Query|TagPrefix|TagSum|Ref)"'
|
||||
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
|
||||
! stdout '"(Dir|Info|GoMod|Zip)"'
|
||||
@ -188,7 +188,7 @@ stdout '"Reuse": true'
|
||||
stdout '"Query": "fc3a09f3dc5c"'
|
||||
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/hello"'
|
||||
stdout '"URL": ".*/git/hello"'
|
||||
! stdout '"(TagPrefix|Ref)"'
|
||||
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
|
||||
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
|
||||
@ -251,7 +251,7 @@ stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.2.2"'
|
||||
stdout '"Query": "latest"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
|
||||
stdout '"Ref": "refs/tags/v0.2.2"'
|
||||
@ -265,7 +265,7 @@ stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.2.2"'
|
||||
! stdout '"Query":'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
! stdout '"TagSum"'
|
||||
stdout '"Ref": "refs/tags/v0.2.2"'
|
||||
@ -279,7 +279,7 @@ stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
|
||||
stdout '"Query": "master"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
|
||||
stdout '"Ref": "refs/heads/master"'
|
||||
@ -293,7 +293,7 @@ stdout '"Reuse": true'
|
||||
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
|
||||
stdout '"Query": "master"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"TagPrefix"'
|
||||
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
|
||||
stdout '"Ref": "refs/heads/master"'
|
||||
@ -306,7 +306,7 @@ go mod download -reuse=prefixtagtests.json -x -json vcs-test.golang.org/git/pref
|
||||
stdout '"Version": "v0.0.10"'
|
||||
stdout '"Query": "latest"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/prefixtagtests"'
|
||||
stdout '"URL": ".*/git/prefixtagtests"'
|
||||
stdout '"Subdir": "sub"'
|
||||
stdout '"TagPrefix": "sub/"'
|
||||
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
|
||||
@ -329,7 +329,7 @@ stderr 'git fetch'
|
||||
stdout '"Version": "v0.2.2"'
|
||||
! stdout '"Query"'
|
||||
stdout '"VCS": "git"'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
! stdout '"(TagPrefix|TagSum)"'
|
||||
stdout '"Ref": "refs/tags/v0.2.2"'
|
||||
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
|
||||
@ -343,7 +343,7 @@ cp tagtestsv022.json tagtestsv022badurl.json
|
||||
replace 'git/tagtests\"' 'git/tagtestsXXX\"' tagtestsv022badurl.json
|
||||
go mod download -reuse=tagtestsv022badurl.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
|
||||
! stdout '"Reuse": true'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
stdout '"Dir"'
|
||||
stdout '"Info"'
|
||||
stdout '"GoMod"'
|
||||
@ -354,14 +354,14 @@ cp tagtestsv022.json tagtestsv022badvcs.json
|
||||
replace '\"git\"' '\"gitXXX\"' tagtestsv022badvcs.json
|
||||
go mod download -reuse=tagtestsv022badvcs.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
|
||||
! stdout '"Reuse": true'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
|
||||
# reuse with stale Dir
|
||||
cp tagtestsv022.json tagtestsv022baddir.json
|
||||
replace '\t\t\"Ref\":' '\t\t\"Subdir\": \"subdir\",\n\t\t\"Ref\":' tagtestsv022baddir.json
|
||||
go mod download -reuse=tagtestsv022baddir.json -x -json vcs-test.golang.org/git/tagtests.git@v0.2.2
|
||||
! stdout '"Reuse": true'
|
||||
stdout '"URL": "https://vcs-test.golang.org/git/tagtests"'
|
||||
stdout '"URL": ".*/git/tagtests"'
|
||||
|
||||
# reuse with stale TagSum
|
||||
cp tagtests.json tagtestsbadtagsum.json
|
||||
|
14
src/cmd/go/testdata/vcstest/README
vendored
Normal file
14
src/cmd/go/testdata/vcstest/README
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
The scripts in this directory set up version-control repos for use in
|
||||
tests of cmd/go and its subpackages.
|
||||
|
||||
They are written in a dialect of the same script language as in
|
||||
cmd/go/testdata/script, and the outputs are hosted by the server in
|
||||
cmd/go/internal/vcweb.
|
||||
|
||||
To see the conditions and commands available for these scripts, run:
|
||||
|
||||
go test cmd/go/internal/vcweb -v --run=TestHelp
|
||||
|
||||
To host these scripts in a standalone server, run:
|
||||
|
||||
go test cmd/go/internal/vcweb/vcstest -v --port=0
|
32
src/cmd/go/testdata/vcstest/bzr/hello.txt
vendored
Normal file
32
src/cmd/go/testdata/vcstest/bzr/hello.txt
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
handle bzr
|
||||
|
||||
env BZR_EMAIL='Russ Cox <rsc@google.com>'
|
||||
|
||||
bzr init-repo .
|
||||
|
||||
bzr init b
|
||||
cd b
|
||||
cp ../hello.go .
|
||||
bzr add hello.go
|
||||
bzr commit --commit-time='2017-09-21 21:20:12 -0400' -m 'hello world'
|
||||
bzr push ..
|
||||
cd ..
|
||||
rm b
|
||||
|
||||
bzr log
|
||||
cmp stdout .bzr-log
|
||||
|
||||
-- .bzr-log --
|
||||
------------------------------------------------------------
|
||||
revno: 1
|
||||
committer: Russ Cox <rsc@google.com>
|
||||
branch nick: b
|
||||
timestamp: Thu 2017-09-21 21:20:12 -0400
|
||||
message:
|
||||
hello world
|
||||
-- hello.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello, world")
|
||||
}
|
22
src/cmd/go/testdata/vcstest/fossil/hello.txt
vendored
Normal file
22
src/cmd/go/testdata/vcstest/fossil/hello.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
handle fossil
|
||||
|
||||
env USER=rsc
|
||||
fossil init --date-override 2017-09-22T01:15:36Z hello.fossil
|
||||
fossil open --keep hello.fossil
|
||||
|
||||
fossil add hello.go
|
||||
fossil commit --no-prompt --nosign --date-override 2017-09-22T01:19:07Z --comment 'hello world'
|
||||
|
||||
fossil timeline --oneline
|
||||
cmp stdout .fossil-timeline
|
||||
|
||||
-- .fossil-timeline --
|
||||
d4c7dcdc29 hello world
|
||||
58da0d15e9 initial empty check-in
|
||||
+++ no more data (2) +++
|
||||
-- hello.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello, world")
|
||||
}
|
39
src/cmd/go/testdata/vcstest/git/commit-after-tag.txt
vendored
Normal file
39
src/cmd/go/testdata/vcstest/git/commit-after-tag.txt
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-07-15T17:16:47-04:00
|
||||
git add go.mod main.go
|
||||
git commit -m 'all: add go.mod and main.go'
|
||||
git tag v1.0.0
|
||||
|
||||
at 2019-07-15T17:17:27-04:00
|
||||
cp _next/main.go main.go
|
||||
git add main.go
|
||||
git commit -m 'add init function'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
b325d82 (HEAD -> master) add init function
|
||||
8da67e0 (tag: v1.0.0) all: add go.mod and main.go
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/commit-after-tag.git
|
||||
|
||||
go 1.13
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
-- _next/main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
func init() {}
|
24
src/cmd/go/testdata/vcstest/git/empty-v2-without-v1.txt
vendored
Normal file
24
src/cmd/go/testdata/vcstest/git/empty-v2-without-v1.txt
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-10-07T14:15:32-04:00
|
||||
git add go.mod
|
||||
git commit -m 'add go.mod file without go source files'
|
||||
git tag v2.0.0
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
122733c (HEAD -> master, tag: v2.0.0) add go.mod file without go source files
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/empty-v2-without-v1.git/v2
|
||||
|
||||
go 1.14
|
21
src/cmd/go/testdata/vcstest/git/emptytest.txt
vendored
Normal file
21
src/cmd/go/testdata/vcstest/git/emptytest.txt
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-07-03T22:35:49-04:00
|
||||
git add go.mod
|
||||
git commit -m 'initial'
|
||||
|
||||
git log --oneline
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
7bb9146 initial
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/emptytest.git
|
67
src/cmd/go/testdata/vcstest/git/gitrepo1.txt
vendored
Normal file
67
src/cmd/go/testdata/vcstest/git/gitrepo1.txt
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-04-17T15:43:22-04:00
|
||||
unquote ''
|
||||
cp stdout README
|
||||
git add README
|
||||
git commit -a -m 'empty README'
|
||||
git tag v1.2.3
|
||||
|
||||
at 2018-04-17T15:45:48-04:00
|
||||
git branch -c v2
|
||||
git checkout v2
|
||||
echo 'v2'
|
||||
cp stdout v2
|
||||
git add v2
|
||||
git commit -a -m 'v2'
|
||||
git tag v2.3
|
||||
git tag v2.0.1
|
||||
git branch -c v2.3.4
|
||||
|
||||
at 2018-04-17T16:00:19-04:00
|
||||
echo 'intermediate'
|
||||
cp stdout foo.txt
|
||||
git add foo.txt
|
||||
git commit -a -m 'intermediate'
|
||||
|
||||
at 2018-04-17T16:00:32-04:00
|
||||
echo 'another'
|
||||
cp stdout another.txt
|
||||
git add another.txt
|
||||
git commit -a -m 'another'
|
||||
git tag v2.0.2
|
||||
|
||||
at 2018-04-17T16:16:52-04:00
|
||||
git branch -c master v3
|
||||
git checkout v3
|
||||
mkdir v3/sub/dir
|
||||
echo 'v3/sub/dir/file'
|
||||
cp stdout v3/sub/dir/file.txt
|
||||
git add v3
|
||||
git commit -a -m 'add v3/sub/dir/file.txt'
|
||||
|
||||
at 2018-04-17T22:23:00-04:00
|
||||
git checkout master
|
||||
git tag -a v1.2.4-annotated -m 'v1.2.4-annotated'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
ede458df7cd0fdca520df19a33158086a8a68e81 refs/heads/master
|
||||
9d02800338b8a55be062c838d1f02e0c5780b9eb refs/heads/v2
|
||||
76a00fb249b7f93091bc2c89a789dab1fc1bc26f refs/heads/v2.3.4
|
||||
a8205f853c297ad2c3c502ba9a355b35b7dd3ca5 refs/heads/v3
|
||||
ede458df7cd0fdca520df19a33158086a8a68e81 refs/tags/v1.2.3
|
||||
b004e48a345a86ed7a2fb7debfa7e0b2f9b0dd91 refs/tags/v1.2.4-annotated
|
||||
76a00fb249b7f93091bc2c89a789dab1fc1bc26f refs/tags/v2.0.1
|
||||
9d02800338b8a55be062c838d1f02e0c5780b9eb refs/tags/v2.0.2
|
||||
76a00fb249b7f93091bc2c89a789dab1fc1bc26f refs/tags/v2.3
|
25
src/cmd/go/testdata/vcstest/git/hello.txt
vendored
Normal file
25
src/cmd/go/testdata/vcstest/git/hello.txt
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME=bwk
|
||||
env GIT_AUTHOR_EMAIL=bwk
|
||||
env GIT_COMMITTER_NAME='Russ Cox'
|
||||
env GIT_COMMITTER_EMAIL='rsc@golang.org'
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2017-09-21T21:05:58-04:00
|
||||
git add hello.go
|
||||
git commit -a -m 'hello'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
fc3a09f (HEAD -> master) hello
|
||||
-- hello.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello, world")
|
||||
}
|
32
src/cmd/go/testdata/vcstest/git/insecurerepo.txt
vendored
Normal file
32
src/cmd/go/testdata/vcstest/git/insecurerepo.txt
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-04-03T13:30:35-04:00
|
||||
git add go.mod
|
||||
git commit -m 'all: initialize module'
|
||||
|
||||
at 2019-09-04T14:39:48-04:00
|
||||
git add main.go
|
||||
git commit -m 'main: add Go source file'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
6fecd21 (HEAD -> master) main: add Go source file
|
||||
d1a15cd all: initialize module
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/insecure/go/insecure
|
||||
|
||||
go 1.13
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
23
src/cmd/go/testdata/vcstest/git/mainonly.txt
vendored
Normal file
23
src/cmd/go/testdata/vcstest/git/mainonly.txt
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-09-05T14:07:43-04:00
|
||||
git add main.go
|
||||
git commit -a -m 'add main.go'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
8a27e8b (HEAD -> master) add main.go
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
10
src/cmd/go/testdata/vcstest/git/missingrepo.txt
vendored
Normal file
10
src/cmd/go/testdata/vcstest/git/missingrepo.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
handle dir
|
||||
|
||||
-- missingrepo-git/index.html --
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta name="go-import" content="vcs-test.golang.org/go/missingrepo/missingrepo-git git https://vcs-test.golang.org/git/missingrepo">
|
||||
-- missingrepo-git/notmissing/index.html --
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta name="go-import" content="vcs-test.golang.org/go/missingrepo/missingrepo-git/notmissing git https://vcs-test.golang.org/git/mainonly">
|
33
src/cmd/go/testdata/vcstest/git/modlegacy1-new.txt
vendored
Normal file
33
src/cmd/go/testdata/vcstest/git/modlegacy1-new.txt
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-04-25T11:00:57-04:00
|
||||
git add go.mod new.go p1 p2
|
||||
git commit -m 'initial commit'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
36cc50a (HEAD -> master) initial commit
|
||||
-- go.mod --
|
||||
module "vcs-test.golang.org/git/modlegacy1-new.git/v2"
|
||||
-- new.go --
|
||||
package new
|
||||
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-new.git/v2/p2"
|
||||
-- p1/p1.go --
|
||||
package p1
|
||||
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-old.git/p2"
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-new.git"
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-new.git/p2"
|
||||
-- p2/p2.go --
|
||||
package p2
|
27
src/cmd/go/testdata/vcstest/git/modlegacy1-old.txt
vendored
Normal file
27
src/cmd/go/testdata/vcstest/git/modlegacy1-old.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-04-25T10:59:24-04:00
|
||||
git add p1 p2
|
||||
git commit -m 'initial commit'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
6b4ba8b (HEAD -> master) initial commit
|
||||
-- p1/p1.go --
|
||||
package p1
|
||||
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-old.git/p2"
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-new.git/p1"
|
||||
import _ "vcs-test.golang.org/git/modlegacy1-new.git"
|
||||
-- p2/p2.go --
|
||||
package p2
|
27
src/cmd/go/testdata/vcstest/git/no-tags.txt
vendored
Normal file
27
src/cmd/go/testdata/vcstest/git/no-tags.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-07-15T17:20:47-04:00
|
||||
git add go.mod main.go
|
||||
git commit -m 'all: add go.mod and main.go'
|
||||
|
||||
git log --oneline --decorate=short
|
||||
cmp stdout .git-log
|
||||
|
||||
-- .git-log --
|
||||
e706ba1 (HEAD -> master) all: add go.mod and main.go
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/no-tags.git
|
||||
|
||||
go 1.13
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
48
src/cmd/go/testdata/vcstest/git/odd-tags.txt
vendored
Normal file
48
src/cmd/go/testdata/vcstest/git/odd-tags.txt
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
|
||||
at 2022-02-23T13:48:02-05:00
|
||||
git add README.txt
|
||||
git commit -m 'initial state'
|
||||
git tag 'v2.0.0+incompatible'
|
||||
|
||||
at 2022-02-23T13:48:35-05:00
|
||||
git rm -r README.txt
|
||||
git add go.mod
|
||||
git commit -m 'migrate to Go modules'
|
||||
git tag 'v0.1.0+build-metadata'
|
||||
|
||||
at 2022-02-23T14:41:55-05:00
|
||||
git branch -c v3-dev
|
||||
git checkout v3-dev
|
||||
cp v3/go.mod go.mod
|
||||
git commit go.mod -m 'update to /v3'
|
||||
git tag 'v3.0.0-20220223184802-12d19af20458'
|
||||
|
||||
git checkout main
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
9d863d525bbfcc8eda09364738c4032393711a56 refs/heads/main
|
||||
cce3d0f5d2ec85678cca3c45ac4a87f3be5efaca refs/heads/v3-dev
|
||||
9d863d525bbfcc8eda09364738c4032393711a56 refs/tags/v0.1.0+build-metadata
|
||||
12d19af204585b0db3d2a876ceddf5b9323f5a4a refs/tags/v2.0.0+incompatible
|
||||
cce3d0f5d2ec85678cca3c45ac4a87f3be5efaca refs/tags/v3.0.0-20220223184802-12d19af20458
|
||||
-- README.txt --
|
||||
This module lacks a go.mod file.
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/odd-tags.git
|
||||
|
||||
go 1.18
|
||||
-- v3/go.mod --
|
||||
module vcs-test.golang.org/git/odd-tags.git/v3
|
||||
|
||||
go 1.18
|
53
src/cmd/go/testdata/vcstest/git/prefixtagtests.txt
vendored
Normal file
53
src/cmd/go/testdata/vcstest/git/prefixtagtests.txt
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Jay Conrod'
|
||||
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
at 2019-05-09T18:35:00-04:00
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
git add sub
|
||||
git commit -m 'create module sub'
|
||||
|
||||
echo 'v0.1.0'
|
||||
cp stdout status
|
||||
git add status
|
||||
git commit -a -m 'v0.1.0'
|
||||
git tag 'v0.1.0'
|
||||
|
||||
echo 'sub/v0.0.9'
|
||||
cp stdout status
|
||||
git commit -a -m 'sub/v0.0.9'
|
||||
git tag 'sub/v0.0.9'
|
||||
|
||||
echo 'sub/v0.0.10'
|
||||
cp stdout status
|
||||
git commit -a -m 'sub/v0.0.10'
|
||||
git tag 'sub/v0.0.10'
|
||||
|
||||
echo 'v0.2.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'v0.2.0'
|
||||
git tag 'v0.2.0'
|
||||
|
||||
echo 'after last tag'
|
||||
cp stdout status
|
||||
git commit -a -m 'after last tag'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
c3ee5d0dfbb9bf3c4d8bb2bce24cd8d14d2d4238 refs/heads/master
|
||||
2b7c4692e12c109263cab51b416fcc835ddd7eae refs/tags/sub/v0.0.10
|
||||
883885166298d79a0561d571a3044ec5db2e7c28 refs/tags/sub/v0.0.9
|
||||
db89fc573cfb939faf0aa0660671eb4cf8b8b673 refs/tags/v0.1.0
|
||||
1abe41965749e50828dd41de8d12c6ebc8e4e131 refs/tags/v0.2.0
|
||||
-- sub/go.mod --
|
||||
module vcs-test.golang.org/git/prefixtagtests.git/sub
|
||||
-- sub/sub.go --
|
||||
package sub
|
273
src/cmd/go/testdata/vcstest/git/querytest.txt
vendored
Normal file
273
src/cmd/go/testdata/vcstest/git/querytest.txt
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-07-03T22:31:01-04:00
|
||||
git add go.mod
|
||||
git commit -a -m 'v1'
|
||||
git tag start
|
||||
|
||||
git branch -c v2
|
||||
|
||||
at 2018-07-03T22:33:47-04:00
|
||||
echo 'before v0.0.0-pre1'
|
||||
cp stdout status
|
||||
git add status
|
||||
git commit -a -m 'before v0.0.0-pre1'
|
||||
|
||||
echo 'at v0.0.0-pre1'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.0.0-pre1'
|
||||
git tag 'v0.0.0-pre1'
|
||||
|
||||
echo 'before v0.0.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.0.0'
|
||||
|
||||
echo 'at v0.0.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.0.0'
|
||||
git tag 'v0.0.0'
|
||||
|
||||
echo 'before v0.0.1'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.0.1'
|
||||
|
||||
echo 'at v0.0.1'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.0.1'
|
||||
git tag 'v0.0.1'
|
||||
|
||||
echo 'before v0.0.2'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.0.2'
|
||||
|
||||
echo 'at v0.0.2'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.0.2'
|
||||
git tag 'v0.0.2'
|
||||
|
||||
echo 'before v0.0.3'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.0.3'
|
||||
|
||||
echo 'at v0.0.3'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.0.3'
|
||||
git tag 'v0.0.3'
|
||||
git tag favorite
|
||||
|
||||
echo 'before v0.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.1.0'
|
||||
|
||||
echo 'at v0.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.1.0'
|
||||
git tag v0.1.0
|
||||
|
||||
echo 'before v0.1.1'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.1.1'
|
||||
|
||||
echo 'at v0.1.1'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.1.1'
|
||||
git tag 'v0.1.1'
|
||||
|
||||
echo 'before v0.1.2'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.1.2'
|
||||
|
||||
echo 'at v0.1.2'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.1.2'
|
||||
git tag 'v0.1.2'
|
||||
|
||||
echo 'before v0.3.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v0.3.0'
|
||||
|
||||
echo 'at v0.3.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v0.3.0'
|
||||
git tag 'v0.3.0'
|
||||
|
||||
echo 'before v1.0.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.0.0'
|
||||
|
||||
echo 'at v1.0.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.0.0'
|
||||
git tag 'v1.0.0'
|
||||
|
||||
echo 'before v1.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.1.0'
|
||||
|
||||
echo 'at v1.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.1.0'
|
||||
git tag 'v1.1.0'
|
||||
|
||||
echo 'before v1.9.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.9.0'
|
||||
|
||||
echo 'at v1.9.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.9.0'
|
||||
git tag 'v1.9.0'
|
||||
|
||||
echo 'before v1.9.9'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.9.9'
|
||||
|
||||
echo 'at v1.9.9'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.9.9'
|
||||
git tag 'v1.9.9'
|
||||
|
||||
at 2018-07-03T22:45:01-04:00
|
||||
echo 'before v1.9.10-pre1'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.9.10-pre1'
|
||||
|
||||
echo 'at v1.9.10-pre1'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.9.10-pre1'
|
||||
git tag 'v1.9.10-pre1'
|
||||
|
||||
at 2018-07-03T22:50:24-04:00
|
||||
git checkout v2
|
||||
cp v2/go.mod go.mod
|
||||
git add go.mod
|
||||
git commit -a -m 'v2'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'before v2.0.0'
|
||||
cp stdout status
|
||||
git add status
|
||||
git commit -a -m 'before v2.0.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'at v2.0.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v2.0.0'
|
||||
git tag 'v2.0.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'before v2.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v2.1.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'at v2.1.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v2.1.0'
|
||||
git tag 'v2.1.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'before v2.2.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v2.2.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'at v2.2.0'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v2.2.0'
|
||||
git tag 'v2.2.0'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'before v2.5.5'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v2.5.5'
|
||||
|
||||
at 2018-07-03T22:51:14-04:00
|
||||
echo 'at v2.5.5'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v2.5.5'
|
||||
git tag 'v2.5.5'
|
||||
|
||||
at 2018-07-03T23:35:18-04:00
|
||||
echo 'after v2.5.5'
|
||||
cp stdout status
|
||||
git commit -a -m 'after v2.5.5'
|
||||
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL=bcmills@google.com
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git checkout v2.5.5
|
||||
|
||||
at 2019-05-13T17:13:56-04:00
|
||||
echo 'before v2.6.0-pre1'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v2.6.0-pre1'
|
||||
|
||||
at 2019-05-13T17:13:56-04:00
|
||||
echo 'at v2.6.0-pre1'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v2.6.0-pre1'
|
||||
git tag 'v2.6.0-pre1'
|
||||
|
||||
git checkout master
|
||||
|
||||
at 2019-05-13T16:11:25-04:00
|
||||
echo 'before v1.9.10-pre2+metadata'
|
||||
cp stdout status
|
||||
git commit -a -m 'before v1.9.10-pre2+metadata'
|
||||
|
||||
at 2019-05-13T16:11:26-04:00
|
||||
echo 'at v1.9.10-pre2+metadata'
|
||||
cp stdout status
|
||||
git commit -a -m 'at v1.9.10-pre2+metadata'
|
||||
git tag 'v1.9.10-pre2+metadata'
|
||||
|
||||
at 2019-12-20T08:46:14-05:00
|
||||
echo 'after v1.9.10-pre2+metadata'
|
||||
cp stdout status
|
||||
git commit -a -m 'after v1.9.10-pre2+metadata'
|
||||
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
ed5ffdaa1f5e7e0be6f5ba2d63097026506224f2 refs/heads/master
|
||||
feed8f518cf4a7215a3b2a8268b8b0746dcbb12d refs/heads/v2
|
||||
f6abd4e3ed7f2297bc8fd2888bd6d5412e255fcc refs/tags/favorite
|
||||
5e9e31667ddfe16e9350f4bd00acc933c8cd5e56 refs/tags/start
|
||||
0de900e0063bcc310ea0621bfbc227a9b4e3b020 refs/tags/v0.0.0
|
||||
e5ec98b1c15df29e3bd346d538d73b6e8c3b500c refs/tags/v0.0.0-pre1
|
||||
179bc86b1be3f6d4553f77ebe68a8b6d750ceff8 refs/tags/v0.0.1
|
||||
81da2346e009fa1072fe4de3a9a223398ea8ec39 refs/tags/v0.0.2
|
||||
f6abd4e3ed7f2297bc8fd2888bd6d5412e255fcc refs/tags/v0.0.3
|
||||
7a1b6bf60ae5bb2b2bd49d152e0bbad806056122 refs/tags/v0.1.0
|
||||
daedca9abee3171fe45e0344098a993675ac799e refs/tags/v0.1.1
|
||||
ce829e0f1c45a2eca0f1ad16d7c1aca7cddb433b refs/tags/v0.1.2
|
||||
44aadfee25d86acb32d6f352afd1d602b0e3a651 refs/tags/v0.3.0
|
||||
20756d3a393908b2edb5db0f0bb954e962860168 refs/tags/v1.0.0
|
||||
b0bf267f64b7d5b5cabe22fbcad22f3f1642b7e5 refs/tags/v1.1.0
|
||||
609dca58c03f0ddf1d8ebe46c1f74fc6a99f3e73 refs/tags/v1.9.0
|
||||
e0cf3de987e660c21b6950e85b317ce5f7fbb9d9 refs/tags/v1.9.10-pre1
|
||||
42abcb6df8eee6983aeca9a307c28ea40530aceb refs/tags/v1.9.10-pre2+metadata
|
||||
5ba9a4ea62136ae86213feba68bc73858f55b7e1 refs/tags/v1.9.9
|
||||
9763aa065ae27c6cacec5ca8b6dfa43a1b31dea0 refs/tags/v2.0.0
|
||||
23c28cb696ff40a2839ce406f2c173aa6c3cdda6 refs/tags/v2.1.0
|
||||
1828ee9f8074075675013e4d488d5d49ddc1b502 refs/tags/v2.2.0
|
||||
d7352560158175e3b6aa11e22efb06d9e87e6eea refs/tags/v2.5.5
|
||||
fb9e35b393eb0cccc37e13e243ce60b4ff8c7eea refs/tags/v2.6.0-pre1
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/querytest.git
|
||||
-- v2/go.mod --
|
||||
module vcs-test.golang.org/git/querytest.git/v2
|
32
src/cmd/go/testdata/vcstest/git/retract-pseudo.txt
vendored
Normal file
32
src/cmd/go/testdata/vcstest/git/retract-pseudo.txt
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Jay Conrod'
|
||||
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
at 2020-10-09T13:37:47-04:00
|
||||
|
||||
git init
|
||||
|
||||
git add go.mod p.go
|
||||
git commit -m 'create module retract-pseudo'
|
||||
git tag v1.0.0
|
||||
|
||||
git mv p.go q.go
|
||||
git commit -m 'trivial change'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
713affd19d7b9b6dc876b603017f3dcaab8ba674 refs/heads/main
|
||||
64c061ed4371ef372b6bbfd58ee32015d6bfc3e5 refs/tags/v1.0.0
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/retract-pseudo.git
|
||||
|
||||
go 1.16
|
||||
|
||||
retract v1.0.0
|
||||
-- p.go --
|
||||
package p
|
52
src/cmd/go/testdata/vcstest/git/semver-branch.txt
vendored
Normal file
52
src/cmd/go/testdata/vcstest/git/semver-branch.txt
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
|
||||
at 2022-02-02T14:15:21-05:00
|
||||
git add pkg go.mod
|
||||
git commit -a -m 'pkg: add empty package'
|
||||
git tag 'v0.1.0'
|
||||
|
||||
at 2022-02-02T14:19:44-05:00
|
||||
git branch -c 'v1.0.0'
|
||||
git branch -c 'v2.0.0'
|
||||
git checkout 'v1.0.0'
|
||||
cp v1/pkg/pkg.go pkg/pkg.go
|
||||
git commit -a -m 'pkg: start developing toward v1.0.0'
|
||||
|
||||
at 2022-02-03T10:53:13-05:00
|
||||
git branch -c 'v3.0.0-devel'
|
||||
git checkout 'v3.0.0-devel'
|
||||
git checkout v0.1.0 pkg/pkg.go
|
||||
git commit -a -m 'pkg: remove panic'
|
||||
git tag v4.0.0-beta.1
|
||||
|
||||
git checkout main
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
33ea7ee36f3e3f44f528664b3712c9fa0cef7502 refs/heads/main
|
||||
09c4d8f6938c7b5eeae46858a72712b8700fa46a refs/heads/v1.0.0
|
||||
33ea7ee36f3e3f44f528664b3712c9fa0cef7502 refs/heads/v2.0.0
|
||||
d59622f6e4d77f008819083582fde71ea1921b0c refs/heads/v3.0.0-devel
|
||||
33ea7ee36f3e3f44f528664b3712c9fa0cef7502 refs/tags/v0.1.0
|
||||
d59622f6e4d77f008819083582fde71ea1921b0c refs/tags/v4.0.0-beta.1
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/semver-branch.git
|
||||
|
||||
go 1.16
|
||||
-- pkg/pkg.go --
|
||||
package pkg
|
||||
-- v1/pkg/pkg.go --
|
||||
package pkg
|
||||
|
||||
func init() {
|
||||
panic("TODO")
|
||||
}
|
44
src/cmd/go/testdata/vcstest/git/tagtests.txt
vendored
Normal file
44
src/cmd/go/testdata/vcstest/git/tagtests.txt
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Jay Conrod'
|
||||
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
at 2019-05-09T18:56:25-04:00
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
git add go.mod tagtests.go
|
||||
git commit -m 'create module tagtests'
|
||||
git branch -c b
|
||||
|
||||
git add v0.2.1
|
||||
git commit -m 'v0.2.1'
|
||||
git tag 'v0.2.1'
|
||||
|
||||
git checkout b
|
||||
git add 'v0.2.2'
|
||||
git commit -m 'v0.2.2'
|
||||
git tag 'v0.2.2'
|
||||
|
||||
git checkout master
|
||||
git merge b -m 'merge'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
59356c8cd18c5fe9a598167d98a6843e52d57952 refs/heads/b
|
||||
c7818c24fa2f3f714c67d0a6d3e411c85a518d1f refs/heads/master
|
||||
101c49f5af1b2466332158058cf5f03c8cca6429 refs/tags/v0.2.1
|
||||
59356c8cd18c5fe9a598167d98a6843e52d57952 refs/tags/v0.2.2
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/tagtests.git
|
||||
-- tagtests.go --
|
||||
package tagtests
|
||||
-- v0.2.1 --
|
||||
v0.2.1
|
||||
-- v0.2.2 --
|
||||
v0.2.2
|
26
src/cmd/go/testdata/vcstest/git/v2repo.txt
vendored
Normal file
26
src/cmd/go/testdata/vcstest/git/v2repo.txt
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-04-03T11:52:15-04:00
|
||||
env GIT_AUTHOR_DATE=2019-04-03T11:44:11-04:00
|
||||
git add go.mod
|
||||
git commit -m 'all: add go.mod'
|
||||
git tag 'v2.0.0'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
203b91c896acd173aa719e4cdcb7d463c4b090fa refs/heads/master
|
||||
203b91c896acd173aa719e4cdcb7d463c4b090fa refs/tags/v2.0.0
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/go/v2module/v2
|
||||
|
||||
go 1.12
|
34
src/cmd/go/testdata/vcstest/git/v2sub.txt
vendored
Normal file
34
src/cmd/go/testdata/vcstest/git/v2sub.txt
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
|
||||
at 2022-02-22T15:53:33-05:00
|
||||
git add v2sub.go v2
|
||||
git commit -m 'all: add package v2sub and v2sub/v2'
|
||||
git tag v2.0.0
|
||||
|
||||
at 2022-02-22T15:55:07-05:00
|
||||
git add README.txt
|
||||
git commit -m 'v2sub: add README.txt'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5 refs/heads/main
|
||||
5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b refs/tags/v2.0.0
|
||||
-- v2/go.mod --
|
||||
module vcs-test.golang.org/git/v2sub.git/v2
|
||||
|
||||
go 1.16
|
||||
-- v2/v2sub.go --
|
||||
package v2sub
|
||||
-- v2sub.go --
|
||||
package v2sub
|
||||
-- README.txt --
|
||||
This root module lacks a go.mod file.
|
28
src/cmd/go/testdata/vcstest/git/v3pkg.txt
vendored
Normal file
28
src/cmd/go/testdata/vcstest/git/v3pkg.txt
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Bryan C. Mills'
|
||||
env GIT_AUTHOR_EMAIL='bcmills@google.com'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2019-07-15T14:01:24-04:00
|
||||
env GIT_AUTHOR_DATE=2019-07-15T13:59:34-04:00
|
||||
git add go.mod v3pkg.go
|
||||
git commit -a -m 'all: add go.mod with v3 path'
|
||||
git tag 'v3.0.0'
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
a3eab1261b8e3164bcbde9171c23d5fd36e32a85 refs/heads/master
|
||||
a3eab1261b8e3164bcbde9171c23d5fd36e32a85 refs/tags/v3.0.0
|
||||
-- go.mod --
|
||||
module vcs-test.golang.org/git/v3pkg.git/v3
|
||||
|
||||
go 1.13
|
||||
-- v3pkg.go --
|
||||
package v3pkg
|
257
src/cmd/go/testdata/vcstest/git/vgotest1.txt
vendored
Normal file
257
src/cmd/go/testdata/vcstest/git/vgotest1.txt
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
handle git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-02-19T17:21:09-05:00
|
||||
git add LICENSE README.md
|
||||
git commit -m 'initial commit'
|
||||
|
||||
git checkout --detach HEAD
|
||||
|
||||
at 2018-02-19T18:10:06-05:00
|
||||
mkdir pkg
|
||||
echo 'package p // pkg/p.go'
|
||||
cp stdout pkg/p.go
|
||||
git add pkg/p.go
|
||||
git commit -m 'add pkg/p.go'
|
||||
git tag v0.0.0
|
||||
git tag v1.0.0
|
||||
git tag mytag
|
||||
|
||||
git checkout --detach HEAD
|
||||
|
||||
at 2018-02-19T18:14:23-05:00
|
||||
mkdir v2
|
||||
echo 'module "github.com/rsc/vgotest1/v2" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod v2'
|
||||
git tag v2.0.1
|
||||
|
||||
at 2018-02-19T18:15:11-05:00
|
||||
mkdir submod/pkg
|
||||
echo 'package p // submod/pkg/p.go'
|
||||
cp stdout submod/pkg/p.go
|
||||
git add submod/pkg/p.go
|
||||
git commit -m 'submod/pkg/p.go'
|
||||
git tag v2.0.2
|
||||
|
||||
at 2018-02-19T18:16:04-05:00
|
||||
echo 'module "github.com/rsc/vgotest" // v2/go.mod'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'v2/go.mod: bad go.mod (no version)'
|
||||
git tag v2.0.3
|
||||
|
||||
at 2018-02-19T19:03:38-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T18:16:38-05:00
|
||||
echo 'module "github.com/rsc/vgotest1/v2" // v2/go.mod'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'v2/go.mod: fix'
|
||||
git tag v2.0.4
|
||||
|
||||
at 2018-02-19T19:03:59-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T18:17:02-05:00
|
||||
echo 'module "github.com/rsc/vgotest1" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod: drop v2'
|
||||
git tag v2.0.5
|
||||
|
||||
git checkout --detach mytag
|
||||
|
||||
at 2018-02-19T18:10:28-05:00
|
||||
echo 'module "github.com/rsc/vgotest1" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod'
|
||||
git tag v0.0.1
|
||||
git tag v1.0.1
|
||||
|
||||
at 2018-02-19T18:11:28-05:00
|
||||
mkdir submod/pkg
|
||||
echo 'package pkg // submod/pkg/p.go'
|
||||
cp stdout submod/pkg/p.go
|
||||
git add submod
|
||||
git commit -m 'submod/pkg/p.go'
|
||||
git tag v1.0.2
|
||||
|
||||
at 2018-02-19T18:12:07-05:00
|
||||
echo 'module "github.com/vgotest1/submod" // submod/go.mod'
|
||||
cp stdout submod/go.mod
|
||||
git add submod/go.mod
|
||||
git commit -m 'submod/go.mod'
|
||||
git tag v1.0.3
|
||||
git tag submod/v1.0.4
|
||||
|
||||
at 2018-02-19T18:12:59-05:00
|
||||
git apply 0001-submod-go.mod-add-require-vgotest1-v1.1.0.patch
|
||||
git commit -a -m 'submod/go.mod: add require vgotest1 v1.1.0'
|
||||
git tag submod/v1.0.5
|
||||
|
||||
at 2018-02-19T18:13:36-05:00
|
||||
git apply 0002-go.mod-add-require-submod-v1.0.5.patch
|
||||
git commit -a -m 'go.mod: add require submod v1.0.5'
|
||||
git tag v1.1.0
|
||||
|
||||
git checkout master
|
||||
|
||||
at 2018-02-19T17:23:01-05:00
|
||||
mkdir pkg
|
||||
echo 'package pkg'
|
||||
cp stdout pkg/p.go
|
||||
git add pkg/p.go
|
||||
git commit -m 'pkg: add'
|
||||
|
||||
at 2018-02-19T17:30:23-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T17:24:48-05:00
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'add go.mod'
|
||||
|
||||
at 2018-02-19T17:30:45-05:00
|
||||
echo 'module "github.com/vgotest1"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'bad mod path'
|
||||
|
||||
at 2018-02-19T17:31:34-05:00
|
||||
mkdir v2
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'add v2/go.mod'
|
||||
|
||||
at 2018-02-19T17:32:37-05:00
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'say v2 in root go.mod'
|
||||
|
||||
git checkout --detach HEAD
|
||||
at 2018-02-19T17:51:24-05:00
|
||||
# README.md at this commit lacked a trailing newline, so 'git apply' can't
|
||||
# seem to apply it correctly as a patch. Instead, we use 'echo -e' to write
|
||||
# the exact contents.
|
||||
unquote 'This is a test repo for versioned go.\nThere''s nothing useful here.\n\n v0.0.0 - has pkg/p.go\n v0.0.1 - has go.mod\n \n v1.0.0 - has pkg/p.go\n v1.0.1 - has go.mod\n v1.0.2 - has submod/pkg/p.go\n v1.0.3 - has submod/go.mod\n submod/v1.0.4 - same\n submod/v1.0.5 - add requirement on v1.1.0\n v1.1.0 - add requirement on submod/v1.0.5\n \n v2.0.0 - has pkg/p.go\n v2.0.1 - has go.mod with v2 module path\n v2.0.2 - has go.mod with v1 (no version) module path\n v2.0.3 - has v2/go.mod with v2 module path\n v2.0.5 - has go.mod AND v2/go.mod with v2 module path\n '
|
||||
cp stdout README.md
|
||||
mkdir v2/pkg
|
||||
echo 'package q'
|
||||
cp stdout v2/pkg/q.go
|
||||
git add README.md v2/pkg/q.go
|
||||
git commit -m 'add q'
|
||||
git tag v2.0.6
|
||||
|
||||
git checkout --detach mytag~1
|
||||
at 2018-07-18T21:21:27-04:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T18:10:06-05:00
|
||||
mkdir pkg
|
||||
echo 'package p // pkg/p.go'
|
||||
cp stdout pkg/p.go
|
||||
git add pkg/p.go
|
||||
unquote 'add pkg/p.go\n\nv2\n'
|
||||
cp stdout COMMIT_MSG
|
||||
git commit -F COMMIT_MSG
|
||||
git tag v2.0.0
|
||||
|
||||
git checkout master
|
||||
|
||||
git show-ref --tags --heads
|
||||
cmp stdout .git-refs
|
||||
|
||||
-- .git-refs --
|
||||
a08abb797a6764035a9314ed5f1d757e0224f3bf refs/heads/master
|
||||
80d85c5d4d17598a0e9055e7c175a32b415d6128 refs/tags/mytag
|
||||
8afe2b2efed96e0880ecd2a69b98a53b8c2738b6 refs/tags/submod/v1.0.4
|
||||
70fd92eaa4dacf82548d0c6099f5b853ae2c1fc8 refs/tags/submod/v1.0.5
|
||||
80d85c5d4d17598a0e9055e7c175a32b415d6128 refs/tags/v0.0.0
|
||||
5a115c66393dd8c4a5cc3215653850d7f5640d0e refs/tags/v0.0.1
|
||||
80d85c5d4d17598a0e9055e7c175a32b415d6128 refs/tags/v1.0.0
|
||||
5a115c66393dd8c4a5cc3215653850d7f5640d0e refs/tags/v1.0.1
|
||||
2e38a1a347ba4d9e9946ec0ce480710ff445c919 refs/tags/v1.0.2
|
||||
8afe2b2efed96e0880ecd2a69b98a53b8c2738b6 refs/tags/v1.0.3
|
||||
b769f2de407a4db81af9c5de0a06016d60d2ea09 refs/tags/v1.1.0
|
||||
45f53230a74ad275c7127e117ac46914c8126160 refs/tags/v2.0.0
|
||||
ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9 refs/tags/v2.0.1
|
||||
f7b23352af1cd750b11e4673b20b24c2d239430a refs/tags/v2.0.2
|
||||
f18795870fb14388a21ef3ebc1d75911c8694f31 refs/tags/v2.0.3
|
||||
1f863feb76bc7029b78b21c5375644838962f88d refs/tags/v2.0.4
|
||||
2f615117ce481c8efef46e0cc0b4b4dccfac8fea refs/tags/v2.0.5
|
||||
a01a0aef06cbd571294fc5451788cd4eadbfd651 refs/tags/v2.0.6
|
||||
-- LICENSE --
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-- README.md --
|
||||
This is a test repo for versioned go.
|
||||
There's nothing useful here.
|
||||
-- 0001-submod-go.mod-add-require-vgotest1-v1.1.0.patch --
|
||||
From 70fd92eaa4dacf82548d0c6099f5b853ae2c1fc8 Mon Sep 17 00:00:00 2001
|
||||
From: Russ Cox <rsc@golang.org>
|
||||
Date: Mon, 19 Feb 2018 18:12:59 -0500
|
||||
Subject: [PATCH] submod/go.mod: add require vgotest1 v1.1.0
|
||||
|
||||
---
|
||||
submod/go.mod | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/submod/go.mod b/submod/go.mod
|
||||
index 7b18d93..c88de0f 100644
|
||||
--- a/submod/go.mod
|
||||
+++ b/submod/go.mod
|
||||
@@ -1 +1,2 @@
|
||||
module "github.com/vgotest1/submod" // submod/go.mod
|
||||
+require "github.com/vgotest1" v1.1.0
|
||||
--
|
||||
2.36.1.838.g23b219f8e3
|
||||
-- 0002-go.mod-add-require-submod-v1.0.5.patch --
|
||||
From b769f2de407a4db81af9c5de0a06016d60d2ea09 Mon Sep 17 00:00:00 2001
|
||||
From: Russ Cox <rsc@golang.org>
|
||||
Date: Mon, 19 Feb 2018 18:13:36 -0500
|
||||
Subject: [PATCH] go.mod: add require submod v1.0.5
|
||||
|
||||
---
|
||||
go.mod | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/go.mod b/go.mod
|
||||
index ac7a6d7..6118671 100644
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1 +1,2 @@
|
||||
module "github.com/rsc/vgotest1" // root go.mod
|
||||
+require "github.com/rsc/vgotest1/submod" v1.0.5
|
||||
--
|
||||
2.36.1.838.g23b219f8e3
|
17
src/cmd/go/testdata/vcstest/hg/custom-hg-hello.txt
vendored
Normal file
17
src/cmd/go/testdata/vcstest/hg/custom-hg-hello.txt
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
handle hg
|
||||
hg init
|
||||
|
||||
hg add hello.go
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2017-10-10T19:39:36-04:00' --message 'hello'
|
||||
|
||||
hg log -r ':' --template '{node|short} {desc|strip|firstline}\n'
|
||||
cmp stdout .hg-log
|
||||
|
||||
-- .hg-log --
|
||||
a8c8e7a40da9 hello
|
||||
-- hello.go --
|
||||
package main // import "vcs-test.golang.org/go/custom-hg-hello"
|
||||
|
||||
func main() {
|
||||
println("hello")
|
||||
}
|
17
src/cmd/go/testdata/vcstest/hg/hello.txt
vendored
Normal file
17
src/cmd/go/testdata/vcstest/hg/hello.txt
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
handle hg
|
||||
hg init
|
||||
|
||||
hg add hello.go
|
||||
hg commit --user 'bwk' --date '2017-09-21T21:14:14-04:00' --message 'hello world'
|
||||
|
||||
hg log -r ':' --template '{node|short} {desc|strip|firstline}\n'
|
||||
cmp stdout .hg-log
|
||||
|
||||
-- .hg-log --
|
||||
e483a7d9f8c9 hello world
|
||||
-- hello.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello, world")
|
||||
}
|
138
src/cmd/go/testdata/vcstest/hg/hgrepo1.txt
vendored
Normal file
138
src/cmd/go/testdata/vcstest/hg/hgrepo1.txt
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
handle hg
|
||||
|
||||
mkdir git
|
||||
cd git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
at 2018-04-17T15:43:22-04:00
|
||||
unquote ''
|
||||
cp stdout README
|
||||
git add README
|
||||
git commit -a -m 'empty README'
|
||||
git tag v1.2.3
|
||||
|
||||
at 2018-04-17T15:45:48-04:00
|
||||
git branch -c v2
|
||||
git checkout v2
|
||||
echo 'v2'
|
||||
cp stdout v2
|
||||
git add v2
|
||||
git commit -a -m 'v2'
|
||||
git tag v2.3
|
||||
git tag v2.0.1
|
||||
git branch -c v2.3.4
|
||||
git tag branch-v2.3.4
|
||||
|
||||
at 2018-04-17T16:00:19-04:00
|
||||
echo 'intermediate'
|
||||
cp stdout foo.txt
|
||||
git add foo.txt
|
||||
git commit -a -m 'intermediate'
|
||||
|
||||
at 2018-04-17T16:00:32-04:00
|
||||
echo 'another'
|
||||
cp stdout another.txt
|
||||
git add another.txt
|
||||
git commit -a -m 'another'
|
||||
git tag v2.0.2
|
||||
git tag branch-v2
|
||||
|
||||
at 2018-04-17T16:16:52-04:00
|
||||
git branch -c master v3
|
||||
git checkout v3
|
||||
mkdir v3/sub/dir
|
||||
echo 'v3/sub/dir/file'
|
||||
cp stdout v3/sub/dir/file.txt
|
||||
git add v3
|
||||
git commit -a -m 'add v3/sub/dir/file.txt'
|
||||
git tag branch-v3
|
||||
|
||||
at 2018-04-17T22:23:00-04:00
|
||||
git checkout master
|
||||
git tag -a v1.2.4-annotated -m 'v1.2.4-annotated'
|
||||
|
||||
cd ..
|
||||
|
||||
hg init
|
||||
hg convert --datesort ./git .
|
||||
rm ./git
|
||||
|
||||
hg update -C v2
|
||||
hg branch v2
|
||||
unquote ''
|
||||
cp stdout dummy
|
||||
hg add dummy
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2018-06-27T12:15:24-04:00' -m 'dummy'
|
||||
|
||||
# 'hg convert' blindly stamps a tag-update commit at the end of whatever branch
|
||||
# happened to contain the last converted commit — in this case, v3. However, the
|
||||
# original vcs-test.golang.org copy of this repo had this commit on the v3
|
||||
# branch as a descendent of 'add v3/sub/dir/file.txt', so that's where we put it
|
||||
# here. That leaves the convert-repo 'update tags' commit only reachable as the
|
||||
# head of the default branch.
|
||||
hg update -r 4
|
||||
|
||||
hg branch v3
|
||||
unquote ''
|
||||
cp stdout dummy
|
||||
hg add dummy
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2018-06-27T12:15:45-04:00' -m 'dummy'
|
||||
|
||||
hg update v2.3.4
|
||||
hg branch v2.3.4
|
||||
unquote ''
|
||||
cp stdout dummy
|
||||
hg add dummy
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2018-06-27T12:16:10-04:00' -m 'dummy'
|
||||
|
||||
hg tag --user 'Russ Cox <rsc@golang.org>' --date '2018-06-27T12:16:30-04:00' -m 'Removed tag branch-v2, branch-v3, branch-v2.3.4' --remove branch-v2 branch-v3 branch-v2.3.4
|
||||
|
||||
# Adding commits to the above branches updates both the branch heads and the
|
||||
# corresponding bookmarks.
|
||||
# But apparently at some point it did not do so? The original copy of this repo
|
||||
# had bookmarks pointing to the base of each branch instead of the tip. 🤔
|
||||
# Either way, force the bookmarks we care about to match the original copy of
|
||||
# the repo.
|
||||
hg book v2 -r 3 --force
|
||||
hg book v2.3.4 -r 1 --force
|
||||
hg book v3 -r 5 --force
|
||||
|
||||
hg log -G --debug
|
||||
|
||||
hg tags
|
||||
cmp stdout .hg-tags
|
||||
|
||||
# 'hg convert' leaves an 'update tags' commit on the default branch, and that
|
||||
# commit always uses the current date (so is not reproducible). Fortunately,
|
||||
# that commit lands on the 'default' branch and is not tagged as 'tip', so it
|
||||
# seems to be mostly harmless. However, because it is nondeterministic we
|
||||
# should avoid listing it here.
|
||||
hg branches -r 6 -r 7 -r 9
|
||||
cmp stdout .hg-branches
|
||||
|
||||
# Likewise, omit bookmark v3, which ends up on the nondeterministic commit.
|
||||
hg bookmarks -l master v2 v2.3.4
|
||||
cmp stdout .hg-bookmarks
|
||||
|
||||
-- .hg-branches --
|
||||
v2.3.4 9:18518c07eb8e
|
||||
v3 7:a2cad8a2b1bb
|
||||
v2 6:9a4f43d231ec
|
||||
-- .hg-tags --
|
||||
tip 9:18518c07eb8e
|
||||
v2.0.2 3:8f49ee7a6ddc
|
||||
v2.3 1:88fde824ec8b
|
||||
v2.0.1 1:88fde824ec8b
|
||||
v1.2.4-annotated 0:41964ddce118
|
||||
v1.2.3 0:41964ddce118
|
||||
-- .hg-bookmarks --
|
||||
master 0:41964ddce118
|
||||
v2 3:8f49ee7a6ddc
|
||||
v2.3.4 1:88fde824ec8b
|
322
src/cmd/go/testdata/vcstest/hg/vgotest1.txt
vendored
Normal file
322
src/cmd/go/testdata/vcstest/hg/vgotest1.txt
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
handle hg
|
||||
|
||||
cd git
|
||||
|
||||
env GIT_AUTHOR_NAME='Russ Cox'
|
||||
env GIT_AUTHOR_EMAIL='rsc@golang.org'
|
||||
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
|
||||
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
|
||||
|
||||
git init
|
||||
git branch -m master
|
||||
|
||||
# 0
|
||||
at 2018-02-19T17:21:09-05:00
|
||||
git add LICENSE README.md
|
||||
git commit -m 'initial commit'
|
||||
|
||||
# 1
|
||||
git branch -c mybranch
|
||||
git checkout mybranch
|
||||
|
||||
at 2018-02-19T18:10:06-05:00
|
||||
mkdir pkg
|
||||
echo 'package p // pkg/p.go'
|
||||
cp stdout pkg/p.go
|
||||
git add pkg/p.go
|
||||
git commit -m 'add pkg/p.go'
|
||||
git tag v0.0.0
|
||||
git tag v1.0.0
|
||||
git tag v2.0.0
|
||||
git tag mytag
|
||||
|
||||
git branch -c v1
|
||||
git branch -c v2
|
||||
git checkout v2
|
||||
|
||||
# 2
|
||||
at 2018-02-19T18:14:23-05:00
|
||||
mkdir v2
|
||||
echo 'module "github.com/rsc/vgotest1/v2" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod v2'
|
||||
git tag v2.0.1
|
||||
|
||||
# 3
|
||||
at 2018-02-19T18:15:11-05:00
|
||||
mkdir submod/pkg
|
||||
echo 'package p // submod/pkg/p.go'
|
||||
cp stdout submod/pkg/p.go
|
||||
git add submod/pkg/p.go
|
||||
git commit -m 'submod/pkg/p.go'
|
||||
git tag v2.0.2
|
||||
|
||||
# 4
|
||||
at 2018-02-19T18:16:04-05:00
|
||||
echo 'module "github.com/rsc/vgotest" // v2/go.mod'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'v2/go.mod: bad go.mod (no version)'
|
||||
git tag v2.0.3
|
||||
|
||||
# 5
|
||||
at 2018-02-19T19:03:38-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T18:16:38-05:00
|
||||
echo 'module "github.com/rsc/vgotest1/v2" // v2/go.mod'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'v2/go.mod: fix'
|
||||
git tag v2.0.4
|
||||
|
||||
# 6
|
||||
at 2018-02-19T19:03:59-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T18:17:02-05:00
|
||||
echo 'module "github.com/rsc/vgotest1" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod: drop v2'
|
||||
git tag v2.0.5
|
||||
|
||||
git checkout v1
|
||||
|
||||
# 7
|
||||
at 2018-02-19T18:10:28-05:00
|
||||
echo 'module "github.com/rsc/vgotest1" // root go.mod'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'go.mod'
|
||||
git tag v0.0.1
|
||||
git tag v1.0.1
|
||||
|
||||
# 8
|
||||
at 2018-02-19T18:11:28-05:00
|
||||
mkdir submod/pkg
|
||||
echo 'package pkg // submod/pkg/p.go'
|
||||
cp stdout submod/pkg/p.go
|
||||
git add submod
|
||||
git commit -m 'submod/pkg/p.go'
|
||||
git tag v1.0.2
|
||||
|
||||
# 9
|
||||
at 2018-02-19T18:12:07-05:00
|
||||
echo 'module "github.com/vgotest1/submod" // submod/go.mod'
|
||||
cp stdout submod/go.mod
|
||||
git add submod/go.mod
|
||||
git commit -m 'submod/go.mod'
|
||||
git tag v1.0.3
|
||||
git tag submod/v1.0.4
|
||||
|
||||
# 10
|
||||
at 2018-02-19T18:12:59-05:00
|
||||
git apply ../0001-submod-go.mod-add-require-vgotest1-v1.1.0.patch
|
||||
git commit -a -m 'submod/go.mod: add require vgotest1 v1.1.0'
|
||||
git tag submod/v1.0.5
|
||||
|
||||
# 11
|
||||
at 2018-02-19T18:13:36-05:00
|
||||
git apply ../0002-go.mod-add-require-submod-v1.0.5.patch
|
||||
git commit -a -m 'go.mod: add require submod v1.0.5'
|
||||
git tag v1.1.0
|
||||
|
||||
git checkout master
|
||||
|
||||
# 12
|
||||
at 2018-02-19T17:23:01-05:00
|
||||
mkdir pkg
|
||||
echo 'package pkg'
|
||||
cp stdout pkg/p.go
|
||||
git add pkg/p.go
|
||||
git commit -m 'pkg: add'
|
||||
|
||||
# 13
|
||||
at 2018-02-19T17:30:23-05:00
|
||||
env GIT_AUTHOR_DATE=2018-02-19T17:24:48-05:00
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'add go.mod'
|
||||
|
||||
# 14
|
||||
at 2018-02-19T17:30:45-05:00
|
||||
echo 'module "github.com/vgotest1"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'bad mod path'
|
||||
|
||||
# 15
|
||||
at 2018-02-19T17:31:34-05:00
|
||||
mkdir v2
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout v2/go.mod
|
||||
git add v2/go.mod
|
||||
git commit -m 'add v2/go.mod'
|
||||
|
||||
# 16
|
||||
at 2018-02-19T17:32:37-05:00
|
||||
echo 'module "github.com/vgotest1/v2"'
|
||||
cp stdout go.mod
|
||||
git add go.mod
|
||||
git commit -m 'say v2 in root go.mod'
|
||||
|
||||
# 17
|
||||
at 2018-02-19T17:51:24-05:00
|
||||
# README.md at this commit lacked a trailing newline, so 'git apply' can't
|
||||
# seem to apply it correctly as a patch. Instead, we use 'unquote' to write
|
||||
# the exact contents.
|
||||
unquote 'This is a test repo for versioned go.\nThere''s nothing useful here.\n\n v0.0.0 - has pkg/p.go\n v0.0.1 - has go.mod\n \n v1.0.0 - has pkg/p.go\n v1.0.1 - has go.mod\n v1.0.2 - has submod/pkg/p.go\n v1.0.3 - has submod/go.mod\n submod/v1.0.4 - same\n submod/v1.0.5 - add requirement on v1.1.0\n v1.1.0 - add requirement on submod/v1.0.5\n \n v2.0.0 - has pkg/p.go\n v2.0.1 - has go.mod with v2 module path\n v2.0.2 - has go.mod with v1 (no version) module path\n v2.0.3 - has v2/go.mod with v2 module path\n v2.0.5 - has go.mod AND v2/go.mod with v2 module path\n '
|
||||
cp stdout README.md
|
||||
mkdir v2/pkg
|
||||
echo 'package q'
|
||||
cp stdout v2/pkg/q.go
|
||||
git add README.md v2/pkg/q.go
|
||||
git commit -m 'add q'
|
||||
git tag v2.0.6
|
||||
|
||||
cd ..
|
||||
|
||||
hg init
|
||||
hg convert ./git .
|
||||
rm ./git
|
||||
|
||||
# Note: commit #18 is an 'update tags' commit automatically generated by 'hg
|
||||
# convert'. We have no control over its timestamp, so it and its descendent
|
||||
# commit #19 both end up with unpredictable commit hashes.
|
||||
#
|
||||
# Fortunately, these commits don't seem to matter for the purpose of reproducing
|
||||
# the final branches and heads from the original copy of this repo.
|
||||
|
||||
# 19
|
||||
hg update -C -r 18
|
||||
hg tag --user 'Russ Cox <rsc@golang.org>' --date '2018-07-18T21:24:45-04:00' -m 'Removed tag v2.0.0' --remove v2.0.0
|
||||
|
||||
# 20
|
||||
hg branch default
|
||||
hg update -C -r 1
|
||||
echo 'v2'
|
||||
cp stdout v2
|
||||
hg add v2
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2018-07-18T21:25:08-04:00' -m 'v2.0.0'
|
||||
|
||||
# 21
|
||||
hg tag --user 'Russ Cox <rsc@golang.org>' --date '2018-07-18T21:25:13-04:00' -r f0ababb31f75 -m 'Added tag v2.0.0 for changeset f0ababb31f75' v2.0.0
|
||||
|
||||
# 22
|
||||
hg tag --user 'Russ Cox <rsc@golang.org>' --date '2018-07-18T21:26:02-04:00' -m 'Removed tag v2.0.0' --remove v2.0.0
|
||||
|
||||
# 23
|
||||
hg update -C -r 1
|
||||
echo 'v2'
|
||||
cp stdout v2
|
||||
hg add v2
|
||||
hg commit --user 'Russ Cox <rsc@golang.org>' --date '2018-07-19T01:21:27+00:00' -m 'v2'
|
||||
|
||||
# 24
|
||||
hg tag --user 'Russ Cox <rsc@golang.org>' --date '2018-07-18T21:26:33-04:00' -m 'Added tag v2.0.0 for changeset 814fce58e83a' -r 814fce58e83a v2.0.0
|
||||
|
||||
hg book --delete v1
|
||||
hg book --delete v2
|
||||
hg book --force -r 16 master
|
||||
|
||||
hg log -G --debug
|
||||
|
||||
hg tags
|
||||
cmp stdout .hg-tags
|
||||
hg branches
|
||||
cmp stdout .hg-branches
|
||||
hg bookmarks -l master mybranch
|
||||
cmp stdout .hg-bookmarks
|
||||
|
||||
-- .hg-tags --
|
||||
tip 24:645b06ca536d
|
||||
v2.0.0 23:814fce58e83a
|
||||
v2.0.6 17:3d4b89a2d059
|
||||
v1.1.0 11:92c7eb888b4f
|
||||
submod/v1.0.5 10:f3f560a6065c
|
||||
v1.0.3 9:4e58084d459a
|
||||
submod/v1.0.4 9:4e58084d459a
|
||||
v1.0.2 8:3ccdce3897f9
|
||||
v1.0.1 7:7890ea771ced
|
||||
v0.0.1 7:7890ea771ced
|
||||
v2.0.5 6:879ea98f7743
|
||||
v2.0.4 5:bf6388016230
|
||||
v2.0.3 4:a9ad6d1d14eb
|
||||
v2.0.2 3:de3663002f0f
|
||||
v2.0.1 2:f1fc0f22021b
|
||||
v1.0.0 1:e125018e286a
|
||||
v0.0.0 1:e125018e286a
|
||||
mytag 1:e125018e286a
|
||||
-- .hg-branches --
|
||||
default 24:645b06ca536d
|
||||
-- .hg-bookmarks --
|
||||
master 16:577bde103b24
|
||||
mybranch 1:e125018e286a
|
||||
-- git/LICENSE --
|
||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-- git/README.md --
|
||||
This is a test repo for versioned go.
|
||||
There's nothing useful here.
|
||||
-- 0001-submod-go.mod-add-require-vgotest1-v1.1.0.patch --
|
||||
From 70fd92eaa4dacf82548d0c6099f5b853ae2c1fc8 Mon Sep 17 00:00:00 2001
|
||||
From: Russ Cox <rsc@golang.org>
|
||||
Date: Mon, 19 Feb 2018 18:12:59 -0500
|
||||
Subject: [PATCH] submod/go.mod: add require vgotest1 v1.1.0
|
||||
|
||||
---
|
||||
submod/go.mod | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/submod/go.mod b/submod/go.mod
|
||||
index 7b18d93..c88de0f 100644
|
||||
--- a/submod/go.mod
|
||||
+++ b/submod/go.mod
|
||||
@@ -1 +1,2 @@
|
||||
module "github.com/vgotest1/submod" // submod/go.mod
|
||||
+require "github.com/vgotest1" v1.1.0
|
||||
--
|
||||
2.36.1.838.g23b219f8e3
|
||||
-- 0002-go.mod-add-require-submod-v1.0.5.patch --
|
||||
From b769f2de407a4db81af9c5de0a06016d60d2ea09 Mon Sep 17 00:00:00 2001
|
||||
From: Russ Cox <rsc@golang.org>
|
||||
Date: Mon, 19 Feb 2018 18:13:36 -0500
|
||||
Subject: [PATCH] go.mod: add require submod v1.0.5
|
||||
|
||||
---
|
||||
go.mod | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/go.mod b/go.mod
|
||||
index ac7a6d7..6118671 100644
|
||||
--- a/go.mod
|
||||
+++ b/go.mod
|
||||
@@ -1 +1,2 @@
|
||||
module "github.com/rsc/vgotest1" // root go.mod
|
||||
+require "github.com/rsc/vgotest1/submod" v1.0.5
|
||||
--
|
||||
2.36.1.838.g23b219f8e3
|
Loading…
Reference in New Issue
Block a user