diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-07-14 08:41:14 +0200 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2025-07-14 08:41:14 +0200 |
| commit | a999e73e28f0875fc811c62725712d01818e3b59 (patch) | |
| tree | ef5546e714b29d126ad1f06f158b8c8886ed2822 /bin/doctor.rb | |
| parent | 0ee7a0b129facc85063a042d685613cd4f0a1d2e (diff) | |
| download | dotfiles-a999e73e28f0875fc811c62725712d01818e3b59.tar.gz dotfiles-a999e73e28f0875fc811c62725712d01818e3b59.zip | |
bin: Introduce the doctor.rb install/update script
This replaces the good ol' install.sh script, and it allows me to not
only install on a new system, but also upgrade dependencies, repair
broken links, etc. This is certainly not Nix, but at least it's not as
bad as it used to be.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'bin/doctor.rb')
| -rwxr-xr-x | bin/doctor.rb | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/bin/doctor.rb b/bin/doctor.rb new file mode 100755 index 0000000..3b0093a --- /dev/null +++ b/bin/doctor.rb @@ -0,0 +1,192 @@ +# frozen_string_literal: true + +# Copyright (C) 2025-Ω Miquel Sabaté Solà <mikisabate@gmail.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +require 'fileutils' +require 'pathname' + +## +# Early checks. + +raise 'Only Linux on x86 supported!' if RUBY_PLATFORM != 'x86_64-linux' +raise 'Only CRuby, sorry!' if RUBY_ENGINE != 'ruby' + +## +# Util functions. + +def has?(executable:) + exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] + + ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| + exts.each do |ext| + exe = File.join(path, "#{executable}#{ext}") + return exe if File.executable?(exe) && !File.directory?(exe) + end + end + + false +end + +## +# Mandatory binaries. + +puts '0. Checking on binaries needed for the system.' + +pending = [] +%w[git curl emacs vim mise go cargo ruby rg].each do |bin| + pending << bin unless has?(executable: bin) +end + +if pending.size.positive? + puts "You need to install: #{pending.join(', ')}." + exit 0 +end + +## +# Symbolic links and all that jazz. + +puts '1. Creating symlinks.' + +raise 'Dude, something is really funky on your HOME!' unless Dir.exist?(Dir.home) + +SOURCE = Pathname.new("#{File.dirname(__FILE__)}/..").realpath + +files = %w[ + bin .vim + .gnupg/gpg-agent.conf .gnupg/gpg.conf + .config/alacritty .config/emacs .config/gdb .config/ghostty .config/irb + .config/mise .config/msmtp .config/mimeapps.list .config/user-dirs.dirs + .bash_profile .bashrc .clang-format .gemrc .gitconfig .gitconfig-suse + .hunspell_ca_ES .inputrc .mbsyncrc .psqlrc .rvmrc .tmux.conf .valgrindrc .vimrc +] + +files.each do |f| + dst = File.join(Dir.home, f) + FileUtils.rm_f(dst) + + src = File.join(SOURCE, f) + File.symlink(src, dst) +end + +# The global .gitignore needs a rename. +dst = File.join(Dir.home, '.gitignore') +FileUtils.rm_f(dst) +File.symlink(File.join(SOURCE, '.global.gitignore'), dst) + +## +# Stuff I'm wildly downloading from the internet. + +puts "2. Downloading stuff from the internet." + +src_home = File.join(Dir.home, 'src/github.com/mssola') + +# The 'g' utility. +if File.exist?(File.join(src_home, 'g')) + Dir.chdir(File.join(src_home, 'g')) + puts ">> pulling github.com/mssola/g..." + system('git pull --rebase') +else + Dir.chdir(src_home) + puts ">> cloning github.com/mssola/g..." + system('git clone git@github.com:mssola/g.git') +end + +# And link the relevant files from 'g'. +%w[g.sh gcompletion.sh].each do |file| + dst = File.join(Dir.home, ".#{file}") + FileUtils.rm_f(dst) if File.exist?(dst) + File.symlink(File.join(src_home, "g/#{file}"), dst) +end + +# The 'soria' theme for GNU Emacs. +if File.exist?(File.join(src_home, 'soria')) + Dir.chdir(File.join(src_home, 'soria')) + puts ">> pulling github.com/mssola/soria..." + system('git pull --rebase') +else + Dir.chdir(src_home) + puts ">> cloning github.com/mssola/soria..." + system('git clone git@github.com:mssola/soria.git') +end + +# git-prompt +puts ">> downloading git-prompt.sh from git/contrib..." +dst = File.join(Dir.home, '.git-prompt.sh') +FileUtils.rm_f(dst) if File.exist?(dst) +system("curl -o #{dst} https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh") +puts '' + +## +# Dependencies from programming languages. + +puts "3. Installing/updating dependencies from programming languages." + +system('go install golang.org/x/tools/gopls@latest') +system('go install golang.org/x/tools/cmd/goimports@latest') + +system('gem install rubocop') +system('gem install solargraph') + +## +# Optional stuff. + +extra = [] +unless has?(executable: 'delta') + extra << 'git-delta' + puts "[!!] 'git-delta' is not installed: 'magit-delta' won't work!" +end + +unless has?(executable: 'mu') + extra << 'maildir-utils' + puts "[!!] 'mu/mu4e' is not installed: email won't work!" +end + +unless has?(executable: 'mbsync') + extra << 'isync' + puts "[!!] 'mbsync' is not installed: fetching emails won't work!" +end + +unless has?(executable: 'difft') + extra << 'difftastic' + puts "[!!] 'difftastic' is not installed: git won't look as awesome!" +end + +git_send_email = "/usr/libexec/git/git-send-email" +if !File.exist?(git_send_email) || !File.executable?(git_send_email) + extra << 'git-email' + puts "[!!] 'git send-email' is not installed: you won't be able to send patches via email!" +end + +if extra.size.positive? + print "\n=> You can install all of that with:\n" + puts " => zypper in #{extra.join(' ')}" +end + +## +# Binaries which need to go global. + +extra = [] +(Dir.glob(SOURCE.join('bin/zypper-*')) << SOURCE.join('bin/e')).map do |src| + dst = "/usr/bin/#{File.basename(src)}" + extra << "ln -s #{src} #{dst}" unless File.exist?(dst) +end + +if extra.size.positive? + print "\n=> Extra work: run the following while being *root*.\n\n" + puts extra.join("\n") +end + +puts "Done!" |
