Skip to content

Commit 8420234

Browse files
authored
Go rewrite copy comments script (#11715)
1 parent a0ffcbb commit 8420234

File tree

277 files changed

+1524
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

277 files changed

+1524
-8
lines changed

mmv1/description-copy.go

+279-6
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,287 @@ func CopyAllDescriptions(tempMode bool) {
2222
"attributes:",
2323
}
2424

25-
for i, id := range identifiers {
26-
CopyText(id, len(identifiers)-1 == i, tempMode)
25+
for _, id := range identifiers {
26+
CopyText(id, tempMode)
2727
}
28+
29+
copyComments(tempMode)
30+
}
31+
32+
// TODO rewrite: ServicePerimeters.yaml is an exeption and needs manually fixing the comments over after switchover
33+
// Used to copy/paste comments from Ruby -> Go YAML files
34+
func copyComments(tempMode bool) {
35+
log.Printf("Starting to copy comments from Ruby yaml files to Go yaml files")
36+
37+
renamedFields := map[string]string{
38+
"skip_sweeper": "exclude_sweeper",
39+
"skip_delete": "exclude_delete",
40+
"skip_test": "exclude_test",
41+
"skip_import_test": "exclude_import_test",
42+
"skip_docs": "exclude_docs",
43+
"skip_attribution_label": "exclude_attribution_label",
44+
"skip_read": "exclude_read",
45+
"skip_default_cdiff": "exclude_default_cdiff",
46+
"skip_docs_values": "skip_docs_values",
47+
"values": "enum_values",
48+
}
49+
var allProductFiles []string = make([]string, 0)
50+
glob := "products/**/go_product.yaml"
51+
if tempMode {
52+
glob = "products/**/*.temp"
53+
}
54+
files, err := filepath.Glob(glob)
55+
if err != nil {
56+
return
57+
}
58+
for _, filePath := range files {
59+
dir := filepath.Dir(filePath)
60+
allProductFiles = append(allProductFiles, fmt.Sprintf("products/%s", filepath.Base(dir)))
61+
}
62+
63+
for _, productPath := range allProductFiles {
64+
// Gather go and ruby file pairs
65+
yamlMap := make(map[string][]string)
66+
yamlPaths, err := filepath.Glob(fmt.Sprintf("%s/*", productPath))
67+
if err != nil {
68+
log.Fatalf("Cannot get yaml files: %v", err)
69+
}
70+
for _, yamlPath := range yamlPaths {
71+
if strings.HasSuffix(yamlPath, "_new") {
72+
continue
73+
}
74+
75+
if tempMode {
76+
cutName, found := strings.CutSuffix(yamlPath, ".temp")
77+
if !found {
78+
continue
79+
}
80+
81+
baseName := filepath.Base(yamlPath)
82+
yamlMap[baseName] = make([]string, 2)
83+
yamlMap[baseName][1] = yamlPath
84+
yamlMap[baseName][0] = cutName
85+
continue
86+
}
87+
88+
fileName := filepath.Base(yamlPath)
89+
baseName, found := strings.CutPrefix(fileName, "go_")
90+
if yamlMap[baseName] == nil {
91+
yamlMap[baseName] = make([]string, 2)
92+
}
93+
if found {
94+
yamlMap[baseName][1] = yamlPath
95+
} else {
96+
yamlMap[baseName][0] = yamlPath
97+
}
98+
}
99+
100+
for _, files := range yamlMap {
101+
rubyPath := files[0]
102+
goPath := files[1]
103+
104+
recordingComments := false
105+
comments := ""
106+
commentsMap := make(map[string]string, 0)
107+
nestedNameLine := ""
108+
previousNameLine := ""
109+
trimmedPreviousLine := ""
110+
111+
// Ready Ruby yaml
112+
wholeLineComment, err := regexp.Compile(`^\s*#.*?`)
113+
if err != nil {
114+
log.Fatalf("Cannot compile the regular expression: %v", err)
115+
}
116+
117+
if err != nil {
118+
log.Fatalf("Cannot compile the regular expression: %v", err)
119+
}
120+
121+
file, _ := os.Open(rubyPath)
122+
defer file.Close()
123+
scanner := bufio.NewScanner(file)
124+
for scanner.Scan() {
125+
line := scanner.Text()
126+
if line == "" {
127+
if recordingComments {
128+
comments = fmt.Sprintf("%s\n%s", comments, line)
129+
}
130+
continue
131+
}
132+
133+
if wholeLineComment.MatchString(line) {
134+
if !recordingComments {
135+
recordingComments = true
136+
comments = line
137+
} else {
138+
comments = fmt.Sprintf("%s\n%s", comments, line)
139+
}
140+
} else {
141+
normalizedLine := line
142+
143+
indexOfComment := strings.Index(normalizedLine, " # ")
144+
if indexOfComment > 0 { // The comments are in the same line with the code
145+
comments = normalizedLine[indexOfComment:]
146+
recordingComments = true
147+
normalizedLine = strings.TrimRight(normalizedLine[:indexOfComment], " ")
148+
}
149+
150+
normalizedLine = strings.ReplaceAll(normalizedLine, "'", "")
151+
normalizedLine = strings.ReplaceAll(normalizedLine, `"`, "")
152+
normalizedLine = strings.ReplaceAll(normalizedLine, `\`, "")
153+
normalizedLine = strings.ReplaceAll(normalizedLine, ": :", ": ")
154+
normalizedLine = strings.ReplaceAll(normalizedLine, "- :", "- ")
155+
trimmed := strings.TrimSpace(normalizedLine)
156+
index := strings.Index(normalizedLine, trimmed)
157+
158+
if index == 0 {
159+
previousNameLine = ""
160+
nestedNameLine = ""
161+
} else if index >= 2 && (strings.HasPrefix(trimmedPreviousLine, "- !ruby/object") || strings.HasPrefix(trimmedPreviousLine, "--- !ruby/object")) {
162+
normalizedLine = fmt.Sprintf("%s- %s", normalizedLine[:index-2], normalizedLine[index:])
163+
164+
if strings.HasPrefix(trimmed, "name:") {
165+
if nestedNameLine != "" {
166+
previousNameLine = nestedNameLine
167+
}
168+
nestedNameLine = normalizedLine
169+
}
170+
}
171+
172+
trimmedPreviousLine = trimmed
173+
174+
if recordingComments {
175+
if !strings.HasPrefix(comments, "# Copyright") {
176+
// The line is a type, for example - !ruby/object:Api::Type::Array.
177+
// The lines of types are not present in Go yaml files
178+
if strings.HasPrefix(trimmed, "- !ruby/object") || strings.HasPrefix(trimmed, "--- !ruby/object") {
179+
continue
180+
}
181+
182+
// Remove suffix " !ruby/object" as the types are not present in Go yaml files
183+
indexOfRuby := strings.Index(normalizedLine, ": !ruby/object")
184+
if indexOfRuby >= 0 {
185+
normalizedLine = normalizedLine[:indexOfRuby+1]
186+
}
187+
// Remove suffix Api::Type::
188+
indexOfRuby = strings.Index(normalizedLine, " Api::Type::")
189+
if indexOfRuby >= 0 {
190+
normalizedLine = normalizedLine[:indexOfRuby]
191+
}
192+
193+
// Some fields are renamed during yaml file conversion
194+
field := strings.Split(normalizedLine, ":")[0]
195+
if shouldUseFieldName(normalizedLine) {
196+
normalizedLine = field
197+
}
198+
199+
field = strings.TrimSpace(field)
200+
if goName, ok := renamedFields[field]; ok {
201+
normalizedLine = strings.Replace(normalizedLine, field, goName, 1)
202+
}
203+
204+
key := fmt.Sprintf("%s$%s$%s", previousNameLine, nestedNameLine, normalizedLine)
205+
commentsMap[key] = comments
206+
}
207+
recordingComments = false
208+
comments = ""
209+
}
210+
}
211+
}
212+
213+
// Read Go yaml while writing to a temp file
214+
firstLine := true
215+
nestedNameLine = ""
216+
previousNameLine = ""
217+
newFilePath := fmt.Sprintf("%s_new", goPath)
218+
fo, _ := os.Create(newFilePath)
219+
w := bufio.NewWriter(fo)
220+
file, _ = os.Open(goPath)
221+
defer file.Close()
222+
scanner = bufio.NewScanner(file)
223+
for scanner.Scan() {
224+
line := scanner.Text()
225+
226+
if firstLine {
227+
if strings.Contains(line, "NOT CONVERTED - RUN YAML MODE") {
228+
firstLine = false
229+
continue
230+
} else {
231+
break
232+
}
233+
}
234+
235+
if len(commentsMap) > 0 && !wholeLineComment.MatchString(line) && line != "" { // This line is not a comment
236+
normalizedLine := strings.ReplaceAll(line, "'", "")
237+
normalizedLine = strings.ReplaceAll(normalizedLine, `"`, "")
238+
trimmed := strings.TrimSpace(normalizedLine)
239+
index := strings.Index(normalizedLine, trimmed)
240+
241+
if index == 0 {
242+
previousNameLine = ""
243+
nestedNameLine = ""
244+
} else if index >= 2 && strings.HasPrefix(trimmed, "- name:") {
245+
if nestedNameLine != "" {
246+
previousNameLine = nestedNameLine
247+
}
248+
nestedNameLine = normalizedLine
249+
}
250+
251+
field := strings.Split(normalizedLine, ":")[0]
252+
if shouldUseFieldName(normalizedLine) {
253+
normalizedLine = field
254+
}
255+
256+
key := fmt.Sprintf("%s$%s$%s", previousNameLine, nestedNameLine, normalizedLine)
257+
if comments, ok := commentsMap[key]; ok {
258+
delete(commentsMap, key)
259+
line = fmt.Sprintf("%s\n%s", comments, line)
260+
}
261+
}
262+
_, err := w.WriteString(fmt.Sprintf("%s\n", line))
263+
if err != nil {
264+
log.Fatalf("Error when writing the line %s: %#v", line, err)
265+
}
266+
}
267+
268+
if !firstLine {
269+
// Flush writes any buffered data to the underlying io.Writer.
270+
if err = w.Flush(); err != nil {
271+
panic(err)
272+
}
273+
274+
if len(commentsMap) > 0 {
275+
log.Printf("Some comments in rubyPath %s are not copied over: %#v", rubyPath, commentsMap)
276+
}
277+
// Overwrite original file with temp
278+
os.Rename(newFilePath, goPath)
279+
} else {
280+
os.Remove(newFilePath)
281+
}
282+
}
283+
}
284+
log.Printf("Finished to copy comments from Ruby yaml files to Go yaml files")
285+
}
286+
287+
// custom template files in Go yaml files have different names
288+
// The format of primary_resource_name for enum is different in Go yaml files
289+
func shouldUseFieldName(line string) bool {
290+
filedNames := []string{
291+
"templates/terraform/",
292+
"primary_resource_name:",
293+
"default_value:",
294+
"deprecation_message:",
295+
}
296+
for _, fieldName := range filedNames {
297+
if strings.Contains(line, fieldName) {
298+
return true
299+
}
300+
}
301+
return false
28302
}
29303

30304
// Used to copy/paste text from Ruby -> Go YAML files
31-
func CopyText(identifier string, last, tempMode bool) {
305+
func CopyText(identifier string, tempMode bool) {
32306
var allProductFiles []string = make([]string, 0)
33307
glob := "products/**/go_product.yaml"
34308
if tempMode {
@@ -135,14 +409,13 @@ func CopyText(identifier string, last, tempMode bool) {
135409
if firstLine {
136410
if strings.Contains(line, "NOT CONVERTED - RUN YAML MODE") {
137411
firstLine = false
138-
if !last {
139-
w.WriteString(fmt.Sprintf("NOT CONVERTED - RUN YAML MODE\n"))
140-
}
412+
w.WriteString(fmt.Sprintf("NOT CONVERTED - RUN YAML MODE\n"))
141413
continue
142414
} else {
143415
break
144416
}
145417
}
418+
146419
if strings.Contains(line, identifier) {
147420
if index >= len(text) {
148421
log.Printf("did not replace %s correctly! Is the file named correctly?", goPath)

mmv1/products/accesscontextmanager/go_AccessLevel.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
# Warning: This is a temporary file, and should not be edited directly
1515
---
16+
# This is the singular of `AccessLevels`, any changes here should be made to `AccessLevels` as well
1617
name: 'AccessLevel'
1718
description: |
1819
An AccessLevel is a label that can be applied to requests to GCP services,
@@ -31,6 +32,11 @@ docs:
3132
id_format: '{{name}}'
3233
base_url: ''
3334
self_link: '{{name}}'
35+
# This is an unusual API, so we need to use a few fields to map the methods
36+
# to the right URL.
37+
# create_url is the Create URL
38+
# base_url is the Get and Delete and Patch URL. It is empty on purpose.
39+
# List won't work yet. It should share a URL with Create.
3440
create_url: '{{parent}}/accessLevels'
3541
update_verb: 'PATCH'
3642
update_mask: true
@@ -57,6 +63,7 @@ async:
5763
custom_code:
5864
encoder: 'templates/terraform/encoders/go/access_level_never_send_parent.go.tmpl'
5965
custom_import: 'templates/terraform/custom_import/go/set_access_policy_parent_from_self_link.go.tmpl'
66+
# Skipping the sweeper due to the non-standard base_url
6067
exclude_sweeper: true
6168
examples:
6269
- name: 'access_context_manager_access_level_basic'
@@ -65,6 +72,8 @@ examples:
6572
access_level_name: 'chromeos_no_lock'
6673
exclude_test: true
6774
parameters:
75+
# Parent is a path parameter that _cannot_ be read or sent in the request at all.
76+
# This must be done at the provider level.
6877
- name: 'parent'
6978
type: String
7079
description: |
@@ -111,6 +120,8 @@ properties:
111120
enum_values:
112121
- 'AND'
113122
- 'OR'
123+
# All of the false defaults below here are omitted on purpose.
124+
# Let's keep this as simple as possible, since they will all be set by the API.
114125
- name: 'conditions'
115126
type: Array
116127
description: |

mmv1/products/accesscontextmanager/go_AccessLevelCondition.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ docs:
3737
id_format: '{{access_level}}'
3838
base_url: ''
3939
self_link: '{{access_level}}'
40+
# This is an unusual API, so we need to use a few fields to map the methods
41+
# to the right URL.
42+
# create_url is the Create URL
43+
# base_url is the Get and Delete and Patch URL. It is empty on purpose.
44+
# List won't work yet. It should share a URL with Create.
4045
create_url: '{{access_level}}'
4146
create_verb: 'PATCH'
4247
update_mask: true
@@ -45,6 +50,7 @@ immutable: true
4550
mutex: '{{access_level}}'
4651
import_format:
4752
- '{{access_level}}'
53+
# no unique way to specify
4854
exclude_import: true
4955
timeouts:
5056
insert_minutes: 20
@@ -73,6 +79,7 @@ nested_query:
7379
modify_by_patch: true
7480
custom_code:
7581
exclude_tgc: true
82+
# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under AccessLevel
7683
exclude_sweeper: true
7784
examples:
7885
- name: 'access_context_manager_access_level_condition_basic'

0 commit comments

Comments
 (0)