@@ -18,11 +18,14 @@ import (
1818 "context"
1919 "encoding/json"
2020 "fmt"
21+ "io/fs"
2122 "log"
2223 "os"
2324 "path/filepath"
2425 "strings"
2526
27+ "cloud.google.com/go/internal/gensnippets"
28+ "golang.org/x/sys/execabs"
2629 "gopkg.in/yaml.v2"
2730)
2831
@@ -74,7 +77,18 @@ func (g *GapicGenerator) Regen(ctx context.Context) error {
7477 return err
7578 }
7679
77- if err := g .addModReplaceGenproto (); err != nil {
80+ if err := forEachMod (g .googleCloudDir , g .addModReplaceGenproto ); err != nil {
81+ return err
82+ }
83+
84+ snippetDir := filepath .Join (g .googleCloudDir , "internal" , "generated" , "snippets" )
85+ if err := gensnippets .Generate (g .googleCloudDir , snippetDir ); err != nil {
86+ return fmt .Errorf ("error generating snippets: %v" , err )
87+ }
88+ if err := replaceAllForSnippets (g .googleCloudDir , snippetDir ); err != nil {
89+ return err
90+ }
91+ if err := goModTidy (snippetDir ); err != nil {
7892 return err
7993 }
8094
@@ -86,25 +100,85 @@ func (g *GapicGenerator) Regen(ctx context.Context) error {
86100 return err
87101 }
88102
89- if err := g . dropModReplaceGenproto ( ); err != nil {
103+ if err := forEachMod ( g . googleCloudDir , g . dropModReplaceGenproto ); err != nil {
90104 return err
91105 }
92106
93107 return nil
94108}
95109
110+ // forEachMod runs the given function with the directory of
111+ // every non-internal module.
112+ func forEachMod (rootDir string , fn func (dir string ) error ) error {
113+ return filepath .WalkDir (rootDir , func (path string , d fs.DirEntry , err error ) error {
114+ if err != nil {
115+ return err
116+ }
117+ if strings .Contains (path , "internal" ) {
118+ return filepath .SkipDir
119+ }
120+ if d .Name () == "go.mod" {
121+ if err := fn (filepath .Dir (path )); err != nil {
122+ return err
123+ }
124+ }
125+ return nil
126+ })
127+ }
128+
129+ func goModTidy (dir string ) error {
130+ log .Printf ("[%s] running go mod tidy" , dir )
131+ c := command ("go" , "mod" , "tidy" )
132+ c .Dir = dir
133+ c .Env = []string {
134+ fmt .Sprintf ("PATH=%s" , os .Getenv ("PATH" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
135+ fmt .Sprintf ("HOME=%s" , os .Getenv ("HOME" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
136+ }
137+ return c .Run ()
138+ }
139+
140+ func replaceAllForSnippets (googleCloudDir , snippetDir string ) error {
141+ return forEachMod (googleCloudDir , func (dir string ) error {
142+ if dir == snippetDir {
143+ return nil
144+ }
145+
146+ // Get the module name in this dir.
147+ modC := execabs .Command ("go" , "list" , "-m" )
148+ modC .Dir = dir
149+ mod , err := modC .Output ()
150+ if err != nil {
151+ return err
152+ }
153+
154+ // Replace it. Use a relative path to avoid issues on different systems.
155+ rel , err := filepath .Rel (snippetDir , dir )
156+ if err != nil {
157+ return err
158+ }
159+ c := command ("bash" , "-c" , `go mod edit -replace "$MODULE=$MODULE_PATH"` )
160+ c .Dir = snippetDir
161+ c .Env = []string {
162+ fmt .Sprintf ("PATH=%s" , os .Getenv ("PATH" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
163+ fmt .Sprintf ("HOME=%s" , os .Getenv ("HOME" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
164+ fmt .Sprintf ("MODULE=%s" , mod ),
165+ fmt .Sprintf ("MODULE_PATH=%s" , rel ),
166+ }
167+ return c .Run ()
168+ })
169+ }
170+
96171// addModReplaceGenproto adds a genproto replace statement that points genproto
97172// to the local copy. This is necessary since the remote genproto may not have
98173// changes that are necessary for the in-flight regen.
99- func (g * GapicGenerator ) addModReplaceGenproto () error {
100- log .Println ( " adding temporary genproto replace statement" )
174+ func (g * GapicGenerator ) addModReplaceGenproto (dir string ) error {
175+ log .Printf ( "[%s] adding temporary genproto replace statement", dir )
101176 c := command ("bash" , "-c" , `
102177set -ex
103178
104- GENPROTO_VERSION=$(cat go.mod | cat go.mod | grep genproto | awk '{print $2}')
105- go mod edit -replace "google.golang.org/genproto@$GENPROTO_VERSION=$GENPROTO_DIR"
179+ go mod edit -replace "google.golang.org/genproto=$GENPROTO_DIR"
106180` )
107- c .Dir = g . googleCloudDir
181+ c .Dir = dir
108182 c .Env = []string {
109183 "GENPROTO_DIR=" + g .genprotoDir ,
110184 fmt .Sprintf ("PATH=%s" , os .Getenv ("PATH" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
@@ -115,15 +189,14 @@ go mod edit -replace "google.golang.org/genproto@$GENPROTO_VERSION=$GENPROTO_DIR
115189
116190// dropModReplaceGenproto drops the genproto replace statement. It is intended
117191// to be run after addModReplaceGenproto.
118- func (g * GapicGenerator ) dropModReplaceGenproto () error {
119- log .Println ( " removing genproto replace statement" )
192+ func (g * GapicGenerator ) dropModReplaceGenproto (dir string ) error {
193+ log .Printf ( "[%s] removing genproto replace statement", dir )
120194 c := command ("bash" , "-c" , `
121195set -ex
122196
123- GENPROTO_VERSION=$(cat go.mod | cat go.mod | grep genproto | grep -v replace | awk '{print $2}')
124- go mod edit -dropreplace "google.golang.org/genproto@$GENPROTO_VERSION"
197+ go mod edit -dropreplace "google.golang.org/genproto"
125198` )
126- c .Dir = g . googleCloudDir
199+ c .Dir = dir
127200 c .Env = []string {
128201 fmt .Sprintf ("PATH=%s" , os .Getenv ("PATH" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
129202 fmt .Sprintf ("HOME=%s" , os .Getenv ("HOME" )), // TODO(deklerk): Why do we need to do this? Doesn't seem to be necessary in other exec.Commands.
0 commit comments