Eric Bower
·
2026-02-25
1package main
2
3import (
4 "context"
5 "flag"
6 "fmt"
7 "log/slog"
8 "net/http"
9 "os"
10 "os/signal"
11 "syscall"
12 "time"
13
14 "github.com/picosh/patchbin"
15 "github.com/picosh/patchbin/fixtures"
16 "github.com/picosh/patchbin/util"
17)
18
19func main() {
20 cleanupFlag := flag.Bool("cleanup", true, "Clean up tmp dir after quitting (default: true)")
21 flag.Parse()
22
23 opts := &slog.HandlerOptions{
24 AddSource: true,
25 }
26 logger := slog.New(
27 slog.NewTextHandler(os.Stdout, opts),
28 )
29
30 dataDir := util.CreateTmpDir()
31 defer func() {
32 if *cleanupFlag {
33 _ = os.RemoveAll(dataDir)
34 }
35 }()
36
37 adminKey, userKey := util.GenerateKeys()
38 cfgPath := util.CreateCfgFile(dataDir, cfgTmpl, adminKey)
39 patchbin.LoadConfigFile(cfgPath, logger)
40 cfg := patchbin.NewGitCfg(logger)
41
42 ctx, cancel := context.WithCancel(context.Background())
43 defer cancel()
44 s := patchbin.GitSshServer(ctx, cfg)
45 go func() {
46 _ = s.ListenAndServe()
47 }()
48 time.Sleep(time.Millisecond * 100)
49 w := patchbin.GitWebServer(cfg)
50 addr := fmt.Sprintf("%s:%s", cfg.Host, cfg.WebPort)
51 go func() {
52 _ = http.ListenAndServe(addr, w)
53 }()
54
55 // Hack to wait for startup
56 time.Sleep(time.Millisecond * 100)
57
58 patch, err := fixtures.Fixtures.ReadFile("single.patch")
59 if err != nil {
60 panic(err)
61 }
62 otherPatch, err := fixtures.Fixtures.ReadFile("with-cover.patch")
63 if err != nil {
64 panic(err)
65 }
66 rd1, err := fixtures.Fixtures.ReadFile("a_b_reorder.patch")
67 if err != nil {
68 panic(err)
69 }
70 rd2, err := fixtures.Fixtures.ReadFile("a_c_changed_commit.patch")
71 if err != nil {
72 panic(err)
73 }
74
75 // Opened patch (creator opens their own PR)
76 userKey.MustCmd(patch, "pr create test")
77 userKey.MustCmd(nil, "pr edit 1 Opened patch")
78 userKey.MustCmd(nil, `pr open --comment "ready for review" 1`)
79
80 // Drafted patch (creator sets back to draft)
81 userKey.MustCmd(patch, "pr create test")
82 userKey.MustCmd(nil, "pr edit 2 Drafted patch")
83 userKey.MustCmd(nil, `pr draft --comment "need more work" 2`)
84
85 // Opened then re-drafted by creator
86 userKey.MustCmd(patch, "pr create test")
87 userKey.MustCmd(nil, "pr edit 3 Opened then re-drafted")
88 userKey.MustCmd(nil, `pr open 3`)
89 userKey.MustCmd(nil, `pr draft --comment "Woops, didn't mean to submit yet" 3`)
90
91 // Patchset added by another user, creator opens
92 userKey.MustCmd(patch, "pr create test")
93 userKey.MustCmd(nil, "pr edit 5 Patchset from another user")
94 adminKey.MustCmd(otherPatch, `pr add 5`)
95 userKey.MustCmd(nil, `pr open --comment "updated with feedback" 5`)
96
97 // Patchset added by another user, creator drafts
98 userKey.MustCmd(patch, "pr create test")
99 userKey.MustCmd(nil, "pr edit 6 Patchset then drafted")
100 adminKey.MustCmd(otherPatch, `pr add 6`)
101 userKey.MustCmd(nil, `pr draft --comment "taking a step back on this" 6`)
102
103 // Range Diff
104 userKey.MustCmd(rd1, "pr create test")
105 userKey.MustCmd(nil, "pr edit 7 Range Diff")
106 userKey.MustCmd(rd2, "pr add 7")
107
108 fmt.Println("time to do some testing...")
109 ch := make(chan os.Signal, 1)
110 signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
111 <-ch
112}
113
114// args: tmpdir, adminKey
115var cfgTmpl = `
116url = "localhost"
117data_dir = %q
118admins = [%q]
119time_format = "01/02/2006 15:04:05 07:00"`