2024 Clojure 现状调查! 分享您的想法。

欢迎!请参见关于 页面以获取更多关于如何工作的信息。

0
tools.deps
已关闭
{code:title=src/foo/core.clj}
(ns foo.core)

(defn -main [& args]
  (prn args))



$ clj -Srepro -Sdeps '{:aliases {:space {:main-opts ["-m" "foo.core" "-co" "{:aot-cache true}"]}}}' -Aspace
("-co" "{:aot-cache" "true}")


预期将有两个选项传递给 {{foo.core/-main}},而不是三个。
关闭时备注:Clojure CLI 1.10.2.786 预发布版中可用的修复。

13 条答案

0

评论者:pesterhazy

附上两个补丁,一个用于 "brew install" 仓库,一个用于 "tools deps" 仓库。

采用的方法是使用反斜杠引用写入 .main 文件的参数,例如

\-\-n\a\m\e \J\o\h\n\ \S\n\o\w

更改中 bash 部分使用 eval 解串,并将其拆分成多个参数。

两个补丁需要同时应用。

0
_评论者:pessterhazy_

应用补丁后,示例代码正确输出了:


("-co" "{:aot-cache true}")


顺便说一句,我发现两个辅助脚本 "try" 和 "demo" 在测试涉及 brew-install 和 tools.deps.alpha 的更改时很有用: https://github.com/pesterhazy/brew-install/pull/1/files#diff-d67b65744525f3bb15715e95ba3117eb
0

评论者:alexmiller

你能讨论一下引用方法或使用 eval 的潜在缺点吗?

你们还遇到了其他处理此问题的方法吗?

0

评论者:alexmiller

另外,如果用户有现有的(非转义的)缓存的 main 文件,他们的体验如何?也就是说,它是否与现有的缓存文件向后兼容?

0

评论者:alexmiller

看起来使用 eval 读取任意用户文件(这两点之间可能被操纵)的方法具有显著的安全风险: http://mywiki.wooledge.org/BashFAQ/048 因此我更愿意在这里找到一种替代方法。

0

评论者:pesterhazy

关于替代方案,Bash 代码需要能够读取 .main 文件并将内容拆分为单个参数。理想情况下,这应该通过 Bash 内置函数来完成,即不启动另一个进程。

使用纯 Bash 无法解析 JSON 或 EDN。另一种可能性是按换行符分隔参数。但将 Bash 代码读取回数组的工作既不简单,至少与使用 eval 解析内容一样不简单。

使用 eval 内置函数的潜在缺点是,与 Clojure 读取器一样,Bash 读取器可能具有副作用。例如,当内容包含 $(rm /important/file)>/important/file 时。

然而,我们控制写入文件的代码,并且转义了所有字符。因此,美元符号和大于符号会被加上反斜杠。我认为这是安全的。

我需要考虑向后/向前兼容性——这是个很好的观点。

0
by

评论者:pesterhazy

向后兼容问题的简单解决方案是使用不同的后缀,如 .qmain,或者在文件开头使用一个特殊的字符串,如 1. 引用。

0
by

评论者:pesterhazy

另一个选项是在Eval之前检查输入:

[[ "\\a\\b\\c \\d" =~^(\\.| *)*$ ]]

0
by

评论人:arichiardi

确实非常有用的脚本(我意思是尝试和演示)

0
by

评论者:pesterhazy

作为对 eval 的替代,Bash 代码可以手动逐字符将字符串读取到数组中。参数需要通过定界符分隔。

我想到了三种可能的定界符:

  • NUL:无法工作,因为 readarray 在 Bash3 中不可用(由 macOS 强制实施),并且 NUL 无法存储在 Bash 变量中
  • 空格
  • 换行符

由于换行符在主要选项中不太可能出现,因此我会选择它。然而,换行符可能仍然会出现,因此 Clojure 代码应该使用反斜杠转义它们。此外,还需要转义字面上的反斜杠。

我已经证明了这个方法与 Bash3 一致:https://github.com/clojure/brew-install/pull/3/files#diff-b3212e45e19f61de4754a755466b793f

如果这听起来是对的,我将更新补丁。

0
by

评论人:dottedmag

我已经附加了 {{brew-install-nul-terminated.patch}} 和 {{tda-nul-terminated.patch}},它们将 {{.main}} 文件的格式更改为使用 NUL 结尾而不是空格分隔的参数。

向后兼容性
- 补丁会更改缓存ID,因此带有旧 {{.main}} 格式的缓存将不会被重用
在之前的处理中,{{:main-opts}} 中的 NUL 字符被处理得不一致:在 Bash < 4.3(例如 MacOS)中,NUL 字符后的参数被跳过,而在 Bash >= 4.3(例如新的 Linux)中,NUL 字符被跳过,所以我们在这里重用 NUL 作为参数分隔符并没有破坏任何东西。

操作系统兼容性
— Bash >= 2.04(大约在 2000 年发布,所有相关操作系统都有更新的 Bash)

替代方法

  • 代替以 NUL 结尾行来转义空格
    — 优点:没有?
    — 缺点:Bash 解析代码变得更加复杂(除非使用 {{eval}} 并解决相关的问题)
  • 使用 {{.main2}} 文件而不是更改现有缓存条目的散列值
    — 优点:升级后可以重用不需要 {{.main}} 文件的现有缓存条目
    — 缺点:在 {{clojure}} 中需要额外的复杂逻辑来检测带有 {{.main}} 文件的缓存条目,将它们视为过时,并在刷新缓存后删除旧的 {{.main}} 文件。
0
by
参考: https://clojure.atlassian.net/browse/TDEPS-56(由 mfikes 报告)
...