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强制要求)中不可用,并且在Bash变量中无法存储NUL
  • 空格
  • 换行符

由于在主选项中不太可能出现换行符,因此我会选择它。然而,换行符仍然可能发生,因此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(例如 Mac OS)的情况下,在 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 报告)
...