commit b3dba4542f2a676c74c76ca7222d8ef54c3752db Author: Artur Gurgul Date: Fri Aug 1 12:52:57 2025 +0200 init diff --git a/bin/dat b/bin/dat new file mode 100755 index 0000000..ce39498 --- /dev/null +++ b/bin/dat @@ -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 diff --git a/bin/img.create b/bin/img.create new file mode 100755 index 0000000..f0fba67 --- /dev/null +++ b/bin/img.create @@ -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 + diff --git a/bin/img.extend b/bin/img.extend new file mode 100755 index 0000000..41d0f1d --- /dev/null +++ b/bin/img.extend @@ -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 + diff --git a/bin/img.run b/bin/img.run new file mode 100755 index 0000000..5a030ca --- /dev/null +++ b/bin/img.run @@ -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 diff --git a/bin/makeshell b/bin/makeshell new file mode 100644 index 0000000..0a71f89 --- /dev/null +++ b/bin/makeshell @@ -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 diff --git a/bin/pclean b/bin/pclean new file mode 100755 index 0000000..928c316 --- /dev/null +++ b/bin/pclean @@ -0,0 +1,3 @@ + +make clean +git clean -fdx diff --git a/bin/server b/bin/server new file mode 100755 index 0000000..0019550 --- /dev/null +++ b/bin/server @@ -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 \ No newline at end of file diff --git a/bin/shell b/bin/shell new file mode 100755 index 0000000..01b6e78 --- /dev/null +++ b/bin/shell @@ -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 + diff --git a/bin/test-env b/bin/test-env new file mode 100755 index 0000000..64076bb --- /dev/null +++ b/bin/test-env @@ -0,0 +1,6 @@ +#!/usr/bin/bash + +echo "Passed prefix: $PREFIX" +echo "Dat: $DAT_ROOT" +echo "test: ${TEST_ENV}" +echo "TT: $TT" diff --git a/bin/vm b/bin/vm new file mode 100755 index 0000000..ed29799 --- /dev/null +++ b/bin/vm @@ -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 diff --git a/bin/zshrc/brew b/bin/zshrc/brew new file mode 100644 index 0000000..4e13a77 --- /dev/null +++ b/bin/zshrc/brew @@ -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 \ No newline at end of file diff --git a/bin/zshrc/init b/bin/zshrc/init new file mode 100644 index 0000000..151a61e --- /dev/null +++ b/bin/zshrc/init @@ -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 \ No newline at end of file diff --git a/bin/zshrc/prompt b/bin/zshrc/prompt new file mode 100644 index 0000000..529d4ec --- /dev/null +++ b/bin/zshrc/prompt @@ -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 + + + diff --git a/bin/zshrc/utils b/bin/zshrc/utils new file mode 100644 index 0000000..a862dd8 --- /dev/null +++ b/bin/zshrc/utils @@ -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 \ No newline at end of file diff --git a/home/.config/nvim/init.lua b/home/.config/nvim/init.lua new file mode 100644 index 0000000..1f37ecf --- /dev/null +++ b/home/.config/nvim/init.lua @@ -0,0 +1,4 @@ +require("plugins") +require("options") +require("keymaps") +require("lsp") \ No newline at end of file diff --git a/home/.config/nvim/lua/keymaps.lua b/home/.config/nvim/lua/keymaps.lua new file mode 100644 index 0000000..48e81e4 --- /dev/null +++ b/home/.config/nvim/lua/keymaps.lua @@ -0,0 +1,63 @@ +local map = vim.keymap.set + +map('n', 'ff', require('telescope.builtin').find_files, { desc = "Find files" }) +map('n', 'fg', require('telescope.builtin').live_grep, { desc = "Live grep" }) +map('n', 'fb', require('telescope.builtin').buffers, { desc = "Buffers" }) +map('n', '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", "", 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', { 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', { noremap = true, silent = true }) + diff --git a/home/.config/nvim/lua/lsp.lua b/home/.config/nvim/lua/lsp.lua new file mode 100644 index 0000000..1352071 --- /dev/null +++ b/home/.config/nvim/lua/lsp.lua @@ -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({ + [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping.select_prev_item(), + [""] = 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' } + diff --git a/home/.config/nvim/lua/options.lua b/home/.config/nvim/lua/options.lua new file mode 100644 index 0000000..c169551 --- /dev/null +++ b/home/.config/nvim/lua/options.lua @@ -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" +}) + diff --git a/home/.config/nvim/lua/plugins.lua b/home/.config/nvim/lua/plugins.lua new file mode 100644 index 0000000..8ecfd76 --- /dev/null +++ b/home/.config/nvim/lua/plugins.lua @@ -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, +}) diff --git a/home/.gnupg/gpg-agent.conf b/home/.gnupg/gpg-agent.conf new file mode 100644 index 0000000..1d54635 --- /dev/null +++ b/home/.gnupg/gpg-agent.conf @@ -0,0 +1,8 @@ +# restarting an agent +# gpgconf --kill gpg-agent +# gpgconf --launch gpg-agent + + +default-cache-ttl 1209600 +max-cache-ttl 1209600 + diff --git a/home/.local/bin/index b/home/.local/bin/index new file mode 100755 index 0000000..2ad4cbc --- /dev/null +++ b/home/.local/bin/index @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require 'storage' + +puts Storage.get_mounting_point("FBB4EC0E-2D2E-4EEE-AB16-8C1265D5F3EF") diff --git a/install b/install new file mode 100755 index 0000000..3c5243c --- /dev/null +++ b/install @@ -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 < 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 + diff --git a/lib/make.rb b/lib/make.rb new file mode 100644 index 0000000..edbf753 --- /dev/null +++ b/lib/make.rb @@ -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 \ No newline at end of file diff --git a/lib/server.rb b/lib/server.rb new file mode 100644 index 0000000..3ca1c97 --- /dev/null +++ b/lib/server.rb @@ -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 \ No newline at end of file diff --git a/lib/storage.rb b/lib/storage.rb new file mode 100644 index 0000000..2508d7d --- /dev/null +++ b/lib/storage.rb @@ -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 diff --git a/lib/system.rb b/lib/system.rb new file mode 100644 index 0000000..14aee45 --- /dev/null +++ b/lib/system.rb @@ -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 diff --git a/lib/system/debian.rb b/lib/system/debian.rb new file mode 100644 index 0000000..61170c8 --- /dev/null +++ b/lib/system/debian.rb @@ -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 diff --git a/lib/system/macos.rb b/lib/system/macos.rb new file mode 100644 index 0000000..7cacd3d --- /dev/null +++ b/lib/system/macos.rb @@ -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 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0bae34a --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ + +# Installing the environment + +```bash +curl -sSL https://gitlab.com/artur.gurgul/home/-/raw/main/install | bash +``` diff --git a/recipes/dry-run.yml b/recipes/dry-run.yml new file mode 100644 index 0000000..f5258b5 --- /dev/null +++ b/recipes/dry-run.yml @@ -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 + diff --git a/recipes/forgejo.yml b/recipes/forgejo.yml new file mode 100644 index 0000000..110c29e --- /dev/null +++ b/recipes/forgejo.yml @@ -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 diff --git a/recipes/gcc.yml b/recipes/gcc.yml new file mode 100644 index 0000000..0cd1029 --- /dev/null +++ b/recipes/gcc.yml @@ -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 diff --git a/recipes/llvm.yml b/recipes/llvm.yml new file mode 100644 index 0000000..aec9cfc --- /dev/null +++ b/recipes/llvm.yml @@ -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 diff --git a/recipes/meson.yml b/recipes/meson.yml new file mode 100644 index 0000000..390374e --- /dev/null +++ b/recipes/meson.yml @@ -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 . diff --git a/recipes/node.yml b/recipes/node.yml new file mode 100644 index 0000000..701d531 --- /dev/null +++ b/recipes/node.yml @@ -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 diff --git a/recipes/nvim.yml b/recipes/nvim.yml new file mode 100644 index 0000000..34d8313 --- /dev/null +++ b/recipes/nvim.yml @@ -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 diff --git a/recipes/python.yml b/recipes/python.yml new file mode 100644 index 0000000..e476fd0 --- /dev/null +++ b/recipes/python.yml @@ -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 diff --git a/recipes/ruby.yml b/recipes/ruby.yml new file mode 100644 index 0000000..b715b8a --- /dev/null +++ b/recipes/ruby.yml @@ -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 diff --git a/recipes/test.yml b/recipes/test.yml new file mode 100644 index 0000000..3cd05e9 --- /dev/null +++ b/recipes/test.yml @@ -0,0 +1,8 @@ + +environment: + TEST_ENV: testowa + +steps: + - test-env + - ls -lah + - TT=val test-env diff --git a/recipes/wayland.yml b/recipes/wayland.yml new file mode 100644 index 0000000..a731ded --- /dev/null +++ b/recipes/wayland.yml @@ -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 diff --git a/recipes/webkit.yml b/recipes/webkit.yml new file mode 100644 index 0000000..c2dca0f --- /dev/null +++ b/recipes/webkit.yml @@ -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 + diff --git a/recipes/wlroots.yml b/recipes/wlroots.yml new file mode 100644 index 0000000..f466c2b --- /dev/null +++ b/recipes/wlroots.yml @@ -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: + diff --git a/recipes/zsh.yml b/recipes/zsh.yml new file mode 100644 index 0000000..01173df --- /dev/null +++ b/recipes/zsh.yml @@ -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