github.com/jmigpin/editor@v1.6.0/util/goutil/modules.go (about) 1 package goutil 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "github.com/jmigpin/editor/util/osutil" 11 "golang.org/x/mod/modfile" 12 ) 13 14 //---------- 15 16 func ReadGoMod(ctx context.Context, dir string, env []string) (*modfile.File, error) { 17 f, _, err := ParseDirGoMod(dir) 18 if err != nil { 19 return nil, err 20 } 21 return f, nil 22 } 23 24 //---------- 25 26 func GoModInit(ctx context.Context, dir, modPath string, env []string) error { 27 args := []string{"go", "mod", "init"} 28 if modPath != "" { 29 args = append(args, modPath) 30 } 31 _, err := runGoModCmd(ctx, dir, args, env) 32 return err 33 } 34 35 func GoModTidy(ctx context.Context, dir string, env []string) error { 36 args := []string{"go", "mod", "tidy"} 37 _, err := runGoModCmd(ctx, dir, args, env) 38 return err 39 } 40 41 func GoModRequire(ctx context.Context, dir, path string, env []string) error { 42 args := []string{"go", "mod", "edit", "-require=" + path} 43 _, err := runGoModCmd(ctx, dir, args, env) 44 return err 45 } 46 47 func GoModExclude(ctx context.Context, dir, path string, env []string) error { 48 args := []string{"go", "mod", "edit", "-exclude=" + path} 49 _, err := runGoModCmd(ctx, dir, args, env) 50 return err 51 } 52 53 func GoModReplace(ctx context.Context, dir, old, new string, env []string) error { 54 //// fails when using directories that contain the version in the name. So it would not allow a downloaded module to be used (contains directories with '@' version in the name). 55 //args := []string{"go", "mod", "edit", "-replace=" + old + "=" + new} 56 //_, err := runGoModCmd(ctx, dir, args, env) 57 //return err 58 59 // simple append to the file (works, but can add repeated strings) 60 //return goModReplaceUsingAppend(ctx, dir, old, new) 61 62 f, fname, err := ParseDirGoMod(dir) 63 if err != nil { 64 return err 65 } 66 if err := f.AddReplace(old, "", new, ""); err != nil { 67 return err 68 } 69 f.Cleanup() 70 b, err := f.Format() 71 if err != nil { 72 return err 73 } 74 return ioutil.WriteFile(fname, b, 0660) 75 } 76 77 //---------- 78 79 func runGoModCmd(ctx context.Context, dir string, args []string, env []string) ([]byte, error) { 80 cmd := osutil.NewCmd(ctx, args...) 81 cmd.Dir = dir 82 cmd.Env = env 83 bout, err := osutil.RunCmdStdoutAndStderrInErr(cmd, nil) 84 if err != nil { 85 return nil, fmt.Errorf("runGoMod: %v (args=%v, dir=%v)", err, args, dir) 86 } 87 return bout, nil 88 } 89 90 //---------- 91 92 func FindGoMod(dir string) (string, bool) { 93 return findFileUp(dir, "go.mod") 94 } 95 func FindGoSum(dir string) (string, bool) { 96 return findFileUp(dir, "go.sum") 97 } 98 func findFileUp(dir, name string) (string, bool) { 99 for { 100 fp := filepath.Join(dir, name) 101 _, err := os.Stat(fp) 102 if err == nil { 103 return fp, true 104 } 105 // parent dir 106 oldDir := dir 107 dir = filepath.Dir(dir) 108 isRoot := oldDir == dir 109 if isRoot { 110 return "", false 111 } 112 } 113 } 114 115 //---------- 116 117 func ParseDirGoMod(dir string) (*modfile.File, string, error) { 118 name, b, err := readDirGoModFile(dir) 119 if err != nil { 120 return nil, "", err 121 } 122 f, err := modfile.Parse(name, b, nil) // ParseLax will not read replaces's 123 if err != nil { 124 return nil, "", err 125 } 126 return f, name, nil 127 } 128 129 func readDirGoModFile(dir string) (string, []byte, error) { 130 s := filepath.Join(dir, "go.mod") 131 b, err := ioutil.ReadFile(s) 132 return s, b, err 133 } 134 135 //---------- 136 137 //func GoModCreateContent(dir string, content string) error { 138 // filename := filepath.Join(dir, "go.mod") 139 // f, err := os.Create(filename) 140 // if err != nil { 141 // return err 142 // } 143 // defer f.Close() 144 // if _, err := fmt.Fprintf(f, content); err != nil { 145 // return err 146 // } 147 // return nil 148 //} 149 150 //---------- 151 152 //func goModReplaceUsingAppend(ctx context.Context, dir, old, new string) error { 153 // filename := filepath.Join(dir, "go.mod") 154 // f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 155 // if err != nil { 156 // return err 157 // } 158 // defer f.Close() 159 // u := "replace " + old + " => " + new 160 // if _, err := f.WriteString("\n" + u + "\n"); err != nil { 161 // return err 162 // } 163 // return nil 164 //}