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 要求)中没有 readarray,且 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-terminated 的参数,而不是空格分隔。

向后兼容性
- 补丁更改了缓存 ID,因此旧格式 {{.main}} 中的缓存无法重复使用
- 在 {{:main-opts}} 之前,NUL 字符的处理不一致:在 Bash < 4.3 时(例如 MacOS),NUL 字符之后的参数剩余部分被跳过,在 Bash >= 4.3 时(例如全新的 Linux),NUL 字符被跳过,因此通过将 NUL 作为参数分隔符来重新使用,我们没有破坏任何东西。

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

其他方法

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