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

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