From: Andrej Shadura <andrew.shadura@collabora.co.uk>
Date: Sun, 29 Jan 2023 17:34:13 +0100
Subject: Add Ubuntu images and unofficial Debian images, default to Debian

---
 src/pkg/utils/utils.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 4 deletions(-)

--- a/src/pkg/utils/utils.go
+++ b/src/pkg/utils/utils.go
@@ -28,6 +28,7 @@
 	"strings"
 	"syscall"
 	"time"
+	"unicode/utf8"
 
 	"github.com/acobaugh/osrelease"
 	"github.com/containers/toolbox/pkg/shell"
@@ -49,10 +50,10 @@
 }
 
 const (
-	containerNamePrefixFallback = "fedora-toolbox"
-	distroFallback              = "fedora"
+	containerNamePrefixFallback = "debian-toolbox"
+	distroFallback              = "debian"
 	idTruncLength               = 12
-	releaseFallback             = "37"
+	releaseFallback             = "unstable"
 )
 
 const (
@@ -108,6 +109,18 @@
 			getFullyQualifiedImageRHEL,
 			parseReleaseRHEL,
 		},
+		"debian": {
+			"debian-toolbox",
+			"debian-toolbox",
+			getFullyQualifiedImageDebian,
+			parseReleaseDebian,
+		},
+		"ubuntu": {
+			"ubuntu-toolbox",
+			"ubuntu-toolbox",
+			getFullyQualifiedImageUbuntu,
+			parseReleaseUbuntu,
+		},
 	}
 )
 
@@ -134,7 +147,7 @@
 	if err == nil {
 		if distroObj, supportedDistro := supportedDistros[hostID]; supportedDistro {
 			release, err := GetHostVersionID()
-			if err == nil {
+			if err == nil && release != "" {
 				containerNamePrefixDefault = distroObj.ContainerNamePrefix
 				distroDefault = hostID
 				releaseDefault = release
@@ -343,6 +356,16 @@
 	return imageFull
 }
 
+func getFullyQualifiedImageDebian(image, release string) string {
+	imageFull := "quay.io/toolbx-images/" + image
+	return imageFull
+}
+
+func getFullyQualifiedImageUbuntu(image, release string) string {
+	imageFull := "quay.io/toolbx/" + image
+	return imageFull
+}
+
 // GetGroupForSudo returns the name of the sudoers group.
 //
 // Some distros call it 'sudo' (eg. Ubuntu) and some call it 'wheel' (eg. Fedora).
@@ -636,6 +659,60 @@
 	return release, err
 }
 
+func parseReleaseDebian(release string) (string, error) {
+	releaseN, err := strconv.Atoi(release)
+	if err == nil {
+		if releaseN < 10 {
+			return "", &ParseReleaseError{"The oldest supported Debian release is Debian 10 (Buster)."}
+		}
+	}
+
+	return release, nil
+}
+
+func parseReleaseUbuntu(release string) (string, error) {
+	releaseParts := strings.Split(release, ".")
+	if len(releaseParts) != 2 {
+		return "", &ParseReleaseError{"The release must be in the 'YY.MM' format."}
+	}
+
+	releaseYear, err := strconv.Atoi(releaseParts[0])
+	if err != nil {
+		logrus.Debugf("Parsing release year %s as an integer failed: %s", releaseParts[0], err)
+		return "", &ParseReleaseError{"The release must be in the 'YY.MM' format."}
+	}
+
+	if releaseYear < 4 {
+		return "", &ParseReleaseError{"The release year must be 4 or more."}
+	}
+
+	releaseYearLen := utf8.RuneCountInString(releaseParts[0])
+	if releaseYearLen > 2 {
+		return "", &ParseReleaseError{"The release year cannot have more than two digits."}
+	} else if releaseYear < 10 && releaseYearLen == 2 {
+		return "", &ParseReleaseError{"The release year cannot have a leading zero."}
+	}
+
+	releaseMonth, err := strconv.Atoi(releaseParts[1])
+	if err != nil {
+		logrus.Debugf("Parsing release month %s as an integer failed: %s", releaseParts[1], err)
+		return "", &ParseReleaseError{"The release must be in the 'YY.MM' format."}
+	}
+
+	if releaseMonth < 1 {
+		return "", &ParseReleaseError{"The release month must be between 01 and 12."}
+	} else if releaseMonth > 12 {
+		return "", &ParseReleaseError{"The release month must be between 01 and 12."}
+	}
+
+	releaseMonthLen := utf8.RuneCountInString(releaseParts[1])
+	if releaseMonthLen != 2 {
+		return "", &ParseReleaseError{"The release month must have two digits."}
+	}
+
+	return release, nil
+}
+
 func parseReleaseFedora(release string) (string, error) {
 	if strings.HasPrefix(release, "F") || strings.HasPrefix(release, "f") {
 		release = release[1:]
