|
6 | 6 | "os" |
7 | 7 | "path/filepath" |
8 | 8 | "sort" |
| 9 | + "strings" |
9 | 10 | "time" |
10 | 11 |
|
11 | 12 | "github.com/google/uuid" |
@@ -167,9 +168,20 @@ func (*OfficialRegistry) createPackages(entry *types.RegistryEntry) []model.Pack |
167 | 168 | }) |
168 | 169 | } |
169 | 170 |
|
| 171 | + // Extract registry and version information from the image reference |
| 172 | + registryBaseURL, identifier, version, err := parseImageReference(entry.Image) |
| 173 | + if err != nil { |
| 174 | + // Continue with fallback values |
| 175 | + registryBaseURL = "" |
| 176 | + identifier = entry.Image |
| 177 | + version = "" |
| 178 | + } |
| 179 | + |
170 | 180 | pkg := model.Package{ |
171 | | - RegistryType: model.RegistryTypeOCI, // Docker/OCI container |
172 | | - Identifier: entry.Image, // TODO: Fix that since it's a toolhive's assumption |
| 181 | + RegistryType: model.RegistryTypeOCI, |
| 182 | + RegistryBaseURL: registryBaseURL, |
| 183 | + Identifier: identifier, |
| 184 | + Version: version, |
173 | 185 | EnvironmentVariables: envVars, |
174 | 186 | } |
175 | 187 |
|
@@ -348,3 +360,61 @@ func (*OfficialRegistry) convertStatus(status string) model.Status { |
348 | 360 | return model.StatusActive // Default to active |
349 | 361 | } |
350 | 362 | } |
| 363 | + |
| 364 | +// parseImageReference parses a container image reference into basic components |
| 365 | +// Returns error if registry has a port (not supported) |
| 366 | +func parseImageReference(image string) (registryBaseURL, identifier, version string, err error) { |
| 367 | + // Check for port in registry (not supported) |
| 368 | + if strings.Contains(image, ":") && strings.Count(image, ":") > 1 { |
| 369 | + // Multiple colons might indicate registry:port/image:tag |
| 370 | + parts := strings.Split(image, "/") |
| 371 | + if len(parts) > 0 && strings.Contains(parts[0], ":") { |
| 372 | + // First part has colon, likely registry:port |
| 373 | + return "", "", "", fmt.Errorf("registry with port not supported: %s", parts[0]) |
| 374 | + } |
| 375 | + } |
| 376 | + |
| 377 | + // Handle digest (@sha256:...) |
| 378 | + if strings.Contains(image, "@") { |
| 379 | + parts := strings.SplitN(image, "@", 2) |
| 380 | + imageRef := parts[0] |
| 381 | + digest := parts[1] |
| 382 | + |
| 383 | + reg, name := splitRegistryAndName(imageRef) |
| 384 | + return reg, name, digest, nil |
| 385 | + } |
| 386 | + |
| 387 | + // Handle tag (:tag) |
| 388 | + if strings.Contains(image, ":") { |
| 389 | + parts := strings.SplitN(image, ":", 2) |
| 390 | + imageRef := parts[0] |
| 391 | + tag := parts[1] |
| 392 | + |
| 393 | + reg, name := splitRegistryAndName(imageRef) |
| 394 | + return reg, name, tag, nil |
| 395 | + } |
| 396 | + |
| 397 | + // No tag or digest - default to latest |
| 398 | + reg, name := splitRegistryAndName(image) |
| 399 | + return reg, name, "latest", nil |
| 400 | +} |
| 401 | + |
| 402 | +// splitRegistryAndName splits image into registry and name parts |
| 403 | +func splitRegistryAndName(image string) (registryBaseURL, identifier string) { |
| 404 | + // No slash = Docker Hub image |
| 405 | + if !strings.Contains(image, "/") { |
| 406 | + return "https://docker.io", image |
| 407 | + } |
| 408 | + |
| 409 | + // Has slash - check if first part looks like registry |
| 410 | + parts := strings.SplitN(image, "/", 2) |
| 411 | + firstPart := parts[0] |
| 412 | + |
| 413 | + // If first part has dot, assume it's a registry hostname |
| 414 | + if strings.Contains(firstPart, ".") { |
| 415 | + return "https://" + firstPart, parts[1] |
| 416 | + } |
| 417 | + |
| 418 | + // Otherwise assume Docker Hub with namespace |
| 419 | + return "https://docker.io", image |
| 420 | +} |
0 commit comments