add Git Remote Nostr URL format so clients can provide appropriate clone urls. This is used by ngit and gitworkshop.dev minus the usage of nip05 addresses. See this discussion of the format: https://njump.me/nevent1qvzqqqqqqypzpgqgmmc409hm4xsdd74sf68a2uyf9pwel4g9mfdg8l5244t6x4jdqy88wumn8ghj7mn0wvhxcmmv9uqsuamnwvaz7tmwdaejumr0dshsqg993aqt7e4v2p3cu06axwzsz999s798d04u27e50nn52la7t6t5dy94kk26 add wider git remote helper spec implemented by git plugin bundled with 'ngit'
9.2 KiB
NIP-34
git
stuff
draft
optional
This NIP defines all the ways code collaboration using and adjacent to git
can be done using Nostr.
Repository announcements
Git repositories are hosted in Git-enabled servers, but their existence can be announced using Nostr events, as well as their willingness to receive patches, bug reports and comments in general.
{
"kind": 30617,
"content": "",
"tags": [
["d", "<repo-id>"], // usually kebab-case short name
["name", "<human-readable project name>"],
["description", "brief human-readable project description>"],
["web", "<url for browsing>", ...], // a webpage url, if the git server being used provides such a thing
["clone", "<url for git-cloning>", ...], // a url to be given to `git clone` so anyone can clone it
["relays", "<relay-url>", ...] // relays that this repository will monitor for patches and issues
["r", "<earliest-unique-commit-id>", "euc"]
["maintainers", "<other-recognized-maintainer>", ...]
]
}
The tags web
, clone
, relays
, maintainers
can have multiple values.
The r
tag annotated with the "euc"
marker should be the commit ID of the earliest unique commit of this repo, made to identify it among forks and group it with other repositories hosted elsewhere that may represent essentially the same project. In most cases it will be the root commit of a repository. In case of a permanent fork between two projects, then the first commit after the fork should be used.
Except d
, all tags are optional.
Repository state announcements
An optional source of truth for the state of branches and tags in a repository.
{
"kind": 30618,
"content": "",
"tags": [
["d", "<repo-id>"], // matches the identifier in the coresponding repository announcement
["refs/<heads|tags>/<branch-or-tag-name>","<commit-id>"]
["HEAD", "ref: refs/heads/<branch-name>"]
]
}
The refs
tag may appear multiple times, or none.
If no refs
tags are present, the author is no longer tracking repository state using this event. This approach enables the author to restart tracking state at a later time unlike NIP-09 deletion requests.
The refs
tag can be optionally extended to enable clients to identify how many commits ahead a ref is:
{
"tags": [
["refs/<heads|tags>/<branch-or-tag-name>", "<commit-id>", "<shorthand-parent-commit-id>", "<shorthand-grandparent>", ...],
]
}
Patches
Patches can be sent by anyone to any repository. Patches to a specific repository SHOULD be sent to the relays specified in that repository's announcement event's "relays"
tag. Patch events SHOULD include an a
tag pointing to that repository's announcement address.
Patches in a patch set SHOULD include a NIP-10 e
reply
tag pointing to the previous patch.
The first patch revision in a patch revision SHOULD include a NIP-10 e
reply
to the original root patch.
{
"kind": 1617,
"content": "<patch>", // contents of <git format-patch>
"tags": [
["a", "30617:<base-repo-owner-pubkey>:<base-repo-id>"],
["r", "<earliest-unique-commit-id-of-repo>"] // so clients can subscribe to all patches sent to a local git repo
["p", "<repository-owner>"],
["p", "<other-user>"], // optionally send the patch to another user to bring it to their attention
["t", "root"], // omitted for additional patches in a series
// for the first patch in a revision
["t", "root-revision"],
// optional tags for when it is desirable that the merged patch has a stable commit id
// these fields are necessary for ensuring that the commit resulting from applying a patch
// has the same id as it had in the proposer's machine -- all these tags can be omitted
// if the maintainer doesn't care about these things
["commit", "<current-commit-id>"],
["r", "<current-commit-id>"] // so clients can find existing patches for a specific commit
["parent-commit", "<parent-commit-id>"],
["commit-pgp-sig", "-----BEGIN PGP SIGNATURE-----..."], // empty string for unsigned commit
["committer", "<name>", "<email>", "<timestamp>", "<timezone offset in minutes>"],
["branch-name", "<custom-branch-name>"], // optional short name for use by git-remote-nostr
]
}
The first patch in a series MAY be a cover letter in the format produced by git format-patch
.
Issues
Issues are Markdown text that is just human-readable conversational threads related to the repository: bug reports, feature requests, questions or comments of any kind. Like patches, these SHOULD be sent to the relays specified in that repository's announcement event's "relays"
tag.
Issues may have a subject
tag, which clients can utilize to display a header. Additionally, one or more t
tags may be included to provide labels for the issue.
{
"kind": 1621,
"content": "<markdown text>",
"tags": [
["a", "30617:<base-repo-owner-pubkey>:<base-repo-id>"],
["p", "<repository-owner>"]
["subject", "<issue-subject>"]
["t", "<issue-label>"]
["t", "<another-issue-label>"]
]
}
Replies
Replies are also Markdown text. The difference is that they MUST be issued as replies to either a kind:1621
issue or a kind:1617
patch event. The threading of replies and patches should follow NIP-10 rules.
{
"kind": 1622,
"content": "<markdown text>",
"tags": [
["a", "30617:<base-repo-owner-pubkey>:<base-repo-id>", "<relay-url>"],
["e", "<issue-or-patch-id-hex>", "", "root"],
// other "e" and "p" tags should be applied here when necessary, following the threading rules of NIP-10
["p", "<patch-author-pubkey-hex>", "", "mention"],
["e", "<previous-reply-id-hex>", "", "reply"]
// rest of tags...
]
// other fields...
}
Status
Root Patches and Issues have a Status that defaults to 'Open' and can be set by issuing Status events.
{
"kind": 1630, // Open
"kind": 1631, // Applied / Merged for Patches; Resolved for Issues
"kind": 1632, // Closed
"kind": 1633, // Draft
"content": "<markdown text>",
"tags": [
["e", "<issue-or-original-root-patch-id-hex>", "", "root"],
["e", "<accepted-revision-root-id-hex>", "", "reply"], // for when revisions applied
["p", "<repository-owner>"],
["p", "<root-event-author>"],
["p", "<revision-author>"],
// optional for improved subscription filter efficiency
["a", "30617:<base-repo-owner-pubkey>:<base-repo-id>", "<relay-url>"],
["r", "<earliest-unique-commit-id-of-repo>"]
// optional for `1631` status
["e", "<applied-or-merged-patch-event-id>", "", "mention"], // for each
// when merged
["merge-commit", "<merge-commit-id>"]
["r", "<merge-commit-id>"]
// when applied
["applied-as-commits", "<commit-id-in-master-branch>", ...]
["r", "<applied-commit-id>"] // for each
]
}
The Status event with the largest created_at date is valid.
The Status of a patch-revision defaults to either that of the root-patch, or 1632
(Closed) if the root-patch's Status is 1631
and the patch-revision isn't tagged in the 1631
event.
Git client nostr plugin (git-remote-nostr)
Definition: Clone URL - a git remote URL listed under the clone
tag of the repositories kind 30617
event
The offical git client supports interacting with 'remotes' using custom protocols via git-remote-helpers.
An implementation of git-remote-nostr SHOULD:
1. Use Git Remote Nostr URL Format
Struture:
nostr://
- git syntax for a protocol URL<user>@
- optional ssh user for interacting with Clone URLs<protocol>/
- optional prefered protocol for interacting with Clone URLs. eg. ssh or https- kind
30617
event coordinate in format:<naddr>
<npub|nip05-address>/<identifier>
<npub|nip05-address>/<relay-hint*>/<identifier>
*relay hints SHOULD be URL encoded eg ws%3A%2F%2Funencrypted.com
and may omit wss://
for brevity and readability.
for example nostr://dan@gitworkshop.dev/ngit
or nostr://npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/relay.damus.io/ngit
2. Manage state on nostr and access objects via Clone URLs
Store and retrieve state in the 30618
event and git objects in the Clone URLs. Proxy state updates to each Clone URLs.
If a 30618
cannot be found or git config item nostr.nostate
is true
, use state from the first Clone URL.
3. Use pr/*
branch namespace for 'Open' patches
Each 'Open' patch / patch set on repository relays SHOULD be have a corresponding branch in the format:
pr/<branch-name*>(<first-8-chars-of-hex-root-patch-event-id)
A branch pushed in the format pr/<branch-name>
should be published as a:
- patch / patch set, if there is no upstream branch
- patch revision, if there is a upstream branch with conflicts
- as additional patches in the set, if there is an upstream branch without conflicts
*<branch-name>
is the first 60 chars of root event branch-name
tag if present, or the commit subject, with invalid chars replaced with -
.
Possible things to be added later
- "branch merge" kind (specifying a URL from where to fetch the branch to be merged)
- inline file comments kind (we probably need one for patches and a different one for merged files)