vendor: update all dependencies to latest versions
This commit is contained in:
+397
@@ -0,0 +1,397 @@
|
||||
// +build go1.9
|
||||
|
||||
// Copyright 2017 Microsoft Corporation and contributors
|
||||
//
|
||||
// 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.
|
||||
|
||||
// profileBuilder creates a series of packages filled entirely with alias types
|
||||
// and functions supporting those alias types by directing traffic to the
|
||||
// functions supporting the original types. This is useful associating a series
|
||||
// of packages in separate API Versions for easier/safer use.
|
||||
//
|
||||
// The Azure-SDK-for-Go teams intends to use this tool to generated profiles
|
||||
// that we will publish in this repository for general use. However, this tool
|
||||
// in the case that one has their own list of Services at given API Versions,
|
||||
// this may prove to be a useful tool for you.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/marstr/collection"
|
||||
goalias "github.com/marstr/goalias/model"
|
||||
"github.com/marstr/randname"
|
||||
)
|
||||
|
||||
var (
|
||||
profileName string
|
||||
outputLocation string
|
||||
inputRoot string
|
||||
inputList io.Reader
|
||||
packageStrategy collection.Enumerable
|
||||
outputLog *log.Logger
|
||||
errLog *log.Logger
|
||||
)
|
||||
|
||||
// WellKnownStrategy is an Enumerable which lists all known strategies for choosing packages for a profile.
|
||||
type WellKnownStrategy string
|
||||
|
||||
// This block declares the definitive list of WellKnownStrategies
|
||||
const (
|
||||
WellKnownStrategyList WellKnownStrategy = "list"
|
||||
WellKnownStrategyLatest WellKnownStrategy = "latest"
|
||||
WellKnownStrategyPreview WellKnownStrategy = "preview"
|
||||
)
|
||||
|
||||
const armPathModifier = "mgmt"
|
||||
|
||||
// If not the empty string, this string should be stamped into files generated by the profileBuilder.
|
||||
// Note: This variable should be set by passing the argument "-X main.version=`{your value}`" to the Go linker. example: `go build -ldflags "-X main.version=f43d726b6e3f1e3eb7cbdba3982f0253000d5dc5"`
|
||||
var version string
|
||||
|
||||
func main() {
|
||||
var packages collection.Enumerator
|
||||
|
||||
type alias struct {
|
||||
*goalias.AliasPackage
|
||||
TargetPath string
|
||||
}
|
||||
|
||||
// Find the names of all of the packages for inclusion in this profile.
|
||||
packages = packageStrategy.Enumerate(nil).Select(func(x interface{}) interface{} {
|
||||
if cast, ok := x.(string); ok {
|
||||
return cast
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// Parse the packages that were selected for inclusion in this profile.
|
||||
packages = packages.SelectMany(func(x interface{}) collection.Enumerator {
|
||||
results := make(chan interface{})
|
||||
|
||||
go func() {
|
||||
defer close(results)
|
||||
|
||||
cast, ok := x.(string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
files := token.NewFileSet()
|
||||
parsed, err := parser.ParseDir(files, cast, nil, 0)
|
||||
if err != nil {
|
||||
errLog.Printf("Couldn't open %q because: %v", cast, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, entry := range parsed {
|
||||
results <- entry
|
||||
}
|
||||
}()
|
||||
|
||||
return results
|
||||
})
|
||||
|
||||
// Generate the alias package from the originally parsed one.
|
||||
packages = packages.ParallelSelect(func(x interface{}) interface{} {
|
||||
var err error
|
||||
var subject *goalias.AliasPackage
|
||||
cast, ok := x.(*ast.Package)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
var bundle alias
|
||||
for filename := range cast.Files {
|
||||
bundle.TargetPath = filepath.Dir(filename)
|
||||
bundle.TargetPath = trimGoPath(bundle.TargetPath)
|
||||
subject, err = goalias.NewAliasPackage(cast, bundle.TargetPath)
|
||||
if err != nil {
|
||||
errLog.Print(err)
|
||||
return nil
|
||||
}
|
||||
bundle.TargetPath, err = getAliasPath(bundle.TargetPath, profileName)
|
||||
if err != nil {
|
||||
errLog.Print(err)
|
||||
return nil
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
bundle.AliasPackage = subject
|
||||
return &bundle
|
||||
})
|
||||
packages = packages.Where(func(x interface{}) bool {
|
||||
return x != nil
|
||||
})
|
||||
|
||||
// Update the "UserAgent" function in the generated profile, if it is present.
|
||||
packages = packages.Select(func(x interface{}) interface{} {
|
||||
cast := x.(*alias)
|
||||
|
||||
var userAgent *ast.FuncDecl
|
||||
|
||||
// Grab all functions in the alias package named "UserAgent"
|
||||
userAgentCandidates := collection.Where(collection.AsEnumerable(cast.Files["models.go"].Decls), func(x interface{}) bool {
|
||||
cast, ok := x.(*ast.FuncDecl)
|
||||
return ok && cast.Name.Name == "UserAgent"
|
||||
})
|
||||
|
||||
// There should really only be one of them, otherwise bailout because we don't understand the world anymore.
|
||||
candidate, err := collection.Single(userAgentCandidates)
|
||||
if err != nil {
|
||||
return x
|
||||
}
|
||||
userAgent, ok := candidate.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
return x
|
||||
}
|
||||
|
||||
// Grab the expression being returned.
|
||||
retResults := &userAgent.Body.List[0].(*ast.ReturnStmt).Results[0]
|
||||
|
||||
// Append a string literal to the result
|
||||
updated := &ast.BinaryExpr{
|
||||
Op: token.ADD,
|
||||
X: *retResults,
|
||||
Y: &ast.BasicLit{
|
||||
Value: fmt.Sprintf("\" profiles/%s\"", profileName),
|
||||
},
|
||||
}
|
||||
|
||||
*retResults = updated
|
||||
return x
|
||||
})
|
||||
|
||||
// Add the MSFT Copyright Header, then write the alias package to disk.
|
||||
products := packages.ParallelSelect(func(x interface{}) interface{} {
|
||||
cast, ok := x.(*alias)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
files := token.NewFileSet()
|
||||
|
||||
outputPath := filepath.Join(outputLocation, cast.TargetPath, "models.go")
|
||||
outputPath = strings.Replace(outputPath, `\`, `/`, -1)
|
||||
err := os.MkdirAll(path.Dir(outputPath), os.ModePerm|os.ModeDir)
|
||||
if err != nil {
|
||||
errLog.Print("error creating directory:", err)
|
||||
return false
|
||||
}
|
||||
|
||||
outputFile, err := os.Create(outputPath)
|
||||
if err != nil {
|
||||
errLog.Print("error creating file: ", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: This should really be added by the `goalias` package itself. Doing it here is a work around
|
||||
fmt.Fprintln(outputFile, "// +build go1.9")
|
||||
fmt.Fprintln(outputFile)
|
||||
|
||||
generatorStampBuilder := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(generatorStampBuilder, "// Copyright %4d Microsoft Corporation\n", time.Now().Year())
|
||||
fmt.Fprintln(generatorStampBuilder, `//
|
||||
// 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.`)
|
||||
|
||||
fmt.Fprintln(outputFile, generatorStampBuilder.String())
|
||||
|
||||
generatorStampBuilder.Reset()
|
||||
|
||||
fmt.Fprintln(generatorStampBuilder, "// This code was auto-generated by:")
|
||||
fmt.Fprintln(generatorStampBuilder, "// github.com/Azure/azure-sdk-for-go/tools/profileBuilder")
|
||||
|
||||
if version != "" {
|
||||
fmt.Fprintln(generatorStampBuilder, "// commit ID:", version)
|
||||
}
|
||||
fmt.Fprintln(generatorStampBuilder)
|
||||
fmt.Fprint(outputFile, generatorStampBuilder.String())
|
||||
|
||||
outputLog.Printf("Writing File: %s", outputPath)
|
||||
printer.Fprint(outputFile, files, cast.ModelFile())
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
generated := 0
|
||||
|
||||
// Write each aliased package that was found
|
||||
for entry := range products {
|
||||
if entry.(bool) {
|
||||
generated++
|
||||
}
|
||||
}
|
||||
outputLog.Print(generated, " packages generated.")
|
||||
|
||||
if err := exec.Command("gofmt", "-w", outputLocation).Run(); err == nil {
|
||||
outputLog.Print("Success formatting profile.")
|
||||
} else {
|
||||
errLog.Print("Trouble formatting profile: ", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
const defaultName = "{randomly generated}"
|
||||
|
||||
var selectedStrategy string
|
||||
var inputListLocation string
|
||||
var useVerbose bool
|
||||
|
||||
flag.StringVar(&profileName, "name", defaultName, "The name that should be given to the generated profile.")
|
||||
flag.StringVar(&outputLocation, "o", defaultOutputLocation(), "The output location for the package generated as a profile.")
|
||||
flag.StringVar(&inputRoot, "root", defaultInputRoot(), "The location of the Azure SDK for Go's service packages.")
|
||||
flag.StringVar(&inputListLocation, "l", "", "If the `list` strategy is chosen, -l is the location of the file to read for said list. If not present, stdin is used.")
|
||||
flag.StringVar(&selectedStrategy, "s", string(WellKnownStrategyLatest), "The strategy to employ for finding packages to put in a profile.")
|
||||
flag.BoolVar(&useVerbose, "v", false, "Write status to stderr as the program progresses")
|
||||
flag.Parse()
|
||||
|
||||
// Setup Verbose Status Log and Error Log
|
||||
var logWriter io.Writer
|
||||
if useVerbose {
|
||||
logWriter = os.Stderr
|
||||
} else {
|
||||
logWriter = ioutil.Discard
|
||||
}
|
||||
outputLog = log.New(logWriter, "[STATUS] ", 0)
|
||||
outputLog.Print("Status Logging Enabled")
|
||||
|
||||
errLog = log.New(logWriter, "[ERROR] ", 0)
|
||||
|
||||
if version != "" {
|
||||
outputLog.Print("profileBuilder Version: ", version)
|
||||
}
|
||||
|
||||
// Sort out the Profile Name to be used.
|
||||
if profileName == defaultName {
|
||||
profileName = randname.AdjNoun{}.Generate()
|
||||
outputLog.Print("Profile Name Set to: ", profileName)
|
||||
}
|
||||
|
||||
inputList = os.Stdin
|
||||
if inputListLocation == "" {
|
||||
outputLog.Print("Reading input from standard input")
|
||||
} else {
|
||||
var err error
|
||||
outputLog.Print("Reading input from: ", inputListLocation)
|
||||
inputList, err = os.Open(inputListLocation)
|
||||
if err != nil {
|
||||
errLog.Print(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
wellKnownStrategies := map[WellKnownStrategy]collection.Enumerable{
|
||||
WellKnownStrategyList: ListStrategy{Reader: inputList},
|
||||
WellKnownStrategyLatest: LatestStrategy{Root: inputRoot, Predicate: IgnorePreview, VerboseOutput: outputLog},
|
||||
WellKnownStrategyPreview: LatestStrategy{Root: inputRoot, Predicate: AcceptAll},
|
||||
}
|
||||
|
||||
if s, ok := wellKnownStrategies[WellKnownStrategy(selectedStrategy)]; ok {
|
||||
packageStrategy = s
|
||||
outputLog.Printf("Using Well Known Strategy: %s", selectedStrategy)
|
||||
} else {
|
||||
errLog.Printf("Unknown strategy for identifying packages: %s\n", selectedStrategy)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// AzureSDKforGoLocation returns the default location for the Azure-SDK-for-Go to reside.
|
||||
func AzureSDKforGoLocation() string {
|
||||
return path.Join(
|
||||
os.Getenv("GOPATH"),
|
||||
"src",
|
||||
"github.com",
|
||||
"Azure",
|
||||
"azure-sdk-for-go",
|
||||
)
|
||||
}
|
||||
|
||||
func defaultOutputLocation() string {
|
||||
return path.Join(AzureSDKforGoLocation(), "profiles")
|
||||
}
|
||||
|
||||
func defaultInputRoot() string {
|
||||
return path.Join(AzureSDKforGoLocation(), "services")
|
||||
}
|
||||
|
||||
// getAliasPath takes an existing API Version path and a package name, and converts the path
|
||||
// to a path which uses the new profile layout.
|
||||
func getAliasPath(subject, profile string) (transformed string, err error) {
|
||||
subject = strings.TrimSuffix(subject, "/")
|
||||
subject = trimGoPath(subject)
|
||||
|
||||
matches := packageName.FindAllStringSubmatch(subject, -1)
|
||||
if matches == nil {
|
||||
err = errors.New("path does not resemble a known package path")
|
||||
return
|
||||
}
|
||||
|
||||
output := []string{
|
||||
profile,
|
||||
matches[0][1],
|
||||
}
|
||||
|
||||
if matches[0][2] == armPathModifier {
|
||||
output = append(output, armPathModifier)
|
||||
}
|
||||
|
||||
output = append(output, matches[0][4])
|
||||
|
||||
transformed = strings.Join(output, "/")
|
||||
return
|
||||
}
|
||||
|
||||
// trimGoPath removes the prefix defined in the environment variabe GOPATH if it is present in the string provided.
|
||||
var trimGoPath = func() func(string) string {
|
||||
splitGo := strings.Split(os.Getenv("GOPATH"), string(os.PathSeparator))
|
||||
splitGo = append(splitGo, "src")
|
||||
|
||||
return func(subject string) string {
|
||||
splitPath := strings.Split(subject, string(os.PathSeparator))
|
||||
for i, dir := range splitGo {
|
||||
if splitPath[i] != dir {
|
||||
return subject
|
||||
}
|
||||
}
|
||||
packageIdentifier := splitPath[len(splitGo):]
|
||||
return path.Join(packageIdentifier...)
|
||||
}
|
||||
}()
|
||||
Reference in New Issue
Block a user