使用 Sourcegraph 搜索代码
Sourcegraph 是一款用于在大规模代码库中进行搜索和导航的工具。该工具提供了多种搜索方式,包括正则表达式搜索,以及相对较新的、具备语言感知能力的“结构化搜索”。其开源核心提供了代码搜索、跳转到定义等“代码智能”功能,帮助开发者理解跨多个仓库的代码库。Sourcegraph 的代码搜索工具可以在鼠标悬停时显示函数和方法的文档,并让开发者快速跳转到定义或查找某个标识符的所有引用。
Sourcegraph 服务端主要使用 Go 编写,核心部分以 Apache 2.0 协议开源;各种“企业版”扩展则采用专有许可。Sourcegraph 背后的公司每月发布一个新版本,其中最新版本(3.18)改进了对 C++ 的支持,而 3.17 版本则带来了更快、更准确的代码搜索,并支持 AND 和 OR 搜索运算符。
代码搜索
Sourcegraph 的核心功能是能够跨一个或多个仓库搜索代码。即使搜索数百个仓库,结果通常也能在一两秒内返回。默认的查询方式是字面量搜索,它会对类似 "foo bar" 这样的搜索字符串进行精确匹配,包括引号在内。点击搜索栏右侧的 .* 图标可切换到正则表达式搜索,这两种搜索模式都支持区分大小写的匹配(点击 Aa 图标即可)。
[] 图标可切换到“结构化搜索”,这是一种由供职于 Sourcegraph 的 Rijnard van Tonder 为其 Comby 项目创建的搜索语法。结构化搜索具备语言感知能力,在处理嵌套表达式和多行语句方面比正则表达式更出色。结构化搜索查询常被用于发现潜在的缺陷或可简化的代码,例如,针对以下内容的查询:
fmt.Sprintf(":[str]")该查询可以找出那些只有一个字符串字面量参数、因而可以省去 fmt.Sprintf() 调用的地方。
文档中有一张架构图,展示了 Sourcegraph 安装后会运行的各个进程。此外还有对“搜索查询的生命周期”更详细的说明。前端首先会在查询中查找 repo: 过滤器,以确定需要搜索哪些仓库。服务端将仓库列表与大多数其他 Sourcegraph 元数据一起存储在 PostgreSQL 数据库中;Git 仓库则会按常规方式克隆并存储在文件系统中。
接下来,服务端会判断哪些仓库已建立索引(如果搜索查询中指定了特定版本,则针对该版本判断)以及哪些尚未索引:仓库的索引构建和已索引的搜索都由 zoekt 处理,这是一个用 Go 编写的、基于 trigram 的代码搜索库。(对使用 trigram 搜索代码感兴趣的读者,可能会想阅读 Go 技术负责人 Russ Cox 关于此话题的文章)。
对于尚未建立索引的仓库版本,则由一个独立的“searcher”进程来处理(该进程可通过 Kubernetes 水平扩展)。它会从 Sourcegraph 的服务端(即 gitserver)获取仓库的 zip 归档,并遍历其中的文件,使用 Go 的 regexp 包进行正则表达式匹配,或使用 Comby 库进行结构化搜索。默认情况下仅对仓库的默认分支建立索引,但 Sourcegraph 3.18 新增了对非默认分支建立索引的能力。
代码智能
Sourcegraph 的第二大核心功能是其所谓的“代码智能”:能够跳转到光标所在变量或函数的定义,或查找其所有引用。默认情况下,这些功能使用的是“基于搜索的启发式方法,而非将代码解析为 AST [抽象语法树]
”,不过在我测试中,这些启发式方法表现得相当准确。该工具在 C、Python 和 Go 中都能顺利找到定义,甚至能找到 Python 中动态赋值的定义(例如能够跳转到我在 scandir 项目中被赋值和重新赋值的 scandir_python 名称的定义)。
近期,Sourcegraph 还基于微软的 Language Server Index Format(LSIF)实现了一项更精确的代码搜索功能(该功能使用特定语言的解析树,而非搜索启发式方法),LSIF 是一种基于 JSON 的文件格式,用于存储由索引器为语言工具提取的数据。Sourcegraph 为多种语言编写或维护了 LSIF 索引器,包括 Go、C/C++ 和 Python(均为 MIT 许可)。目前,Sourcegraph 中的 LSIF 支持是可选启用的,据文档所述:“它提供了快速而精确的代码智能,但需要定期生成并上传到你的 Sourcegraph 实例。
”Sourcegraph 的建议是在每次提交时都生成并上传 LSIF 数据,不过开发者也可以设置为定期任务,以较低频率进行索引。
代码智能查询分为三种类型:悬停查询(检索与符号相关联的文档以显示为“悬停文本”)、跳转到定义查询,以及查找引用查询。如果存在精确的 LSIF 信息则会优先使用,否则 Sourcegraph 会回退到基于 Ctags 与搜索相结合的“模糊”结果。
是否开源?
Sourcegraph 采用开放核心(open core)授权模式,但其交付方式有些特殊:包括专有代码在内的所有源码都位于同一个公开仓库中,但 enterprise/ 和 web/src/enterprise/ 目录下的代码适用 Sourcegraph Enterprise 许可,其余代码则采用 Apache 许可。Sourcegraph 提供的预构建 Docker 镜像包含了企业版代码,“以提供平滑升级到 Sourcegraph Enterprise 的路径
”,不过仓库中也提供了一个可构建完全开源镜像的构建脚本。企业版代码中包含一项检查,会禁止超过十个用户使用,但在开源构建中则不会包含该限制。总体而言,构建和安装开源版本文档不够完善,其安装脚本也可能遗漏了一些步骤——给人的感觉明显是二等公民。
Sourcegraph(公司)运行着该系统的一个托管版本,允许任何人搜索来自各个代码托管平台的“热门”公开仓库。目前尚不清楚“热门”是如何定义的,也不清楚该托管版本具体索引了哪些仓库,但该版本很好地展示了可用功能。公司的定价页面列出了仅限企业版的功能,包括:Campaigns 多仓库重构工具、对多个代码托管平台的支持、自定义品牌、在线培训等。
安装部署
按照安装文档中的说明,使用 docker-compose 方式安装预构建的 Sourcegraph 镜像非常快捷。几分钟内就能启动运行,再花几分钟即可完成配置。由于我在本地机器上运行,因此使用 ngrok 隧道(临时)提供一个支持 https 的公网域名(运行本身并不需要它,但某些功能在提供该域名时会表现更好)。更快捷的单命令 Docker 安装方式也能正常工作,但我决定尝试 docker-compose 方案:它看起来更贴近实际,因为该方式被推荐用于中小型生产部署,而不仅仅是本地测试。对于更大规模、高可用的部署,Sourcegraph 推荐部署在 Kubernetes 集群上。
整个配置过程需要的操作很少:创建一个管理员用户,并将系统指向代码托管平台(就我而言,需要创建一个 GitHub 访问令牌以允许 Sourcegraph 访问我在 GitHub 上的公开和私有仓库)。添加访问令牌后,Sourcegraph 便开始克隆并索引这些仓库。几分钟后,它们就可以被搜索了。该系统针对自托管进行了优化;可以推测,公司希望让开发者能够轻松地为少量测试用户搭建系统(然后在用户数超过十人时再要求付费)。
其中一个可能让人犹豫的“功能”是 Sourcegraph 所谓的“pings”;默认情况下,该工具大约每 30 分钟向 https://sourcegraph.com/.api/updates.com 发送一次 POST 请求,“以帮助我们的产品和客户团队
”。这种“关键遥测
”包括“初始站点安装者的电子邮件地址
”和“现有用户账户总数
”,推测是为了让公司在达到十用户阈值时能够联系安装者洽谈企业版付费事宜。该功能只能通过修改源码来关闭(ping 代码位于开源核心中,因此可以注释掉这一行来移除它)。默认情况下,系统还会发送部分产品功能的聚合使用信息,但可以通过设置 DisableNonCriticalTelemetry 配置项来关闭。值得肯定的是,Sourcegraph 对其“ping 理念”十分坦率,并明确表示从不发送源代码、文件名或具体的搜索查询。
浏览器与编辑器集成
除了搜索服务和 Web 界面外,Sourcegraph 还为 Chrome 和 Firefox 提供了浏览器扩展,使其功能在使用 GitHub、GitLab 等代码托管平台浏览时也能使用。例如,在 GitHub 上审查拉取请求时,安装了 Sourcegraph 扩展的开发者可以快速跳转到定义、查找所有引用,或查看某个接口的实现。自 2019 年 6 月起,GitHub 也推出了类似功能,使用的是其 semantic 库,不过 Sourcegraph 浏览器扩展似乎功能更强(例如,它能找到结构体字段,而不仅仅是函数和方法)。Sourcegraph 浏览器扩展会尽可能让开发者停留在 github.com 上,但对于某些链接和定义,则会跳转到 Sourcegraph 实例的 URL。
Sourcegraph 还为四款主流编辑器(Visual Studio Code、Atom、IntelliJ 和 Sublime Text)提供了编辑器集成。这些插件允许开发者在 Sourcegraph 中打开当前文件,或使用 Sourcegraph 搜索选中的文本(插件会在浏览器中打开结果)。浏览器扩展和编辑器插件契合 Sourcegraph 的一项原则:“我们最终希望成为一个将开发者使用的所有工具连接起来的平台
”。
结语
Sourcegraph 的开发过程也相当开放,有针对即将发布的 3.19 和 3.20 版本的跟踪议题,以及一份仍在完善中的路线图。除了计划对核心功能(搜索和代码智能)进行诸多改进,例如实现与 OpenGrok 的功能对等外,公司似乎还在开发其云服务,而 Campaigns 功能也将迎来重大改进。
Sourcegraph 看起来是一个设计精良、颇具实用价值的系统,尤其适用于大型代码库和大型开发团队。事实上,文档暗示该工具可能并不适合小团队:“对于处理较大代码库或团队(15 名以上开发者)的开发者而言,Sourcegraph 更有用。
”一些人可能也会因开源构建支持不佳以及会“回传”信息的 pings 而望而却步;不过,看起来仍有一些人坚持使用开源版本并成功将其运行起来。
随机一篇博客
![Sourcegraph 搜索 [Sourcegraph 搜索]](https://static.lwn.net/images/2020/sourcegraph-search-sm.png)
评论
登录后参与讨论