mirror of
https://github.com/caddyserver/xcaddy.git
synced 2025-01-22 08:36:28 +01:00
Support go.mod replace version pinning (#27)
* support go.mod replace version pinning * use string replace instead of regex * Minor cleanups Co-authored-by: Matthew Holt <mholt@users.noreply.github.com>
This commit is contained in:
parent
1fec98156c
commit
b7fd102f41
4 changed files with 120 additions and 17 deletions
25
builder.go
25
builder.go
|
@ -140,13 +140,34 @@ type Dependency struct {
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReplacementPath represents an old or new path component
|
||||||
|
// within a Go module replacement directive.
|
||||||
|
type ReplacementPath string
|
||||||
|
|
||||||
|
// Param reformats a go.mod replace directive to be
|
||||||
|
// compatible with the `go mod edit` command.
|
||||||
|
func (r ReplacementPath) Param() string {
|
||||||
|
return strings.Replace(string(r), " ", "@", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ReplacementPath) String() string { return string(r) }
|
||||||
|
|
||||||
// Replace represents a Go module replacement.
|
// Replace represents a Go module replacement.
|
||||||
type Replace struct {
|
type Replace struct {
|
||||||
// The import path of the module being replaced.
|
// The import path of the module being replaced.
|
||||||
Old string `json:"old,omitempty"`
|
Old ReplacementPath `json:"old,omitempty"`
|
||||||
|
|
||||||
// The path to the replacement module.
|
// The path to the replacement module.
|
||||||
New string `json:"new,omitempty"`
|
New ReplacementPath `json:"new,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReplace creates a new instance of Replace provided old and
|
||||||
|
// new Go module paths
|
||||||
|
func NewReplace(old, new string) Replace {
|
||||||
|
return Replace{
|
||||||
|
Old: ReplacementPath(old),
|
||||||
|
New: ReplacementPath(new),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newTempFolder creates a new folder in a temporary location.
|
// newTempFolder creates a new folder in a temporary location.
|
||||||
|
|
88
builder_test.go
Normal file
88
builder_test.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2020 Matthew Holt
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package xcaddy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReplacementPath_Param(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
r ReplacementPath
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Empty",
|
||||||
|
ReplacementPath(""),
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ModulePath",
|
||||||
|
ReplacementPath("github.com/x/y"),
|
||||||
|
"github.com/x/y",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ModulePath Version Pinned",
|
||||||
|
ReplacementPath("github.com/x/y v0.0.0-20200101000000-xxxxxxxxxxxx"),
|
||||||
|
"github.com/x/y@v0.0.0-20200101000000-xxxxxxxxxxxx",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FilePath",
|
||||||
|
ReplacementPath("/x/y/z"),
|
||||||
|
"/x/y/z",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
fmt.Println(tt.r.Param())
|
||||||
|
if got := tt.r.Param(); got != tt.want {
|
||||||
|
t.Errorf("ReplacementPath.Param() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewReplace(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
old string
|
||||||
|
new string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want Replace
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Empty",
|
||||||
|
args{"", ""},
|
||||||
|
Replace{"", ""},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Constructor",
|
||||||
|
args{"a", "b"},
|
||||||
|
Replace{"a", "b"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := NewReplace(tt.args.old, tt.args.new); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("NewReplace() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,10 +74,7 @@ func runBuild(ctx context.Context, args []string) error {
|
||||||
Version: ver,
|
Version: ver,
|
||||||
})
|
})
|
||||||
if repl != "" {
|
if repl != "" {
|
||||||
replacements = append(replacements, xcaddy.Replace{
|
replacements = append(replacements, xcaddy.NewReplace(mod, repl))
|
||||||
Old: mod,
|
|
||||||
New: repl,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "--output":
|
case "--output":
|
||||||
|
@ -168,10 +165,7 @@ func runDev(ctx context.Context, args []string) error {
|
||||||
// make sure the module being developed is replaced
|
// make sure the module being developed is replaced
|
||||||
// so that the local copy is used
|
// so that the local copy is used
|
||||||
replacements := []xcaddy.Replace{
|
replacements := []xcaddy.Replace{
|
||||||
{
|
xcaddy.NewReplace(currentModule, moduleDir),
|
||||||
Old: currentModule,
|
|
||||||
New: moduleDir,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace directives only apply to the top-level/main go.mod,
|
// replace directives only apply to the top-level/main go.mod,
|
||||||
|
@ -189,10 +183,10 @@ func runDev(ctx context.Context, args []string) error {
|
||||||
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
|
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
replacements = append(replacements, xcaddy.Replace{
|
replacements = append(replacements, xcaddy.NewReplace(
|
||||||
Old: strings.TrimSpace(parts[0]),
|
strings.TrimSpace(parts[0]),
|
||||||
New: strings.TrimSpace(parts[1]),
|
strings.TrimSpace(parts[1]),
|
||||||
})
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconcile remaining path segments; for example if a module foo/a
|
// reconcile remaining path segments; for example if a module foo/a
|
||||||
|
|
|
@ -109,14 +109,14 @@ func (b Builder) newEnvironment(ctx context.Context) (*environment, error) {
|
||||||
// specify module replacements before pinning versions
|
// specify module replacements before pinning versions
|
||||||
replaced := make(map[string]string)
|
replaced := make(map[string]string)
|
||||||
for _, r := range b.Replacements {
|
for _, r := range b.Replacements {
|
||||||
log.Printf("[INFO] Replace %s => %s", r.Old, r.New)
|
log.Printf("[INFO] Replace %s => %s", r.Old.String(), r.New.String())
|
||||||
cmd := env.newCommand("go", "mod", "edit",
|
cmd := env.newCommand("go", "mod", "edit",
|
||||||
"-replace", fmt.Sprintf("%s=%s", r.Old, r.New))
|
"-replace", fmt.Sprintf("%s=%s", r.Old.Param(), r.New.Param()))
|
||||||
err := env.runCommand(ctx, cmd, 10*time.Second)
|
err := env.runCommand(ctx, cmd, 10*time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
replaced[r.Old] = r.New
|
replaced[r.Old.String()] = r.New.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for early abort
|
// check for early abort
|
||||||
|
|
Loading…
Reference in a new issue