MCPcopy Create free account
hub / github.com/ddev/ddev / installAddonRecursive

Function installAddonRecursive

pkg/ddevapp/addons.go:1160–1225  ·  view source on GitHub ↗

installAddonRecursive installs an addon and its dependencies recursively

(app *DdevApp, addonName string, verbose bool)

Source from the content-addressed store, hash-verified

1158
1159// installAddonRecursive installs an addon and its dependencies recursively
1160func installAddonRecursive(app *DdevApp, addonName string, verbose bool) error {
1161 // Normalize the addon identifier for consistent circular dependency detection
1162 normalizedName := NormalizeAddonIdentifier(addonName)
1163
1164 // Check for circular dependencies using normalized name
1165 if installStackMap[normalizedName] {
1166 return fmt.Errorf("circular dependency detected: %s",
1167 strings.Join(append(installStack, addonName), " -> "))
1168 }
1169
1170 installStack = append(installStack, addonName)
1171 installStackMap[normalizedName] = true
1172 defer func() {
1173 // Clean up both slice and map using normalized name
1174 installStack = installStack[:len(installStack)-1]
1175 delete(installStackMap, normalizedName)
1176 }()
1177
1178 // Handle different dependency formats (same as ddev add-on get)
1179 parts := strings.Split(addonName, "/")
1180 extractedDir := ""
1181 tarballURL := ""
1182 var cleanup func()
1183
1184 switch {
1185 // Local directory path (check this first before GitHub parsing)
1186 case fileutil.IsDirectory(addonName):
1187 extractedDir = addonName
1188 if verbose {
1189 util.Success("Installing from local directory: %s", addonName)
1190 }
1191
1192 // Local tarball file
1193 case fileutil.FileExists(addonName) && (strings.HasSuffix(filepath.Base(addonName), "tar.gz") || strings.HasSuffix(filepath.Base(addonName), "tar") || strings.HasSuffix(filepath.Base(addonName), "tgz")):
1194 var err error
1195 extractedDir, cleanup, err = archive.ExtractTarballWithCleanup(addonName, true)
1196 if err != nil {
1197 return fmt.Errorf("unable to extract %s: %v", addonName, err)
1198 }
1199 defer cleanup()
1200
1201 // URL to tarball (including GitHub tarball URLs)
1202 case strings.HasPrefix(addonName, "http://") || strings.HasPrefix(addonName, "https://"):
1203 tarballURL = addonName
1204 var err error
1205 extractedDir, cleanup, err = archive.DownloadAndExtractTarball(tarballURL, true)
1206 if err != nil {
1207 return fmt.Errorf("unable to download %v: %v", addonName, err)
1208 }
1209 defer cleanup()
1210
1211 // GitHub owner/repo format (check this last, and exclude paths)
1212 case len(parts) == 2 && !strings.Contains(addonName, ".") && !strings.HasPrefix(addonName, "."):
1213 return InstallAddonFromGitHub(app, addonName, "", verbose)
1214
1215 default:
1216 return fmt.Errorf("unsupported dependency format: %s (must be owner/repo, /path/to/addon, or https://...)", addonName)
1217 }

Callers 1

InstallDependenciesFunction · 0.85

Calls 9

IsDirectoryFunction · 0.92
SuccessFunction · 0.92
FileExistsFunction · 0.92
NormalizeAddonIdentifierFunction · 0.85
InstallAddonFromGitHubFunction · 0.85
ErrorfMethod · 0.80

Tested by

no test coverage detected