This commit is contained in:
Artur Gurgul 2025-08-01 12:52:57 +02:00
commit b3dba4542f
44 changed files with 1596 additions and 0 deletions

77
bin/dat Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env ruby
require 'optparse'
require 'ostruct'
# dat set private git://repo
# dat init private
# dat install
# dat reinstall
options = OpenStruct.new
# take the first so OptionParser will not see it
subcommand = ARGV.shift&.to_sym
OptionParser.new do |opt|
opt.on('-i', '--install', 'Install dat for the user') { |o| options.type = :install }
opt.on('-u', '--update', 'Update') do |o|
options.type = :update
end
opt.on('-n', '--name NAME', 'Make the recipe') do |o|
options.name = o
end
opt.on('--cache', 'Use cache') do |o|
options.use_cache = true
end
opt.on('-t', '--target TARGET', ['user', 'usr', 'package', 'pkg', 'system', 'sys'], 'Target type (user, package, system)') do |target|
normalized = case target.downcase
when 'user', 'usr'
:user
when 'package', 'pkg'
:package
when 'system', 'sys'
:system
end
options.target = normalized
end
end.parse!
case subcommand
when :install
puts "installing...."
require 'install'
Install.base_install
when :update
puts "updating...."
require 'install'
Install.base_update
when :make
puts "making..."
require 'make'
Make.command(options)
when :goto
Dir.chdir(ENV["DAT_ROOT"])
when :vm
puts 'vm command'
# dat vm --create name
# dat vm --run name --graphic (default no graphic)
# Idea ===========
# dat vm --pool --execute script.sh
else
puts "Error not found #{options.type}"
end
# install locally for the user
# dat install
# dat set git://repo
# dat init
# dat deinit
# dat reinstall

77
bin/img.create Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env ruby
require 'open-uri'
require 'zip' # gem install rubyzip
require 'stringio'
require 'fileutils'
require 'uri'
require 'xz' # gem install ruby-xz
url = 'https://artur.gurgul.pro/static/vms/debian.ext2.img.zip'
# 'https://artur.gurgul.pro/static/vms/linux-v1.zip'
# debian.ext2.img.zip debian.ext4.img.zip linux-v1.zip
# sudo fdisk -l debian.img
# [sudo] password for artur:
# Disk debian.img: 4 GiB, 4294967296 bytes, 8388608 sectors
# Units: sectors of 1 * 512 = 512 bytes
# Sector size (logical/physical): 512 bytes / 512 bytes
# I/O size (minimum/optimal): 512 bytes / 512 bytes
# Disklabel type: dos
# Disk identifier: 0x878d05dc
#
# Device Boot Start End Sectors Size Id Type
# debian.img1 * 2048 8386559 8384512 4G 83 Linux
# artur@gurgul.xyz ~/vm ➜ sudo mount -o loop,offset=1048576 debian.img /mnt
# 1048576 = 512 * 2048
# sudo tar --xattrs --acls --numeric-owner -cpf - -C /mnt/diskimg . | xz -T0 > disk-backup.tar.xz
# To preserve all metadata, ownership, permissions, symlinks, devices, etc., use tar with --xattrs, --numeric-owner
# -cpf - → write tar to stdout
# -C /mnt/diskimg . → change directory so root of the archive matches root of the image
# xz -T0 → compress using all CPU cores
# https://chatgpt.com/c/688b32da-5e14-8327-9abc-b83a44252c05
# compare for differences
# sudo diff -r /mnt/diskimg /tmp/old
# Determine file extension
ext = File.extname(URI.parse(url).path)
# Open remote stream
URI.open(url) do |remote_file|
case ext
when '.zip'
puts "Processing ZIP file..."
buffer = remote_file.read
Zip::File.open_buffer(StringIO.new(buffer)) do |zip_file|
zip_file.each do |entry|
puts "Extracting #{entry.name}..."
target_path = File.join(Dir.pwd, entry.name)
FileUtils.mkdir_p(File.dirname(target_path))
entry.extract(target_path) { true } # Overwrite if exists
end
end
when '.xz'
puts "Processing XZ file..."
# Use XZ::StreamReader to decompress on-the-fly
xz_reader = XZ::StreamReader.new(remote_file)
# Assume .xz contains a single file; decide on output name
output_filename = File.basename(url, '.xz')
output_path = File.join(Dir.pwd, output_filename)
File.open(output_path, 'wb') do |out|
IO.copy_stream(xz_reader, out)
end
puts "Decompressed to #{output_path}"
else
puts "Unsupported file extension: #{ext}"
end
end

73
bin/img.extend Executable file
View file

@ -0,0 +1,73 @@
#!/usr/bin/env ruby
# truncate -s +10G
# Usage: ruby extend_mbr.rb disk.img
SECTOR_SIZE = 512
MBR_SIZE = 512
PARTITION_ENTRY_OFFSET = 446
PARTITION_ENTRY_SIZE = 16
MAX_PARTITIONS = 4
if ARGV.length != 1
puts "Usage: #{$0} disk.img"
exit 1
end
image_path = ARGV[0]
# Read disk image and MBR
image_size = File.size(image_path)
total_sectors = image_size / SECTOR_SIZE
puts ">> Image size: #{image_size} bytes"
puts ">> Total sectors: #{total_sectors}"
File.open(image_path, 'rb+') do |f|
mbr = f.read(MBR_SIZE).dup
last_partition_index = nil
start_sector = nil
# Find last valid partition
MAX_PARTITIONS.times do |i|
offset = PARTITION_ENTRY_OFFSET + i * PARTITION_ENTRY_SIZE
part_type = mbr.getbyte(offset + 4)
if part_type != 0x00
last_partition_index = i
end
end
if last_partition_index.nil?
abort "!! No valid partitions found in MBR"
end
entry_offset = PARTITION_ENTRY_OFFSET + last_partition_index * PARTITION_ENTRY_SIZE
# Read start sector (little-endian uint32 at offset +8)
start_sector_bytes = mbr.byteslice(entry_offset + 8, 4)
start_sector = start_sector_bytes.unpack("V").first
new_size = total_sectors - start_sector
puts ">> Found partition ##{last_partition_index + 1}"
puts " Start sector: #{start_sector}"
puts " New size: #{new_size} sectors"
# Pack new size (little-endian uint32)
new_size_bytes = [new_size].pack("V")
mbr[entry_offset + 12, 4] = new_size_bytes
# Write back modified MBR
f.seek(0)
f.write(mbr)
puts "✅ MBR updated. Partition now fills remaining disk space."
end
# sudo e2fsck -f /dev/sda1
# sudo resize2fs /dev/sda1

13
bin/img.run Executable file
View file

@ -0,0 +1,13 @@
#!/usr/bin/bash
# mount -t 9p -o trans=virtio,version=9p2000.L host0 /root
qemu-system-x86_64 -append "root=/dev/sda1 console=ttyS0" \
-kernel "$HOME/Desktop/debian/vmlinuz-linux" \
-initrd "$HOME/Desktop/debian/initramfs-linux.img" \
-m 2048 \
-smp $(sysctl -n hw.logicalcpu) \
-cpu qemu64 \
-virtfs local,path=.,security_model=none,mount_tag=host0 \
-drive format=raw,file=debian.img \
-nographic

14
bin/makeshell Normal file
View file

@ -0,0 +1,14 @@
cp ./shell /usr/bin/shell
# append to /etc/shells
# /etc/shells
# useradd -mg users -s /usr/bin/shell user
# chsh -s /usr/bin/shell user
# For the cuurent user
#chsh -s /usr/bin/shell

3
bin/pclean Executable file
View file

@ -0,0 +1,3 @@
make clean
git clean -fdx

18
bin/server Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env ruby
require 'server_manager'
# server application add file.yml
# ServerManager.init_sapplication("filename")
# server application remove name
# ServerManager.remove_application("service_name")
# server application passwd name
# ServerManager.application_passwd("service_name")
# server user add user-name
# server user remove user-name
# server user passwd user-name
# server install app-name

17
bin/shell Executable file
View file

@ -0,0 +1,17 @@
#!/bin/bash
# Try to get home directory safely
USER_HOME=$(getent passwd "$USER" | cut -d: -f6)
MYZSH="$USER_HOME/.local/bin/zsh"
if [ -x "$MYZSH" ]; then
echo "user own shell"
exec "$MYZSH" -i
elif command -v zsh >/dev/null 2>&1; then
echo "system zsh shell"
exec "$(command -v zsh)"
else
echo "fallback, default bash"
exec bash
fi

6
bin/test-env Executable file
View file

@ -0,0 +1,6 @@
#!/usr/bin/bash
echo "Passed prefix: $PREFIX"
echo "Dat: $DAT_ROOT"
echo "test: ${TEST_ENV}"
echo "TT: $TT"

27
bin/vm Executable file
View file

@ -0,0 +1,27 @@
# mount -t 9p -o trans=virtio,version=9p2000.L share /home/user
# this add to brake and inspect /dev if /dev/sda1 not found
# -append "root=/dev/sda1 console=ttyS0 rd.break"
function run {
qemu-system-x86_64 -append "root=/dev/sda1 console=ttyS0 rd.break" \
-kernel "vmlinuz-linux" \
-initrd "initramfs-linux.img" \
-m 2048 \
-smp $(sysctl -n hw.logicalcpu) \
-cpu qemu64 \
-virtfs local,path=.,security_model=none,mount_tag=share \
-drive id=root-disk,if=none,format=raw,file=linux.img \
-device ide-hd,bus=ide.0,drive=root-disk \
-drive id=data-disk,if=none,format=qcow2,file=dat.qcow2 \
-device ide-hd,bus=ide.1,drive=data-disk \
-nographic
}
function reset {
qemu-img create -f qcow2 dat.qcow2 32G
}
$1

9
bin/zshrc/brew Normal file
View file

@ -0,0 +1,9 @@
if [[ "$OSTYPE" == "darwin"* ]]; then
ARCH=$(uname -m)
if [[ "$ARCH" == "arm64" ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ "$ARCH" == "x86_64" ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
fi

21
bin/zshrc/init Normal file
View file

@ -0,0 +1,21 @@
# sources that might alter the path
. $DAT_ROOT/bin/zshrc/brew
export PATH="$DAT_ROOT/bin:$HOME/.local/bin:$PATH"
export RUBYLIB="$DAT_ROOT/lib"
export PASSWORD_STORE_DIR=$HOME/.local/secure-vault/passwords
path=("$GEM_HOME/bin" $path)
alias gf='git log --all --oneline | fzf'
function cdd {
cd $DAT_ROOT
}
. $DAT_ROOT/bin/zshrc/prompt
. $DAT_ROOT/bin/zshrc/utils
bindkey '^e' edit-command-line

44
bin/zshrc/prompt Normal file
View file

@ -0,0 +1,44 @@
# Enable vcs_info
autoload -Uz vcs_info
autoload -Uz add-zsh-hook
# Colors
GRAY="%F{245}"
PURPLE="%F{141}"
RED="%F{red}"
RESET="%f"
zstyle ':vcs_info:git:*' formats '%b'
zstyle ':vcs_info:*' enable git
git_precmd() {
vcs_info
if [[ -n "${vcs_info_msg_0_}" ]]; then
GIT_PROMPT="${PURPLE}(${RED}${vcs_info_msg_0_}${PURPLE}) "
else
GIT_PROMPT=""
fi
PROMPT="${GRAY}%n@%M ${RESET}%~ ${GIT_PROMPT}${PURPLE}➜ ${RESET}"
}
add-zsh-hook precmd git_precmd
# Prompt
# PROMPT='${GRAY}%n@%m ${RESET}%~ ${PURPLE}(${RED}${vcs_info_msg_0_}${PURPLE}) ➜ ${RESET}'
#
# vcs_info
# PROMPT='${GRAY}%n@%m ${RESET}%~ ${GIT_PROMPT}${PURPLE}➜ ${RESET}'
# PROMPT="${GRAY}%n@%M ${RESET}%~ ${GIT_PROMPT}${PURPLE}➜ ${RESET}"
# Mac OS
# export HOST="gurgul.pro"
# sudo scutil --set HostName "Mac-mini"
# Linux
# sudo hostnamectl set-hostname
# hostnamectl

16
bin/zshrc/utils Normal file
View file

@ -0,0 +1,16 @@
export EDITOR='nvim'
export GIT_EDITOR='nvim'
# git config --global core.editor "nvim"
alias ddd='date +"%d-%m-%Y"'
alias v='nvim'
# should be for linux only
alias ip='ip -c'
alias hist='eval `history | fzf | cut -s -d " " -f4-`'
export LC_ALL=en_US.UTF-8
export HISTSIZE=100000000

View file

@ -0,0 +1,4 @@
require("plugins")
require("options")
require("keymaps")
require("lsp")

View file

@ -0,0 +1,63 @@
local map = vim.keymap.set
map('n', '<leader>ff', require('telescope.builtin').find_files, { desc = "Find files" })
map('n', '<leader>fg', require('telescope.builtin').live_grep, { desc = "Live grep" })
map('n', '<leader>fb', require('telescope.builtin').buffers, { desc = "Buffers" })
map('n', '<leader>fh', require('telescope.builtin').help_tags, { desc = "Help tags" })
-- Project-specific ignored dirs for Telescope
local function load_local_ignore()
local cwd = vim.fn.getcwd()
local config_path = cwd .. "/.nvim.lua"
if vim.fn.filereadable(config_path) == 1 then
local ok, config = pcall(dofile, config_path)
if ok and config.fzf_ignore_dirs then
return config.fzf_ignore_dirs
end
end
return {}
end
local ignored = load_local_ignore()
local ignore_patterns = vim.tbl_map(function(d) return "**/" .. d .. "/*" end, ignored)
require('telescope').setup {
defaults = {
file_ignore_patterns = ignore_patterns,
}
}
-- za: Telescope open in current tab
vim.keymap.set('n', 'za', function()
require("telescope.builtin").find_files()
end, { desc = "Telescope: open file in current tab" })
-- zt: Telescope open in new tab
vim.keymap.set('n', 'zt', function()
require("telescope.builtin").find_files({
attach_mappings = function(_, map)
map("i", "<CR>", function(prompt_bufnr)
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
local entry = action_state.get_selected_entry()
actions.close(prompt_bufnr)
vim.cmd("tabedit " .. entry.value)
end)
return true
end,
})
end, { desc = "Telescope: open file in new tab" })
-- FZF
vim.keymap.set('n', 'zs', ':FZF<CR>', { noremap = true, silent = true })
vim.api.nvim_create_user_command('FZFInTab', function()
vim.fn['fzf#run'](vim.fn['fzf#wrap']({
sink = function(selected)
vim.cmd('tabedit ' .. selected)
end
}))
end, {})
vim.keymap.set('n', 'zy', ':FZFInTab<CR>', { noremap = true, silent = true })

View file

@ -0,0 +1,43 @@
local lspconfig = require("lspconfig")
-- Swift LSP
lspconfig.sourcekit.setup {}
-- Go LSP
lspconfig.gopls.setup {
cmd = { "gopls" },
filetypes = { "go", "gomod" },
root_dir = lspconfig.util.root_pattern("go.mod", ".git"),
settings = {
gopls = {
analyses = { unusedparams = true },
staticcheck = true,
},
},
}
-- Completion
local cmp = require("cmp")
cmp.setup({
snippet = {
expand = function(args)
vim.fn["vsnip#anonymous"](args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<Tab>"] = cmp.mapping.select_next_item(),
["<S-Tab>"] = cmp.mapping.select_prev_item(),
["<CR>"] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "vsnip" },
}, {
{ name = "buffer" },
{ name = "path" },
})
})
-- Syntastic config
vim.g.syntastic_swift_checkers = { 'swiftlint', 'swiftpm' }

View file

@ -0,0 +1,22 @@
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true
vim.opt.relativenumber = true
vim.opt.number = true
vim.opt.encoding = "utf-8"
vim.opt.list = true
vim.opt.listchars = {
eol = '¬',
tab = '',
trail = '~',
extends = '>',
precedes = '<',
space = '',
}
vim.api.nvim_create_autocmd("InsertLeave", {
pattern = "*",
command = "silent! write"
})

View file

@ -0,0 +1,57 @@
-- bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
-- Core
{ "nvim-lua/plenary.nvim" },
{
"nvim-telescope/telescope.nvim",
tag = "0.1.5",
lazy = false
},
-- LSP and Autocomplete
{ "neovim/nvim-lspconfig" },
{ "hrsh7th/nvim-cmp" },
{ "hrsh7th/cmp-nvim-lsp" },
{ "hrsh7th/cmp-buffer" },
{ "hrsh7th/cmp-path" },
{ "hrsh7th/cmp-cmdline" },
{ "hrsh7th/cmp-vsnip" },
{ "hrsh7th/vim-vsnip" },
-- Treesitter
{ "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" },
-- Appearance
{ "tomasiser/vim-code-dark" },
{ "vim-airline/vim-airline" },
{ "vim-airline/vim-airline-themes" },
-- File Explorer / Git / Misc
{ "preservim/nerdtree" },
{ "tpope/vim-fugitive" },
{ "rust-lang/rust.vim" },
{ "ray-x/go.nvim" },
{ "vim-syntastic/syntastic" },
{ "tokorom/syntastic-swiftlint.vim" },
})
vim.api.nvim_create_autocmd("User", {
pattern = "LazyDone",
callback = function()
vim.cmd("colorscheme codedark")
end,
})

View file

@ -0,0 +1,8 @@
# restarting an agent
# gpgconf --kill gpg-agent
# gpgconf --launch gpg-agent
default-cache-ttl 1209600
max-cache-ttl 1209600

5
home/.local/bin/index Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env ruby
require 'storage'
puts Storage.get_mounting_point("FBB4EC0E-2D2E-4EEE-AB16-8C1265D5F3EF")

192
install Executable file
View file

@ -0,0 +1,192 @@
#!/usr/bin/env bash
# ./install --system --forced
# --forced (not forced, does not delete old version, just ends in failure)
# --system (refault user)
# Defaults
force=false
system=false
# Parse arguments
for arg in "$@"; do
case "$arg" in
--forced)
forced=true
;;
--system)
system=true
;;
esac
done
# Set INSTALL_HOME to $HOME if not already set
: "${INSTALL_HOME:=$HOME}"
if [ "$system" = true ] && [ "$EUID" -ne 0 ]; then
echo "Not running as root. Re-running with sudo... $0"
exec sudo INSTALL_HOME="$INSTALL_HOME" "$0" "$@"
fi
REPO_URL="https://gitlab.com/artur.gurgul/home.git"
is_debian_like() {
if [ -r /etc/os-release ]; then
. /etc/os-release
if [ "$ID" = "debian" ] || printf '%s' "$ID_LIKE" | grep -qi 'debian'; then
return 0
fi
fi
[ -r /etc/debian_version ]
}
is_macos() {
[ "$(uname)" = "Darwin" ]
}
echo "Forced: $forced"
echo "System: $system"
# local
if [ "$system" = false ]; then
DAT_ROOT="\$HOME/.dat"
else
# system/linux
if is_debian_like; then
DAT_ROOT="/dat"
# MacOS
elif is_macos; then
DAT_ROOT="/opt/dat"
else
echo "OS is not supported"
exit -1
fi
fi
####################### ZSHRC ================================
echo "Create ~/.zshrc"
echo "export DAT_ROOT=$DAT_ROOT" > "$INSTALL_HOME/.zshrc"
echo ". \$DAT_ROOT/bin/zshrc/init" >> "$INSTALL_HOME/.zshrc"
export DAT_ROOT=$(echo "$DAT_ROOT" | envsubst)
####################### Dependencies =========================
debian_install_packages() {
# List of required packages
local packages=("git" "ruby")
local to_install=()
# Determine if we need to use sudo
local SUDO=""
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
fi
# Check each package
for pkg in "${packages[@]}"; do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
to_install+=("$pkg")
fi
done
# Install missing packages
if [ "${#to_install[@]}" -gt 0 ]; then
# Update and upgrade
$SUDO apt update
$SUDO apt upgrade -y
$SUDO apt install -y "${to_install[@]}"
else
echo "All required packages are already installed."
fi
}
macos_install_packages() {
# List of required packages
local packages=("git" "ruby")
local to_install=()
# Check for Homebrew
if ! command -v brew >/dev/null 2>&1; then
echo "Homebrew not found. Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv)" # Adjust for Apple Silicon
fi
# Check each package
for pkg in "${packages[@]}"; do
if ! brew list "$pkg" >/dev/null 2>&1; then
to_install+=("$pkg")
fi
done
# Install missing packages
if [ "${#to_install[@]}" -gt 0 ]; then
# Update Homebrew
brew update
brew install "${to_install[@]}"
else
echo "All required packages are already installed."
fi
}
if is_debian_like; then
debian_install_packages
elif is_macos; then
macos_install_packages
fi
####################### Cleaning previous installs ============
## if forced
clean_previous_installs() {
if [ "$system" = true ]; then
rm -rf /usr/bin/dat
fi
rm -rf $DAT_ROOT
}
if [ "$forced" = true ]; then
clean_previous_installs
fi
####################### Installing... =========================
install_dat() {
if [ -d "$DAT_ROOT" ]; then
if [ -d "$DAT_ROOT/.git" ]; then
echo "Directory exists and is a Git repository. Pulling latest changes..."
git -C "$DAT_ROOT" pull
else
echo "Directory exists but is not a Git repository."
read -p "Do you want to delete it and clone the repository? [y/N]: " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
rm -rf "$DAT_ROOT"
echo "Cloning repository..."
git clone $REPO_URL "$DAT_ROOT"
else
echo "Aborting installation."
return 1
fi
fi
else
echo "Directory does not exist. Cloning repository..."
git clone $REPO_URL "$DAT_ROOT"
fi
}
install_dat
####################### Make it global ========================
# Not done yet
install_global_zsh_deb() {
ln -s /dat/bin/dat /usr/bin/dat
cat > /etc/profile.d/dat.sh <<EOF
export RUBYLIB=$DAT_ROOT
EOF
}
####################### Make shell setable by user =============
####################### Set daemon that updates the dat ========

124
lib/install.rb Normal file
View file

@ -0,0 +1,124 @@
require 'system'
require 'find'
require 'fileutils'
require 'pathname'
module Install
MYSELF = File.symlink?(__FILE__) ? File.readlink(__FILE__) : __FILE__
DAT_LIB = File.expand_path(File.dirname(MYSELF))
DAT_ROOT = Pathname.new(DAT_LIB).parent
HOME = ENV["HOME"]
def self.base_update()
install_symlinks
end
def self.base_install()
#uninstall
install_symlinks
System.install(["neovim", "zsh"])
#install_ohmyzsh
create_zshrc
end
def self.uninstall()
system("rm -rf \"#{HOME}/.oh-my-zsh\"")
end
def self.create_zshrc()
content = <<~TEXT
src() {
[[ -e $1 ]] && source $1
}
export DAT_ROOT="#{DAT_ROOT}"
export RUBYLIB="#{DAT_LIB}"
export PATH="$HOME/.local/share/dat/bin:$HOME/.local/bin:$PATH"
src .zshrc-ohmyzsh
TEXT
File.write("#{ENV["HOME"]}/.zshrc", content)
system("source .zshrc")
end
def self.install_ohmyzsh()
puts "installing ohmyzsh ===="
url_execute 'https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh'
content = <<~TEXT
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="robbyrussell"
plugins=(git)
source $ZSH/oh-my-zsh.sh
TEXT
File.write("#{ENV["HOME"]}/.zshrc-ohmyzsh", content)
end
def self.url_execute(url)
require 'net/http'
require 'uri'
require 'tempfile'
uri = URI.parse(url)
response = Net::HTTP.get_response(uri)
puts "downloading ended"
if response.is_a?(Net::HTTPSuccess)
Tempfile.create(['install', '.sh']) do |file|
file.write(response.body)
file.flush
File.chmod(0755, file.path)
system("/bin/sh", file.path)
puts "=======> step 1"
end
else
puts "Failed to download script: #{response.code} #{response.message}"
end
puts "=======> step 2"
end
# this creates search path for workspace
def self.workspace_search_paths
workspace_path = File.join(DAT_ROOT, "workspace")
Dir["#{workspace_path}/*/bin"].map { |path| "\"#{path}\"" }.join(" ")
end
def self.symlink_dir(from, to)
walk_files from do |path|
puts path
create_symlink File.join(from, path), File.join(to, path)
end
end
def self.install_symlinks()
link_to = File.join(DAT_ROOT, "home")
symlink_dir link_to, HOME
end
def self.create_symlink(source, destination)
destination_dir = File.dirname destination
FileUtils.mkdir_p destination_dir unless File.exist? destination_dir
if File.symlink? destination
File.delete destination
elsif File.exist? destination
File.delete destination
end
File.symlink source, destination
end
def self.walk_files(base_path)
raise ArgumentError, "Base path must be a directory" unless File.directory? base_path
Find.find base_path do |path|
rel_path = path.sub "#{base_path}/" , ""
if File.file? path
yield rel_path if block_given?
end
end
end
end

179
lib/make.rb Normal file
View file

@ -0,0 +1,179 @@
require 'yaml'
require 'tmpdir'
require 'system'
require 'ostruct'
require 'fileutils'
require 'open3'
# make for: the user, system, package
# as regular user, if dependencies provided
# user: $HOME/.local
# as super user
# system: /
# package: /pkg/$name/$version/
module Make
def self.rostruct(obj)
case obj
when Hash
OpenStruct.new(obj.transform_values { |v| rostruct(v) })
when Array
obj.map { |v| rostruct(v) }
else
obj
end
end
class Context
attr_accessor :name, :use_cache, :environment, :steps, :packages, :repository
attr_accessor :target
def initialize(options: OpenStruct.new)
@target = options.target || :user
@name = options.name
@use_cache = options.use_cache || false
makefile_path = "#{ENV["DAT_ROOT"]}/recipes/#{@name}.yml"
puts "recipe at: #{makefile_path}"
makefile = YAML.load_file(makefile_path)
# puts makefile_path
# puts makefile
@packages = makefile["packages"] || []
@repository = Make.rostruct(makefile["repository"] || OpenStruct.new)
@steps = makefile["steps"] || []
@environment = ENV.to_h.merge(
"PREFIX" => get_prefix
)
environment = makefile["environment"]
if environment != nil
@environment = environment.merge(@environment)
end
end
def get_prefix
case @target
when :user
"#{ENV["HOME"]}/.local"
when :package
"/pkg/#{@name}/#{@repository.branch}"
when :system
"/"
end
end
# Root project directory
def rpd
puts @repository
if @use_cache
path = "#{ENV["HOME"]}/.cache/dat/build/#{@name}/#{@repository.branch}"
FileUtils.mkdir_p(path)
yield path
else
Dir.mktmpdir do |tmp_path|
yield tmp_path
end
end
end
def local_repo
"#{ENV["HOME"]}/.cache/dat/repo/#{@name}.git"
end
def to_s
vars = instance_variables.map do |var|
"#{var.to_s.delete('@')}: #{instance_variable_get(var).inspect}"
end
"Context(#{vars.join(', ')})"
end
end
class Builder
attr_accessor :context, :cwd
def initialize(context)
@context = context
end
def execute(command)
if command.strip.start_with?("cd ")
eval_cmd = command.sub(/^cd /, 'echo ')
# new_dir = `#{eval_cmd}`.strip
new_dir, stderr, status = Open3.capture3(@context.environment, eval_cmd)
begin
puts "Dir: #{Dir.pwd}"
# new_dir = File.expand_path(new_dir)
new_dir = new_dir.strip
puts "Exists #{new_dir} => #{Dir.exist?(new_dir)}"
Dir.chdir(new_dir)
puts "Changed directory to #{Dir.pwd}"
rescue Errno::ENOENT
puts "Directory not found: #{new_dir}"
end
else
system(@context.environment, command)
end
end
def build
install
@context.rpd do | path |
@cwd = path
checkout
puts "path: #{path}"
Dir.chdir(path)
@context.steps.each do |command|
# system(env, command)
execute(command)
# need to be refreshed
# rehash # hash -r # https://chatgpt.com/c/6880b3d6-b190-8330-9623-0458254d2881
end
end
end
def checkout
repo_path = @context.local_repo
repo_url = @context.repository.url
branch = @context.repository.branch
puts "Local bare git repo path: #{repo_path}"
if Dir.exist?(repo_path) && !Dir.empty?(repo_path)
puts "Bare repo exists, fetching updates..."
Dir.chdir(repo_path) do
system("git fetch origin")
end
else
puts "Cloning bare repository..."
FileUtils.mkdir_p(repo_path)
system("git clone --bare #{repo_url} #{repo_path}")
end
system("git --git-dir=#{repo_path} --work-tree=#{@cwd} checkout -f #{branch}")
end
def install
System.install(context.packages)
end
end
# dat make -t pkg --cache --name dry-run
# dat make --name dry-run
def self.command(options)
context = Context.new(options: options)
builder = Builder.new(context)
builder.build
end
end

25
lib/server.rb Normal file
View file

@ -0,0 +1,25 @@
module Server
def self.setup(domain)
self.install_domain("gurgul.org")
end
def self.install_domain(domain)
self.install(["certbot", "nginx"])
system("sudo certbot certonly --manual --preferred-challenges=dns -d \"*.#{domain}\" -d \"#{domain}\"")
# check if direcotry exists /etc/letsencrypt/live/gurgul.org
# create user domain =>
end
def self.add_service(name)
end
def self.setting()
system("sudo dpkg-reconfigure locales")
system("sudo apt-get install locales-all")
end
end

28
lib/storage.rb Normal file
View file

@ -0,0 +1,28 @@
require 'plist'
# gem install plist
# gem pristine io-console --version 0.7.2
module Storage
def self.get_mounting_point(uuid)
if RUBY_PLATFORM.include?("darwin")
output = `diskutil list -plist`
plist = Plist.parse_xml(output)
plist["AllDisksAndPartitions"].each do |disk|
if disk["APFSVolumes"]
disk["APFSVolumes"].each do |partition|
if partition["DiskUUID"] == uuid
return partition["MountPoint"]
end
end
end
end
else
puts "TODO: Implement for Linux"
end
return nil
end
end

35
lib/system.rb Normal file
View file

@ -0,0 +1,35 @@
module System
def self.detect_os
case RUBY_PLATFORM
when /darwin/
:macos
when /linux/
if File.exist?('/etc/debian_version')
:debian
else
:linux_other
end
else
:unknown
end
end
OS = detect_os
case OS
when :macos
require_relative './system/macos'
extend MacOSSystem
when :debian
require_relative './system/debian'
extend DebianSystem
else
raise "Operating system not supported"
end
def self.os_info
puts os_name
end
end

45
lib/system/debian.rb Normal file
View file

@ -0,0 +1,45 @@
module DebianSystem
def os_name
"Debian Linux"
end
def install(packages)
missing_packages = packages.reject { |pkg| package_installed?(pkg) }
if missing_packages.empty?
puts "All packages are already installed."
return
end
pkg_list = missing_packages.join(' ')
puts "Installing missing packages: #{pkg_list}"
success = system("sudo apt-get update && sudo apt-get install -y #{pkg_list}")
unless success
puts "Failed to install some packages."
end
end
def package_installed?(package)
system("dpkg -s #{package} > /dev/null 2>&1")
end
def uninstall(packages)
installed_packages = packages.select { |pkg| package_installed?(pkg) }
if installed_packages.empty?
puts "None of the specified packages are installed."
return
end
pkg_list = installed_packages.join(' ')
puts "Uninstalling packages: #{pkg_list}"
success = system("sudo apt-get remove -y #{pkg_list}")
unless success
puts "Failed to uninstall some packages."
end
end
end

45
lib/system/macos.rb Normal file
View file

@ -0,0 +1,45 @@
module MacOSSystem
def os_name
"macOS"
end
def install(packages)
missing_packages = packages.reject { |pkg| package_installed?(pkg) }
if missing_packages.empty?
puts "All packages are already installed."
return
end
pkg_list = missing_packages.join(' ')
puts "Installing missing packages: #{pkg_list}"
success = system("brew install #{pkg_list}")
unless success
puts "Failed to install some packages."
end
end
def package_installed?(package)
system("brew list --formula | grep -qx #{package}")
end
def uninstall(packages)
installed_packages = packages.select { |pkg| package_installed?(pkg) }
if installed_packages.empty?
puts "None of the specified packages are installed."
return
end
pkg_list = installed_packages.join(' ')
puts "Uninstalling packages: #{pkg_list}"
success = system("brew uninstall #{pkg_list}")
unless success
puts "Failed to uninstall some packages."
end
end
end

6
readme.md Normal file
View file

@ -0,0 +1,6 @@
# Installing the environment
```bash
curl -sSL https://gitlab.com/artur.gurgul/home/-/raw/main/install | bash
```

15
recipes/dry-run.yml Normal file
View file

@ -0,0 +1,15 @@
environment:
WORK_DIR: src
packages:
- git
repository:
url: https://gurgul.pro/service/webdav.git
branch: main
steps:
- echo installing in $PREFIX
- cd $WORK_DIR
- ls

23
recipes/forgejo.yml Normal file
View file

@ -0,0 +1,23 @@
environment:
GO_VERSION: 1.22.3
packages:
- git
- make
- curl
- wget
- gcc
- g++
- npm
- build-essential
repository:
url: https://code.forgejo.org/forgejo/forgejo.git
branch: v12.0.0
steps:
- wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz
- mkdir .local
- tar -C ./.local -xzf go$GO_VERSION.linux-amd64.tar.gz
- export PATH=$(pwd)/.local/go/bin:$HOME/go/bin:$PATH

19
recipes/gcc.yml Normal file
View file

@ -0,0 +1,19 @@
packages:
- build-essential
- libgmp-dev
- libmpfr-dev
- libmpc-dev
- flex
- bison
- texinfo
- wget
repository:
url: git://gcc.gnu.org/git/gcc.git
branch: releases/gcc-15.1.0
steps:
- ./contrib/download_prerequisites
- ./configure --prefix=$HOME/.local --enable-languages=c,c++ --disable-multilib
- make -j$(nproc)
- make install

16
recipes/llvm.yml Normal file
View file

@ -0,0 +1,16 @@
repository:
url: https://github.com/llvm/llvm-project.git
branch: llvmorg-20.1.8
steps:
- mkdir build
- cd build
- cd build && cmake -G Ninja ../llvm |
-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld" |
-DCMAKE_C_COMPILER=clang |
-DCMAKE_CXX_COMPILER=clang++ |
-DCMAKE_BUILD_TYPE=Release |
-DCMAKE_INSTALL_PREFIX=../install
- cd build && ninja
- cd build && ninja install

13
recipes/meson.yml Normal file
View file

@ -0,0 +1,13 @@
dependencies:
- python
packages:
ninja-build
repository:
url: https://github.com/mesonbuild/meson.git
branch: 1.8.2
steps:
# - pip install -U pip setuptools
- pip install --user .

21
recipes/node.yml Normal file
View file

@ -0,0 +1,21 @@
environment:
- CC=~/.local/bin/gcc
- CXX=~/.local/bin/g++
- LD_LIBRARY_PATH=~/.local/lib64:$LD_LIBRARY_PATH
packages:
- git
- python3
- make
- g++
- pkg-config
- libssl-dev
repository:
url: https://github.com/nodejs/node.git
branch: v24.4.1
steps:
- ./configure --prefix=$HOME/.local
- make -j$(nproc)
- make install

12
recipes/nvim.yml Normal file
View file

@ -0,0 +1,12 @@
packages:
- cmake
- build-essential
repository:
url: https://github.com/neovim/neovim.git
branch: release-0.11
steps:
- make distclean
- make CMAKE_BUILD_TYPE=Release CMAKE_INSTALL_PREFIX=$HOME/.local
- make install

23
recipes/python.yml Normal file
View file

@ -0,0 +1,23 @@
packages:
- build-essential
- zlib1g-dev
- libncurses5-dev
- libgdbm-dev
- libnss3-dev
- libssl-dev
- libreadline-dev
- libffi-dev
- curl
- libsqlite3-dev
- wget
- libbz2-dev
- liblzma-dev
repository:
url: https://github.com/python/cpython.git
branch: v3.13.5
steps:
- ./configure --enable-optimizations --prefix=$HOME/.local
- make -j"$(nproc)"
- make install

24
recipes/ruby.yml Normal file
View file

@ -0,0 +1,24 @@
packages:
- autoconf
- bison
- build-essential
- libssl-dev
- libyaml-dev
- libreadline6-dev
- zlib1g-dev
- libncurses5-dev
- libffi-dev
- libgdbm6
- libgdbm-dev
- libdb-dev
- ruby
repository:
url: https://github.com/ruby/ruby.git
branch: v3_4_5
steps:
- ./autogen.sh
- ./configure --prefix=$PREFIX
- make -j"$(nproc)"
- make install

8
recipes/test.yml Normal file
View file

@ -0,0 +1,8 @@
environment:
TEST_ENV: testowa
steps:
- test-env
- ls -lah
- TT=val test-env

14
recipes/wayland.yml Normal file
View file

@ -0,0 +1,14 @@
packages:
- graphviz
- doxygen
- xmlto
repository:
url: https://gitlab.freedesktop.org/wayland/wayland.git
branch: 1.24
steps:
- meson setup build
- ninja -C build
- ninja -C build install

57
recipes/webkit.yml Normal file
View file

@ -0,0 +1,57 @@
packages:
- build-essential
- cmake
- git
- ninja-build
- clang
- libglib2.0-dev
- libgtk-3-dev
- libsoup2.4-dev
- libjpeg-dev
- libpng-dev
- libwebp-dev
- libxml2-dev
- libxslt1-dev
- libsecret-1-dev
- gobject-introspection
- libgirepository1.0-dev
- libenchant-2-dev
- libicu-dev
- libgeoclue-2-dev
- ruby
- ruby-dev
- python3-pip
- liblcms2-dev
- gperf
- bison
- flex
- unifdef
- libwoff1
- libwoff-dev
- libharfbuzz-dev
- libsqlite3-dev
- libatspi2.0-dev
- libtasn1-6-dev
- libwebpdemux2
- libopenjp2-7-dev
- libepoxy-dev
- libbrotli-dev
- libzstd-dev
- gettext
- gi-docgen
- libgstreamer-plugins-base1.0-dev
- libhyphen-dev
- libgstreamer1.0-dev
- libgstreamer-plugins-base1.0-dev
repository:
url: https://github.com/WebKit/WebKit.git
branch: webkitgtk-2.49.3
steps:
- mkdir -p WebKitBuild/Release
- cd WebKitBuild/Release
- cmake -GNinja -DENABLE_SPEECH_SYNTHESIS=OFF -DUSE_LIBBACKTRACE=OFF -DPORT=GTK -DCMAKE_INSTALL_PREFIX=$HOME/.local ../../
- ninja
- ninja install

40
recipes/wlroots.yml Normal file
View file

@ -0,0 +1,40 @@
packages:
- git
- meson
- ninja-build
- cmake
- wayland-protocols
- pkg-config
- scdoc
- libjson-c-dev
- libpcre2-dev
- libevdev-dev
- libudev-dev
- libinput-dev
- libxkbcommon-dev
- libwayland-dev
- libwayland-egl-backend-dev
- libdrm-dev
- libgbm-dev
- libegl1-mesa-dev
- libgles2-mesa-dev
- libxcb1-dev
- libxcb-composite0-dev
- libxcb-xfixes0-dev
- libxcb-image0-dev
- libxcb-render0-dev
- libxcb-res0-dev
- libxcb-icccm4-dev
- libxcb-xkb-dev
- libxcb-ewmh-dev
- libxkbcommon-x11-dev
- libpixman-1-dev
- libsystemd-dev
- libcap-dev
repository:
url: https://gitlab.freedesktop.org/wlroots/wlroots.git
branch: 0.19
steps:

15
recipes/zsh.yml Normal file
View file

@ -0,0 +1,15 @@
packages:
- build-essential
- git
- libncursesw5-dev
- libreadline-dev
repository:
url: https://github.com/zsh-users/zsh.git
branch: zsh-5.9
steps:
- ./Util/preconfig
- ./configure --prefix=$HOME/.local
- make
- make install