repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

commit
e0fbd08
parent
dcc0873
author
Eric Bower
date
2024-05-07 16:23:27 -0400 EDT
changes
3 files changed,  +84, -51
M db.go
M mdw.go
M backend.go
+6, -1
 1@@ -4,6 +4,7 @@ import (
 2 	"log/slog"
 3 	"path/filepath"
 4 
 5+	"github.com/charmbracelet/soft-serve/pkg/utils"
 6 	"github.com/charmbracelet/ssh"
 7 	gossh "golang.org/x/crypto/ssh"
 8 )
 9@@ -18,7 +19,11 @@ func (be *Backend) ReposDir() string {
10 	return filepath.Join(be.Cfg.DataPath, "repos")
11 }
12 
13-func (be *Backend) RepoName(name string) string {
14+func (be *Backend) RepoName(id string) string {
15+	return utils.SanitizeRepo(id)
16+}
17+
18+func (be *Backend) RepoID(name string) string {
19 	return name + ".git"
20 }
21 
M db.go
+2, -1
 1@@ -12,9 +12,10 @@ import (
 2 type PatchRequest struct {
 3 	ID        int64     `db:"id"`
 4 	Pubkey    string    `db:"pubkey"`
 5-	RepoID    int64     `db:"repo_id"`
 6+	RepoID    string    `db:"repo_id"`
 7 	Name      string    `db:"name"`
 8 	Text      string    `db:"text"`
 9+	Status    string    `db:"status"`
10 	CreatedAt time.Time `db:"created_at"`
11 	UpdatedAt time.Time `db:"updated_at"`
12 }
M mdw.go
+76, -49
  1@@ -74,7 +74,8 @@ func flagSet(sesh ssh.Session, cmdName string) *flag.FlagSet {
  2 // echo "here is a comment" | ssh git.sh pr 123 --comment
  3 
  4 type GitPatchRequest interface {
  5-	SubmitPatchRequest(pubkey string, repoName string, patches io.Reader) (*PatchRequest, error)
  6+	GetRepos() ([]string, error)
  7+	SubmitPatchRequest(pubkey string, repoID string, patches io.Reader) (*PatchRequest, error)
  8 	SubmitPatch(pubkey string, prID int64, patch io.Reader, review bool) (*Patch, error)
  9 	GetPatchRequests() ([]*PatchRequest, error)
 10 	GetPatchesByPrID(prID int64) ([]*Patch, error)
 11@@ -88,6 +89,20 @@ type PrCmd struct {
 12 var _ GitPatchRequest = PrCmd{}
 13 var _ GitPatchRequest = (*PrCmd)(nil)
 14 
 15+func (pr PrCmd) GetRepos() ([]string, error) {
 16+	repos := []string{}
 17+	entries, err := os.ReadDir(pr.Backend.ReposDir())
 18+	if err != nil {
 19+		return repos, err
 20+	}
 21+	for _, entry := range entries {
 22+		if entry.IsDir() {
 23+			repos = append(repos, entry.Name())
 24+		}
 25+	}
 26+	return repos, nil
 27+}
 28+
 29 func (pr PrCmd) GetPatchesByPrID(prID int64) ([]*Patch, error) {
 30 	patches := []*Patch{}
 31 	err := pr.Backend.DB.Select(
 32@@ -168,14 +183,15 @@ func (cmd PrCmd) SubmitPatch(pubkey string, prID int64, patch io.Reader, review
 33 	return &patchRec, err
 34 }
 35 
 36-func (cmd PrCmd) SubmitPatchRequest(pubkey string, repoName string, patches io.Reader) (*PatchRequest, error) {
 37-	err := git.EnsureWithin(cmd.Backend.ReposDir(), cmd.Backend.RepoName(repoName))
 38+func (cmd PrCmd) SubmitPatchRequest(pubkey string, repoID string, patches io.Reader) (*PatchRequest, error) {
 39+	err := git.EnsureWithin(cmd.Backend.ReposDir(), repoID)
 40 	if err != nil {
 41 		return nil, err
 42 	}
 43-	_, err = os.Stat(filepath.Join(cmd.Backend.ReposDir(), cmd.Backend.RepoName(repoName)))
 44+	loc := filepath.Join(cmd.Backend.ReposDir(), repoID)
 45+	_, err = os.Stat(loc)
 46 	if os.IsNotExist(err) {
 47-		return nil, fmt.Errorf("repo does not exist: %s", repoName)
 48+		return nil, fmt.Errorf("repo does not exist: %s", loc)
 49 	}
 50 
 51 	// need to read io.Reader from session twice
 52@@ -195,11 +211,12 @@ func (cmd PrCmd) SubmitPatchRequest(pubkey string, repoName string, patches io.R
 53 
 54 	var prID int64
 55 	row := cmd.Backend.DB.QueryRow(
 56-		"INSERT INTO patch_requests (pubkey, repo_id, name, text, updated_at) VALUES(?, ?, ?, ?, ?) RETURNING id",
 57+		"INSERT INTO patch_requests (pubkey, repo_id, name, text, status, updated_at) VALUES(?, ?, ?, ?, ?, ?) RETURNING id",
 58 		pubkey,
 59-		repoName,
 60+		repoID,
 61 		prName,
 62 		prDesc,
 63+		"open",
 64 		time.Now(),
 65 	)
 66 	err = row.Scan(&prID)
 67@@ -247,48 +264,72 @@ func GitPatchRequestMiddleware(be *Backend, pr GitPatchRequest) wish.Middleware
 68 			} else if cmd == "help" {
 69 				wish.Println(sesh, "commands: [help, pr, ls, git-receive-pack, git-upload-pack]")
 70 			} else if cmd == "ls" {
 71-				entries, err := os.ReadDir(be.ReposDir())
 72+				repos, err := pr.GetRepos()
 73 				try(sesh, err)
 74-
 75-				for _, e := range entries {
 76-					if e.IsDir() {
 77-						wish.Println(sesh, utils.SanitizeRepo(e.Name()))
 78-					}
 79+				wish.Printf(sesh, "Name\tDir\n")
 80+				for _, repo := range repos {
 81+					wish.Printf(
 82+						sesh,
 83+						"%s\t%s\n",
 84+						utils.SanitizeRepo(repo),
 85+						filepath.Join(be.ReposDir(), repo),
 86+					)
 87 				}
 88 			} else if cmd == "pr" {
 89 				prCmd := flagSet(sesh, "pr")
 90-				subCmd := strings.TrimSpace(args[2])
 91-				repoName := ""
 92-				var prID int64
 93-				var err error
 94-				if isNumRe.MatchString(subCmd) {
 95-					prID, err = strconv.ParseInt(args[2], 10, 64)
 96-					try(sesh, err)
 97-				} else {
 98-					repoName = utils.SanitizeRepo(subCmd)
 99-				}
100-				help := prCmd.Bool("help", false, "print patch request help")
101 				out := prCmd.Bool("stdout", false, "print patchset to stdout")
102 				accept := prCmd.Bool("accept", false, "mark patch request as accepted")
103 				closed := prCmd.Bool("close", false, "mark patch request as closed")
104 				review := prCmd.Bool("review", false, "mark patch request as reviewed")
105 
106-				if *help {
107-					wish.Println(sesh, "commands: [pr ls, pr {id}]")
108-				} else if prID != 0 && *out {
109-					patches, err := pr.GetPatchesByPrID(prID)
110+				fmt.Println(args)
111+				subCmd := strings.TrimSpace(args[1])
112+
113+				repoID := ""
114+				var prID int64
115+				var err error
116+				// figure out subcommand based on what was passed in
117+				if subCmd == "ls" {
118+					// skip proccessing
119+				} else if isNumRe.MatchString(subCmd) {
120+					// we probably have a patch request id
121+					prID, err = strconv.ParseInt(subCmd, 10, 64)
122 					try(sesh, err)
123+					subCmd = "patchRequest"
124+				} else {
125+					// we probably have a repo name
126+					repoID = be.RepoID(subCmd)
127+					subCmd = "submitPatchRequest"
128+				}
129 
130-					if len(patches) == 0 {
131-						wish.Println(sesh, patches[0].RawText)
132+				if subCmd == "ls" {
133+					prs, err := pr.GetPatchRequests()
134+					try(sesh, err)
135+					wish.Printf(sesh, "Name\tID\n")
136+					for _, req := range prs {
137+						wish.Printf(sesh, "%s\t%d\n", req.Name, req.ID)
138+					}
139+				} else if subCmd == "submitPatchRequest" {
140+					request, err := pr.SubmitPatchRequest(pubkey, repoID, sesh)
141+					if err != nil {
142+						wish.Fatalln(sesh, err)
143 						return
144 					}
145+					wish.Printf(sesh, "Patch Request submitted! (ID:%d)\n", request.ID)
146+				} else if subCmd == "patchRequest" {
147+					if *out {
148+						patches, err := pr.GetPatchesByPrID(prID)
149+						try(sesh, err)
150 
151-					for _, patch := range patches {
152-						wish.Printf(sesh, "%s\n\n\n", patch.RawText)
153-					}
154-				} else if prID != 0 {
155-					if *accept {
156+						if len(patches) == 0 {
157+							wish.Println(sesh, patches[0].RawText)
158+							return
159+						}
160+
161+						for _, patch := range patches {
162+							wish.Printf(sesh, "%s\n\n\n", patch.RawText)
163+						}
164+					} else if *accept {
165 						if !be.IsAdmin(sesh.PublicKey()) {
166 							wish.Fatalln(sesh, "must be admin to accept PR")
167 							return
168@@ -328,24 +369,10 @@ func GitPatchRequestMiddleware(be *Backend, pr GitPatchRequest) wish.Middleware
169 						}
170 						wish.Printf(sesh, "Patch submitted! (ID:%d)\n", patch.ID)
171 					}
172-				} else if subCmd == "ls" {
173-					prs, err := pr.GetPatchRequests()
174-					try(sesh, err)
175-					wish.Printf(sesh, "Name\tID\n")
176-					for _, req := range prs {
177-						wish.Printf(sesh, "%s\t%d\n", req.Name, req.ID)
178-					}
179-				} else if repoName != "" {
180-					request, err := pr.SubmitPatchRequest(pubkey, repoName, sesh)
181-					if err != nil {
182-						wish.Fatalln(sesh, err)
183-					}
184-					wish.Printf(sesh, "Patch Request submitted! (ID:%d)\n", request.ID)
185 				}
186 
187 				return
188 			} else {
189-				fmt.Println("made it here")
190 				next(sesh)
191 				return
192 			}