Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 07:00 UTC
cmd: Allow `add-package` to select version of package (#6665)
* feat: allow versioning of packages * docs: remove xcaddy issue reference
Lucas VerÍssimo Botelho committed
Oct 30, 2024 at 13:48 UTC
d398898b352a6a7e8ac5c24da01dd948fc334d77
2 files changed
+53
-12
cmd/commands.go
+4
-3
@@ -409,12 +409,13 @@ latest versions. EXPERIMENTAL: May be changed or removed.
409
410
RegisterCommand(Command{
411
Name: "add-package",
412
- Usage: "<packages...>",
412
+ Usage: "<package[@version]...>",
413
Short: "Adds Caddy packages (EXPERIMENTAL)",
414
Long: `
415
Downloads an updated Caddy binary with the specified packages (module/plugin)
416
-added. Retains existing packages. Returns an error if the any of packages are
417
-already included. EXPERIMENTAL: May be changed or removed.
416
+added, with an optional version specified (e.g., "package@version"). Retains
417
+existing packages. Returns an error if any of the specified packages are already
418
+included. EXPERIMENTAL: May be changed or removed.
419
`,
420
CobraFunc: func(cmd *cobra.Command) {
421
cmd.Flags().BoolP("keep-backup", "k", false, "Keep the backed up binary, instead of deleting it")
cmd/packagesfuncs.go
+49
-9
@@ -46,6 +46,25 @@ func cmdUpgrade(fl Flags) (int, error) {
46
return upgradeBuild(pluginPkgs, fl)
47
}
48
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
+
68
func cmdAddPackage(fl Flags) (int, error) {
69
if len(fl.Args()) == 0 {
70
return caddy.ExitCodeFailedStartup, fmt.Errorf("at least one package name must be specified")
@@ -60,10 +79,15 @@ func cmdAddPackage(fl Flags) (int, error) {
79
}
80
81
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) {
88
return caddy.ExitCodeFailedStartup, fmt.Errorf("package is already added")
89
}
66
- pluginPkgs[arg] = struct{}{}
90
+ pluginPkgs[module] = pluginPackage{Version: version, Path: module}
91
}
92
93
return upgradeBuild(pluginPkgs, fl)
@@ -83,7 +107,11 @@ func cmdRemovePackage(fl Flags) (int, error) {
107
}
108
109
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 {
115
// package does not exist
116
return caddy.ExitCodeFailedStartup, fmt.Errorf("package is not added")
117
}
@@ -93,7 +121,7 @@ func cmdRemovePackage(fl Flags) (int, error) {
121
return upgradeBuild(pluginPkgs, fl)
122
}
123
96
-func upgradeBuild(pluginPkgs map[string]struct{}, fl Flags) (int, error) {
124
+func upgradeBuild(pluginPkgs map[string]pluginPackage, fl Flags) (int, error) {
125
l := caddy.Log()
126
127
thisExecPath, err := os.Executable()
@@ -120,8 +148,8 @@ func upgradeBuild(pluginPkgs map[string]struct{}, fl Flags) (int, error) {
148
"os": {runtime.GOOS},
149
"arch": {runtime.GOARCH},
150
}
123
- for pkg := range pluginPkgs {
124
- qs.Add("p", pkg)
151
+ for _, pkgInfo := range pluginPkgs {
152
+ qs.Add("p", pkgInfo.String())
153
}
154
155
// initiate the build
@@ -276,14 +304,14 @@ func downloadBuild(qs url.Values) (*http.Response, error) {
304
return resp, nil
305
}
306
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)
309
for _, mod := range modules {
310
if mod.goModule.Replace != nil {
311
return nil, fmt.Errorf("cannot auto-upgrade when Go module has been replaced: %s => %s",
312
mod.goModule.Path, mod.goModule.Replace.Path)
313
}
286
- pluginPkgs[mod.goModule.Path] = struct{}{}
314
+ pluginPkgs[mod.goModule.Path] = pluginPackage{Version: mod.goModule.Version, Path: mod.goModule.Path}
315
}
316
return pluginPkgs, nil
317
}
@@ -312,3 +340,15 @@ func writeCaddyBinary(path string, body *io.ReadCloser, fileInfo os.FileInfo) er
340
}
341
342
const 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
+}