| src | ||
| .gitignore | ||
| .scalafmt.conf | ||
| package-native.sh | ||
| project.scala | ||
| README.md | ||
syncedtrees workspace
syncedtrees/ 是这个工具自己的 Scala CLI 工作区。
设计更新
相较于之前的单文件原型,这个工作区版本做了这些升级:
- 动态发现 worktree:通过
git worktree list --porcelain实时发现,而不是在配置里维护 tree 列表。 - Schema 驱动配置读取:配置会被反序列化为
RawConfig/ResolvedConfig,并结合 CatsValidated做语义校验。 - Cats Effect 架构:主流程和副作用都通过
IO组织,便于扩展和测试。 - os-lib 系统操作:命令执行采用
os.proc,简化子进程调用和输出处理。 - 独立 workspace:源码、测试、scalafmt、打包产物都放在
syncedtrees/下管理。
目录结构
syncedtrees/
.scalafmt.conf
project.scala
README.md
package-native.sh
dist/
src/
main/scala/syncedtrees/
test/scala/syncedtrees/
运行
从 workspace 根目录的上一层执行:
scala-cli run --server=false syncedtrees -- --help
scala-cli run --server=false syncedtrees -- init ./tree-a
scala-cli run --server=false syncedtrees -- status '*'
scala-cli run --server=false syncedtrees -- sync tree-b
scala-cli run --server=false syncedtrees -- cleanup tree-b
scala-cli run --server=false syncedtrees -- exec tree-b pwd
scala-cli run --server=false syncedtrees -- new tree-c feat/my-branch main
注意:像 --config、--dry-run、--verbose 这样的全局参数需要放在子命令之前。例如:
scala-cli run --server=false syncedtrees -- --config ./custom.conf init ./tree-a
scala-cli run --server=false syncedtrees -- --dry-run sync tree-b
配置
默认配置仍然在工作区根目录的 syncedtrees.conf。
如果还没有配置文件,先运行:
scala-cli run --server=false syncedtrees -- init ./tree-a
init 会:
- 校验传入路径是否是 git repo / worktree
- 生成 starter
syncedtrees.conf - 自动填入
primaryTree、primaryTreePath、defaultBaseBranch - 输出后续操作提示
支持 camelCase,也兼容 kebab-case:
basePath/base-pathsharedRoot/shared-rootprimaryTree/primary-treedefaultBaseBranch/default-base-branchtreeSettings/tree-settingsdisabledLinks/disabled-links
links 里的每一项支持这些字段:
namesourcetargetoptionaloverwritecopy
例如:
links = [
{
name = "agents-md"
source = "AGENTS.md"
target = "AGENTS.md"
overwrite = true
copy = true
}
]
其中 copy = true 时,sync 会把 source 复制到目标位置;如果 source 是目录,会递归复制目录内容,而不是创建符号链接。overwrite = true 时,如果目标位置已经有旧文件、旧目录,或者旧的符号链接(包括 drifted symlink),会先清理目标,再复制/创建;默认是 false,会保持现状并继续报 blocked。cleanup 会删除 copy = true 且内容仍与 source 对应的受管文件或目录,也会继续删除普通 link 模式生成的符号链接;如果 copy 目标已经被本地改动到不再匹配 source,则会跳过,避免误删本地内容。
运行时不再依赖代码内置默认业务配置;如果配置项缺失或为空,会直接报错并提示修正。
打包 native image
已提供脚本:
./syncedtrees/package-native.sh
脚本会优先使用你当前 SDKMAN 环境里已经可用的 native-image;
如果当前 SDK 没有 native-image,则自动回退到 scala-cli 通过 coursier 拉取
graalvm-java21 来完成打包。脚本默认传递 --no-fallback,因此会尽量产出
真正可独立运行的 native binary,而不是 fallback image。
它会产出:
syncedtrees/dist/syncedtrees
也可以手动执行:
scala-cli --power package --server=false syncedtrees \
--native-image \
--graalvm-args --no-fallback \
--jvm graalvm-java21 \
--main-class syncedtrees.Main \
-f \
-o syncedtrees/dist/syncedtrees
测试与格式化
scala-cli compile --server=false syncedtrees
scala-cli test --server=false syncedtrees
scala-cli fmt syncedtrees