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}")


就事论事,我发现两个辅助脚本 "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 内置函数来完成,即不启动另一个进程。

解析 JSON 或 EDN 使用纯 Bash 是不可能的。另一种可能性是通过换行符拆分参数。但是,将它们读入数组的 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
通过
...