Skip to content

Commit d398898

Browse files
authored
cmd: Allow add-package to select version of package (#6665)
* feat: allow versioning of packages * docs: remove xcaddy issue reference
1 parent eaaa2e5 commit d398898

File tree

2 files changed

+53
-12
lines changed

2 files changed

+53
-12
lines changed

cmd/commands.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,13 @@ latest versions. EXPERIMENTAL: May be changed or removed.
409409

410410
RegisterCommand(Command{
411411
Name: "add-package",
412-
Usage: "<packages...>",
412+
Usage: "<package[@version]...>",
413413
Short: "Adds Caddy packages (EXPERIMENTAL)",
414414
Long: `
415415
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.
418419
`,
419420
CobraFunc: func(cmd *cobra.Command) {
420421
cmd.Flags().BoolP("keep-backup", "k", false, "Keep the backed up binary, instead of deleting it")

cmd/packagesfuncs.go

+49-9
Original file line numberDiff line numberDiff line change
@@ -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+
4968
func 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

314342
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+
}

0 commit comments

Comments
 (0)