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}},而不是三个。
以以下备注关闭:Fix可用在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 发表评论:

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

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:不会工作,因为readarray在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
参考:https://clojure.atlassian.net/browse/TDEPS-56(由mfikes报告)
...