211 lines
7.3 KiB
Markdown
211 lines
7.3 KiB
Markdown
# Adding New Linux Distributions
|
|
|
|
This guide explains how to add support for new Linux distributions to the dankdots installer using the new consolidated architecture.
|
|
|
|
## Architecture Overview
|
|
|
|
The codebase uses a simple, consolidated approach where each distribution is completely self-contained:
|
|
|
|
- **All-in-One** (`internal/distros/{distro}.go`) - Complete distribution implementation
|
|
- **Auto-Registration** - Distributions register themselves via `init()` functions
|
|
- **Shared Base** - Common functionality inherited from `BaseDistribution`
|
|
|
|
## Adding Support
|
|
|
|
### Method 1: Use Existing Implementation (Derivatives)
|
|
|
|
For distros that are derivatives (like CachyOS being Arch-based), you can register them to use an existing implementation.
|
|
|
|
**Example: Adding CachyOS (Arch-based)**
|
|
|
|
```go
|
|
// internal/distros/arch.go - add to the init function
|
|
func init() {
|
|
Register("arch", "#1793D1", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewArchDistribution(config, logChan)
|
|
})
|
|
Register("cachyos", "#318CE7", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewArchDistribution(config, logChan) // CachyOS uses Arch implementation but different color
|
|
})
|
|
}
|
|
```
|
|
|
|
That's it! CachyOS now uses Arch's detection and installation logic.
|
|
|
|
**Example: Adding Ubuntu derivatives**
|
|
|
|
```go
|
|
// internal/distros/ubuntu.go (after you create it)
|
|
func init() {
|
|
Register("ubuntu", "#E95420", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewUbuntuDistribution(config, logChan)
|
|
})
|
|
Register("kubuntu", "#0079C1", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewUbuntuDistribution(config, logChan) // Kubuntu uses Ubuntu implementation but different color
|
|
})
|
|
Register("xubuntu", "#2F5BEA", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewUbuntuDistribution(config, logChan) // Xubuntu uses Ubuntu implementation but different color
|
|
})
|
|
Register("pop", "#48B9C7", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewUbuntuDistribution(config, logChan) // Pop!_OS uses Ubuntu implementation but different color
|
|
})
|
|
}
|
|
```
|
|
|
|
### Method 2: Create New Implementation
|
|
|
|
For entirely new distribution families, create a complete implementation:
|
|
|
|
**Example: Adding openSUSE**
|
|
|
|
Create `internal/distros/opensuse.go`:
|
|
|
|
```go
|
|
package distros
|
|
|
|
import (
|
|
"context"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"github.com/AvengeMedia/danklinux/internal/deps"
|
|
"github.com/AvengeMedia/danklinux/internal/installer"
|
|
)
|
|
|
|
func init() {
|
|
Register("opensuse-leap", "#73BA25", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewOpenSUSEDistribution(config, logChan)
|
|
})
|
|
Register("opensuse-tumbleweed", "#73BA25", func(config DistroConfig, logChan chan<- string) Distribution {
|
|
return NewOpenSUSEDistribution(config, logChan)
|
|
})
|
|
}
|
|
|
|
type OpenSUSEDistribution struct {
|
|
*BaseDistribution
|
|
*ManualPackageInstaller
|
|
config DistroConfig
|
|
}
|
|
|
|
func NewOpenSUSEDistribution(config DistroConfig, logChan chan<- string) *OpenSUSEDistribution {
|
|
base := NewBaseDistribution(logChan)
|
|
return &OpenSUSEDistribution{
|
|
BaseDistribution: base,
|
|
ManualPackageInstaller: &ManualPackageInstaller{BaseDistribution: base},
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) GetID() string {
|
|
return o.config.ID
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) GetColorHex() string {
|
|
return o.config.ColorHex
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) GetPackageManager() PackageManagerType {
|
|
return PackageManagerZypper
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) GetPackageMapping(wm deps.WindowManager) map[string]PackageMapping {
|
|
return map[string]PackageMapping{
|
|
"git": {Name: "git", Repository: RepoTypeSystem},
|
|
"ghostty": {Name: "ghostty", Repository: RepoTypeManual}, // Build from source
|
|
"kitty": {Name: "kitty", Repository: RepoTypeSystem},
|
|
// ... map all required packages to openSUSE equivalents
|
|
}
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) DetectDependencies(ctx context.Context, wm deps.WindowManager) ([]deps.Dependency, error) {
|
|
return o.DetectDependenciesWithTerminal(ctx, wm, deps.TerminalGhostty)
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) DetectDependenciesWithTerminal(ctx context.Context, wm deps.WindowManager, terminal deps.Terminal) ([]deps.Dependency, error) {
|
|
var dependencies []deps.Dependency
|
|
|
|
// Use base methods for common functionality
|
|
dependencies = append(dependencies, o.detectDMS())
|
|
dependencies = append(dependencies, o.detectSpecificTerminal(terminal))
|
|
dependencies = append(dependencies, o.detectGit())
|
|
// ... add openSUSE-specific detection
|
|
|
|
return dependencies, nil
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) InstallPackages(ctx context.Context, dependencies []deps.Dependency, wm deps.WindowManager, sudoPassword string, reinstallFlags map[string]bool, progressChan chan<- installer.InstallProgressMsg) error {
|
|
// Implement installation logic using zypper
|
|
// Use o.InstallManualPackages() for source builds
|
|
return nil
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) InstallPrerequisites(ctx context.Context, sudoPassword string, progressChan chan<- installer.InstallProgressMsg) error {
|
|
// Install build tools, enable repositories, etc.
|
|
return nil
|
|
}
|
|
|
|
func (o *OpenSUSEDistribution) packageInstalled(pkg string) bool {
|
|
cmd := exec.Command("rpm", "-q", pkg)
|
|
err := cmd.Run()
|
|
return err == nil
|
|
}
|
|
```
|
|
|
|
## Repository Types
|
|
|
|
The system supports these repository types:
|
|
|
|
- `RepoTypeSystem` - Main system repository (zypper, apt, dnf, pacman)
|
|
- `RepoTypeAUR` - Arch User Repository
|
|
- `RepoTypeCOPR` - Fedora COPR
|
|
- `RepoTypePPA` - Ubuntu PPA
|
|
- `RepoTypeManual` - Build from source
|
|
|
|
## Package Manager Support
|
|
|
|
To add a new package manager, add it to `internal/distros/interface.go`:
|
|
|
|
```go
|
|
const (
|
|
PackageManagerPacman PackageManagerType = "pacman"
|
|
PackageManagerDNF PackageManagerType = "dnf"
|
|
PackageManagerAPT PackageManagerType = "apt"
|
|
PackageManagerZypper PackageManagerType = "zypper"
|
|
PackageManagerPortage PackageManagerType = "portage" // Add new ones here
|
|
)
|
|
```
|
|
|
|
## Testing Your Implementation
|
|
|
|
1. Build: `go build -o dankdots ./cmd/main.go`
|
|
2. Test on target distribution
|
|
3. Verify all packages detect and install correctly
|
|
4. Test both window managers (Hyprland, Niri)
|
|
5. Test both terminals (Ghostty, Kitty)
|
|
|
|
## Detection Process
|
|
|
|
The system automatically detects supported distributions by:
|
|
|
|
1. Reading `/etc/os-release` for the `ID` field
|
|
2. Looking up the ID in the distribution registry
|
|
3. Creating an instance using the registered constructor function
|
|
|
|
No hardcoded lists to maintain - everything is driven by the registry!
|
|
|
|
## Benefits of New Architecture
|
|
|
|
- ✅ **Single file per distro** - All logic in one place
|
|
- ✅ **Auto-registration** - No factory methods to update
|
|
- ✅ **Shared functionality** - Inherit common features
|
|
- ✅ **No duplication** - Manual builds and fonts are shared
|
|
- ✅ **Easy derivatives** - One line to support a new derivative
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create your distribution file in `internal/distros/`
|
|
3. Test thoroughly on your target distribution
|
|
4. Submit a pull request with example output
|
|
|
|
The maintainers will review and provide feedback. Thank you for expanding dankdots support! |