请在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
_由 pesterhazy 发表的评论:

应用了补丁后,示例正确地打印


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


FWIW,我发现这两个辅助脚本 "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

作为一个替代方案,可以通过以下方式将字符串手动读入 Bash 的数组中,逐个字符。

三个可能的分隔符浮现在脑海中

  • NUL:由于在 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 结尾而不是空格分隔的参数。

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

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

替代方案

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