- commit
- 84dd266
- parent
- 1824e58
- author
- Eric Bower
- date
- 2024-07-14 08:12:55 -0400 EDT
refactor: move patch parsing code
4 files changed,
+232,
-107
+87,
-0
1@@ -0,0 +1,87 @@
2+From 71a58613493dd0211a576ed6531c5ee712a03ff3 Mon Sep 17 00:00:00 2001
3+From: Eric Bower <me@erock.io>
4+Date: Sun, 14 Jul 2024 07:14:44 -0400
5+Subject: [PATCH 0/2] Add torch deps
6+
7+I took the liberty of adding a requirements file for python.
8+
9+Bob Sour (1):
10+ chore: add torch to requirements
11+
12+Eric Bower (1):
13+ feat: lets build an rnn
14+
15+ README.md | 4 ++--
16+ requirements.txt | 1 +
17+ train.py | 5 +++++
18+ 3 files changed, 8 insertions(+), 2 deletions(-)
19+ create mode 100644 requirements.txt
20+ create mode 100644 train.py
21+
22+--
23+2.45.2
24+
25+From 59456574a0bfee9f71c91c13046173c820152346 Mon Sep 17 00:00:00 2001
26+From: Eric Bower <me@erock.io>
27+Date: Wed, 3 Jul 2024 15:18:47 -0400
28+Subject: [PATCH 1/2] feat: lets build an rnn
29+
30+---
31+ README.md | 4 ++--
32+ train.py | 2 ++
33+ 2 files changed, 4 insertions(+), 2 deletions(-)
34+ create mode 100644 train.py
35+
36+diff --git a/README.md b/README.md
37+index 586bc0d..8f3a780 100644
38+--- a/README.md
39++++ b/README.md
40+@@ -1,3 +1,3 @@
41+-# test
42++# Let's build an RNN
43+
44+-testing git pr
45++This repo demonstrates building an RNN using `pytorch`
46+diff --git a/train.py b/train.py
47+new file mode 100644
48+index 0000000..5c027f4
49+--- /dev/null
50++++ b/train.py
51+@@ -0,0 +1,2 @@
52++if __name__ == "__main__":
53++ print("train!")
54+--
55+2.45.2
56+
57+
58+From 71a58613493dd0211a576ed6531c5ee712a03ff3 Mon Sep 17 00:00:00 2001
59+From: Bob Sour <bob@bower.sh>
60+Date: Fri, 5 Jul 2024 18:57:03 +0000
61+Subject: [PATCH 2/2] chore: add torch to requirements
62+
63+---
64+ requirements.txt | 1 +
65+ train.py | 3 +++
66+ 2 files changed, 4 insertions(+)
67+ create mode 100644 requirements.txt
68+
69+diff --git a/requirements.txt b/requirements.txt
70+new file mode 100644
71+index 0000000..4968a39
72+--- /dev/null
73++++ b/requirements.txt
74+@@ -0,0 +1 @@
75++torch==2.3.1
76+diff --git a/train.py b/train.py
77+index 5c027f4..8f32fe2 100644
78+--- a/train.py
79++++ b/train.py
80+@@ -1,2 +1,5 @@
81++import torch
82++
83+ if __name__ == "__main__":
84+ print("train!")
85++ print(torch.rand(6,6))
86+--
87+2.45.2
88+
M
pr.go
+2,
-107
1@@ -1,17 +1,11 @@
2 package git
3
4 import (
5- "crypto/sha256"
6- "database/sql"
7- "encoding/hex"
8 "errors"
9 "fmt"
10 "io"
11- "regexp"
12- "strings"
13 "time"
14
15- "github.com/bluekeyes/go-gitdiff/gitdiff"
16 "github.com/jmoiron/sqlx"
17 )
18
19@@ -336,105 +330,6 @@ func (cmd PrCmd) CreateEventLog(eventLog EventLog) error {
20 return err
21 }
22
23-// calcContentSha calculates a shasum containing the important content
24-// changes related to a patch.
25-// We cannot rely on patch.CommitSha because it includes the commit date
26-// that will change when a user fetches and applies the patch locally.
27-func (cmd PrCmd) calcContentSha(diffFiles []*gitdiff.File, header *gitdiff.PatchHeader) string {
28- authorName := ""
29- authorEmail := ""
30- if header.Author != nil {
31- authorName = header.Author.Name
32- authorEmail = header.Author.Email
33- }
34- content := fmt.Sprintf(
35- "%s\n%s\n%s\n%s\n%s\n",
36- header.Title,
37- header.Body,
38- authorName,
39- authorEmail,
40- header.AuthorDate,
41- )
42- for _, diff := range diffFiles {
43- dff := fmt.Sprintf(
44- "%s->%s %s..%s %s->%s\n",
45- diff.OldName, diff.NewName,
46- diff.OldOIDPrefix, diff.NewOIDPrefix,
47- diff.OldMode.String(), diff.NewMode.String(),
48- )
49- content += dff
50- }
51- sha := sha256.Sum256([]byte(content))
52- shaStr := hex.EncodeToString(sha[:])
53- return shaStr
54-}
55-
56-func splitPatchSet(patchset string) []string {
57- return strings.Split(patchset, "\n\n\n")
58-}
59-
60-func findBaseCommit(patch string) string {
61- re := regexp.MustCompile(`base-commit: (.+)\s*`)
62- strs := re.FindStringSubmatch(patch)
63- baseCommit := ""
64- if len(strs) > 1 {
65- baseCommit = strs[1]
66- }
67- return baseCommit
68-}
69-
70-func (cmd PrCmd) parsePatchSet(patchset io.Reader) ([]*Patch, error) {
71- patches := []*Patch{}
72- buf := new(strings.Builder)
73- _, err := io.Copy(buf, patchset)
74- if err != nil {
75- return nil, err
76- }
77-
78- patchesRaw := splitPatchSet(buf.String())
79- for _, patchRaw := range patchesRaw {
80- reader := strings.NewReader(patchRaw)
81- diffFiles, preamble, err := gitdiff.Parse(reader)
82- if err != nil {
83- return nil, err
84- }
85- header, err := gitdiff.ParsePatchHeader(preamble)
86- if err != nil {
87- return nil, err
88- }
89-
90- if len(diffFiles) == 0 {
91- cmd.Backend.Logger.Info("not diff files found for patch, skipping")
92- continue
93- }
94-
95- baseCommit := findBaseCommit(patchRaw)
96- authorName := "Unknown"
97- authorEmail := ""
98- if header.Author != nil {
99- authorName = header.Author.Name
100- authorEmail = header.Author.Email
101- }
102-
103- contentSha := cmd.calcContentSha(diffFiles, header)
104-
105- patches = append(patches, &Patch{
106- AuthorName: authorName,
107- AuthorEmail: authorEmail,
108- AuthorDate: header.AuthorDate.UTC().String(),
109- Title: header.Title,
110- Body: header.Body,
111- BodyAppendix: header.BodyAppendix,
112- CommitSha: header.SHA,
113- ContentSha: contentSha,
114- RawText: patchRaw,
115- BaseCommitSha: sql.NullString{String: baseCommit},
116- })
117- }
118-
119- return patches, nil
120-}
121-
122 func (cmd PrCmd) createPatch(tx *sqlx.Tx, review bool, patch *Patch) (int64, error) {
123 patchExists := []Patch{}
124 _ = cmd.Backend.DB.Select(&patchExists, "SELECT * FROM patches WHERE patch_request_id=? AND content_sha=?", patch.PatchRequestID, patch.ContentSha)
125@@ -479,7 +374,7 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, userID int64, patchset io.Rea
126 _ = tx.Rollback()
127 }()
128
129- patches, err := cmd.parsePatchSet(patchset)
130+ patches, err := parsePatchSet(patchset)
131 if err != nil {
132 return nil, err
133 }
134@@ -549,7 +444,7 @@ func (cmd PrCmd) SubmitPatchSet(prID int64, userID int64, op PatchsetOp, patchse
135 _ = tx.Rollback()
136 }()
137
138- patches, err := cmd.parsePatchSet(patchset)
139+ patches, err := parsePatchSet(patchset)
140 if err != nil {
141 return fin, err
142 }
M
util.go
+109,
-0
1@@ -1,15 +1,22 @@
2 package git
3
4 import (
5+ "crypto/sha256"
6+ "database/sql"
7+ "encoding/hex"
8 "fmt"
9+ "io"
10 "math/rand"
11+ "regexp"
12 "strconv"
13 "strings"
14
15+ "github.com/bluekeyes/go-gitdiff/gitdiff"
16 "github.com/charmbracelet/ssh"
17 )
18
19 var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
20+var startOfPatch = "From "
21
22 // https://stackoverflow.com/a/22892986
23 func randSeq(n int) string {
24@@ -104,6 +111,108 @@ func filterPatches(ranger *Ranger, patches []*Patch) []*Patch {
25 return patches[ranger.Left:ranger.Right]
26 }
27
28+func splitPatchSet(patchset string) []string {
29+ return strings.Split(patchset, "\n"+startOfPatch)
30+}
31+
32+func findBaseCommit(patch string) string {
33+ re := regexp.MustCompile(`base-commit: (.+)\s*`)
34+ strs := re.FindStringSubmatch(patch)
35+ baseCommit := ""
36+ if len(strs) > 1 {
37+ baseCommit = strs[1]
38+ }
39+ return baseCommit
40+}
41+
42+func parsePatchSet(patchset io.Reader) ([]*Patch, error) {
43+ patches := []*Patch{}
44+ buf := new(strings.Builder)
45+ _, err := io.Copy(buf, patchset)
46+ if err != nil {
47+ return nil, err
48+ }
49+
50+ patchesRaw := splitPatchSet(buf.String())
51+ for idx, patchRaw := range patchesRaw {
52+ patchStr := patchRaw
53+ if idx > 0 {
54+ patchStr = startOfPatch + patchRaw
55+ }
56+ reader := strings.NewReader(patchStr)
57+ diffFiles, preamble, err := gitdiff.Parse(reader)
58+ if err != nil {
59+ return nil, err
60+ }
61+ header, err := gitdiff.ParsePatchHeader(preamble)
62+ if err != nil {
63+ return nil, err
64+ }
65+
66+ baseCommit := findBaseCommit(patchRaw)
67+ authorName := "Unknown"
68+ authorEmail := ""
69+ if header.Author != nil {
70+ authorName = header.Author.Name
71+ authorEmail = header.Author.Email
72+ }
73+
74+ if len(diffFiles) == 0 {
75+ continue
76+ }
77+
78+ contentSha := calcContentSha(diffFiles, header)
79+
80+ patches = append(patches, &Patch{
81+ AuthorName: authorName,
82+ AuthorEmail: authorEmail,
83+ AuthorDate: header.AuthorDate.UTC().String(),
84+ Title: header.Title,
85+ Body: header.Body,
86+ BodyAppendix: header.BodyAppendix,
87+ CommitSha: header.SHA,
88+ ContentSha: contentSha,
89+ RawText: patchRaw,
90+ BaseCommitSha: sql.NullString{String: baseCommit},
91+ })
92+ }
93+
94+ return patches, nil
95+}
96+
97+// calcContentSha calculates a shasum containing the important content
98+// changes related to a patch.
99+// We cannot rely on patch.CommitSha because it includes the commit date
100+// that will change when a user fetches and applies the patch locally.
101+func calcContentSha(diffFiles []*gitdiff.File, header *gitdiff.PatchHeader) string {
102+ authorName := ""
103+ authorEmail := ""
104+ if header.Author != nil {
105+ authorName = header.Author.Name
106+ authorEmail = header.Author.Email
107+ }
108+ content := fmt.Sprintf(
109+ "%s\n%s\n%s\n%s\n%s\n",
110+ header.Title,
111+ header.Body,
112+ authorName,
113+ authorEmail,
114+ header.AuthorDate,
115+ )
116+ for _, diff := range diffFiles {
117+ dff := fmt.Sprintf(
118+ "%s->%s %s..%s %s->%s\n",
119+ diff.OldName, diff.NewName,
120+ diff.OldOIDPrefix, diff.NewOIDPrefix,
121+ diff.OldMode.String(), diff.NewMode.String(),
122+ )
123+ content += dff
124+ }
125+ sha := sha256.Sum256([]byte(content))
126+ shaStr := hex.EncodeToString(sha[:])
127+ return shaStr
128+}
129+
130 /* func gitServiceCommands(sesh ssh.Session, be *Backend, cmd, repoName string) error {
131 name := utils.SanitizeRepo(repoName)
132 // git bare repositories should end in ".git"
+34,
-0
1@@ -0,0 +1,34 @@
2+package git
3+
4+import (
5+ "os"
6+ "testing"
7+)
8+
9+func TestParsePatchsetWithCover(t *testing.T) {
10+ file, err := os.Open("fixtures/with-cover.patch")
11+ defer func() {
12+ _ = file.Close()
13+ }()
14+ if err != nil {
15+ t.Fatalf(err.Error())
16+ }
17+ actual, err := parsePatchSet(file)
18+ if err != nil {
19+ t.Fatalf(err.Error())
20+ }
21+ expected := []*Patch{
22+ // {Title: "Add torch deps"},
23+ {Title: "feat: lets build an rnn"},
24+ {Title: "chore: add torch to requirements"},
25+ }
26+ if len(actual) != len(expected) {
27+ t.Fatalf("patches not same length (expected:%d, actual:%d)\n", len(expected), len(actual))
28+ }
29+ for idx, act := range actual {
30+ exp := expected[idx]
31+ if exp.Title != act.Title {
32+ t.Fatalf("title does not match expected (expected:%s, actual:%s)", exp.Title, act.Title)
33+ }
34+ }
35+}