| Age | Commit message (Collapse) | Author |
|
Regression introduced in 28ad5440: ngit sync crashed with
'invalid refspec refs/remotes/origin/v1.4.4^{}:refs/tags/v1.4.4^{}'
on repos with annotated tags. Fixed by guarding all three iteration
sites in sync.rs and identify_remote_sync_issues in list.rs; also
corrected the always-false logic bug in invalid_nostr_state_ref.
|
|
kind-5 deletion events that only #e-tag a PR Kind event (kind 1618)
were never fetched because proposal_ids was built from Kind::GitPatch
events only. The deleted PR event remained in the local cache and
continued to appear as a remote ref (refs/heads/pr/<branch>).
|
|
allows users to repair repos whose state event is missing ^{} peeled refs
for annotated tags (or any other corruption) without needing to push a new
ref. the new event is signed with a fresh timestamp and broadcast to all
repo relays and the user's write relays.
|
|
RepoState::try_from was explicitly discarding all refs/tags/*^{} entries
("peeled" refs) when parsing the nostr state event. This meant the list
command only advertised the tag object OID, but git requires two lines for
annotated tags:
<tag-object-oid> refs/tags/v1.0.0
<commit-oid> refs/tags/v1.0.0^{}
Without the ^{} peeled line git cannot resolve the tag to a commit, so
git fetch --prune treats it as unresolvable and deletes it.
The nostr state event already stores both entries correctly (written by
generate_updated_state in push.rs). The fix simply stops try_from from
discarding the ^{} entries on read, so they flow through to the list
output unchanged.
|
|
Replace nsec.app with bucket.coracle.social and nos.lol.
|
|
Sync the defaults vector to the user's actual selections after each
prompt in multi_select_with_custom_value, so deselected items are not
shown as checked on the next loop iteration.
|
|
Previously NostrConnect was only instantiated after the user selected
'waiting for signer app to connect...', so any connection made while
the prompt was visible was missed. Now listening starts immediately
after the QR/URL is displayed, with a spinner that auto-resolves on
connection rather than requiring a manual prompt dismissal.
|
|
reduces noise in normal usage; messages still appear with -v flag
|
|
allows non-interactive bunker:// URL login without requiring --nsec,
by connecting to the remote signer and saving credentials to git config
|
|
display signer relays below QR code and nostrconnect URL with an option
to change them via the existing multiselect UI before connecting
|
|
Add a deletions counter to FetchReport, incremented in
process_fetched_events for each kind-5 event received and accumulated
across relays in consolidate_fetch_reports. The count is included in
the fetch summary display (e.g. "1 deletion", "2 deletions").
|
|
Add a non_proposal_event_ids parameter to get_fetch_filters and a
corresponding field on FetchRequest. On each fetch, the event IDs of
cached repo announcements and the state event are collected and used to
build a dedicated kind-5 filter keyed on #e tags, as specified by
NIP-09. The existing #a-tagged filter already covers addressable-event
deletions; this new filter catches deletions from clients that follow
NIP-09 strictly and do not embed a repo coordinate in their deletion
event.
|
|
When pushing a pr/ branch, the ahead slice is reversed by callers before
being passed to generate_patches_or_pr_event_or_pr_updates, making it
oldest-first. The tip/first_commit assignments were backwards (using
first()/last() as if the slice were youngest-first), so the merge-base
was computed as the parent of the PR tip rather than the parent of the
oldest commit. Multi-commit PRs therefore showed only 1 commit when
applied via ngit apply.
Adds an integration test that pushes a two-commit large-file PR branch
and asserts the merge-base tag equals the main branch tip.
|
|
update_remote_refs_pushed was calling peel_to_commit() for all refs,
discarding the tag object OID for annotated tags. This caused a mismatch
with generate_updated_state, which correctly stores the tag object OID in
the nostr state event. ngit sync would then push the commit OID to grasp
servers that expected the tag object OID, causing rejections.
|
|
The use_concise flag in send_events was computed with || instead of &&,
causing !is_test to short-circuit to true in production and making
--verbose have no effect on published event display.
|
|
git-remote-nostr now walks the per-relay state events captured in
FetchReport::state_per_relay (newest first) and advertises the first
one whose every OID is either present on at least one git server
(confirmed via list_refs) or already available locally. If no such
state event exists it falls back to the raw git server state.
Previously the latest nostr state event was always used regardless of
whether its OIDs had been pushed to any server, causing catastrophic
missing-object errors during clone or fetch when a state event was
published ahead of the corresponding git push.
|
|
refspec_remote_ref_name() only stripped refs/heads/, so tag refspecs
produced refs/remotes/origin/refs/tags/v1.0.0 instead of
refs/remotes/origin/v1.0.0. ngit sync reads the latter form, so the
tracking ref was never found and sync failed with 'src refspec does not
match any existing object'.
|
|
FetchReport now captures the full state event seen on each relay during
the nostr fetch (state_per_relay: HashMap<RelayUrl, Option<Event>>).
ngit sync uses this to identify grasp server relays with a missing or
outdated state event and publishes the current state event to them
before attempting git pushes, preventing rejections. An existing login
is loaded silently (no prompt, no profile fetch) to provide a signer
for NIP-42 auth if requested.
|
|
When all git servers reject or skip a push, delete the newly-published
state event from the local nostr cache and restore the previous state
event (if any), so that a subsequent retry starts from a clean baseline
rather than a state that no server ever accepted.
|
|
When publishing the nostr state event before a git push, use the relay
results from send_events to skip any grasp server whose internal relay
did not receive the event. Print a clear warning for each skipped server
and emit error lines for all refs if no git servers remain to push to.
|
|
Change send_events() return type from Result<()> to
Result<Vec<(String, bool)>> so callers can inspect which relays
accepted events. Update the finish message to show
"Published to X/N relays (failed: ...)" instead of the unconditional
"Published ... to nostr relays".
|
|
When syncing, the nostr state stores refs with full names like
refs/heads/master and refs/tags/v1.0.0. Git tracking refs strip the
refs/heads/ prefix, so the tracking ref lives at refs/remotes/origin/master
not refs/remotes/origin/refs/heads/master.
The sync code was interpolating the full nostr_ref_name into the source
side of the refspec, producing the invalid double-prefixed path. Strip
refs/heads/ or refs/tags/ before constructing the tracking ref segment,
consistent with how git_remote_nostr/push.rs already handles this.
|
|
Any -o option passed to `git push` that is not handled by ngit
(title, description) is forwarded verbatim to the git server via
git2::PushOptions::remote_push_options. This allows options such as
`-o secret-scanning.skip` to pass through transparently.
`ngit send` gains a matching -o / --push-option flag for the same
purpose.
|
|
The Nix environment provides libgit2 1.9.2 via nixpkgs, which
libgit2-sys picks up at build time instead of using its bundled version.
This caused test assertions that hardcode the libgit2 version string
(appended by libgit2 to patch output) to fail after commit 319bb7f
added new Cargo dependencies, though the exact mechanism by which those
dependencies triggered the switch from the bundled 1.9.1 to the system
1.9.2 remains unclear.
Also bump git2 from 0.20.2 to 0.20.4 in both Cargo.toml files so the
bundled libgit2-sys version (0.18.3+1.9.2) properly aligns with the
1.9.2 version in use.
|
|
Implement a custom WebSocketTransport that races IPv6 and IPv4 connections
with a 250ms head start for IPv6, matching browser behavior. This prevents
broken IPv6 from blocking all relay connections indefinitely.
This is a temporary fix until the upstream async-wsocket PR is merged:
https://github.com/shadowylab/async-wsocket/pull/42
|
|
- print hint line immediately, before coordinate lookup and relay fetch
- users see available subcommands (init, edit, accept) without waiting
|
|
- make repo name bold yellow as a title; section headings bold dim
- add dim horizontal rules above and below the name/description block
- move earliest unique commit to the bottom (after additional relays)
- add --offline flag to skip network fetch and use local cache only
|
|
- suppress fetch summary (no updates / updates: X)
- write blank line to stderr after relay errors for clear separation
- show identifier below title only when it differs from name
- show earliest unique commit (root_commit) in metadata
- restructure infrastructure into grasp servers / additional git
servers / additional relays sections
- display grasp servers by domain only (strip scheme, npub, repo path)
- strip wss:// prefix from relay display
- show maintainer names from metadata cache; fall back to short npub
- append (you) next to the current user's name wherever it appears
- show [name] attribution and the maintainer model note only when
there is more than one maintainer
|
|
- `ngit repo` (no subcommand): show repository info including maintainer
tree, per-maintainer infrastructure attribution, and a note explaining
the union-vs-personal field model and recursive maintainer sets
- `ngit repo init`: alias for `ngit init`
- `ngit repo edit`: same as init but signals intent to update an existing
repository announcement
- `ngit repo accept`: scoped command for co-maintainers to publish their
announcement; errors with clear messages for all other states (trusted
maintainer, already accepted, not invited, no repo found)
|
|
nos.lol always prompts for nip42 auth even for reading, making it
unsuitable as a default relay.
|
|
when a co-maintainer has no grasp servers of their own, fall back to
the trusted maintainer's grasp servers rather than jumping straight to
system defaults. if the trusted maintainer only uses a single grasp
server, the first system default is appended for redundancy. system
defaults are only used when neither the user nor the trusted maintainer
has any grasp servers configured.
|
|
With no default relays seeded, the multi-select add option was
incorrectly pre-selected when the list was empty. Now add/add-another
is always unselected by default so enter skips straight through.
|
|
Public relays are no longer recommended; grasp servers cover relay
needs. The interactive prompt now reflects this.
|
|
ngit init and accept_maintainership_with_defaults no longer seed relay
lists from the client default set. The relay list in a Kind:30617
announcement now contains only grasp-server-derived relay URLs; no
additional public relays are suggested or added automatically.
|
|
move apply_grasp_infrastructure, latest_event_repo_ref to lib/repo_ref.rs
and wait_for_grasp_servers + grasp_servers_from_user_or_fallback to a
new lib/accept_maintainership.rs so both binaries can share them.
add accept_maintainership_with_defaults which publishes the co-maintainer's
own Kind:30617 announcement with defaults (user grasp servers, shared
metadata from existing events) then waits for grasp server provisioning
and updates nostr.repo config and origin remote.
replace the push error block with a call to accept_maintainership_with_defaults
so pushing now silently accepts co-maintainership instead of failing.
|
|
when a co-maintainer runs ngit init, it now clearly states upfront
that they are accepting a co-maintainership offer (not creating a
new repo), shows who offered it, and on completion confirms the
acceptance and explains they can now push. updating an existing
co-maintainer announcement also gets its own clear message.
|
|
the previous message said 'run ngit init' with no explanation of why or
what it does. the new message explains the user has been offered
co-maintainership, names the repo, and points to 'ngit init -d' for a
fast non-interactive acceptance path.
|
|
Adds value_name attribute to the id argument so the usage line reads
`<ID|nevent>` instead of `<ID>`, making nevent bech32 support discoverable
without reading --help.
|
|
Remove the patch_supports_commit_ids gates in checkout.rs and list.rs
that pre-dated the mbox fallback logic. apply_patch_chain already
handles all fallback cases. Also replace the main-branch TODO fallback
in make_commits_for_proposal with get_parent_commit_from_patch, which
uses timestamp-based best-guess when the parent-commit tag is absent.
|
|
When applying a chain of patches without parent-commit tags, each
patch's parent was resolved independently, meaning patch2 would not
parent off the OID patch1 actually produced. Thread next_parent_override
through the loop and guard the early-return in create_commit_from_patch
so the override is always honoured.
|
|
- Replace .unwrap() calls in filter closure with pattern-let guards
so a missing/invalid mbox commit id conservatively includes the patch
- Use the OID returned by create_commit_from_patch as branch tip instead
of the tag commit id, which may differ for GPG-signed commits
- Add module-level doc comment to mbox_parser explaining design rationale
and known limitations around the mbox envelope SHA1
|
|
- Use mailparse crate to handle RFC 2047 encoded-words (Q/B encoding)
and RFC 2822 header folding in Subject and From headers
- Fix email signature separator check: use exact match 'line == "-- "'
instead of starts_with to avoid false positives on body lines
- Remove dead/incorrect asctime parsing in committer date extraction;
simplify to always return None (falls back to author_timestamp)
|
|
- Add mbox_parser module to extract metadata from patch content
- Extract author/committer from From: and Date: headers when tags missing
- Extract commit message body as fallback for description tag
- Implement best-guess parent commit logic using committer timestamps
- Update patch_supports_commit_ids to accept mbox-parseable patches
- Enable patches without optional tags to appear as pr/ branches
|
|
Instead of erroring when a proposal uses PR format (kind 1618/1619),
ngit apply now fetches the tip commit from git servers, determines the
base commit via the merge-base tag or by walking ahead of main, generates
patch text for each commit using git2, and applies via git am.
Also fixes a bug where clone-tag server hints were silently skipped in
the fetch fallback, and refactors the git-am invocation into a shared
helper to avoid duplication between the patch and PR code paths.
|
|
apply_grasp_infrastructure was inserting each grasp relay at index 0,
causing later servers to displace earlier ones. the last server in the
list ended up as relays[0] and thus the url relay hint, reversing the
intended priority order.
|
|
instead of generic 'Publishing to nostr relays...' messages, describe
what is being published e.g. 'Publishing 3 patches to nostr relays...'
or 'Publishing 1 announcement and 1 state event to nostr relays...'
|
|
Replace arbitrary 5-second countdown with active polling of grasp
servers during ngit init. Servers are checked every 1s with a 7s
timeout (2s in tests). Shows progress like '1/2 grasp servers ready'.
Grasp servers return 404 until the repo is provisioned, so we poll
until they accept git connections. Proceeds anyway on timeout rather
than failing, since some servers may still be initializing.
|
|
Allow users to specify custom signer relays for nostrconnect login.
Relay URLs are auto-prefixed with wss:// if no scheme is provided.
|
|
Add wss://relay.ditto.pub as a second default signer relay alongside
wss://relay.nsec.app for improved reliability during nostrconnect login.
|
|
Ensures the relay hint is always a grasp server when configured.
|
|
Git wraps push-option values in double quotes and doubles backslashes
when the value contains special characters. This broke \\n escape
decoding because the key arrived as '"description' instead of
'description'. Added strip_git_quoting() to reverse git's quoting
before parsing the key=value pair.
|
|
- mention remote helper in main help so users know native git commands work
- fix inconsistent indentation in main help template
- update init about to lead with 'publish a repository'
- add 'create' to account subcommand about
- add long_about to send referencing simpler pr/ push flow
- update list about to remove legacy interactive-mode language
- add long_about to checkout/apply pointing to ngit list
|
|
Previously, running ngit without any command would show an error
message. Now it displays the help menu, which is more user-friendly
and follows standard CLI tool conventions.
|
|
The title and description push-options were previously only applied to PR
creation but not to patch series generation. When force-pushing to update
an existing patch series, the custom title and description were ignored.
This change passes the title_description parameter to the patch generation
function, allowing users to customize patch series cover letters via:
git push --force --push-option=title="Title" \
--push-option=description="Description" origin branch
Includes integration test for force-pushing patches with custom cover letter.
|
|
Git push-options are line-based so literal newlines cannot be sent.
Users can now write the two-character sequence \n which is decoded
into real newlines before publishing. Use \\n for a literal backslash-n.
Includes unit tests, integration test, help text, and changelog entry.
|
|
Previously, providing only one of title or description would silently
ignore both. Now returns a clear error message.
|
|
Allows setting PR title and description via git push options:
git push --push-option=title="My PR" \
--push-option=description="Details" origin pr/branch
|
|
Skip network fetch when --offline is set, using only local cache
|
|
Use console::style().yellow() for 'To view/checkout/apply' hints
to match git CLI hint styling.
|
|
Users may not be aware that ngit list defaults to filtering by
open,draft status. Display the active filter at the top of the
output to make this clear.
|
|
Shows 'To view: ngit list <id>' when listing proposals without an id,
helping users discover they can view individual proposals in detail.
|
|
this prevents cli output errors on tests such as:
finds_based_on_naddr_on_embeded_relay_and_added_as_origin_remote
|
|
that expect whitespace then something
|
|
this took a lot of investigation to work out why this was failing
|
|
hide details in non-verbose mode
|
|
always report publishing and finish with published
|
|
to be consistent with the summary version
|
|
'maintainers' is missleading as the announcement authors may not be in
the maitnainer set
|
|
so that report gets removed when not in verbose mode
and fix removal so summary displayed instead 1st line of original report.
|
|
to ensure verbose mode is used during tests
|
|
Apply the same hidden-to-visible MultiProgress pattern used for fetch
to send_events. In concise mode (non-verbose, non-test, non-silent),
a spinner is shown immediately and the detail progress bars are
revealed after a delay, using the deferred bar finish mechanism.
|
|
as its not fetching from git servers just yet
|
|
The heading bar was being inserted into the MultiProgress after the
draw target switch, but by then all relay bars were already finished
so indicatif did not re-render the layout. Pre-add the heading bar
at creation time (position 0, before relay bars) and only call
finish_with_message on it after the draw target switches to stderr.
|
|
The 'fetching updates...' heading was finished with finish_with_message
while the draw target was still hidden, so indicatif never rendered it.
Move the draw target switch before the heading insertion so the heading
renders immediately when added.
|
|
fetching_with_report_for_helper unconditionally cleared the progress
reporter, wiping error bars that showed relay timeouts. Only clear
when all relays succeeded (or in verbose mode where bars were always
visible), matching the pattern in fetching_with_report.
|
|
indicatif does not re-render bars that called finish_with_message while
the draw target was hidden. Instead of trying to force a redraw, defer
the finish_with_message call until after the draw target switches to
stderr. A BarRevealState coordinates between relay tasks and the timer:
bars that complete before the 5s reveal store their finish state in a
mutex-protected list, which the timer flushes after switching the draw
target. Bars completing after reveal finish immediately as before.
|
|
tick() is a no-op when enable_steady_tick() is active. Use
force_draw() on a bar to trigger a full MultiState redraw
including bars that finished while the draw target was hidden.
|
|
Use a ProgressBar inside the detail multi for the heading instead
of eprintln so it gets cleared with progress_reporter.clear()
and never appears when fetch completes before the delay.
|
|
Replace the broken SpinnerState approach (which checked should_expand at
task spawn time when all tasks spawn simultaneously) with a two-MultiProgress
pattern: a visible spinner shown immediately, and a hidden detail multi that
every relay task always adds bars to. A background timer reveals the detail
bars after 5s, printing a heading before switching the draw target.
|
|
Shows a progress spinner when fetching from git remotes in non-verbose mode.
Suppresses git fetch output and listing messages when not in verbose mode.
Uses NGITTEST environment variable for test timeouts.
|
|
Adds a global --verbose/-v flag that sets NGIT_VERBOSE environment variable.
Also sets NGIT_VERBOSE automatically when NGIT_TEST is set.
|
|
Progress reporters were not being cleared after successful operations,
leaving progress bars visible in the terminal output. Now they are
properly cleared when all operations complete without errors.
|
|
Truncated IDs cannot be used with --id flag for checkout or apply commands.
|
|
Reorganize imports and fix formatting issues flagged by clippy and rustfmt.
|
|
When a PR branch already exists locally, the previous code would silently
move the branch pointer without checking for tracking or fast-forward safety.
Now:
- If branch has tracking: checkout and warn user to git pull
- If no tracking and fast-forward: safely move pointer
- If no tracking and diverged: show copy-paste commands for reset/rebase
- If commit not found locally: suggest fetching
Uses console crate for yellow output instead of hardcoded ANSI codes.
|
|
When a nostr:// remote exists, run git fetch instead of internal fetch
to populate remote tracking refs. Then checkout the remote branch with
proper upstream tracking so git pull works correctly.
|
|
- Add --status flag for filtering (default: open,draft)
- Add --json flag for JSON output
- Add optional <id> argument for showing proposal details
- Rename interactive logic to launch_interactive()
- Non-interactive mode outputs table format by default
- Use -i flag for interactive mode
Phase 3 of non-interactive ngit list implementation.
|
|
Adds a new 'ngit apply <event-id>' command that applies proposal patches
to the current branch. Supports --stdout flag to output patches for
piping to git am.
Phase 2 of non-interactive ngit list implementation.
|
|
Adds a new 'ngit checkout <event-id|nevent>' command that creates or
updates a proposal branch and checks it out. Supports both PRs and
patches with parent-commit references.
Phase 1 of non-interactive ngit list implementation.
|
|
When user is the maintainer and runs ngit init without args, validate
against cached repo_ref before making network requests. This avoids
unnecessary relay timeouts when the error would be 'no arguments
specified, use --force'.
|
|
The list command is inherently interactive - it presents menus for
browsing and selecting proposals. Without interactive mode, all
choice() calls auto-select default index 0, causing the first
proposal to be checked out immediately without user input.
|
|
multi-input flag that inherits from the latest pushed announcement
event, defaulting to empty when no existing hashtags are found
|
|
alas an idea before its time has yet come.
|
|
Allow multiple values via repeated --relay flags
instead of the less intuitive plural --relays form.
|
|
Allow multiple values via repeated --grasp-server flags
instead of the less intuitive plural --grasp-servers form.
|
|
- Add --relay flag to 'ngit account create' allowing users to specify
relay URLs (repeatable). Defaults to relay-default-set when not provided.
- Remove fallback relays from fetch when repo context exists (repo
coordinate provided). Only use them for bootstrapping (profile discovery
with no repo context).
- Remove fallback relays from publish when repo or user relays exist.
Only use them when neither is available (e.g. new account signup).
- Update --customize help text to reflect new relay-default-set behavior.
|
|
The more_fallback_relays field is never consumed anywhere in the codebase.
Removing it from the Client struct, Params struct, trait definition, and all
related initialization code.
|
|
The relay.nostr.band relay is now offline and should be removed
from the default relay set.
|
|
Rewrite ngit send to support non-interactive mode:
- Add validation for required arguments (title/description)
- Add --force flag to bypass commit suitability checks
- Add --no-cover-letter flag to skip cover letter
- Improve error messages for missing required fields
- Update title/description/cover-letter logic for non-interactive mode
- Add comprehensive tests for non-interactive behavior
|
|
Complete rewrite of ngit init to support non-interactive mode by default.
Key changes:
- Implement hybrid validation (validate all args upfront, fail fast)
- Add --grasp-servers flag for specifying git servers
- Prefer --name over --identifier for better UX
- Add comprehensive validation with helpful error messages
- Support both clone and init-from-existing-repo workflows
- Add --force flag to bypass safety checks
- Update tests for new non-interactive behavior
- Add test utilities for non-interactive testing
|