diff options
Diffstat (limited to 'src/bin/ngit/cli.rs')
| -rw-r--r-- | src/bin/ngit/cli.rs | 220 |
1 files changed, 184 insertions, 36 deletions
diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index c2364e6..452491c 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs | |||
| @@ -8,7 +8,7 @@ use crate::sub_commands; | |||
| 8 | #[command( | 8 | #[command( |
| 9 | author, | 9 | author, |
| 10 | version, | 10 | version, |
| 11 | help_template = "{name} {version}\nnostr plugin for git\n includes a remote helper so native git commands (clone, fetch, push) work with nostr:// URLs\n - clone a nostr repository, or add as a remote, by using the url format nostr://npub123/identifier\n - remote branches beginning with `pr/` are open PRs from contributors; `ngit list` can be used to view all PRs\n - to open a PR, push a branch with the prefix `pr/` or use `ngit send` for advanced options\n set title and description via push options:\n git push -o 'title=My PR' -o 'description=line1\\n\\nline2' -u origin pr/branch\n - publish a repository to nostr with `ngit init`\n\n{usage}\n{all-args}" | 11 | help_template = "{name} {version}\nnostr plugin for git\n includes a remote helper so native git commands (clone, fetch, push) work with nostr:// URLs\n - clone a nostr repository, or add as a remote, by using the url format nostr://npub123/identifier\n - remote branches beginning with `pr/` are open PRs from contributors; `ngit pr list` can be used to view all PRs\n - to open a PR, push a branch with the prefix `pr/` or use `ngit send` for advanced options\n set title and description via push options:\n git push -o 'title=My PR' -o 'description=line1\\n\\nline2' -u origin pr/branch\n - publish a repository to nostr with `ngit init`\n\n{usage}\n{all-args}" |
| 12 | )] | 12 | )] |
| 13 | #[command(propagate_version = true)] | 13 | #[command(propagate_version = true)] |
| 14 | #[allow(clippy::struct_excessive_bools)] | 14 | #[allow(clippy::struct_excessive_bools)] |
| @@ -119,6 +119,59 @@ pub enum Commands { | |||
| 119 | long_about = "submit PR with advanced options\n\nfor a simpler flow, push a branch with the `pr/` prefix using native git:\n git push -o 'title=My PR' -o 'description=details here' -u origin pr/my-branch" | 119 | long_about = "submit PR with advanced options\n\nfor a simpler flow, push a branch with the `pr/` prefix using native git:\n git push -o 'title=My PR' -o 'description=details here' -u origin pr/my-branch" |
| 120 | )] | 120 | )] |
| 121 | Send(sub_commands::send::SubCommandArgs), | 121 | Send(sub_commands::send::SubCommandArgs), |
| 122 | /// work with pull requests | ||
| 123 | #[command( | ||
| 124 | long_about = "work with pull requests\n\nPRs are created by pushing a branch with the `pr/` prefix:\n git push -u origin pr/my-branch\nor with advanced options via `ngit send`" | ||
| 125 | )] | ||
| 126 | Pr(PrSubCommandArgs), | ||
| 127 | /// work with issues | ||
| 128 | Issue(IssueSubCommandArgs), | ||
| 129 | /// update repo git servers to reflect nostr state (add, update or delete | ||
| 130 | /// remote refs) | ||
| 131 | Sync(sub_commands::sync::SubCommandArgs), | ||
| 132 | /// create account, login, logout or export keys | ||
| 133 | Account(AccountSubCommandArgs), | ||
| 134 | } | ||
| 135 | |||
| 136 | #[derive(Subcommand)] | ||
| 137 | pub enum AccountCommands { | ||
| 138 | /// login with nsec or nostr connect | ||
| 139 | Login(sub_commands::login::SubCommandArgs), | ||
| 140 | /// remove nostr account details stored in git config | ||
| 141 | Logout, | ||
| 142 | /// export nostr keys to login to other nostr clients | ||
| 143 | ExportKeys, | ||
| 144 | /// create a new nostr account | ||
| 145 | Create(sub_commands::create::SubCommandArgs), | ||
| 146 | } | ||
| 147 | |||
| 148 | #[derive(clap::Parser)] | ||
| 149 | pub struct AccountSubCommandArgs { | ||
| 150 | #[command(subcommand)] | ||
| 151 | pub account_command: AccountCommands, | ||
| 152 | } | ||
| 153 | |||
| 154 | #[derive(clap::Parser)] | ||
| 155 | pub struct RepoSubCommandArgs { | ||
| 156 | #[command(subcommand)] | ||
| 157 | pub repo_command: Option<RepoCommands>, | ||
| 158 | /// Use local cache only, skip network fetch | ||
| 159 | #[arg(long)] | ||
| 160 | pub offline: bool, | ||
| 161 | } | ||
| 162 | |||
| 163 | // --------------------------------------------------------------------------- | ||
| 164 | // PR subcommand group | ||
| 165 | // --------------------------------------------------------------------------- | ||
| 166 | |||
| 167 | #[derive(clap::Parser)] | ||
| 168 | pub struct PrSubCommandArgs { | ||
| 169 | #[command(subcommand)] | ||
| 170 | pub pr_command: PrCommands, | ||
| 171 | } | ||
| 172 | |||
| 173 | #[derive(Subcommand)] | ||
| 174 | pub enum PrCommands { | ||
| 122 | /// list PRs and view details | 175 | /// list PRs and view details |
| 123 | List { | 176 | List { |
| 124 | /// Filter by status (comma-separated: open,draft,closed,applied) | 177 | /// Filter by status (comma-separated: open,draft,closed,applied) |
| @@ -134,11 +187,21 @@ pub enum Commands { | |||
| 134 | #[arg(long)] | 187 | #[arg(long)] |
| 135 | offline: bool, | 188 | offline: bool, |
| 136 | }, | 189 | }, |
| 137 | /// list issues | 190 | /// view a PR and its comments |
| 138 | Issue(IssueSubCommandArgs), | 191 | View { |
| 192 | /// Proposal event-id (hex) or nevent (bech32) | ||
| 193 | #[arg(value_name = "ID|nevent")] | ||
| 194 | id: String, | ||
| 195 | /// Output as JSON | ||
| 196 | #[arg(long)] | ||
| 197 | json: bool, | ||
| 198 | /// Use local cache only, skip network fetch | ||
| 199 | #[arg(long)] | ||
| 200 | offline: bool, | ||
| 201 | }, | ||
| 139 | /// checkout a proposal branch by event-id or nevent | 202 | /// checkout a proposal branch by event-id or nevent |
| 140 | #[command( | 203 | #[command( |
| 141 | long_about = "checkout a proposal branch by event-id or nevent\n\nuse `ngit list` to find proposal IDs" | 204 | long_about = "checkout a proposal branch by event-id or nevent\n\nuse `ngit pr list` to find proposal IDs" |
| 142 | )] | 205 | )] |
| 143 | Checkout { | 206 | Checkout { |
| 144 | /// Proposal event-id (hex) or nevent (bech32) | 207 | /// Proposal event-id (hex) or nevent (bech32) |
| @@ -150,7 +213,7 @@ pub enum Commands { | |||
| 150 | }, | 213 | }, |
| 151 | /// apply proposal patches to current branch | 214 | /// apply proposal patches to current branch |
| 152 | #[command( | 215 | #[command( |
| 153 | long_about = "apply proposal patches to current branch\n\nuse `ngit list` to find proposal IDs" | 216 | long_about = "apply proposal patches to current branch\n\nuse `ngit pr list` to find proposal IDs" |
| 154 | )] | 217 | )] |
| 155 | Apply { | 218 | Apply { |
| 156 | /// Proposal event-id or nevent | 219 | /// Proposal event-id or nevent |
| @@ -163,39 +226,70 @@ pub enum Commands { | |||
| 163 | #[arg(long)] | 226 | #[arg(long)] |
| 164 | offline: bool, | 227 | offline: bool, |
| 165 | }, | 228 | }, |
| 166 | /// update repo git servers to reflect nostr state (add, update or delete | 229 | /// submit PR with advanced options (alias for `ngit send`) |
| 167 | /// remote refs) | 230 | #[command( |
| 168 | Sync(sub_commands::sync::SubCommandArgs), | 231 | long_about = "submit PR with advanced options\n\nfor a simpler flow, push a branch with the `pr/` prefix using native git:\n git push -o 'title=My PR' -o 'description=details here' -u origin pr/my-branch" |
| 169 | /// create account, login, logout or export keys | 232 | )] |
| 170 | Account(AccountSubCommandArgs), | 233 | Send(sub_commands::send::SubCommandArgs), |
| 171 | } | 234 | /// close a PR (author or maintainer only) |
| 172 | 235 | Close { | |
| 173 | #[derive(Subcommand)] | 236 | /// Proposal event-id (hex) or nevent (bech32) |
| 174 | pub enum AccountCommands { | 237 | #[arg(value_name = "ID|nevent")] |
| 175 | /// login with nsec or nostr connect | 238 | id: String, |
| 176 | Login(sub_commands::login::SubCommandArgs), | 239 | /// Use local cache only, skip network fetch |
| 177 | /// remove nostr account details stored in git config | 240 | #[arg(long)] |
| 178 | Logout, | 241 | offline: bool, |
| 179 | /// export nostr keys to login to other nostr clients | 242 | }, |
| 180 | ExportKeys, | 243 | /// reopen a closed PR (author or maintainer only) |
| 181 | /// create a new nostr account | 244 | Reopen { |
| 182 | Create(sub_commands::create::SubCommandArgs), | 245 | /// Proposal event-id (hex) or nevent (bech32) |
| 183 | } | 246 | #[arg(value_name = "ID|nevent")] |
| 184 | 247 | id: String, | |
| 185 | #[derive(clap::Parser)] | 248 | /// Use local cache only, skip network fetch |
| 186 | pub struct AccountSubCommandArgs { | 249 | #[arg(long)] |
| 187 | #[command(subcommand)] | 250 | offline: bool, |
| 188 | pub account_command: AccountCommands, | 251 | }, |
| 252 | /// mark a draft PR as ready for review (author or maintainer only) | ||
| 253 | Ready { | ||
| 254 | /// Proposal event-id (hex) or nevent (bech32) | ||
| 255 | #[arg(value_name = "ID|nevent")] | ||
| 256 | id: String, | ||
| 257 | /// Use local cache only, skip network fetch | ||
| 258 | #[arg(long)] | ||
| 259 | offline: bool, | ||
| 260 | }, | ||
| 261 | /// add a comment to a PR | ||
| 262 | Comment { | ||
| 263 | /// Proposal event-id (hex) or nevent (bech32) | ||
| 264 | #[arg(value_name = "ID|nevent")] | ||
| 265 | id: String, | ||
| 266 | /// Comment body | ||
| 267 | #[arg(long)] | ||
| 268 | body: String, | ||
| 269 | /// Use local cache only, skip network fetch | ||
| 270 | #[arg(long)] | ||
| 271 | offline: bool, | ||
| 272 | }, | ||
| 273 | /// merge a PR into the current branch (maintainer only) | ||
| 274 | #[command( | ||
| 275 | long_about = "merge a PR into the current branch (maintainer only)\n\nperforms a git merge of the PR branch; push afterwards to update the nostr state" | ||
| 276 | )] | ||
| 277 | Merge { | ||
| 278 | /// Proposal event-id (hex) or nevent (bech32) | ||
| 279 | #[arg(value_name = "ID|nevent")] | ||
| 280 | id: String, | ||
| 281 | /// Use squash merge | ||
| 282 | #[arg(long)] | ||
| 283 | squash: bool, | ||
| 284 | /// Use local cache only, skip network fetch | ||
| 285 | #[arg(long)] | ||
| 286 | offline: bool, | ||
| 287 | }, | ||
| 189 | } | 288 | } |
| 190 | 289 | ||
| 191 | #[derive(clap::Parser)] | 290 | // --------------------------------------------------------------------------- |
| 192 | pub struct RepoSubCommandArgs { | 291 | // Issue subcommand group |
| 193 | #[command(subcommand)] | 292 | // --------------------------------------------------------------------------- |
| 194 | pub repo_command: Option<RepoCommands>, | ||
| 195 | /// Use local cache only, skip network fetch | ||
| 196 | #[arg(long)] | ||
| 197 | pub offline: bool, | ||
| 198 | } | ||
| 199 | 293 | ||
| 200 | #[derive(clap::Parser)] | 294 | #[derive(clap::Parser)] |
| 201 | pub struct IssueSubCommandArgs { | 295 | pub struct IssueSubCommandArgs { |
| @@ -223,6 +317,60 @@ pub enum IssueCommands { | |||
| 223 | #[arg(long)] | 317 | #[arg(long)] |
| 224 | offline: bool, | 318 | offline: bool, |
| 225 | }, | 319 | }, |
| 320 | /// view an issue and its comments | ||
| 321 | View { | ||
| 322 | /// Issue event-id (hex) or nevent (bech32) | ||
| 323 | #[arg(value_name = "ID|nevent")] | ||
| 324 | id: String, | ||
| 325 | /// Output as JSON | ||
| 326 | #[arg(long)] | ||
| 327 | json: bool, | ||
| 328 | /// Use local cache only, skip network fetch | ||
| 329 | #[arg(long)] | ||
| 330 | offline: bool, | ||
| 331 | }, | ||
| 332 | /// create a new issue | ||
| 333 | Create { | ||
| 334 | /// Issue title | ||
| 335 | #[arg(long)] | ||
| 336 | title: Option<String>, | ||
| 337 | /// Issue body / description | ||
| 338 | #[arg(long)] | ||
| 339 | body: Option<String>, | ||
| 340 | /// Hashtag labels (repeatable: --label bug --label help-wanted) | ||
| 341 | #[arg(long = "label", value_name = "LABEL")] | ||
| 342 | labels: Vec<String>, | ||
| 343 | }, | ||
| 344 | /// close an issue (author or maintainer only) | ||
| 345 | Close { | ||
| 346 | /// Issue event-id (hex) or nevent (bech32) | ||
| 347 | #[arg(value_name = "ID|nevent")] | ||
| 348 | id: String, | ||
| 349 | /// Use local cache only, skip network fetch | ||
| 350 | #[arg(long)] | ||
| 351 | offline: bool, | ||
| 352 | }, | ||
| 353 | /// reopen a closed issue (author or maintainer only) | ||
| 354 | Reopen { | ||
| 355 | /// Issue event-id (hex) or nevent (bech32) | ||
| 356 | #[arg(value_name = "ID|nevent")] | ||
| 357 | id: String, | ||
| 358 | /// Use local cache only, skip network fetch | ||
| 359 | #[arg(long)] | ||
| 360 | offline: bool, | ||
| 361 | }, | ||
| 362 | /// add a comment to an issue | ||
| 363 | Comment { | ||
| 364 | /// Issue event-id (hex) or nevent (bech32) | ||
| 365 | #[arg(value_name = "ID|nevent")] | ||
| 366 | id: String, | ||
| 367 | /// Comment body | ||
| 368 | #[arg(long)] | ||
| 369 | body: String, | ||
| 370 | /// Use local cache only, skip network fetch | ||
| 371 | #[arg(long)] | ||
| 372 | offline: bool, | ||
| 373 | }, | ||
| 226 | } | 374 | } |
| 227 | 375 | ||
| 228 | #[derive(Subcommand)] | 376 | #[derive(Subcommand)] |