ok/jj
1
0
Fork 0
forked from mirrors/jj
jj/prerelease/contributing/index.html

1384 lines
No EOL
32 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://ilyagr.github.io/jj/prerelease/contributing/">
<link rel="prev" href="../technical/conflicts/">
<link rel="next" href="../code-of-conduct/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.2.3">
<title>Guidelines and Setup - Jujutsu docs</title>
<link rel="stylesheet" href="../assets/stylesheets/main.0e669242.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr">
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#how-to-contribute" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden>
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Jujutsu docs" class="md-header__button md-logo" aria-label="Jujutsu docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Jujutsu docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Guidelines and Setup
</span>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Jujutsu docs" class="md-nav__button md-logo" aria-label="Jujutsu docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
</a>
Jujutsu docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" >
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Getting started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Getting started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../install-and-setup/" class="md-nav__link">
<span class="md-ellipsis">
Installation and Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial/" class="md-nav__link">
<span class="md-ellipsis">
Tutorial and Birds-Eye View
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../github/" class="md-nav__link">
<span class="md-ellipsis">
Working with Github
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../FAQ/" class="md-nav__link">
<span class="md-ellipsis">
FAQ
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
Concepts
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Concepts
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../working-copy/" class="md-nav__link">
<span class="md-ellipsis">
Working Copy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../branches/" class="md-nav__link">
<span class="md-ellipsis">
Branches
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../conflicts/" class="md-nav__link">
<span class="md-ellipsis">
Conflicts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../operation-log/" class="md-nav__link">
<span class="md-ellipsis">
Operation Log
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../glossary/" class="md-nav__link">
<span class="md-ellipsis">
Glossary
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Configuration
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../config/" class="md-nav__link">
<span class="md-ellipsis">
Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../revsets/" class="md-nav__link">
<span class="md-ellipsis">
Revset language
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../templates/" class="md-nav__link">
<span class="md-ellipsis">
Templating language
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Comparisons
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Comparisons
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../git-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Git comparison
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../git-compatibility/" class="md-nav__link">
<span class="md-ellipsis">
Git compatibility
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../sapling-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Sapling
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../related-work/" class="md-nav__link">
<span class="md-ellipsis">
Other related work
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
Technical details
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Technical details
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../technical/architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../technical/concurrency/" class="md-nav__link">
<span class="md-ellipsis">
Concurrency
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../technical/conflicts/" class="md-nav__link">
<span class="md-ellipsis">
Conflicts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" checked>
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Contributing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Contributing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Guidelines and Setup
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Guidelines and Setup
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#policies" class="md-nav__link">
Policies
</a>
<nav class="md-nav" aria-label="Policies">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#contributor-license-agreement" class="md-nav__link">
Contributor License Agreement
</a>
</li>
<li class="md-nav__item">
<a href="#code-reviews" class="md-nav__link">
Code reviews
</a>
</li>
<li class="md-nav__item">
<a href="#community-guidelines" class="md-nav__link">
Community Guidelines
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#learning-rust" class="md-nav__link">
Learning Rust
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-a-development-environment" class="md-nav__link">
Setting up a development environment
</a>
<nav class="md-nav" aria-label="Setting up a development environment">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
Summary
</a>
</li>
<li class="md-nav__item">
<a href="#explanation" class="md-nav__link">
Explanation
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#docs-experimental" class="md-nav__link">
Docs (experimental)
</a>
<nav class="md-nav" aria-label="Docs (experimental)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#notes-on-using-poetry" class="md-nav__link">
Notes on using poetry
</a>
</li>
<li class="md-nav__item">
<a href="#notes-on-mkdocs-and-mike" class="md-nav__link">
Notes on mkdocs and mike
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../code-of-conduct/" class="md-nav__link">
<span class="md-ellipsis">
Code of conduct
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" >
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
Design docs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Design docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../design/git-submodules/" class="md-nav__link">
<span class="md-ellipsis">
git-submodules
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/git-submodule-storage/" class="md-nav__link">
<span class="md-ellipsis">
git-submodule-storage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/tracking-branches/" class="md-nav__link">
<span class="md-ellipsis">
Tracking branches
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#policies" class="md-nav__link">
Policies
</a>
<nav class="md-nav" aria-label="Policies">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#contributor-license-agreement" class="md-nav__link">
Contributor License Agreement
</a>
</li>
<li class="md-nav__item">
<a href="#code-reviews" class="md-nav__link">
Code reviews
</a>
</li>
<li class="md-nav__item">
<a href="#community-guidelines" class="md-nav__link">
Community Guidelines
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#learning-rust" class="md-nav__link">
Learning Rust
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-a-development-environment" class="md-nav__link">
Setting up a development environment
</a>
<nav class="md-nav" aria-label="Setting up a development environment">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
Summary
</a>
</li>
<li class="md-nav__item">
<a href="#explanation" class="md-nav__link">
Explanation
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#docs-experimental" class="md-nav__link">
Docs (experimental)
</a>
<nav class="md-nav" aria-label="Docs (experimental)">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#notes-on-using-poetry" class="md-nav__link">
Notes on using poetry
</a>
</li>
<li class="md-nav__item">
<a href="#notes-on-mkdocs-and-mike" class="md-nav__link">
Notes on mkdocs and mike
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="how-to-contribute">How to Contribute</h1>
<h2 id="policies">Policies</h2>
<p>We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.</p>
<h3 id="contributor-license-agreement">Contributor License Agreement</h3>
<p>Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <a href="https://cla.developers.google.com/">https://cla.developers.google.com/</a> to see
your current agreements on file or to sign a new one.</p>
<p>You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.</p>
<h3 id="code-reviews">Code reviews</h3>
<p>All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
<a href="https://help.github.com/articles/about-pull-requests/">GitHub Help</a> for more
information on using pull requests.</p>
<p>Unlike many GitHub projects (but like many VCS projects), we care more about the
contents of commits than about the contents of PRs. We review each commit
separately, and we don't squash them when the PR is ready.</p>
<p>Each commit should ideally do one thing. For example, if you need to refactor a
function in order to add a new feature cleanly, put the refactoring in one
commit and the new feature in a different commit. If the refactoring itself
consists of many parts, try to separate out those into separate commits. You can
use <code>jj split</code> to do it if you didn't realize ahead of time how it should be
split up. Include tests and documentation in the same commit as the code the
test and document. The commit message should describe the changes in the commit;
the PR description can even be empty, but feel free to include a personal
message.</p>
<p>When you address comments on a PR, don't make the changes in a commit on top (as
is typical on GitHub). Instead, please make the changes in the appropriate
commit. You can do that by checking out the commit (<code>jj checkout/new &lt;commit&gt;</code>)
and then squash in the changes when you're done (<code>jj squash</code>). <code>jj git push</code>
will automatically force-push the branch.</p>
<p>When your first PR has been approved, we typically give you contributor access,
so you can address any remaining minor comments and then merge the PR yourself
when you're ready. If you realize that some comments require non-trivial
changes, please ask your reviewer to take another look.</p>
<h3 id="community-guidelines">Community Guidelines</h3>
<p>This project follows <a href="https://opensource.google/conduct/">Google's Open Source Community
Guidelines</a>.</p>
<h2 id="learning-rust">Learning Rust</h2>
<p>In addition to the <a href="https://doc.rust-lang.org/book/">Rust Book</a> and the other
excellent resources at https://www.rust-lang.org/learn, we recommend the
<a href="https://google.github.io/comprehensive-rust/">"Comprehensive Rust" mini-course</a>
for an overview, especially if you are familiar with C++.</p>
<h2 id="setting-up-a-development-environment">Setting up a development environment</h2>
<p>To develop <code>jj</code>, the mandatory steps are simply
to <a href="https://www.rust-lang.org/tools/install">install Rust</a> (the default
installer options are fine), clone the repository, and use <code>cargo build</code>
, <code>cargo fmt</code>,
<code>cargo clippy --workspace --all-targets</code>, and
<code>cargo test --workspace</code>. If you are preparing a PR, there are some additional
recommended steps.</p>
<h3 id="summary">Summary</h3>
<p>One-time setup:</p>
<div class="codehilite"><pre><span></span><code>rustup toolchain add nightly # wanted for &#39;rustfmt&#39;
rustup toolchain add 1.71 # also specified in Cargo.toml
cargo install cargo-insta
cargo install cargo-watch
cargo install cargo-nextest
</code></pre></div>
<p>During development (adapt according to your preference):</p>
<div class="codehilite"><pre><span></span><code>cargo watch --ignore &#39;.jj/**&#39; -s \
&#39;cargo clippy --workspace --all-targets \
&amp;&amp; cargo +1.71 check --workspace --all-targets&#39;
cargo +nightly fmt # Occasionally
cargo nextest run --workspace # Occasionally
cargo insta test --workspace --test-runner nextest # Occasionally
</code></pre></div>
<p>WARNING: Build artifacts from debug builds and especially from repeated
invocations of <code>cargo test</code> can quickly take up 10s of GB of disk space.
Cargo will happily use up your entire hard drive. If this happens, run
<code>cargo clean</code>.</p>
<h3 id="explanation">Explanation</h3>
<p>These are listed roughly in order of decreasing importance.</p>
<ol>
<li>
<p>Nearly any change to <code>jj</code>'s CLI will require writing or updating snapshot
tests that use the <a href="https://insta.rs/"><code>insta</code></a> crate. To make this
convenient, install the <code>cargo-insta</code> binary.
Use <code>cargo insta test --workspace</code> to run tests,
and <code>cargo insta review --workspace</code> to update the snapshot tests.
The <code>--workspace</code> flag is needed to run the tests on all crates; by default,
only the crate in the current directory is tested.</p>
</li>
<li>
<p>Github CI checks require that the code is formatted with the <em>nightly</em>
version of <code>rustfmt</code>. To do this on your computer, install the nightly
toolchain and use <code>cargo +nightly fmt</code>.</p>
</li>
<li>
<p>Your code will be rejected if it cannot be compiled with the minimal
supported version of Rust ("MSRV"). Currently, <code>jj</code> follows a rather
casual MSRV policy: "The current <code>rustc</code> stable version, minus one."
As of this writing, that version is <strong>1.71.0</strong>.</p>
</li>
<li>
<p>Your code needs to pass <code>cargo clippy</code>. You can also
use <code>cargo +nightly clippy</code> if you wish to see more warnings.</p>
</li>
<li>
<p>You may also want to install and use <code>cargo-watch</code>. In this case, you should
exclude <code>.jj</code>. directory from the filesystem watcher, as it gets updated on
every <code>jj log</code>.</p>
</li>
<li>
<p>To run tests more quickly, use <code>cargo nextest run --workspace</code>. To
use <code>nextest</code> with <code>insta</code>,
use <code>cargo insta test --workspace --test-runner nextest</code>.</p>
</li>
</ol>
<p>## Modifying protobuffers (this is not common)</p>
<p>Occasionally, you may need to change the <code>.proto</code> files that define jj's data
storage format. In this case, you will need to add a few steps to the above
workflow.</p>
<ul>
<li>Install the <code>protoc</code> compiler. This usually means either <code>apt-get install
protobuf-compiler</code> or downloading <a href="https://github.com/protocolbuffers/protobuf/releases">an official release</a>. The
[<code>prost</code> library docs] have additional advice.</li>
<li>Run <code>cargo run -p gen-protos</code> regularly (or after every edit to a <code>.proto</code>
file). This is the same as running <code>cargo run</code> from <code>lib/gen-protos</code>. The
<code>gen-protos</code> binary will use the <code>prost-build</code> library to compile the
<code>.proto</code> files into <code>.rs</code> files.</li>
<li>If you are adding a new <code>.proto</code> file, you will need to edit the list of
these files in <code>lib/gen-protos/src/main.rs</code>.</li>
</ul>
<p>The <code>.rs</code> files generated from <code>.proto</code> files are included in the repository,
and there is a Github CI check that will complain if they do not match.</p>
<h2 id="docs-experimental">Docs (experimental)</h2>
<h3 id="notes-on-using-poetry">Notes on using <code>poetry</code></h3>
<p>Can be installed with a package manager.</p>
<div class="codehilite"><pre><span></span><code><span class="c1"># https://github.com/python-poetry/poetry/issues/1917</span>
<span class="nv">PYTHON_KEYRING_BACKEND</span><span class="o">=</span>keyring.backends.fail.Keyring<span class="w"> </span>poetry<span class="w"> </span>install
poetry<span class="w"> </span>shell
</code></pre></div>
<h3 id="notes-on-mkdocs-and-mike">Notes on <code>mkdocs</code> and <code>mike</code></h3>
<p>Something like <code>jj co v0.8.0 &amp;&amp; mike deploy v0.8.0 --prefix mkdocs</code> changes the
<code>mkdocs</code> dir on the <code>gh-pages</code> branch.</p>
<p>Mark one version as <code>latest</code> or <code>stable</code>, another as <code>main</code>.</p>
<p>It's recommended to do this as <code>mike set-default --push latest</code>.</p>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.78eede0e.min.js"></script>
</body>
</html>