@@ -46,6 +46,25 @@ func cmdUpgrade(fl Flags) (int, error) {
4646 return upgradeBuild (pluginPkgs , fl )
4747}
4848
49+ func splitModule (arg string ) (module , version string , err error ) {
50+ const versionSplit = "@"
51+
52+ // accommodate module paths that have @ in them, but we can only tolerate that if there's also
53+ // a version, otherwise we don't know if it's a version separator or part of the file path
54+ lastVersionSplit := strings .LastIndex (arg , versionSplit )
55+ if lastVersionSplit < 0 {
56+ module = arg
57+ } else {
58+ module , version = arg [:lastVersionSplit ], arg [lastVersionSplit + 1 :]
59+ }
60+
61+ if module == "" {
62+ err = fmt .Errorf ("module name is required" )
63+ }
64+
65+ return
66+ }
67+
4968func cmdAddPackage (fl Flags ) (int , error ) {
5069 if len (fl .Args ()) == 0 {
5170 return caddy .ExitCodeFailedStartup , fmt .Errorf ("at least one package name must be specified" )
@@ -60,10 +79,15 @@ func cmdAddPackage(fl Flags) (int, error) {
6079 }
6180
6281 for _ , arg := range fl .Args () {
63- if _ , ok := pluginPkgs [arg ]; ok {
82+ module , version , err := splitModule (arg )
83+ if err != nil {
84+ return caddy .ExitCodeFailedStartup , fmt .Errorf ("invalid module name: %v" , err )
85+ }
86+ // only allow a version to be specified if it's different from the existing version
87+ if _ , ok := pluginPkgs [module ]; ok && ! (version != "" && pluginPkgs [module ].Version != version ) {
6488 return caddy .ExitCodeFailedStartup , fmt .Errorf ("package is already added" )
6589 }
66- pluginPkgs [arg ] = struct {}{ }
90+ pluginPkgs [module ] = pluginPackage { Version : version , Path : module }
6791 }
6892
6993 return upgradeBuild (pluginPkgs , fl )
@@ -83,7 +107,11 @@ func cmdRemovePackage(fl Flags) (int, error) {
83107 }
84108
85109 for _ , arg := range fl .Args () {
86- if _ , ok := pluginPkgs [arg ]; ! ok {
110+ module , _ , err := splitModule (arg )
111+ if err != nil {
112+ return caddy .ExitCodeFailedStartup , fmt .Errorf ("invalid module name: %v" , err )
113+ }
114+ if _ , ok := pluginPkgs [module ]; ! ok {
87115 // package does not exist
88116 return caddy .ExitCodeFailedStartup , fmt .Errorf ("package is not added" )
89117 }
@@ -93,7 +121,7 @@ func cmdRemovePackage(fl Flags) (int, error) {
93121 return upgradeBuild (pluginPkgs , fl )
94122}
95123
96- func upgradeBuild (pluginPkgs map [string ]struct {} , fl Flags ) (int , error ) {
124+ func upgradeBuild (pluginPkgs map [string ]pluginPackage , fl Flags ) (int , error ) {
97125 l := caddy .Log ()
98126
99127 thisExecPath , err := os .Executable ()
@@ -120,8 +148,8 @@ func upgradeBuild(pluginPkgs map[string]struct{}, fl Flags) (int, error) {
120148 "os" : {runtime .GOOS },
121149 "arch" : {runtime .GOARCH },
122150 }
123- for pkg := range pluginPkgs {
124- qs .Add ("p" , pkg )
151+ for _ , pkgInfo := range pluginPkgs {
152+ qs .Add ("p" , pkgInfo . String () )
125153 }
126154
127155 // initiate the build
@@ -276,14 +304,14 @@ func downloadBuild(qs url.Values) (*http.Response, error) {
276304 return resp , nil
277305}
278306
279- func getPluginPackages (modules []moduleInfo ) (map [string ]struct {} , error ) {
280- pluginPkgs := make (map [string ]struct {} )
307+ func getPluginPackages (modules []moduleInfo ) (map [string ]pluginPackage , error ) {
308+ pluginPkgs := make (map [string ]pluginPackage )
281309 for _ , mod := range modules {
282310 if mod .goModule .Replace != nil {
283311 return nil , fmt .Errorf ("cannot auto-upgrade when Go module has been replaced: %s => %s" ,
284312 mod .goModule .Path , mod .goModule .Replace .Path )
285313 }
286- pluginPkgs [mod .goModule .Path ] = struct {}{ }
314+ pluginPkgs [mod .goModule .Path ] = pluginPackage { Version : mod . goModule . Version , Path : mod . goModule . Path }
287315 }
288316 return pluginPkgs , nil
289317}
@@ -312,3 +340,15 @@ func writeCaddyBinary(path string, body *io.ReadCloser, fileInfo os.FileInfo) er
312340}
313341
314342const downloadPath = "https://caddyserver.com/api/download"
343+
344+ type pluginPackage struct {
345+ Version string
346+ Path string
347+ }
348+
349+ func (p pluginPackage ) String () string {
350+ if p .Version == "" {
351+ return p .Path
352+ }
353+ return p .Path + "@" + p .Version
354+ }
0 commit comments