git-pr

created pr with 111.1 on 2026-02-23T18:28:22Z · by c8ef7d19
cmds
checkout latest patchset:
ssh pr.pico.sh print 111 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 111.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 111

Patchset 111.1 on 2026-02-23T18:28:22Z · commit 2ff4b8b

+34 -15 cli.go #
......@@ -13,6 +13,10 @@ import (
1313 "github.com/urfave/cli/v2"
1414 )
1515
16+func errNotExist(host, pubkey string) error {
17+ return fmt.Errorf("User does not exist, run `ssh <username>@%s register` to create an account\nPubkey: %s", host, pubkey)
18+}
19+
1620 func NewTabWriter(out io.Writer) *tabwriter.Writer {
1721 return tabwriter.NewWriter(out, 0, 0, 1, ' ', tabwriter.TabIndent)
1822 }
......@@ -237,7 +241,7 @@ To get started, submit a new patch request:
237241 pubkey := be.Pubkey(sesh.PublicKey())
238242 user, err := pr.GetUserByPubkey(pubkey)
239243 if err != nil {
240- return err
244+ return errNotExist(be.Cfg.Host, pubkey)
241245 }
242246 isPubkey := cCtx.Bool("pubkey")
243247 prID := cCtx.Int64("pr")
......@@ -290,6 +294,21 @@ To get started, submit a new patch request:
290294 return nil
291295 },
292296 },
297+ {
298+ Name: "register",
299+ Usage: "Create an account",
300+ Args: true,
301+ Flags: []cli.Flag{},
302+ Action: func(cCtx *cli.Context) error {
303+ pubkey := be.Pubkey(sesh.PublicKey())
304+ user, err := pr.RegisterUser(pubkey, userName)
305+ if err != nil {
306+ return err
307+ }
308+ wish.Printf(sesh, "User created successfully!\nUser: %s\nPubkey: %s\n", user.Name, pubkey)
309+ return nil
310+ },
311+ },
293312 {
294313 Name: "ps",
295314 Usage: "Mange patchsets",
......@@ -347,9 +366,9 @@ To get started, submit a new patch request:
347366 Args: true,
348367 ArgsUsage: "[repoName]",
349368 Action: func(cCtx *cli.Context) error {
350- user, err := pr.UpsertUser(pubkey, userName)
369+ user, err := pr.GetUserByPubkey(pubkey)
351370 if err != nil {
352- return err
371+ return errNotExist(be.Cfg.Host, pubkey)
353372 }
354373
355374 args := cCtx.Args()
......@@ -528,9 +547,9 @@ To get started, submit a new patch request:
528547 Args: true,
529548 ArgsUsage: "[repoName]",
530549 Action: func(cCtx *cli.Context) error {
531- user, err := pr.UpsertUser(pubkey, userName)
550+ user, err := pr.GetUserByPubkey(pubkey)
532551 if err != nil {
533- return err
552+ return errNotExist(be.Cfg.Host, pubkey)
534553 }
535554
536555 args := cCtx.Args()
......@@ -631,9 +650,9 @@ To get started, submit a new patch request:
631650 return err
632651 }
633652
634- user, err := pr.UpsertUser(pubkey, userName)
653+ user, err := pr.GetUserByPubkey(pubkey)
635654 if err != nil {
636- return err
655+ return errNotExist(be.Cfg.Host, pubkey)
637656 }
638657
639658 repo, err := pr.GetRepoByID(prq.RepoID)
......@@ -717,9 +736,9 @@ To get started, submit a new patch request:
717736 return fmt.Errorf("PR has already been closed")
718737 }
719738
720- user, err := pr.UpsertUser(pubkey, userName)
739+ user, err := pr.GetUserByPubkey(pubkey)
721740 if err != nil {
722- return err
741+ return errNotExist(be.Cfg.Host, pubkey)
723742 }
724743
725744 err = pr.UpdatePatchRequestStatus(prID, user.ID, StatusClosed, cCtx.String("comment"))
......@@ -782,9 +801,9 @@ To get started, submit a new patch request:
782801 return fmt.Errorf("PR is already open")
783802 }
784803
785- user, err := pr.UpsertUser(pubkey, userName)
804+ user, err := pr.GetUserByPubkey(pubkey)
786805 if err != nil {
787- return err
806+ return errNotExist(be.Cfg.Host, pubkey)
788807 }
789808
790809 err = pr.UpdatePatchRequestStatus(prID, user.ID, StatusOpen, cCtx.String("comment"))
......@@ -814,9 +833,9 @@ To get started, submit a new patch request:
814833 return err
815834 }
816835
817- user, err := pr.UpsertUser(pubkey, userName)
836+ user, err := pr.GetUserByPubkey(pubkey)
818837 if err != nil {
819- return err
838+ return errNotExist(be.Cfg.Host, pubkey)
820839 }
821840
822841 repo, err := pr.GetRepoByID(prq.RepoID)
......@@ -885,9 +904,9 @@ To get started, submit a new patch request:
885904 return err
886905 }
887906
888- user, err := pr.UpsertUser(pubkey, userName)
907+ user, err := pr.GetUserByPubkey(pubkey)
889908 if err != nil {
890- return err
909+ return errNotExist(be.Cfg.Host, pubkey)
891910 }
892911
893912 isReview := cCtx.Bool("review")
+6 -0 e2e_test.go #
......@@ -31,6 +31,9 @@ func testSingleTenantE2E(t *testing.T) {
3131 // Hack to wait for startup
3232 time.Sleep(time.Millisecond * 100)
3333
34+ suite.userKey.MustCmd(suite.patch, "register")
35+ suite.adminKey.MustCmd(suite.patch, "register")
36+
3437 t.Log("User cannot create repo")
3538 _, err := suite.userKey.Cmd(suite.patch, "pr create test")
3639 if err == nil {
......@@ -63,6 +66,9 @@ func testMultiTenantE2E(t *testing.T) {
6366
6467 time.Sleep(time.Millisecond * 100)
6568
69+ suite.userKey.MustCmd(suite.patch, "register")
70+ suite.adminKey.MustCmd(suite.patch, "register")
71+
6672 t.Log("Admin should be able to create a repo")
6773 suite.adminKey.MustCmd(nil, "repo create test")
6874
+6 -6 pr.go #
......@@ -31,7 +31,7 @@ type GitPatchRequest interface {
3131 GetRepoByID(repoID int64) (*Repo, error)
3232 GetRepoByName(user *User, repoName string) (*Repo, error)
3333 CreateRepo(user *User, repoName string) (*Repo, error)
34- UpsertUser(pubkey, name string) (*User, error)
34+ RegisterUser(pubkey, name string) (*User, error)
3535 IsBanned(pubkey, ipAddress string) error
3636 SubmitPatchRequest(repoID int64, userID int64, patchset io.Reader) (*PatchRequest, error)
3737 SubmitPatchset(prID, userID int64, op PatchsetOp, patchset io.Reader) ([]*Patch, error)
......@@ -194,16 +194,16 @@ func (pr PrCmd) createUser(pubkey, name string) (*User, error) {
194194 return user, err
195195 }
196196
197-func (pr PrCmd) UpsertUser(pubkey, name string) (*User, error) {
197+func (pr PrCmd) RegisterUser(pubkey, name string) (*User, error) {
198198 sanName := strings.ToLower(name)
199199 if pubkey == "" {
200200 return nil, fmt.Errorf("must provide pubkey during upsert")
201201 }
202- user, err := pr.GetUserByPubkey(pubkey)
203- if err != nil {
204- user, err = pr.createUser(pubkey, sanName)
202+ _, err := pr.GetUserByPubkey(pubkey)
203+ if err == nil {
204+ return nil, fmt.Errorf("pubkey is already registered by another user")
205205 }
206- return user, err
206+ return pr.createUser(pubkey, sanName)
207207 }
208208
209209 func (pr PrCmd) GetPatchsetsByPrID(prID int64) ([]*Patchset, error) {
Back to top