Dotfiles, część 2: argumenty

W poprzedniej części przedstawiłem zarys sposobu działania frameworku obsługującego instalację i zarządzanie zbiorami konfiguracji, którego jestem autorem, i którego używam na co dzień. W tej części opowiem bardziej szczegółowo o tym jak wywołuje się polecenia instalacji.

Potrzeba argumentów pozycyjnych

O tym, że instalacja modułów wywoływana jest przez polecenie config-manage install, a także o tym co wtedy dzieje się pod maską, nie będę przypominał, gdyż ten temat załatwiliśmy poprzednim razem. Czasem jednak chcielibyśmy dodatkowo sparametryzować wywołania instalatora. Na przykład, możemy zechcieć stworzyć1 moduł pkg, który będzie skarbnicą zasad kompilacji i instalacji paczek. Nie ma sensu przekompilowywać wszystkich paczek za każdym razem, gdyż zajęłoby to zbyt wiele czasu - kompilacja jest niezbędna tylko w przypadku braku danej paczki lub potrzeby jej aktualizacji.

Summa summarum config-manage to program do wywoływania szeregu komend. Dlatego niezbędna będzie nam komenda, która na podstawie przekazanych parametrów wywoła odpowiednie zadania kompilacji/instalacji dla konkretnej paczki. Będzie to parametryzowany skrypt, który umieścimy wewnątrz katalogu modułu. Drzewo plików może wówczas wyglądać następująco:

$HOME/config/
    pkg/
        firefox/
            Makefile
        neovim/
            Makefile
        other-program/
            Makefile
        install

    config.ini

Sam skrypt install może zaś wyglądać na przykład tak:

#!/bin/bash

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

if [[ "$1" != "" ]]; then
    for name in $@; do
        (cd "$DIR/$name" && make && make install)
    done
    exit
fi

for pkg in $(find "${DIR}" -mindepth 1 -maxdepth 1 -type d); do
    (cd "$DIR/$pkg" && make && make install)
done

Jego jedynym zadaniem jest przeanalizowanie przekazanych mu nazw paczek i wywołanie dla nich poleceń make i make install, które zawierają ostateczny opis procedury kompilacji i instalacji. W przypadku gdy skrypt nie otrzyma żadnego parametru, rozpocznie kompilację wszystkich paczek znalezionych w tym samym katalogu, w którym się znajduje.

Oczywiście skrypt taki może wywoływać dowolne inne polecenia i być w dowolnie skomplikowany - podałem jedynie łatwy do przetrawienia przykład.

Wywołanie skryptu install

Tak uzbrojeni, musimy teraz jedynie przekazać odpowiednie argumenty do skryptu install. Z poziomu konsoli wywołalibyśmy go np. poleceniem pkg/install neovim albo pkg/install firefox. W przypadku programu config-manage sprawa jest nieco bardziej skomplikowana, ale nie znów aż tak bardzo: dla każdego argumentu polecenia install lub uninstall można podać po dwukropku dodatkowe argumenty, które zostaną przypisane do specjalnej zmiennej ${posargs} dostępnej wewnątrz pliku konfiguracyjnego. Sekcja pliku config.ini dla modułu pkg wyglądać będzie w naszym przypadku następująco:

[pkg]
install_cmd = ${targetname}/install ${posargs}

Jeśli install_cmd zawierałoby więcej komend, to każda z nich mogłaby przyjmować zmienną ${posargs} (co jednak wielce prawdopodobnie nie ma większego sensu).

Samo wywołanie config-manage wyglądać będzie następująco (zwracam uwagę na drugie wywołanie: jeśli potrzebujemy rozdzielić spacjami część argumentów/opcji, musimy całość ująć w cudzysłów tak, aby słowo firefox zostało potraktowane jako część wywołania modułu pkg, a nie oddzielnego modułu o nazwie firefox):

$ config-manage install pkg:neovim pkg:firefox

$ config-manage install "pkg:neovim firefox"

Możemy pójść o krok dalej i połączyć zasady automatycznej kompilacji paczek i instalacji ich plików konfiguracyjnych. Jak? W bardzo prosty sposób: poprzez rekursywne wywołanie config-manage z wnętrza konfiguracji modułu. Poniżej przedstawiam przykład instalacji programu neovim:

[neovim]
install_cmd = which nvim > /dev/null || config-manage install pkg:neovim
              ${stow_install}
              nvim -c ":PlugClean!" -c ":PlugUpdate" -c ":PlugInstall" -c ":qa!"

Powyższa zasada wykonuje następujące kroki:

  1. sprawdza, czy program nvim jest dostępny w $PATH użytkownika, a jeśli nie jest, to go próbuje zainstalować przy pomocy modułu pkg;
  2. tworzy odpowiednie dowiązania symboliczne przy pomocy GNU Stow;
  3. instaluje pluginy vima.

Pragnę przy okazji zaznaczyć, że wywołanie instalacji paczki w pierwszej komendzie jako rekursywnego config-manage jest preferowane w stosunku do zwykłego wywołania skryptu pkg/install z tego powodu, że zasada modułu pkg może wykonywać jeszcze jakieś dodatkowe czynności (np. sprawdzanie wersji, instalacja zależności), których nie ma sensu dublować w opisach innych modułów.

W następnej części

W gruncie rzeczy przekazywanie argumentów do modułów jest proste i intuicyjne, żeby nie powiedzieć “banalne”, jednak wymagało omówienia, głównie z tego powodu, że zarządzanie instalacją oprogramowania, które nie znajduje się w repozytoriach systemowych to rzecz spora, a config-manage nieco ją uprzyjemnia.

W następnych częściach przyjrzymy się bliżej programowi GNU Stow oraz skryptom pomocniczym, które są dostarczane razem z frameworkiem. Opiszę także w jaki sposób utrzymuję spójne repozytorium z plikami konfiguracyjnym: jak są one dzielone między różnymi komputerami i jak owo repozytorium jest połączone z frameworkiem.

Ciąg dalszy nastąpi…


  1. czyt.: używam takiego modułu na co dzień.