git-pr
created pr with
56.1
added 56.2
1: 0200c93 ! 1: a2710a3 refactor: custom index page
added 56.3
1: a2710a3 < -: ------- refactor: custom index page
-: ------- > 1: 7338b44 feat: allow config `desc` to add a description box to index page
added 56.4
1: 7338b44 < -: ------- feat: allow config `desc` to add a description box to index page
-: ------- > 1: 26daea4 feat(pgs): lru cache for object info and special files
-: ------- > 2: b004b64 chore(pgs): use http cache clear event to rm lru cache for special files
-: ------- > 3: 59f5618 refactor(pgs): store lru cache on web router
changed status to
accepted
cmds
checkout latest patchset:
ssh pr.pico.sh print 56 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 56.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 56set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 56set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 56
Patchset
56.3
feat: allow config `desc` to add a description box to index page
Eric Bower
2025-03-28T14:47:13Zrefactor: consolidate docs page onto index This change will allow maintainers to add a description box to the top of their git-pr instance as an introduction to their service.
Semantic diff summary
0 added,
5 modified,
0 signature changed,
1 removed
across 2 analyzed files
(5 files skipped: unsupported file type)
+2
-0
cfg.go
#
+1
-0
git-pr.toml
#
+1
-1
static/git-pr.css
#
+0
-283
tmpl/docs.html
#
| ... | ... | @@ -1,283 +0,0 @@ | |
| 1 | - | {{template "base" .}} | |
| 2 | - | ||
| 3 | - | {{define "title"}}git-pr{{end}} | |
| 4 | - | ||
| 5 | - | {{define "meta"}} | |
| 6 | - | <link rel="alternate" type="application/atom+xml" | |
| 7 | - | title="RSS feed for git collaboration server" | |
| 8 | - | href="/rss" /> | |
| 9 | - | {{end}} | |
| 10 | - | ||
| 11 | - | {{define "body"}} | |
| 12 | - | <header class="group"> | |
| 13 | - | <h1 class="text-2xl"><a href="/">DASHBOARD</a> / docs</h1> | |
| 14 | - | <div> | |
| 15 | - | <span>A pastebin supercharged for git collaboration</span> · | |
| 16 | - | <a href="https://github.com/picosh/git-pr">github</a> · | |
| 17 | - | <a href="https://youtu.be/d28Dih-BBUw">demo video</a> | |
| 18 | - | </div> | |
| 19 | - | <pre class="m-0">ssh {{.MetaData.URL}} help</pre> | |
| 20 | - | </header> | |
| 21 | - | ||
| 22 | - | <main class="group"> | |
| 23 | - | <details> | |
| 24 | - | <summary>Intro</summary> | |
| 25 | - | ||
| 26 | - | <div> | |
| 27 | - | <p> | |
| 28 | - | We are trying to build the simplest git collaboration tool. The goal is to make | |
| 29 | - | self-hosting as simple as running an SSH server -- all without | |
| 30 | - | sacrificing external collaborators time and energy. | |
| 31 | - | </p> | |
| 32 | - | ||
| 33 | - | <blockquote> | |
| 34 | - | <code>git format-patch</code> isn't the problem and pull requests aren't the solution. | |
| 35 | - | </blockquote> | |
| 36 | - | ||
| 37 | - | <p> | |
| 38 | - | We are combining mailing list and pull request workflows. In order to build the | |
| 39 | - | simplest collaboration tool, we needed something as simple as generating patches | |
| 40 | - | but the ease-of-use of pull requests. | |
| 41 | - | </p> | |
| 42 | - | ||
| 43 | - | <p> | |
| 44 | - | The goal is not to create another code forge, the goal is to create a very | |
| 45 | - | simple self-hosted git solution with the ability to collaborate with external | |
| 46 | - | contributors. All the code owner needs to setup a running git server: | |
| 47 | - | </p> | |
| 48 | - | ||
| 49 | - | <ul><li>A single golang binary</li></ul> | |
| 50 | - | ||
| 51 | - | <div> | |
| 52 | - | All an external contributor needs is: | |
| 53 | - | </div> | |
| 54 | - | ||
| 55 | - | <ul> | |
| 56 | - | <li>An SSH keypair</li> | |
| 57 | - | <li>An SSH client</li> | |
| 58 | - | </ul> | |
| 59 | - | ||
| 60 | - | <div>Then everyone subscribes to our RSS feeds to receive updates to patch requests.</div> | |
| 61 | - | ||
| 62 | - | <h2 class="text-xl">the problem</h2> | |
| 63 | - | ||
| 64 | - | <p> | |
| 65 | - | Email is great as a decentralized system to send and receive changes (patchsets) | |
| 66 | - | to a git repo. However, onboarding a new user to a mailing list, properly | |
| 67 | - | setting up their email client, and then finally submitting the code contribution | |
| 68 | - | is enough to make many developers give up. Further, because we are leveraging | |
| 69 | - | the email protocol for collaboration, we are limited by its feature-set. For | |
| 70 | - | example, it is not possible to make edits to emails, everyone has a different | |
| 71 | - | client, those clients have different limitations around plain text email and | |
| 72 | - | downloading patches from it. | |
| 73 | - | </p> | |
| 74 | - | ||
| 75 | - | <p> | |
| 76 | - | Github pull requests are easy to use, easy to edit, and easy to manage. The | |
| 77 | - | downside is it forces the user to be inside their website to perform reviews. | |
| 78 | - | For quick changes, this is great, but when you start reading code within a web | |
| 79 | - | browser, there are quite a few downsides. At a certain point, it makes more | |
| 80 | - | sense to review code inside your local development environment, IDE, etc. There | |
| 81 | - | are tools and plugins that allow users to review PRs inside their IDE, but it | |
| 82 | - | requires a herculean effort to make it usable. | |
| 83 | - | </p> | |
| 84 | - | ||
| 85 | - | <p> | |
| 86 | - | Further, self-hosted solutions that mimic a pull request require a lot of | |
| 87 | - | infrastructure in order to manage it. A database, a web site connected to git, | |
| 88 | - | admin management, and services to manage it all. Another big point of friction: | |
| 89 | - | before an external user submits a code change, they first need to create an | |
| 90 | - | account and then login. This adds quite a bit of friction for a self-hosted | |
| 91 | - | solution, not only for an external contributor, but also for the code owner who | |
| 92 | - | has to provision the infra. Often times they also have to fork the repo within | |
| 93 | - | the code forge before submitting a PR. Then they never make a contribution ever | |
| 94 | - | again and keep a forked repo around forever. That seems silly. | |
| 95 | - | </p> | |
| 96 | - | ||
| 97 | - | <h2 class="text-xl">introducing patch requests (PR)</h2> | |
| 98 | - | ||
| 99 | - | <p> | |
| 100 | - | Instead, we want to create a self-hosted git "server" that can handle sending | |
| 101 | - | and receiving patches without the cumbersome nature of setting up email or the | |
| 102 | - | limitations imposed by the email protocol. Further, we want the primary workflow | |
| 103 | - | to surround the local development environment. Github is bringing the IDE to the | |
| 104 | - | browser in order to support their workflow, we want to flip that idea on its | |
| 105 | - | head by making code reviews a first-class citizen inside your local development | |
| 106 | - | environment. | |
| 107 | - | </p> | |
| 108 | - | ||
| 109 | - | <p> | |
| 110 | - | We see this as a hybrid between the github workflow of a pull request and | |
| 111 | - | sending and receiving patches over email. | |
| 112 | - | </p> | |
| 113 | - | ||
| 114 | - | <p> | |
| 115 | - | The basic idea is to leverage an SSH app to handle most of the interaction | |
| 116 | - | between contributor and owner of a project. Everything can be done completely | |
| 117 | - | within the terminal, in a way that is ergonomic and fully featured. | |
| 118 | - | </p> | |
| 119 | - | ||
| 120 | - | <p> | |
| 121 | - | Notifications would happen with RSS and all state mutations would result in the | |
| 122 | - | generation of static web assets so it can all be hosted using a simple file web | |
| 123 | - | server. | |
| 124 | - | </p> | |
| 125 | - | ||
| 126 | - | <h3 class="text-lg">format-patch workflow</h3> | |
| 127 | - | ||
| 128 | - | <p> | |
| 129 | - | The fundamental collaboration tool here is <code>format-patch</code>. Whether you a | |
| 130 | - | submitting code changes or you are reviewing code changes, it all happens in | |
| 131 | - | code. Both contributor and owner are simply creating new commits and generating | |
| 132 | - | patches on top of each other. This obviates the need to have a web viewer where | |
| 133 | - | the reviewing can "comment" on a line of code block. There's no need, apply the | |
| 134 | - | contributor's patches, write comments or code changes, generate a new patch, | |
| 135 | - | send the patch to the git server as a "review." This flow also works the exact | |
| 136 | - | same if two users are collaborating on a set of changes. | |
| 137 | - | </p> | |
| 138 | - | ||
| 139 | - | <p> | |
| 140 | - | This also solves the problem of sending multiple patchsets for the same code | |
| 141 | - | change. There's a single, central Patch Request where all changes and | |
| 142 | - | collaboration happens. | |
| 143 | - | </p> | |
| 144 | - | ||
| 145 | - | <p> | |
| 146 | - | We could figure out a way to leverage <code>git notes</code> for reviews / comments, but | |
| 147 | - | honestly, that solution feels brutal and outside the comfort level of most git | |
| 148 | - | users. Just send reviews as code and write comments in the programming language | |
| 149 | - | you are using. It's the job of the contributor to "address" those comments and | |
| 150 | - | then remove them in subsequent patches. This is the forcing function to address | |
| 151 | - | all comments: the patch won't be merged if there are comment unaddressed in | |
| 152 | - | code; they cannot be ignored or else they will be upstreamed erroneously. | |
| 153 | - | </p> | |
| 154 | - | </div> | |
| 155 | - | </details> | |
| 156 | - | ||
| 157 | - | <details> | |
| 158 | - | <summary>How do Patch Requests work?</summary> | |
| 159 | - | <div> | |
| 160 | - | Patch requests (PR) are the simplest way to submit, review, and accept changes to your git repository. | |
| 161 | - | Here's how it works: | |
| 162 | - | </div> | |
| 163 | - | ||
| 164 | - | <ol> | |
| 165 | - | <li>External contributor clones repo (<code>git-clone</code>)</li> | |
| 166 | - | <li>External contributor makes a code change (<code>git-add</code> & <code>git-commit</code>)</li> | |
| 167 | - | <li>External contributor generates patches (<code>git-format-patch</code>)</li> | |
| 168 | - | <li>External contributor submits a PR to SSH server</li> | |
| 169 | - | <li>Owner receives RSS notification that there's a new PR</li> | |
| 170 | - | <li>Owner applies patches locally (<code>git-am</code>) from SSH server</li> | |
| 171 | - | <li>Owner makes suggestions in code! (<code>git-add</code> & <code>git-commit</code>)</li> | |
| 172 | - | <li>Owner submits review by piping patch to SSH server (<code>git-format-patch</code>)</li> | |
| 173 | - | <li>External contributor receives RSS notification of the PR review</li> | |
| 174 | - | <li>External contributor re-applies patches (<code>git-am</code>)</li> | |
| 175 | - | <li>External contributor reviews and removes comments in code!</li> | |
| 176 | - | <li>External contributor submits another patch (<code>git-format-patch</code>)</li> | |
| 177 | - | <li>Owner applies patches locally (<code>git-am</code>)</li> | |
| 178 | - | <li>Owner marks PR as accepted and pushes code to main (<code>git-push</code>)</li> | |
| 179 | - | </ol> | |
| 180 | - | ||
| 181 | - | <div>Example commands</div> | |
| 182 | - | ||
| 183 | - | <pre># Owner hosts repo `test.git` using github | |
| 184 | - | ||
| 185 | - | # Contributor clones repo | |
| 186 | - | git clone git@github.com:picosh/test.git | |
| 187 | - | ||
| 188 | - | # Contributor wants to make a change | |
| 189 | - | # Contributor makes changes via commits | |
| 190 | - | git add -A && git commit -m "fix: some bugs" | |
| 191 | - | ||
| 192 | - | # Contributor runs: | |
| 193 | - | git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr create test | |
| 194 | - | # > Patch Request has been created (ID: 1) | |
| 195 | - | ||
| 196 | - | # Owner can checkout patch: | |
| 197 | - | ssh {{.MetaData.URL}} pr print 1 | git am -3 | |
| 198 | - | # Owner can comment (IN CODE), commit, then send another format-patch | |
| 199 | - | # on top of the PR: | |
| 200 | - | git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr add --review 1 | |
| 201 | - | # UI clearly marks patch as a review | |
| 202 | - | ||
| 203 | - | # Contributor can checkout reviews | |
| 204 | - | ssh {{.MetaData.URL}} pr print 1 | git am -3 | |
| 205 | - | ||
| 206 | - | # Owner can reject a pr: | |
| 207 | - | ssh {{.MetaData.URL}} pr close 1 | |
| 208 | - | ||
| 209 | - | # Owner can accept a pr: | |
| 210 | - | ssh {{.MetaData.URL}} pr accept 1 | |
| 211 | - | ||
| 212 | - | # Owner can prep PR for upstream: | |
| 213 | - | git rebase -i origin/main | |
| 214 | - | ||
| 215 | - | # Then push to upstream | |
| 216 | - | git push origin main | |
| 217 | - | ||
| 218 | - | # Done! | |
| 219 | - | </pre> | |
| 220 | - | </details> | |
| 221 | - | ||
| 222 | - | <details> | |
| 223 | - | <summary>What's a repo?</summary> | |
| 224 | - | ||
| 225 | - | <div> | |
| 226 | - | A repo is designed to mimick a git repo, but it's really just a tag. When | |
| 227 | - | submitting a patch request, if the user does not provide a repo name then | |
| 228 | - | the default "bin" will be selected. When a user creates a repo they become | |
| 229 | - | the repo owner and have special privileges. | |
| 230 | - | </div> | |
| 231 | - | </details> | |
| 232 | - | ||
| 233 | - | <details> | |
| 234 | - | <summary>Can anyone use this service?</summary> | |
| 235 | - | ||
| 236 | - | <div> | |
| 237 | - | This service is a public space for anyone to freely create "repos" and | |
| 238 | - | collaborate with users. Anyone is able to add patchsets to a patch request | |
| 239 | - | and anyone is able to review any other patch requests, regardless of repo. | |
| 240 | - | </div> | |
| 241 | - | </details> | |
| 242 | - | ||
| 243 | - | <details> | |
| 244 | - | <summary>First time user experience</summary> | |
| 245 | - | ||
| 246 | - | <div> | |
| 247 | - | Using this service for the first time? Creating a patch request is simple: | |
| 248 | - | </div> | |
| 249 | - | ||
| 250 | - | <pre>git format-patch main --stdout | ssh pr.pico.sh pr create {repo}</pre> | |
| 251 | - | ||
| 252 | - | <div>When running that command we will automatically create a user and a repo if one doesn't exist.</div> | |
| 253 | - | ||
| 254 | - | <div>Want to submit a v2 of the patch request?</div> | |
| 255 | - | ||
| 256 | - | <pre>git format-patch main --stdout | ssh pr.pico.sh pr add {prID}</pre> | |
| 257 | - | </details> | |
| 258 | - | ||
| 259 | - | <details> | |
| 260 | - | <summary>How do I receive notifications?</summary> | |
| 261 | - | ||
| 262 | - | <div> | |
| 263 | - | We have different RSS feeds depending on the use case. This is how you | |
| 264 | - | can receive notifications for when someone submits or reviews patch requests. | |
| 265 | - | </div> | |
| 266 | - | </details> | |
| 267 | - | ||
| 268 | - | <details> | |
| 269 | - | <summary>Alternative git collaboration systems</summary> | |
| 270 | - | ||
| 271 | - | <div> | |
| 272 | - | <ol> | |
| 273 | - | <li><a href="https://gerritcodereview.com/">Gerrit</a></li> | |
| 274 | - | <li><a href="https://we.phorge.it/">Phorge</a> (fork of Phabricator)</li> | |
| 275 | - | <li><a href="https://graphite.dev/docs/cli-quick-start">Graphite</a></li> | |
| 276 | - | <li><a href="https://codeapprove.com/">CodeApprove</a></li> | |
| 277 | - | <li><a href="https://reviewable.io/">Reviewable</a></li> | |
| 278 | - | </ol> | |
| 279 | - | </div> | |
| 280 | - | </details> | |
| 281 | - | </main> | |
| 282 | - | ||
| 283 | - | {{end}} |
+215
-19
tmpl/index.html
#
| ... | ... | @@ -10,38 +10,234 @@ | |
| 10 | 10 | ||
| 11 | 11 | {{define "body"}} | |
| 12 | 12 | <header class="group"> | |
| 13 | - | <h1 class="text-2xl">patchbin</h1> | |
| 13 | + | <h1 class="text-2xl">git-pr</h1> | |
| 14 | 14 | <div> | |
| 15 | 15 | <span>A pastebin supercharged for git collaboration</span> · | |
| 16 | - | <a href="/docs">docs</a> | |
| 16 | + | <a href="https://github.com/picosh/git-pr">github</a> · | |
| 17 | + | <a href="https://youtu.be/d28Dih-BBUw">demo video</a> | |
| 17 | 18 | </div> | |
| 18 | 19 | ||
| 20 | + | {{if .MetaData.Desc}} | |
| 19 | 21 | <div class="box-sm"> | |
| 20 | - | <div> | |
| 21 | - | Welcome to <a href="https://pico.sh">pico's</a> managed patchbin service! | |
| 22 | - | This is a <strong>public</strong> service that is free to anyone who wants | |
| 23 | - | to collaborate on git patches. The idea is simple: submit a patchset to | |
| 24 | - | our service and let anyone collaborate on it by submitting follow-up patchsets. | |
| 25 | - | Using this service for the first time? Creating a patch request is simple: | |
| 26 | - | </div> | |
| 22 | + | <div>{{.MetaData.Desc}}</div> | |
| 23 | + | </div> | |
| 24 | + | {{end}} | |
| 27 | 25 | ||
| 28 | - | <pre class="text-sm">git format-patch main --stdout | ssh pr.pico.sh pr create {repo}</pre> | |
| 26 | + | <details> | |
| 27 | + | <summary>Intro</summary> | |
| 29 | 28 | ||
| 30 | 29 | <div> | |
| 31 | - | When running that command we will automatically create a user and a repo | |
| 32 | - | if one doesn't exist. Once the patches have been submitted you'll receive | |
| 33 | - | a link that you can send to a reviewer. Anyone can review patch requests. | |
| 34 | - | Want to submit a v2 of the patch request? | |
| 30 | + | <p> | |
| 31 | + | We are trying to build the simplest git collaboration tool. The goal is to make | |
| 32 | + | self-hosting as simple as running an SSH server -- all without | |
| 33 | + | sacrificing external collaborators time and energy. | |
| 34 | + | </p> | |
| 35 | + | ||
| 36 | + | <blockquote> | |
| 37 | + | <code>git format-patch</code> isn't the problem and pull requests aren't the solution. | |
| 38 | + | </blockquote> | |
| 39 | + | ||
| 40 | + | <p> | |
| 41 | + | We are combining mailing list and pull request workflows. In order to build the | |
| 42 | + | simplest collaboration tool, we needed something as simple as generating patches | |
| 43 | + | but the ease-of-use of pull requests. | |
| 44 | + | </p> | |
| 45 | + | ||
| 46 | + | <p> | |
| 47 | + | The goal is not to create another code forge, the goal is to create a very | |
| 48 | + | simple self-hosted git solution with the ability to collaborate with external | |
| 49 | + | contributors. All the code owner needs to setup a running git server: | |
| 50 | + | </p> | |
| 51 | + | ||
| 52 | + | <ul><li>A single golang binary</li></ul> | |
| 53 | + | ||
| 54 | + | <div> | |
| 55 | + | All an external contributor needs is: | |
| 56 | + | </div> | |
| 57 | + | ||
| 58 | + | <ul> | |
| 59 | + | <li>An SSH keypair</li> | |
| 60 | + | <li>An SSH client</li> | |
| 61 | + | </ul> | |
| 62 | + | ||
| 63 | + | <p>Then everyone subscribes to our RSS feeds to receive updates to patch requests.</p> | |
| 64 | + | ||
| 65 | + | <h2 class="text-xl">the problem</h2> | |
| 66 | + | ||
| 67 | + | <p> | |
| 68 | + | Email is great as a decentralized system to send and receive changes (patchsets) | |
| 69 | + | to a git repo. However, onboarding a new user to a mailing list, properly | |
| 70 | + | setting up their email client, and then finally submitting the code contribution | |
| 71 | + | is enough to make many developers give up. Further, because we are leveraging | |
| 72 | + | the email protocol for collaboration, we are limited by its feature-set. For | |
| 73 | + | example, it is not possible to make edits to emails, everyone has a different | |
| 74 | + | client, those clients have different limitations around plain text email and | |
| 75 | + | downloading patches from it. | |
| 76 | + | </p> | |
| 77 | + | ||
| 78 | + | <p> | |
| 79 | + | Github pull requests are easy to use, easy to edit, and easy to manage. The | |
| 80 | + | downside is it forces the user to be inside their website to perform reviews. | |
| 81 | + | For quick changes, this is great, but when you start reading code within a web | |
| 82 | + | browser, there are quite a few downsides. At a certain point, it makes more | |
| 83 | + | sense to review code inside your local development environment, IDE, etc. There | |
| 84 | + | are tools and plugins that allow users to review PRs inside their IDE, but it | |
| 85 | + | requires a herculean effort to make it usable. | |
| 86 | + | </p> | |
| 87 | + | ||
| 88 | + | <p> | |
| 89 | + | Further, self-hosted solutions that mimic a pull request require a lot of | |
| 90 | + | infrastructure in order to manage it. A database, a web site connected to git, | |
| 91 | + | admin management, and services to manage it all. Another big point of friction: | |
| 92 | + | before an external user submits a code change, they first need to create an | |
| 93 | + | account and then login. This adds quite a bit of friction for a self-hosted | |
| 94 | + | solution, not only for an external contributor, but also for the code owner who | |
| 95 | + | has to provision the infra. Often times they also have to fork the repo within | |
| 96 | + | the code forge before submitting a PR. Then they never make a contribution ever | |
| 97 | + | again and keep a forked repo around forever. That seems silly. | |
| 98 | + | </p> | |
| 99 | + | ||
| 100 | + | <h2 class="text-xl">introducing patch requests (PR)</h2> | |
| 101 | + | ||
| 102 | + | <p> | |
| 103 | + | Instead, we want to create a self-hosted git "server" that can handle sending | |
| 104 | + | and receiving patches without the cumbersome nature of setting up email or the | |
| 105 | + | limitations imposed by the email protocol. Further, we want the primary workflow | |
| 106 | + | to surround the local development environment. Github is bringing the IDE to the | |
| 107 | + | browser in order to support their workflow, we want to flip that idea on its | |
| 108 | + | head by making code reviews a first-class citizen inside your local development | |
| 109 | + | environment. | |
| 110 | + | </p> | |
| 111 | + | ||
| 112 | + | <p> | |
| 113 | + | We see this as a hybrid between the github workflow of a pull request and | |
| 114 | + | sending and receiving patches over email. | |
| 115 | + | </p> | |
| 116 | + | ||
| 117 | + | <p> | |
| 118 | + | The basic idea is to leverage an SSH app to handle most of the interaction | |
| 119 | + | between contributor and owner of a project. Everything can be done completely | |
| 120 | + | within the terminal, in a way that is ergonomic and fully featured. | |
| 121 | + | </p> | |
| 122 | + | ||
| 123 | + | <p> | |
| 124 | + | Notifications would happen with RSS and all state mutations would result in the | |
| 125 | + | generation of static web assets so it can all be hosted using a simple file web | |
| 126 | + | server. | |
| 127 | + | </p> | |
| 128 | + | ||
| 129 | + | <h3 class="text-lg">format-patch workflow</h3> | |
| 130 | + | ||
| 131 | + | <p> | |
| 132 | + | The fundamental collaboration tool here is <code>format-patch</code>. Whether you a | |
| 133 | + | submitting code changes or you are reviewing code changes, it all happens in | |
| 134 | + | code. Both contributor and owner are simply creating new commits and generating | |
| 135 | + | patches on top of each other. This obviates the need to have a web viewer where | |
| 136 | + | the reviewing can "comment" on a line of code block. There's no need, apply the | |
| 137 | + | contributor's patches, write comments or code changes, generate a new patch, | |
| 138 | + | send the patch to the git server as a "review." This flow also works the exact | |
| 139 | + | same if two users are collaborating on a set of changes. | |
| 140 | + | </p> | |
| 141 | + | ||
| 142 | + | <p> | |
| 143 | + | This also solves the problem of sending multiple patchsets for the same code | |
| 144 | + | change. There's a single, central Patch Request where all changes and | |
| 145 | + | collaboration happens. | |
| 146 | + | </p> | |
| 147 | + | ||
| 148 | + | <p> | |
| 149 | + | We could figure out a way to leverage <code>git notes</code> for reviews / comments, but | |
| 150 | + | honestly, that solution feels brutal and outside the comfort level of most git | |
| 151 | + | users. Just send reviews as code and write comments in the programming language | |
| 152 | + | you are using. It's the job of the contributor to "address" those comments and | |
| 153 | + | then remove them in subsequent patches. This is the forcing function to address | |
| 154 | + | all comments: the patch won't be merged if there are comment unaddressed in | |
| 155 | + | code; they cannot be ignored or else they will be upstreamed erroneously. | |
| 156 | + | </p> | |
| 35 | 157 | </div> | |
| 158 | + | </details> | |
| 159 | + | ||
| 160 | + | <details> | |
| 161 | + | <summary>How do Patch Requests work?</summary> | |
| 162 | + | <div> | |
| 163 | + | Patch requests (PR) are the simplest way to submit, review, and accept changes to your git repository. | |
| 164 | + | Here's how it works: | |
| 165 | + | </div> | |
| 166 | + | ||
| 167 | + | <ol> | |
| 168 | + | <li>External contributor clones repo (<code>git-clone</code>)</li> | |
| 169 | + | <li>External contributor makes a code change (<code>git-add</code> & <code>git-commit</code>)</li> | |
| 170 | + | <li>External contributor generates patches (<code>git-format-patch</code>)</li> | |
| 171 | + | <li>External contributor submits a PR to SSH server</li> | |
| 172 | + | <li>Owner receives RSS notification that there's a new PR</li> | |
| 173 | + | <li>Owner applies patches locally (<code>git-am</code>) from SSH server</li> | |
| 174 | + | <li>Owner makes suggestions in code! (<code>git-add</code> & <code>git-commit</code>)</li> | |
| 175 | + | <li>Owner submits review by piping patch to SSH server (<code>git-format-patch</code>)</li> | |
| 176 | + | <li>External contributor receives RSS notification of the PR review</li> | |
| 177 | + | <li>External contributor re-applies patches (<code>git-am</code>)</li> | |
| 178 | + | <li>External contributor reviews and removes comments in code!</li> | |
| 179 | + | <li>External contributor submits another patch (<code>git-format-patch</code>)</li> | |
| 180 | + | <li>Owner applies patches locally (<code>git-am</code>)</li> | |
| 181 | + | <li>Owner marks PR as accepted and pushes code to main (<code>git-push</code>)</li> | |
| 182 | + | </ol> | |
| 183 | + | ||
| 184 | + | <div>Example commands</div> | |
| 185 | + | ||
| 186 | + | <pre># Owner hosts repo `test.git` using github | |
| 187 | + | ||
| 188 | + | # Contributor clones repo | |
| 189 | + | git clone git@github.com:picosh/test.git | |
| 190 | + | ||
| 191 | + | # Contributor wants to make a change | |
| 192 | + | # Contributor makes changes via commits | |
| 193 | + | git add -A && git commit -m "fix: some bugs" | |
| 194 | + | ||
| 195 | + | # Contributor runs: | |
| 196 | + | git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr create test | |
| 197 | + | # > Patch Request has been created (ID: 1) | |
| 198 | + | ||
| 199 | + | # Owner can checkout patch: | |
| 200 | + | ssh {{.MetaData.URL}} pr print 1 | git am -3 | |
| 201 | + | ||
| 202 | + | # Owner can comment (IN CODE), commit, then send another format-patch | |
| 203 | + | # on top of the PR: | |
| 204 | + | git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr add --review 1 | |
| 205 | + | # UI clearly marks patch as a review | |
| 36 | 206 | ||
| 37 | - | <pre class="text-sm">git format-patch main --stdout | ssh pr.pico.sh pr add {prID}</pre> | |
| 207 | + | # Contributor can checkout reviews | |
| 208 | + | ssh {{.MetaData.URL}} print pr-1 | git am -3 | |
| 209 | + | ||
| 210 | + | # Owner can reject a pr: | |
| 211 | + | ssh {{.MetaData.URL}} pr close 1 | |
| 212 | + | ||
| 213 | + | # Owner can accept a pr: | |
| 214 | + | ssh {{.MetaData.URL}} pr accept 1 | |
| 215 | + | ||
| 216 | + | # Owner can prep PR for upstream: | |
| 217 | + | git rebase -i origin/main | |
| 218 | + | ||
| 219 | + | # Then push to upstream | |
| 220 | + | git push origin main | |
| 221 | + | ||
| 222 | + | # Done! | |
| 223 | + | </pre> | |
| 224 | + | </details> | |
| 225 | + | ||
| 226 | + | <details> | |
| 227 | + | <summary>First time user?</summary> | |
| 38 | 228 | ||
| 39 | 229 | <div> | |
| 40 | - | Downloading a patchset is easy as well: | |
| 230 | + | Using this service for the first time? Creating a patch request is simple: | |
| 41 | 231 | </div> | |
| 42 | 232 | ||
| 43 | - | <pre class="text-sm">ssh pr.pico.sh print pr-{prID}</pre> | |
| 44 | - | </div> | |
| 233 | + | <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr create {repo}</pre> | |
| 234 | + | ||
| 235 | + | <div>When running that command we will automatically create a user and a repo if one doesn't exist.</div> | |
| 236 | + | ||
| 237 | + | <div>Want to submit a v2 of the patch request?</div> | |
| 238 | + | ||
| 239 | + | <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr add {prID}</pre> | |
| 240 | + | </details> | |
| 45 | 241 | </header> | |
| 46 | 242 | ||
| 47 | 243 | <main> |
+17
-12
tmpl/pr-header.html
#
| ... | ... | @@ -17,18 +17,23 @@ | |
| 17 | 17 | <details> | |
| 18 | 18 | <summary>Help</summary> | |
| 19 | 19 | <div class="group"> | |
| 20 | - | <pre class="m-0"># checkout latest patchset | |
| 21 | - | ssh {{.MetaData.URL}} print pr-{{.Pr.ID}} | git am -3</pre> | |
| 22 | - | <pre class="m-0"># checkout any patchset in a patch request | |
| 23 | - | ssh {{.MetaData.URL}} print ps-X | git am -3</pre> | |
| 24 | - | <pre class="m-0"># add changes to patch request | |
| 25 | - | git format-patch {{.Branch}} --stdout | ssh {{.MetaData.URL}} pr add {{.Pr.ID}}</pre> | |
| 26 | - | <pre class="m-0"># add review to patch request | |
| 27 | - | git format-patch {{.Branch}} --stdout | ssh {{.MetaData.URL}} pr add --review {{.Pr.ID}}</pre> | |
| 28 | - | <pre class="m-0"># accept PR | |
| 29 | - | ssh {{.MetaData.URL}} pr accept {{.Pr.ID}}</pre> | |
| 30 | - | <pre class="m-0"># close PR | |
| 31 | - | ssh {{.MetaData.URL}} pr close {{.Pr.ID}}</pre> | |
| 20 | + | checkout latest patchset: | |
| 21 | + | <pre class="m-0">ssh {{.MetaData.URL}} print pr-{{.Pr.ID}} | git am -3</pre> | |
| 22 | + | ||
| 23 | + | checkout any patchset in a patch request: | |
| 24 | + | <pre class="m-0">ssh {{.MetaData.URL}} print ps-X | git am -3</pre> | |
| 25 | + | ||
| 26 | + | add changes to patch request: | |
| 27 | + | <pre class="m-0">git format-patch {{.Branch}} --stdout | ssh {{.MetaData.URL}} pr add {{.Pr.ID}}</pre> | |
| 28 | + | ||
| 29 | + | add review to patch request: | |
| 30 | + | <pre class="m-0">git format-patch {{.Branch}} --stdout | ssh {{.MetaData.URL}} pr add --review {{.Pr.ID}}</pre> | |
| 31 | + | ||
| 32 | + | accept PR: | |
| 33 | + | <pre class="m-0">ssh {{.MetaData.URL}} pr accept {{.Pr.ID}}</pre> | |
| 34 | + | ||
| 35 | + | close PR: | |
| 36 | + | <pre class="m-0">ssh {{.MetaData.URL}} pr close {{.Pr.ID}}</pre> | |
| 32 | 37 | </div> | |
| 33 | 38 | </details> | |
| 34 | 39 | </header> |
+5
-22
web.go
#
| ... | ... | @@ -287,25 +287,6 @@ func getPrTableData(web *WebCtx, prs []*PatchRequest, query url.Values) ([]*PrLi | |
| 287 | 287 | return prdata, nil | |
| 288 | 288 | } | |
| 289 | 289 | ||
| 290 | - | func docsHandler(w http.ResponseWriter, r *http.Request) { | |
| 291 | - | web, err := getWebCtx(r) | |
| 292 | - | if err != nil { | |
| 293 | - | w.WriteHeader(http.StatusInternalServerError) | |
| 294 | - | return | |
| 295 | - | } | |
| 296 | - | ||
| 297 | - | w.Header().Set("content-type", "text/html") | |
| 298 | - | tmpl := getTemplate("docs.html") | |
| 299 | - | err = tmpl.ExecuteTemplate(w, "docs.html", BasicData{ | |
| 300 | - | MetaData: MetaData{ | |
| 301 | - | URL: web.Backend.Cfg.Url, | |
| 302 | - | }, | |
| 303 | - | }) | |
| 304 | - | if err != nil { | |
| 305 | - | web.Backend.Logger.Error("cannot execute template", "err", err) | |
| 306 | - | } | |
| 307 | - | } | |
| 308 | - | ||
| 309 | 290 | func indexHandler(w http.ResponseWriter, r *http.Request) { | |
| 310 | 291 | web, err := getWebCtx(r) | |
| 311 | 292 | if err != nil { |
| ... | ... | @@ -349,7 +330,8 @@ func indexHandler(w http.ResponseWriter, r *http.Request) { | |
| 349 | 330 | NumClosed: numClosed, | |
| 350 | 331 | Prs: prdata, | |
| 351 | 332 | MetaData: MetaData{ | |
| 352 | - | URL: web.Backend.Cfg.Url, | |
| 333 | + | URL: web.Backend.Cfg.Url, | |
| 334 | + | Desc: template.HTML(web.Backend.Cfg.Desc), | |
| 353 | 335 | }, | |
| 354 | 336 | }) | |
| 355 | 337 | if err != nil { |
| ... | ... | @@ -1122,6 +1105,7 @@ func StartWebServer(cfg *GitCfg) { | |
| 1122 | 1105 | } | |
| 1123 | 1106 | formatter := formatterHtml.New( | |
| 1124 | 1107 | formatterHtml.WithLineNumbers(true), | |
| 1108 | + | formatterHtml.LineNumbersInTable(true), | |
| 1125 | 1109 | formatterHtml.WithClasses(true), | |
| 1126 | 1110 | formatterHtml.WithLinkableLineNumbers(true, "gitpr"), | |
| 1127 | 1111 | ) |
| ... | ... | @@ -1147,7 +1131,6 @@ func StartWebServer(cfg *GitCfg) { | |
| 1147 | 1131 | http.HandleFunc("GET /r/{user}", ctxMdw(ctx, userDetailHandler)) | |
| 1148 | 1132 | http.HandleFunc("GET /rss/{user}", ctxMdw(ctx, rssHandler)) | |
| 1149 | 1133 | http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler)) | |
| 1150 | - | http.HandleFunc("GET /docs", ctxMdw(ctx, docsHandler)) | |
| 1151 | 1134 | http.HandleFunc("GET /", ctxMdw(ctx, indexHandler)) | |
| 1152 | 1135 | http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler)) | |
| 1153 | 1136 | embedFS, err := getEmbedFS(embedStaticFS, "static") |