请分享您的想法,参与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

评论由:pesterhazy

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

0

评论由:pesterhazy

另一个选择是在使用eval之前检查输入

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

0

评论者:arichiardi

确实非常实用的脚本文档(我是说尝试和演示)

0

评论由:pesterhazy

作为eval的替代,Bash代码可以手动将字符串读入数组,一个字符一个字符。参数需要通过分隔符分开。

三种可能的分隔符

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

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

我完成了一个概念验证,证明这和Bash3一起工作:https://github.com/clojure/brew-install/pull/3/files#diff-b3212e45e19f61de4754a755466b793f

如果这听起来合适,我将更新补丁。

0

评论者: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 报告)
...