我在 Node JS 中检索 Git 标签信息的方法很慢,如何加快速度?
Posted
技术标签:
【中文标题】我在 Node JS 中检索 Git 标签信息的方法很慢,如何加快速度?【英文标题】:My method of retrieving Git tag information in Node JS is slow, how can I speed it up? 【发布时间】:2019-05-31 02:11:59 【问题描述】:我正在创建一个 Node JS 脚本,它需要从存储库中获取所有 Git 标记,以及创建标记的消息和日期,然后将它们保存为 JSON 文件中的条目。例如:
[
"tag": "v1.1.0",
"message": "Add navigation",
"date": "Tue Oct 4 10:19:12 2018 +0100"
,
"tag": "v1.1.1",
"message": "Fix issue with spacing in the navigation",
"date": "Tue Oct 9 12:13:16 2018 +0100"
]
我已经弄清楚了如何做到这一点,使用一些 Node 模块来访问标签,然后执行一些 Git 命令来从每个标签中获取我需要的所有信息。这是使用shelljs 完成的。
我的问题是这很慢。运行gitTag.all((tags) = )
(使用git-tag)很快,因为它只是拉入标签名称。但是,为了获取消息和日期,我在一个循环中为每个标签运行了两个单独的命令:
let msg = shell.exec(`git for-each-ref refs/tags/$tag --format='%(subject)'`, silent:true).stdout;
let date = shell.exec(`git for-each-ref refs/tags/$tag --format='%(authordate)'`, silent:true).stdout;
这两个命令无论如何都有点慢,但是每次为每个标签名称运行它们都需要很长时间。
我有更快的方法吗?
请记住,我是同步运行的,因为另一个 Node 脚本会读取这个 JSON 文件,这可能会导致竞争条件。但是,如果他们也可以解决这个问题,欢迎任何异步想法。
请在下面查看我的完整代码:
const gitTag = require('git-tag')(
localOnly: true,
dir: '.git'
);
const fs = require('fs-extra');
const shell = require('shelljs');
let tagsAllData = [];
let formatString = (string) =>
return string.replace(/^'/, '').replace(/'\n+$/, '');
// Fetch all git tags
gitTag.all((tags) =>
tags.forEach(tag =>
// Collect the tag message and date values
let msg = shell.exec(`git for-each-ref refs/tags/$tag --format='%(subject)'`, silent:true).stdout;
let date = shell.exec(`git for-each-ref refs/tags/$tag --format='%(authordate)'`, silent:true).stdout;
// Create array of tag objects
tagsAllData.push(
'tag': tag,
'message': formatString(msg),
'date': formatString(date)
);
);
// Write the tag data as a JSON file
let tagsJSON = JSON.parse(JSON.stringify(tagsAllData));
fs.writeJSONSync('src/data/tags.json', tagsJSON);
);
【问题讨论】:
shell
函数取决于系统老兄。它将请求发送到系统外壳,然后从外壳获得响应。就是这样,为了快速得到结果,shell需要快速响应,然后只有你的nodeJS
会显示响应。您无需等待即可执行其他功能。但是要加快这个shell
功能。您的系统应该运行良好。
谢谢@BanujanBalendrakumar,我同意 - 这就是我问这个问题的部分原因。我希望有一种更快的方法可以做到这一点,它可能不依赖于系统,或者使用更少的执行。也许还有另一种更有效的获取相同信息的方法。
【参考方案1】:
您的实际代码为每个标签调用两次 shell。为了加快速度,您应该调用 shell,因此最多调用一次 git - 对于 all 标签。在 shell 中是这样的:
git for-each-ref --sort=v:refname --format "tag: %(refname:strip=2) message: %(subject) date: %(creatordate:iso)" refs/tags
输出如下所示:
tag: v2.20.0-rc0 message: Git 2.20-rc0 date: 2018-11-18 18:25:38 +0900
tag: v2.20.0-rc1 message: Git 2.20-rc1 date: 2018-11-21 23:25:15 +0900
tag: v2.20.0-rc2 message: Git 2.20-rc2 date: 2018-12-01 21:45:08 +0900
tag: v2.20.1 message: Git 2.20.1 date: 2018-12-15 12:31:46 +0900
您必须先将此输出拆分为单独的行,然后将每行拆分为字段。您可以通过调整format
以使解析更容易(例如,通过在字段之间使用特殊字符)来简化此操作。
【讨论】:
【参考方案2】:在其他答案的基础上,我还会考虑使整个方法更加异步。 foreach
处于阻塞状态,将取决于每个呼叫的单独结果。
相反,我会使用原生 API 并从中创建一个承诺(如 here 解释的那样)。
您可以使用Promise.all 来汇总结果。这是一个简化的例子
const dateQueries = [];
const msgQueries = [];
tags.forEach(tag =>
const dateQuery = exec(`git for-each-ref refs/tags/$tag --format='%(subject)'`);
const msgQuery = exec(`git for-each-ref refs/tags/$tag --format='%(authordate)'`);
dateQueries.push(dateQuery);
msgQueries.push(msgQuery);
);
const msgResults = await Promise.all(msgQueries);
const dateResults = await Promise.all(dateQueries);
但是,A.H. 的答案是性能更高的答案,因为它优化了查询本身。
【讨论】:
以上是关于我在 Node JS 中检索 Git 标签信息的方法很慢,如何加快速度?的主要内容,如果未能解决你的问题,请参考以下文章
连接到 Heroku node.js 应用程序中的数据库,而不在 git 上显示身份验证详细信息
用于从 git ref 中提取分支名称的 Node.js 包