我在用着GNU 斯托按照以下方式管理我的点文件本指南。这对于机器上没有预先存在的点文件的情况非常有效。例如,如果没有文件~/.config/foo.cfg
,则以下内容可以正常工作:
~/.dotfiles$ mkdir -p foo/.config
~/.dotfiles$ echo My config > foo/.config/foo.cfg
~/.dotfiles$ stow foo
~/.dotfiles$ ls -l ~/.config
lrwxrwxrwx 1 user group 21 Dec 6 19:03 ~/.config -> .dotfiles/foo/.config
~/.config/foo.cfg
如果已经存在,它就变得不那么简单:
~/.dotfiles$ stow foo
WARNING! stowing bar would cause conflicts:
* existing target is neither a link nor a directory: foo.cfg
All operations aborted.
到目前为止,我能找到的唯一解决方案是手动删除~/.config/foo.cfg
并重新运行stow foo
.当向可能有数十个预先存在的 .dot 文件的新计算机配置 stow 存储库时,这是非常尴尬的,并且基本上违背了使用 stow 管理点文件的目的。
斯托有--adopt
选择权。运行的stow --adopt foo
效果是用计算机上foo
预先存在的文件替换存储的文件,然后创建符号链接。foo
我正在寻找的是达到相反效果的方法;将计算机的 .dotfiles 替换为存储版本的符号链接,以便可以使用 Git 存储库中的存储点文件来配置新计算机。
这似乎是使用 Stow 管理点文件的一个明显要求,我觉得我错过了一些东西和/或问题已经解决了。
有任何想法吗?
答案1
我遇到了同样的限制,并且找到了一个与该--adopt
选项配合良好的工作流程。如中所述存放文档:
...它允许目标树中的文件(其内容可能与 stow 包的安装映像中的等效版本不同)被采用到包中,然后通过在 stow 包内运行“git diff ...”之类的内容进行比较,最后要么保留(例如通过“git commit ...”)或丢弃(“git checkout HEAD ...”)。
我的工作流程:
stow
使用该选项运行--adopt
。- 使用 . 将“采用的”文件与我的存储库中最初的文件进行比较
git diff
。 - 使用 放弃“已采用”文件引入的所有更改
git reset --hard
,将整个目录恢复到上次提交的状态。
例子:
# Running from inside .dotfiles repository
❯ tree . -a
.
├── bash
│ ├── .bashrc
│ └── .xprofile
# Stow bash folder as usual and note conflicts (.bashrc in this case)
❯ stow bash
WARNING! stowing bash would cause conflicts:
* existing target is neither a link nor a directory: .bashrc
All operations aborted.
e conflicts
# Rerun Stow with --adopt flag to place conflicting files in .dotfiles repo (no warnings)
❯ stow bash --adopt
# Use git diff to compare adopted and committed file
❯ git diff
diff --git a/bash/.bashrc b/bash/.bashrc
index cbd6843..0ac2879 100644
--- a/bash/.bashrc
+++ b/bash/.bashrc
@@ -1,121 +1 @@
... Line changes are listed ...
# Discard adopted file and revert back to contents as per last commit
❯ git reset --hard
# Done
我是 dotfiles 和 Stow 的新手,所以我可能缺少一些限制。到目前为止我对结果很满意。
答案2
我遇到了同样的问题。我个人使用 Ansible 来自动化我的所有 GNU Stow 命令。虽然 Ansible 脚本可能并不完全符合您的需求,但我的方法可能会帮助您探索不同的选项;您可以在 bash 中编写类似的脚本,可以通过更改下面写的我的 Ansible 剧本中的 shell 命令来实现。
我的 dotfile 文件夹的结构如下:“~/dotfiles/home/”包含子文件夹名称,如“bash”和“zsh”。在此代码片段中,dotfile_packages = "~/dotfiles/home/"
请记住,这是一种不安全的方法,因为您会在无人看管的情况下删除大量文件。
- name: Find all dotfiles subfolders
find:
paths: "{{ dotfile_packages }}"
file_type: directory
recurse: no
register: dotfile_folders
- name: Get list of dotfiles to check for GNU Stow conflicts
shell: find ./home/{{ item }} \( -type f -o -type l \) | sed 's/.\/home\/{{ item }}\///g'
args:
chdir: "{{ repo_dir }}"
register: conflict_files
with_items: "{{ dotfile_folders.files | map(attribute='path') | list | map('basename') }}"
- name: Show list of files to be checked for GNU Stow conflicts
debug:
msg: "{{ item }}"
with_items: "{{ conflict_files.results | map(attribute='stdout_lines') | list | flatten }}"
# If we don't unstow first, the delete operation erases any previously stowed dotfile sources.
# Ignoring errors because sometimes unstow will fail to finish because OS added some untracked files.
- name: Unstow all packages deleting conflict files.
shell: stow -D -d {{ dotfile_packages }} -t ~/ {{ item }}
with_items: "{{ dotfile_folders.files | map(attribute='path') | list | map('basename') }}"
ignore_errors: yes
- name: Delete conflicting files
shell: rm -rf ~/{{ item }}
with_items: "{{ conflict_files.results | map(attribute='stdout_lines') | list | flatten }}"
- name: Symlink dotfiles
shell: stow -d {{ dotfile_packages }} -t ~/ {{ item }}
with_items: "{{ dotfile_folders.files | map(attribute='path') | list | map('basename') }}"
答案3
我通过将 stow 用法包装在生成文件(检查备份目标)
# List of packages to manage with stow
PACKAGES ?= $(filter-out .git .github, $(wildcard */))
# Directory where stow will look for packages. Default is current directory
DIR ?= $$(pwd)
# Default location where stow will create symbolic links
TARGET ?= ${HOME}
IGNORE ?= \.DS_Store
# Stow command to create links
STOW_CMD = stow \
--dir="${DIR}" \
--target="${TARGET}" \
--ignore="${IGNORE}" \
--ignore="\.DS_Store" \
--ignore=".*\.template" \
--no-folding \
--verbose
# Function to backup existing files for a specific package if they exist
define backup_if_exists
checks=$$(${STOW_CMD} --no --verbose ${1} 2>&1 | \
egrep '\* existing target is ' | \
sed 's/ \* existing target is neither a link nor a directory: //'); \
for file in $$checks; do \
filepath=${TARGET}/$$file; \
backup_suffix="backup-$$(date -u +%Y%m%d%H%M%S)"; \
echo "Creating backup $$filepath.$$backup_suffix"; \
mv -h "$$filepath" "$$filepath.$$backup_suffix"; \
done
endef
# Default rule to create symbolic links for all packages
all: stow
# Rule to backup existing configurations
backup:
@echo "Checking for existing files to backup..."
@$(foreach package,$(PACKAGES), \
$(call backup_if_exists,$(package));)
# Rule to link configurations using stow
stow: backup
@echo "Applying stow for packages..."
@$(foreach package,${PACKAGES}, \
$(STOW_CMD) ${package};)
# Rule to remove symbolic links
unstow:
@echo "Removing stow links for packages..."
@$(foreach package,$(PACKAGES), \
$(STOW_CMD) -D $(package);)
# Rule to reapply symbolic links
restow: backup unstow stow
# Rule to display help
help:
@echo ""
@echo "\033[1mUSAGE\033[0m"
@echo ""
@echo " make [target]"
@echo ""
@echo "\033[1mTARGETS\033[0m"
@echo ""
@echo " stow - Create symlinks for all packages (default)"
@echo " restow - Reapply symlinks for all packages"
@echo " unstow - Remove symlinks for all packages (\033[31mcaution\033[0m)"
@echo " help - Show this help message"
@echo ""
.PHONY: all backup stow unstow restow help
这个 Makefile 是做什么的?
- 首次以检查模式启动收起
- 列出已经存在的项目
- 备份文件
- 发射收起
USAGE
make [target]
TARGETS
stow - Create symlinks for all packages (default)
restow - Reapply symlinks for all packages
unstow - Remove symlinks for all packages (caution)
help - Show this help message
答案4
我遇到过同样的问题。这是一个简单的解决方案,假设您正在尝试stow config
:
stow config
# WARNING! stowing config would cause conflicts:
# ...
# All operations aborted.
rsync -a config/ config.bak/ # create a backup; this may not be exactly the right rsync syntax
stow --adopt config.bak # should take ownership of all existing files
stow -D config.bak # remove all the symlinks just created
stow config # should now work fine
rm -rf config.bak