Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 7 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,15 @@
# BADM - Born Again Dotfile Manager

BADM is a new (yes, again a new one) Dotfile manager. It uses Git as its backbone.
BADM is a new (yes, again a new one) dotfile and package manager. It uses Git as its backbone.

This Dotfile manager is **ready to use**, but some features are not implemented yet. Have a
look at [Planned features / Known issues](#planned-features--known-issues) to see what is planned to be added.
Packages are managed via a mixture of declarative and imperative configuration file.

## Setup
**Features:**

If it's your first time you are using this tool, you might want to follow these setup steps:
- [Manage your **dotfiles**](docs/dotfiles_management.md)
- [Manage your **packages**](docs/package_management.md)

### Create a fresh Dotfiles repository

In case you do not have a repository to manage your Dotfiles (or you want to start over) it is pretty straight forward
to get going:

1. Create new Dotfiles repository
1. Create a remote repository (e.g. on GitHub, GitLab, ...). Make sure you are able to push and pull to that
repository.
2. `badm new <REMOTE_REPO_CLONE_URL>`
2. Start managing your Dotfiles
1. `badm add <PATH_TO_FILE> <PATH_TO_FILE2>` &rarr; Your Dotfiles get automatically pushed to your remote repository
2. `badm rm <PATH_TO:FILE> <PATH_TO_FILE2>` &rarr; Your files get removed from the Dotfiles repository and restored
to its original location. **No files get lost!**
3. `badm save` &rarr; Write any changes to the local Dotfiles repository to the remote one. Needed after each change
to local Dotfiles.

### Get an existing BADM repository

`badm get <REMOTE_REPO_CLONE_URL>` - It's that easy.

## Commands
## Command overview

| Command | Action |
|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Expand All @@ -40,12 +20,8 @@ to get going:
| `new` | Initialize a fresh local BADM repository, where new Dotfiles can be added afterwards. |
| `get` | Pull an already existing BADM remote repository and persist everything on the system. |
| `reset` | Reset all changes made by BADM. It replaces populated symlinks with the original Dotfiles. Choose this command if you do not want to use BADM anymore. Choose the `--dryRun` flag to see what would happen when executing this command. |
| `packages` | Install packages. For detailed help visit [Manage your **packages**](docs/package_management.md). |
| `update` | Update BADM to the newest version in-place. |
| `help` | Print helpful information. |
| `version` | Check your current version. |
| `completion` | Generate the autocompletion script for the specified shell. |

## Planned features / Known issues

- Execute custom scripts on wish (e.g. pacman, yay, ...)
- Actual configuration features
84 changes: 84 additions & 0 deletions badm.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://github.com/Koenigseder/badm/blob/master/badm.schema.json",
"title": "BADM Packages Configuration Schema",
"description": "Schema for the BADM packages configuration file.",
"type": "object",
"required": [
"packages"
],
"properties": {
"packages": {
"type": "object",
"description": "Defines package managers, installation scopes, and packages to install.",
"required": [
"packageManagers",
"installScopes"
],
"properties": {
"packageManagers": {
"type": "object",
"description": "A map of package managers and their installation commands.",
"additionalProperties": {
"type": "string",
"description": "The command used to install packages with this package manager."
}
},
"installScopes": {
"type": "object",
"description": "Defines installation variations (e.g., 'basics', 'slim', 'full').",
"additionalProperties": {
"type": "object",
"description": "Definition of an installation scope.",
"properties": {
"dependsOn": {
"type": "string",
"description": "Name of another installation scope that this scope depends on."
},
"packages": {
"type": "object",
"description": "List of packages to install using the defined package managers.",
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"description": "Name of the package to install."
}
}
},
"scripts": {
"type": "array",
"items": {
"type": "string",
"description": "Name of a script to execute after package installation."
}
}
}
}
}
}
},
"scripts": {
"type": "object",
"description": "Defines scripts that can be referenced in installation scopes.",
"additionalProperties": {
"type": "object",
"description": "Definition of a script.",
"required": [
"exec",
"shell"
],
"properties": {
"exec": {
"type": "string",
"description": "The command or script to execute (can be multi-line)."
},
"shell": {
"type": "string",
"description": "The shell in which the script will be executed (e.g., 'bash')."
}
}
}
}
}
}
17 changes: 0 additions & 17 deletions cmd/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,6 @@ func createNewBadmRepo(args []string) {
fmt.Printf("Directory %s already exists\n", repoPath)
}

// Check if .badm.yaml file exists in .dotfiles folder
_, err = os.Stat(cfgFile)
if errors.Is(err, fs.ErrNotExist) {
// Create .badm.yaml if it does not exist
file, err := os.Create(cfgFile)
if err != nil {
fmt.Println("Unable creating .badm.yaml config file:", err)
os.Exit(1)
}

defer file.Close()

fmt.Println("Created .badm.yaml")
} else {
fmt.Println("Config file .badm.yaml already exists")
}

// Check if .gitignore file exists in .dotfiles folder
gitignore := fmt.Sprintf("%s/%s", repoPath, ".gitignore")

Expand Down
41 changes: 41 additions & 0 deletions cmd/packages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package cmd

import (
"fmt"
"os"

pkgs "github.com/Koenigseder/badm/internal/packages"
"github.com/spf13/cobra"
)

func init() {
rootCmd.AddCommand(packages)
}

var packages = &cobra.Command{
Use: "packages",
Short: "Install various packages",
Long: `Install various packages defined in .badm.yaml`,
Run: func(_ *cobra.Command, args []string) {
if len(args) == 0 {
fmt.Println("Please provide a install scope name")
os.Exit(1)
}

installScopeName := args[0]

cfgFile, err := pkgs.ReadConfigFile(cfgFilePath)
if err != nil {
fmt.Printf("Failed reading config file %s: %v\n", cfgFilePath, err)
os.Exit(1)
}

cfgFile.Directory = repoPath

err = cfgFile.InstallPackages(installScopeName)
if err != nil {
fmt.Printf("Failed installing packages for '%s': %v\n", installScopeName, err)
os.Exit(1)
}
},
}
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ var (
homeDir string
repoPath string
repoRootAlias string
cfgFile string
cfgFilePath string

// Flags
overrideExistingFiles bool
Expand Down Expand Up @@ -49,7 +49,7 @@ func init() {
}

repoPath = fmt.Sprintf("%s/%s", homeDir, repoName)
cfgFile = fmt.Sprintf("%s/.badm.yaml", repoPath)
cfgFilePath = fmt.Sprintf("%s/.badm.yaml", repoPath)
}

// Execute the app
Expand Down
39 changes: 39 additions & 0 deletions docs/dotfiles_management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Dotfiles management setup

With **BADM** you are able to manage all your dotfiles in a central place and with minimal effort.

## Relevant commands

| Command | Action |
|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `add` | Add a Dotfile (or multiple) to your remote Dotfile repository. It gets replaced with a symlink. Choose the `--override` flag to override already existing files on your system. |
| `rm` | Remove a Dotfile (or multiple) from your remote Dotfile repository. The symlink gets replaced with the original file. |
| `save` | Write any changes to the local Dotfiles repository to the remote one. Needed after each change to local Dotfiles. |
| `fetch` | Manually fetch the current remote repository stage and persist remote changes onto the local system. Choose the `--override` flag to override already existing files on your system. |
| `new` | Initialize a fresh local BADM repository, where new Dotfiles can be added afterwards. |
| `get` | Pull an already existing BADM remote repository and persist everything on the system. |
| `reset` | Reset all changes made by BADM. It replaces populated symlinks with the original Dotfiles. Choose this command if you do not want to use BADM anymore. Choose the `--dryRun` flag to see what would happen when executing this command. |

## Setup

If it's your first time you are using this tool, you might want to follow these setup steps:

### Create a fresh Dotfiles repository

In case you do not have a repository to manage your Dotfiles (or you want to start over) it is pretty straight forward
to get going:

1. Create new Dotfiles repository
1. Create a remote repository (e.g. on GitHub, GitLab, ...). Make sure you are able to push and pull to that
repository.
2. `badm new <REMOTE_REPO_CLONE_URL>`
2. Start managing your Dotfiles
1. `badm add <PATH_TO_FILE> <PATH_TO_FILE2>` &rarr; Your Dotfiles get automatically pushed to your remote repository
2. `badm rm <PATH_TO:FILE> <PATH_TO_FILE2>` &rarr; Your files get removed from the Dotfiles repository and restored
to its original location. **No files get lost!**
3. `badm save` &rarr; Write any changes to the local Dotfiles repository to the remote one. Needed after each change
to local Dotfiles.

### Get an existing BADM repository

`badm get <REMOTE_REPO_CLONE_URL>` - It's that easy.
111 changes: 111 additions & 0 deletions docs/example.badm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# e.g. `badm packages <installScopeName>`
packages:
# Define package managers with respective commands
packageManagers:
pacman: sudo pacman -S --needed
yay: yay -S --needed
flatpak-flathub: flatpak install flathub

# Define installation variations - dependencies can be included
installScopes:
# The very basics
basics: # Name of variation
packages: # Which packages should be installed
pacman: # Which package manager to use (name of `packageManagers`) - order is respected
- git # Name of package
- base-devel
- bluez
- bluez-utils
# Additionally we execute scripts after package installation
scripts:
- setup-bluetooth

# Slim installation
slim:
dependsOn: basics
packages:
pacman:
- alacritty
- zed
- starship
- okular
- spectacle
- discover
- rofi
yay:
- brave-bin

# Almost full installation
full:
dependsOn: slim # This variation depends on `slim` - `slim` gets executed first
packages:
pacman:
- go
- keepassxc
- signal-desktop
- podman
- flatpak
- discover
yay:
- intellij-idea-ultimate-edition
- megasync-bin
flatpak-flathub:
- com.discordapp.Discord # Discord
- com.spotify.Client # Spotify
- io.podman_desktop.PodmanDesktop # Podman Desktop
- de.haeckerfelix.Fragments # Fragments

# Things needed for Displaylink driver
displaylink:
dependsOn: basics
packages:
pacman:
- linux-lts-headers
yay:
- evdi-dkms
- displaylink
scripts:
- setup-displaylink
- prompt-reboot

# Some things needed for Kubernetes development
k8s:
dependsOn: slim
packages:
pacman:
- kubectl
- minikube

# All scripts - can be referenced with e.g. `script: install-yay`
scripts:
install-yay:
exec: |
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si
cd ..
rm -rf yay
shell: bash

setup-bluetooth:
exec: |
sudo systemctl start bluetooth.service
sudo systemctl enable bluetooth.service
shell: bash

setup-displaylink:
exec: |
sudo systemctl start displaylink.service
sudo systemctl enable displaylink.service
shell: bash

prompt-reboot:
exec: |
read -p "A reboot is required. Reboot now? [y/N] " answer
if [[ "$answer" =~ ^[Yy]$ ]]; then
echo "Rebooting..."
reboot
else
echo "Not rebooting. Have a great day :)"
fi
shell: bash
Loading
Loading