1// Copyright (c) Microsoft Corporation. All rights reserved. 2// Licensed under the MIT License. See License.txt in the project root for license information. 3 4package automation 5 6import ( 7 "fmt" 8 "log" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/Azure/azure-sdk-for-go/tools/generator/autorest" 14 "github.com/Azure/azure-sdk-for-go/tools/generator/autorest/model" 15 "github.com/Azure/azure-sdk-for-go/tools/generator/cmd/automation/validate" 16 "github.com/Azure/azure-sdk-for-go/tools/internal/exports" 17 "github.com/Azure/azure-sdk-for-go/tools/internal/utils" 18) 19 20type generateContext struct { 21 sdkRoot string 22 specRoot string 23 commitHash string 24 25 repoContent map[string]exports.Content 26 27 existingPackages packagesForReadme 28 defaultOptions model.Options 29 additionalOptions []model.Option 30} 31 32func (ctx generateContext) SDKRoot() string { 33 return ctx.sdkRoot 34} 35 36func (ctx generateContext) SpecRoot() string { 37 return ctx.specRoot 38} 39 40func (ctx generateContext) RepoContent() map[string]exports.Content { 41 return ctx.repoContent 42} 43 44var _ autorest.GenerateContext = (*generateContext)(nil) 45 46func (ctx generateContext) generate(readme string) ([]autorest.GenerateResult, []error) { 47 absReadme := filepath.Join(ctx.specRoot, readme) 48 absReadmeGo := filepath.Join(filepath.Dir(absReadme), "readme.go.md") 49 log.Printf("Reading tags from readme.go.md '%s'...", absReadmeGo) 50 reader, err := os.Open(absReadmeGo) 51 if err != nil { 52 return nil, []error{ 53 fmt.Errorf("cannot read from readme.go.md: %+v", err), 54 } 55 } 56 log.Printf("Parsing tags from readme.go.md '%s'...", absReadmeGo) 57 tags, err := autorest.ReadBatchTags(reader) 58 if err != nil { 59 return nil, []error{ 60 fmt.Errorf("cannot read batch tags in readme.go.md '%s': %+v", absReadmeGo, err), 61 } 62 } 63 64 log.Printf("Cleaning all the packages from readme '%s'...", readme) 65 removedPackages, err := clean(ctx.sdkRoot, ctx.existingPackages) 66 if err != nil { 67 return nil, []error{ 68 fmt.Errorf("cannot clean packages from readme '%s': %+v", readme, err), 69 } 70 } 71 72 log.Printf("Generating the following tags: \n[%s]", strings.Join(tags, ", ")) 73 var packageResults []autorest.GenerateResult 74 var errors []error 75 for _, tag := range tags { 76 result, err := ctx.generateForTag(readme, tag) 77 if err != nil { 78 errors = append(errors, err) 79 continue 80 } 81 packageResults = append(packageResults, *result) 82 } 83 84 // also add the removed packages in the results if it is not regenerated 85 for _, removedPackage := range removedPackages { 86 if !contains(packageResults, removedPackage.packageName) { 87 // this package is not regenerated, therefore it is removed 88 packageResults = append(packageResults, autorest.GenerateResult{ 89 Package: autorest.ChangelogResult{ 90 Tag: removedPackage.Tag, 91 PackageName: removedPackage.packageName, 92 PackageFullPath: utils.NormalizePath(filepath.Join(ctx.sdkRoot, removedPackage.packageName)), 93 Changelog: model.Changelog{ 94 RemovedPackage: true, 95 }, 96 }, 97 }) 98 } 99 } 100 101 return packageResults, errors 102} 103 104func (ctx generateContext) generateForTag(readme, tag string) (*autorest.GenerateResult, error) { 105 var options model.Options 106 // Get the proper options to use depending on whether this tag has been already generated in the SDK or not 107 if metadata, ok := ctx.existingPackages[tag]; ok { 108 // this tag has been generated, use the existing parameters in its metadata 109 additionalOptions, err := model.ParseOptions(strings.Split(metadata.AdditionalProperties.AdditionalOptions, " ")) 110 if err != nil { 111 return nil, fmt.Errorf("cannot parse existing defaultOptions for readme '%s'/tag '%s': %+v", readme, tag, err) 112 } 113 options = ctx.defaultOptions.MergeOptions(additionalOptions.Arguments()...) 114 } else { 115 // this is a new tag 116 options = ctx.defaultOptions.MergeOptions(ctx.additionalOptions...) 117 } 118 119 input := autorest.GenerateInput{ 120 Readme: readme, 121 Tag: tag, 122 CommitHash: ctx.commitHash, 123 Options: options, 124 } 125 validateCtx := validate.MetadataValidateContext{ 126 Readme: readme, 127 SDKRoot: ctx.sdkRoot, 128 } 129 return autorest.GeneratePackage(ctx, input, autorest.GenerateOptions{ 130 Stderr: os.Stderr, 131 Stdout: os.Stdout, 132 AutoRestLogPrefix: "[AUTOREST] ", 133 ChangelogTitle: "Unreleased", 134 Validators: []autorest.MetadataValidateFunc{ 135 validateCtx.PreviewCheck, 136 validateCtx.MgmtCheck, 137 validateCtx.NamespaceCheck, 138 }, 139 }) 140} 141