尧图精选

sway 项目贡献指南:从 Pull Request 流程到 C 代码风格规范的完整实践

🕒 发布时间:2026/10/1 2:05:18 📁 来源:尧图网络
桌面应用【免费下载链接】swayi3-compatible Wayland compositor项目地址https://gitcode.com/GitHub_Trending/swa/sway点击查看免费下载本文以 sway 官方维护者文档 CONTRIBUTING.md 为骨架系统讲解向这一 i3-compatible Wayland compositor 提交代码贡献的完整流程包括功能分支工作流、提交信息规范、代码评审流程以及项目独特的 C 语言编码风格括号、缩进、命名、构造/析构函数约定等。读者读完后既能按上游推荐的方式安全地发起 Pull Request也能写出符合 sway 代码库标准、易于评审者合并的 C 代码。一、sway 项目与贡献的整体定位sway 是一个兼容 i3 的 Wayland 合成器compositor当前仓库的核心实现分布在 sway/主程序含 commands/ 命令解析、desktop/ 桌面层、input/ 输入处理、tree/ 窗口树管理、swaybar/、swaymsg/ 与 swaynag/ 等子模块中公共基础设施位于 common/ 与 include/。开始贡献前文档强调了两点基调先沟通再动手建议在发起 Pull Request 之前先到 Libera Chat 的#sway-devel频道与维护者讨论你的计划这会显著提高贡献被接受的几率。规则可以被打破文档明确指出规则就是用来被打破的rules are made to be broken你可以根据实际情况调整或忽略任何一条规范但必须准备好向同行解释你的理由。未来变更范围先理解项目边界这是贡献者必须首先了解的重要信息sway 的核心价值主张已经完成——它是一个功能完备的、兼容 i3 的 Wayland 替代品。项目并不打算扩大超出 i3 目标的范围当前优先级是在其现有范围内提升稳定性、可靠性和性能。因此大多数新的窗口管理功能请求不会被接受即使附带补丁也是如此。这意味着贡献者应当优先考虑 bug 修复、稳定性改进和性能优化类改动而非新功能。二、Pull Request 完整工作流文档首先承认如果你已经有自己的 Pull Request 习惯完全可以沿用。但如果你还没有它推荐了从上游拉取的功能分支feature branch方案。整个过程分为一次性初始化和日常开发两阶段。阶段一一次性初始化Fork Clone 添加上游远程git clone https://github.com/username/sway cd sway git remote add upstream https://github.com/swaywm/sway说明username需替换为你自己的 GitHub 用户名。此后你永远不需要使用自己 fork 的 master 分支一切开发都在从upstream/master拉出的功能分支上进行。阶段二日常功能开发流程git fetch upstream—— 同步上游最新提交git checkout -b add-so-and-so-feature upstream/master—— 以upstream/master为基点创建功能分支如add-so-and-so-feature在分支上添加add并提交commit你的改动git push -u origin add-so-and-so-feature—— 推送到你自己的 fork-u建立跟踪关系从该功能分支发起 Pull Request。这套流程的核心价值在于功能分支始终基于最新的上游 master避免与自己的 fork 主分支产生陈旧合并同时 PR 被合并或拒绝后只需删除分支即可无需清理本地 master。提交 PR 时应当附带的内容当你提交 PR 时文档明确要求提交日志commit log应当承担主要的描述职责说明改动内容及其动机PR 的评论中最好包含一份测试计划test plan供评审者用于在 master 上演示问题如果适用验证应用你的改动后问题不再存在或新功能正确工作把你意识到的所有边界情况edge cases记录下来以便充分测试在提交之前自己先完整执行一遍测试计划。这一要求在源码实践中也有对应体现sway 的测试覆盖了核心逻辑例如 sway/tree/output.c 中输出创建、sway/tree/container.c 中容器创建等关键路径均带有失败处理评审者会期望你的改动同样带有清晰的验证路径。三、提交信息Commit Message规范文档对提交信息给出了三条明确准则核心目标是让未来的git blame更有价值第一行subject限制在 50 个字符以内并且应该是一句能补全句子[When applied, this commit will...]应用此提交后将会……的陈述例如Implement cmd_move实现 cmd_move 命令Fix #742修复 #742 号问题Improve performance of arrange_windows on ARM改进 arrange_windows 在 ARM 上的性能后续行与 subject 之间空一行并包含可选的细节改动理由、引用 GitHub issue可使用 GitHub 的关闭 issue 语法、或补丁中较隐晦的实现细节。主体body内容应该足以解释作者当时在想什么——当后续有人遇到一行看不懂的代码时可以通过git blame找到该提交从提交信息中理解设计意图。此外文档给出一个实用经验法则任何你打算写进 GitHub PR 描述的内容都适合写进扩展提交信息extended commit message中。同时建议把改动拆分为逻辑清晰的多个提交每个提交都有良好的提交信息和自我说明这会显著降低评审难度。四、代码评审Code Review流程当改动提交评审后一名或多名核心提交者core committers会审阅。小型改动可能很快合并但大型改动通常需要多人评审。请做好收到反馈并修改的准备。文档列出的评审流程为五步Triage分流检查提交信息是否合理测试计划是否必要且已提供把你认为应该参与评审的人添加为评审者有权限时用 GitHub 功能否则用 mention。Review评审检查代码风格违规、命名规范违规、缓冲区溢出、内存泄漏、逻辑错误、不可移植代码包括 GNU 扩展用法等。对公共 API 的重大改动需要再拉拢几位成员参与讨论。Execute执行如有测试计划实际执行它。Merge合并所有评审者都同意后合并 PR。File归档如有必要为后续问题创建跟进工单。五、C 代码风格参考Style Reference这是本文档篇幅最大、也最具实操价值的部分。sway 用 C 编写风格类似Linux kernel 风格但有几点显著差异。总体要求是尽量遵循 C11 和 POSIX不要使用 GNU 扩展。5.1 括号Brackets括号始终放在同一行包括函数定义的左括号if/while/for即使只有单条语句也必须加括号。示例来自文档void function(void) { if (condition1) { do_thing1(); } if (condition2) { do_thing2(); } else { do_thing3(); } }5.2 缩进Indentation缩进使用单个 Tab需要换行的长行续行缩进一个额外的 Tab如果被断开的行正在开启一个新的代码块函数、if、while 等续行应缩进两个 Tab以免被误读为代码块的一部分尽量在你认为最能平衡各行的位置断行。really_long_function(argument1, argument2, ..., argument3, argument4); if (condition1 condition2 ... condition3 condition4) { do_thing(); }5.3 行长Line Length假设一个 Tab 宽度等于 4 个空格时尽量保持行宽在 80 列以内如果确实能提升可读性最多可以到 100 列不要不加区分地断行要找好断点让代码易于阅读。5.4 命名Names这是 sway 代码库中最重要的可识别约定全局函数和类型名必须以sway_子模块_前缀命名例如struct sway_output、sway_output_destroy对于文件内私有的 static 函数和类型命名不那么重要且static 函数不应带有sway_前缀。这一约定在仓库中得到了严格贯彻。例如类型struct sway_output定义于 include/sway/tree/root.h 附近的相关头文件struct sway_containerinclude/sway/tree/container.h全局函数container_createsway/tree/container.c、container_destroysway/tree/container.c、output_createsway/tree/output.c、output_begin_destroysway/tree/output.c等而 sway/tree/output.c 中的destroy_scene_layers这类文件内 static 辅助函数则不使用sway_前缀——正是文档规则的直接体现。此外include guard使用头文件相对于 include 目录的文件名全部大写并把非法字符替换为下划线。5.5 构造/析构函数约定Construction/Destruction Functions负责构造和析构对象的函数应写成以下两种形式之一的成对函数init/finish负责初始化/反初始化一个类型但不负责分配内存。它们接受指向预先分配内存的指针例如结构体的某个成员。create/destroy同样负责初始化/反初始化但create会返回指向malloc分配内存的指针destroy负责free它。同时有一个对错误处理非常友好的硬性要求析构函数必须能够接受 NULL 指针或零值zeroed value并干净退出这能极大简化错误处理逻辑。仓库中的实际实现完全遵循了该约定例如 sway/tree/output.c 的output_create使用calloc分配struct sway_output并在任意步骤失败时逐级释放已分配资源后返回 NULLsway/tree/output.csway/tree/container.c 的container_create同样在calloc失败时记录SWAY_ERROR日志并返回 NULL。5.6 错误码Error Codes不返回值的函数应返回stdbool.h的bool来表示成功与否。5.7 宏Macros尽量减少宏的使用尤其是能用函数完成时如果确实需要宏尽量把它放在使用处附近并在用完后#undef掉。5.8 完整示例一个符合规范的函数文档以 wlroots 的wlr_backend_autocreate为例示例代码本身来自 wlroots 而非 sway 源码但完整展示了上述所有风格struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { struct wlr_backend *backend; if (getenv(WAYLAND_DISPLAY) || getenv(_WAYLAND_DISPLAY)) { backend attempt_wl_backend(display); if (backend) { return backend; } } const char *x11_display getenv(DISPLAY); if (x11_display) { return wlr_x11_backend_create(display, x11_display); } // Attempt DRMlibinput struct wlr_session *session wlr_session_create(display); if (!session) { wlr_log(WLR_ERROR, Failed to start a DRM session); return NULL; } int gpu wlr_session_find_gpu(session); if (gpu -1) { wlr_log(WLR_ERROR, Failed to open DRM device); goto error_session; } backend wlr_multi_backend_create(session); if (!backend) { goto error_gpu; } struct wlr_backend *libinput wlr_libinput_backend_create(display, session); if (!libinput) { goto error_multi; } struct wlr_backend *drm wlr_drm_backend_create(display, session, gpu); if (!drm) { goto error_libinput; } wlr_multi_backend_add(backend, libinput); wlr_multi_backend_add(backend, drm); return backend; error_libinput: wlr_backend_destroy(libinput); error_multi: wlr_backend_destroy(backend); error_gpu: wlr_session_close_file(session, gpu); error_session: wlr_session_destroy(session); return NULL; }注意该示例体现的要点函数左括号同行、单语句 if 也带括号、Tab 缩进、错误路径逐级goto清理资源、销毁函数接受已分配对象并干净退出——这正是文档 5.1–5.7 各节约定的综合运用。六、将规范落到仓库实处从命名到资源管理的验证为了让风格规范不只停留在文字层面我们可以用仓库源码验证几项核心约定的实际执行情况sway_前缀约定全局类型与函数确实带前缀。例如struct sway_containerinclude/sway/tree/container.h内部含sway_node、wlr_scene_tree等成员输出子系统在 include/sway/tree/root.h 中以wl_list all_outputs管理sway_output并提供root_find_outputinclude/sway/tree/root.h这类全局查找函数。create/destroy 配对output_createsway/tree/output.c分配并初始化对象output_destroysway/tree/output.c与output_begin_destroysway/tree/output.c负责逐级销毁容器侧container_createsway/tree/container.c与container_destroysway/tree/container.c同样成对出现。错误路径的整洁清理output_create中任何场景树分配失败都会先destroy_scene_layers、再销毁scene_output、最后free并返回 NULLsway/tree/output.c印证了析构必须能干净退出、错误处理要简单的约定。七、贡献前的自检清单综合文档内容提交 PR 前建议逐一核对范围改动是否属于稳定性、可靠性、性能范畴新窗口管理功能大概率不会被接受。沟通是否已在#sway-devel频道与维护者讨论过计划分支是否基于最新upstream/master创建了独立功能分支提交信息subject 是否 ≤50 字符、能否补全When applied, this commit will...body 是否解释了动机并引用了相关 issue测试计划是否在 PR 描述中写清可复现问题的步骤与边界情况并已亲自验证代码风格括号是否同行且单语句也加括号是否使用 Tab 缩进行宽是否在 80–100 列全局符号是否带sway_前缀、static 符号是否不带create/destroy 或 init/finish 是否成对析构是否能接受 NULL/零值错误返回是否用 bool宏是否最小化并就地#undef是否避免 GNU 扩展、遵循 C11 与 POSIX只要改动范围契合项目方向、流程规范、风格达标且自带可执行的测试计划你的贡献就具备了被 sway 核心团队评审和合并的良好基础。赞分享桌面应用【免费下载链接】swayi3-compatible Wayland compositor项目地址https://gitcode.com/GitHub_Trending/swa/sway点击查看免费下载相关推荐esp-iot-solution 贡献指南与编码规范从 Pull Request 到代码风格全流程esp iot solution 贡献指南与编码规范从 Pull Request 到代码风格全流程 本文以仓库根目录的 CONTRIBUTING.rst ht物联网嵌入式驱动开发硬件开发终极text-generation-webui贡献指南从代码规范到Pull Request的完整流程终极text generation webui贡献指南从代码规范到Pull Request的完整流程 text generation webui是一个基于Gr人工智能大模型本地部署模型推理服务AI 应用桌面应用工具调用Rust机器学习入门如何用Awesome-Rust-MachineLearning快速上手Rust机器学习入门如何用Awesome Rust MachineLearning快速上手 Awesome Rust MachineLearning是一个专注上一篇SponsorBlock国际化测试多语言环境下的功能验证下一篇LCD Image Converter嵌入式显示开发的三大难题与解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →