#config-file #unison #yaml-config #generate #sets #server #allenap

app allenap-unison-confgen

从YAML描述中生成Unison配置文件

3个不稳定版本

0.2.0 2024年6月8日
0.1.1 2024年5月11日
0.1.0 2024年5月10日

#119 in 配置

自定义许可协议

24KB
208

Allenap的Unison配置生成器

这帮助我生成我的Unison配置文件。

背景

Unison执行双向文件同步。我编写一个配置文件,运行unison name-of-config-file,然后Unison在这里那里之间同步文件。那里可以是另一个目录,也可以是通过SSH可访问的另一个机器。这通常是它的用途。

我有几台机器需要同步。我没有作为真相来源的中央服务器,所以我通常从几台不同的机器来回同步。有一天,我会在机器A上运行unison以同步到机器B,另一天我会进行反向操作,然后也同步到机器C,以及这些的组合。因此,我想要每台机器上都有相同的配置——所以我使用Unison本身来同步这些配置文件。

我还想同步不同的集合的文件。我想将dotfiles同步到我的云服务器上,但不是我的财务记录。我想将我的编码项目在我的笔记本电脑和我的桌子下的Linux机器之间同步,但不是我的照片。

操作原理

此脚本接受一个配置文件——从stdin读取——描述我拥有的所有主机。例如

# schemes.yaml
hosts:
  alice:
    hostname: alice.example.com
    home: /home/gavin
    sets:
      - common
      - financial
      - github
  bob:
    hostname: bob.example.org
    home: /Users/gavin
    sets:
      - common
      - github
      - photos
  carol:
    hostname: carol.example.net
    home: /home/gavin
    sets:
      - common
      - financial
      - photos

此配置文件描述了三个主机——alicebobcarol——以及每个主机同步的文件集合。

当我将unison-confgen < schemes.yamlalice上运行时,将生成两个配置文件

  • alice-bob.prf
  • alice-carol.prf

这些包含标准Unison配置指令,以在主机之间同步具有共同文件的集合。

现在我可以输入unison alice-bobunison alice-carol

  • alicebob之间同步commongithub集合
  • 同步 Alice 和 Carol 之间的 commonfinancial 集合。

同样,Bob 将拥有 bob-alice.prfbob-carol.prf,而 Carol 将拥有 carol-alice.prfcarol-bob.prf

集合里有什么内容?

集合文件位于 sets 子目录中。它的名字与集合名完全相同,没有文件扩展名。它包含 Unison 配置指令。它不必描述一组文件,但通常可能看起来像

# sets/github
path = GitHub
ignore = Regex GitHub/.*/target
ignore = Name .overmind.sock

路径,如上例中的 GitHub,是相对于 schemes.yaml 中的 home 设置解析的。

这些集合文件在生成的配置文件中以原始形式包含,但增加了一项:可以使用 include 指令来包含另一个集合文件

# sets/all-code
include github
include gitlab
include projects

用法

我将 unison-confgen 二进制文件放在 PATH 上——通常是因为我已使用 cargo install 来安装它,Cargo 的 bin 目录已经在我的 PATH 上。

然后,在 ~/.unison 中,我有 etc/schemes.yaml 配置文件,一个 sets 子目录和一个 Makefile 来驱动它

.PHONY: all
all: clean gen

.PHONY: gen
gen:
	@type unison-confgen >/dev/null || cargo install allenap-unison-confgen
	unison-confgen < etc/schemes.yaml

.PHONY: clean
clean:
	@$(RM) $(wildcard *.prf)

.PHONY: complete
complete: clean gen
	@echo $(basename $(wildcard *.prf))

运行 make -C ~/.unison 会清除所有 .prf 文件并重新生成它们。

complete 目标对于 shell 完成非常有用。我在 ~/.bashrc 中的 Bash 中使用了以下代码

# Unison stuff
# shellcheck disable=SC2317
_unison() {
    local cur words
    # The current word due for completion.
    cur=${COMP_WORDS[COMP_CWORD]}
    # Non-local array storing the possible completions.
    COMPREPLY=()
    case "${cur}" in
        -*)
            words="$(unison -help | awk '/^ -/ { print $1 }')"
            ;;
        *)
            words="$(make -sC ~/.unison complete)"
            ;;
    esac
    mapfile -t COMPREPLY < <(compgen -W "${words}" -- "${cur}")
    return 0
}

for _unison in $(compgen -c unison)
do
    complete -F _unison "$_unison"
done
unset _unison

# Override local hostname. Useful when WiFi publishes a different
# local domain (<cough>FritzBox</cough>), for example.
if [ -f ~/.unison/hostname ]
then
    read -r UNISONLOCALHOSTNAME < ~/.unison/hostname &&
        export UNISONLOCALHOSTNAME
fi

这就全部了。它简单但有效;我已经使用它好几年了。最近我用 Rust(从 Python)重写了它,这是第一次发布。由于它满足了我的所有需求,我可能不会在上面做太多工作。好吧,也许在雨天我

  • 添加一个合适的命令行解析器;
  • 将 shell 完成代码移入 Rust 二进制文件;
  • 消除对那个 Makefile 的需要。

但我不会抱太大的希望。

祝您玩得开心!

许可证

GNU 通用公共许可证 3.0(或更高版本)。请参阅 LICENSE

依赖项

~2–26MB
~381K SLoC