pico

created pr with 19.1 on 2024-08-19T21:12:53Z · by c8ef7d19
added 19.2 on 2024-10-18T20:36:21Z · by c8ef7d19
1: 778bcd8 ! 1: 0f86231 feat: range diff
cmds
checkout latest patchset:
ssh pr.pico.sh print 19 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 19.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 19
set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 19
set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 19
+6 -0 db.go #
......@@ -6,6 +6,7 @@ import (
66 "log/slog"
77 "time"
88
9+ "github.com/bluekeyes/go-gitdiff/gitdiff"
910 "github.com/jmoiron/sqlx"
1011 _ "modernc.org/sqlite"
1112 )
......@@ -67,6 +68,11 @@ type Patch struct {
6768 BaseCommitSha sql.NullString `db:"base_commit_sha"`
6869 RawText string `db:"raw_text"`
6970 CreatedAt time.Time `db:"created_at"`
71+ Files []*gitdiff.File
72+}
73+
74+func (p *Patch) CalcDiff() string {
75+ return p.RawText
7076 }
7177
7278 // EventLog is a event log for RSS or other notification systems.
+31 -0 fixtures/a_b.patch #
......@@ -0,0 +1,31 @@
1+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:07:57 -0400
4+Subject: [PATCH] chore: add torch and create random tensor
5+
6+---
7+ requirements.txt | 1 +
8+ train.py | 3 +++
9+ 2 files changed, 4 insertions(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+diff --git a/train.py b/train.py
20+index 5c027f4..d21dac3 100644
21+--- a/train.py
22++++ b/train.py
23+@@ -1,2 +1,5 @@
24++import torch
25++
26+ if __name__ == "__main__":
27+ print("train!")
28++ torch.rand(3,6)
29+--
30+2.45.2
31+
+55 -0 fixtures/a_b_reorder.patch #
......@@ -0,0 +1,55 @@
1+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:07:57 -0400
4+Subject: [PATCH 1/2] chore: add torch and create random tensor
5+
6+---
7+ requirements.txt | 1 +
8+ train.py | 3 +++
9+ 2 files changed, 4 insertions(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+diff --git a/train.py b/train.py
20+index 5c027f4..d21dac3 100644
21+--- a/train.py
22++++ b/train.py
23+@@ -1,2 +1,5 @@
24++import torch
25++
26+ if __name__ == "__main__":
27+ print("train!")
28++ torch.rand(3,6)
29+--
30+2.45.2
31+
32+
33+From 22dde1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
34+From: Eric Bower <me@erock.io>
35+Date: Tue, 23 Jul 2024 10:14:37 -0400
36+Subject: [PATCH 2/2] docs: readme
37+
38+---
39+ README.md | 4 +++-
40+ 1 file changed, 3 insertions(+), 1 deletion(-)
41+
42+diff --git a/README.md b/README.md
43+index 8f3a780..3043953 100644
44+--- a/README.md
45++++ b/README.md
46+@@ -1,3 +1,5 @@
47+ # Let's build an RNN
48+
49+-This repo demonstrates building an RNN using `pytorch`
50++This repo demonstrates building an RNN using `pytorch`.
51++
52++Here is some more readme information.
53+--
54+2.45.2
55+
+33 -0 fixtures/a_c.patch #
......@@ -0,0 +1,33 @@
1+From 166848469e0b954c2e14233233f3824a46dcddb8 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:06:00 -0400
4+Subject: [PATCH] chore: add torch and create random tensor
5+
6+---
7+ requirements.txt | 1 +
8+ train.py | 3 +++
9+ 2 files changed, 4 insertions(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+diff --git a/train.py b/train.py
20+index 5c027f4..d21dac3 100644
21+--- a/train.py
22++++ b/train.py
23+@@ -1,2 +1,5 @@
24++import torch
25++
26+ if __name__ == "__main__":
27+ print("train!")
28++ torch.rand(3,6)
29+
30+base-commit: 59456574a0bfee9f71c91c13046173c820152346
31+--
32+2.45.2
33+
+80 -0 fixtures/a_c_added_commit.patch #
......@@ -0,0 +1,80 @@
1+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:07:57 -0400
4+Subject: [PATCH 1/3] chore: add torch and create random tensor
5+
6+---
7+ requirements.txt | 1 +
8+ train.py | 3 +++
9+ 2 files changed, 4 insertions(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+diff --git a/train.py b/train.py
20+index 5c027f4..d21dac3 100644
21+--- a/train.py
22++++ b/train.py
23+@@ -1,2 +1,5 @@
24++import torch
25++
26+ if __name__ == "__main__":
27+ print("train!")
28++ torch.rand(3,6)
29+--
30+2.45.2
31+
32+
33+From 22dde1259c34a166d5a9335ebe5236e79541cc63 Mon Sep 17 00:00:00 2001
34+From: Eric Bower <me@erock.io>
35+Date: Tue, 23 Jul 2024 10:14:37 -0400
36+Subject: [PATCH 2/3] docs: readme
37+
38+---
39+ README.md | 4 +++-
40+ 1 file changed, 3 insertions(+), 1 deletion(-)
41+
42+diff --git a/README.md b/README.md
43+index 8f3a780..3043953 100644
44+--- a/README.md
45++++ b/README.md
46+@@ -1,3 +1,5 @@
47+ # Let's build an RNN
48+
49+-This repo demonstrates building an RNN using `pytorch`
50++This repo demonstrates building an RNN using `pytorch`.
51++
52++Here is some more readme information.
53+--
54+2.45.2
55+
56+
57+From b248060488df529b850060b3c86417bb87d490cc Mon Sep 17 00:00:00 2001
58+From: Eric Bower <me@erock.io>
59+Date: Tue, 23 Jul 2024 10:20:44 -0400
60+Subject: [PATCH 3/3] chore: make tensor 6x6
61+
62+---
63+ train.py | 4 +++-
64+ 1 file changed, 3 insertions(+), 1 deletion(-)
65+
66+diff --git a/train.py b/train.py
67+index d21dac3..8cd47e0 100644
68+--- a/train.py
69++++ b/train.py
70+@@ -2,4 +2,6 @@ import torch
71+
72+ if __name__ == "__main__":
73+ print("train!")
74+- torch.rand(3,6)
75++ # let's create a 6x6 tensor!
76++ tensor = torch.rand(6,6)
77++ print(tensor)
78+--
79+2.45.2
80+
+60 -0 fixtures/a_c_changed_commit.patch #
......@@ -0,0 +1,60 @@
1+From 33c682ac27479f501924cf159d0a75ad91deb589 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:07:57 -0400
4+Subject: [PATCH 1/2] chore: add torch and create random tensor
5+
6+---
7+ requirements.txt | 1 +
8+ train.py | 3 +++
9+ 2 files changed, 4 insertions(+)
10+ create mode 100644 requirements.txt
11+
12+diff --git a/requirements.txt b/requirements.txt
13+new file mode 100644
14+index 0000000..4968a39
15+--- /dev/null
16++++ b/requirements.txt
17+@@ -0,0 +1 @@
18++torch==2.3.1
19+diff --git a/train.py b/train.py
20+index 5c027f4..d21dac3 100644
21+--- a/train.py
22++++ b/train.py
23+@@ -1,2 +1,5 @@
24++import torch
25++
26+ if __name__ == "__main__":
27+ print("train!")
28++ torch.rand(3,6)
29+--
30+2.45.2
31+
32+
33+From dce20e70280d92aeb88c3d603ad67043ead772fb Mon Sep 17 00:00:00 2001
34+From: Eric Bower <me@erock.io>
35+Date: Tue, 23 Jul 2024 10:14:37 -0400
36+Subject: [PATCH 2/2] docs: readme
37+
38+---
39+ README.md | 9 ++++++++-
40+ 1 file changed, 8 insertions(+), 1 deletion(-)
41+
42+diff --git a/README.md b/README.md
43+index 8f3a780..ba0293b 100644
44+--- a/README.md
45++++ b/README.md
46+@@ -1,3 +1,10 @@
47+ # Let's build an RNN
48+
49+-This repo demonstrates building an RNN using `pytorch`
50++This repo demonstrates building an RNN using `pytorch`.
51++
52++Here is some more readme information.
53++
54++Here is how to run this project locally:
55++
56++- install python and pip
57++- `pip install -r requirements.txt`
58+--
59+2.45.2
60+
+55 -0 fixtures/a_c_reorder.patch #
......@@ -0,0 +1,55 @@
1+From 7dbb94ca1bc8cadf1ce17dacb89172217d88de07 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:15:23 -0400
4+Subject: [PATCH 1/2] docs: readme
5+
6+---
7+ README.md | 4 +++-
8+ 1 file changed, 3 insertions(+), 1 deletion(-)
9+
10+diff --git a/README.md b/README.md
11+index 8f3a780..3043953 100644
12+--- a/README.md
13++++ b/README.md
14+@@ -1,3 +1,5 @@
15+ # Let's build an RNN
16+
17+-This repo demonstrates building an RNN using `pytorch`
18++This repo demonstrates building an RNN using `pytorch`.
19++
20++Here is some more readme information.
21+--
22+2.45.2
23+
24+
25+From ad175875e2bf320859554bae73743675cc5ce444 Mon Sep 17 00:00:00 2001
26+From: Eric Bower <me@erock.io>
27+Date: Tue, 23 Jul 2024 10:06:00 -0400
28+Subject: [PATCH 2/2] chore: add torch and create random tensor
29+
30+---
31+ requirements.txt | 1 +
32+ train.py | 3 +++
33+ 2 files changed, 4 insertions(+)
34+ create mode 100644 requirements.txt
35+
36+diff --git a/requirements.txt b/requirements.txt
37+new file mode 100644
38+index 0000000..4968a39
39+--- /dev/null
40++++ b/requirements.txt
41+@@ -0,0 +1 @@
42++torch==2.3.1
43+diff --git a/train.py b/train.py
44+index 5c027f4..d21dac3 100644
45+--- a/train.py
46++++ b/train.py
47+@@ -1,2 +1,5 @@
48++import torch
49++
50+ if __name__ == "__main__":
51+ print("train!")
52++ torch.rand(3,6)
53+--
54+2.45.2
55+
+23 -0 fixtures/a_c_rm_commit.patch #
......@@ -0,0 +1,23 @@
1+From 7dbb94ca1bc8cadf1ce17dacb89172217d88de07 Mon Sep 17 00:00:00 2001
2+From: Eric Bower <me@erock.io>
3+Date: Tue, 23 Jul 2024 10:15:23 -0400
4+Subject: [PATCH] docs: readme
5+
6+---
7+ README.md | 4 +++-
8+ 1 file changed, 3 insertions(+), 1 deletion(-)
9+
10+diff --git a/README.md b/README.md
11+index 8f3a780..3043953 100644
12+--- a/README.md
13++++ b/README.md
14+@@ -1,3 +1,5 @@
15+ # Let's build an RNN
16+
17+-This repo demonstrates building an RNN using `pytorch`
18++This repo demonstrates building an RNN using `pytorch`.
19++
20++Here is some more readme information.
21+--
22+2.45.2
23+
+11 -0 fixtures/expected_commit_changed.txt #
......@@ -0,0 +1,11 @@
1+1: 33c682a = 1: 33c682a chore: add torch and create random tensor
2+2: 22dde12 ! 2: 0185f34 docs: readme
3+ @@ README.md
4+ +This repo demonstrates building an RNN using `pytorch`.
5+ +
6+ +Here is some more readme information.
7+ ++
8+ ++Here is how to run this project locally:
9+ ++
10+ ++- install python and pip
11+ ++- `pip install -r requirements.txt`
+1 -0 go.mod #
......@@ -14,6 +14,7 @@ require (
1414 github.com/knadh/koanf/providers/env v0.1.0
1515 github.com/knadh/koanf/providers/file v1.0.0
1616 github.com/knadh/koanf/v2 v2.1.1
17+ github.com/sergi/go-diff v1.1.0
1718 github.com/urfave/cli/v2 v2.27.2
1819 golang.org/x/crypto v0.21.0
1920 modernc.org/sqlite v1.27.0
+13 -2 go.sum #
......@@ -8,8 +8,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
88 github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
99 github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
1010 github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
11-github.com/bluekeyes/go-gitdiff v0.7.2 h1:42jrcVZdjjxXtVsFNYTo/I6T1ZvIiQL+iDDLiH904hw=
12-github.com/bluekeyes/go-gitdiff v0.7.2/go.mod h1:QpfYYO1E0fTVHVZAZKiRjtSGY9823iCdvGXBcEzHGbM=
1311 github.com/bluekeyes/go-gitdiff v0.7.4-0.20240715034416-0a4e55f9a190 h1:k6Ep4yQtmsoP/St4bf7ofXyWc6ITB/FyGy9ewaAn5os=
1412 github.com/bluekeyes/go-gitdiff v0.7.4-0.20240715034416-0a4e55f9a190/go.mod h1:QpfYYO1E0fTVHVZAZKiRjtSGY9823iCdvGXBcEzHGbM=
1513 github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
......@@ -36,6 +34,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lV
3634 github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
3735 github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
3836 github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
37+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3938 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4039 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4140 github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
......@@ -74,8 +73,11 @@ github.com/knadh/koanf/providers/file v1.0.0 h1:DtPvSQBeF+N0QLPMz0yf2bx0nFSxUcnc
7473 github.com/knadh/koanf/providers/file v1.0.0/go.mod h1:/faSBcv2mxPVjFrXck95qeoyoZ5myJ6uxN8OOVNJJCI=
7574 github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM=
7675 github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es=
76+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
7777 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
7878 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
79+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
80+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
7981 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
8082 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
8183 github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
......@@ -107,6 +109,7 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo
107109 github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
108110 github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
109111 github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
112+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
110113 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
111114 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
112115 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
......@@ -119,6 +122,10 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN
119122 github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
120123 github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
121124 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
125+github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
126+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
127+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
128+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
122129 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
123130 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
124131 github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
......@@ -143,6 +150,10 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
143150 golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
144151 golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
145152 golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
153+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
154+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
155+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
156+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
146157 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
147158 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
148159 lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
+2 -2 pr.go #
......@@ -447,7 +447,7 @@ func (cmd PrCmd) SubmitPatchRequest(repoID string, userID int64, patchset io.Rea
447447 _ = tx.Rollback()
448448 }()
449449
450- patches, err := parsePatchset(patchset)
450+ patches, err := ParsePatchset(patchset)
451451 if err != nil {
452452 return nil, err
453453 }
......@@ -541,7 +541,7 @@ func (cmd PrCmd) SubmitPatchset(prID int64, userID int64, op PatchsetOp, patchse
541541 _ = tx.Rollback()
542542 }()
543543
544- patches, err := parsePatchset(patchset)
544+ patches, err := ParsePatchset(patchset)
545545 if err != nil {
546546 return fin, err
547547 }
+219 -0 range_diff.go #
......@@ -0,0 +1,219 @@
1+package git
2+
3+import (
4+ "fmt"
5+ "math"
6+
7+ "github.com/sergi/go-diff/diffmatchpatch"
8+)
9+
10+var COST_MAX = 65536
11+var RANGE_DIFF_CREATION_FACTOR_DEFAULT = 60
12+
13+type PatchRange struct {
14+ *Patch
15+ Matching int
16+ Diff string
17+ DiffSize int
18+ Shown bool
19+}
20+
21+func NewPatchRange(patch *Patch) *PatchRange {
22+ diff := patch.CalcDiff()
23+ return &PatchRange{
24+ Patch: patch,
25+ Matching: -1,
26+ Diff: diff,
27+ DiffSize: len(diff),
28+ Shown: false,
29+ }
30+}
31+
32+func output(a []*PatchRange, b []*PatchRange) string {
33+ out := ""
34+ for i, patchA := range a {
35+ if patchA.Matching == -1 {
36+ out += outputPairHeader(patchA, nil, i+1, -1)
37+ }
38+ }
39+
40+ for j, patchB := range b {
41+ if patchB.Matching == -1 {
42+ out += outputPairHeader(nil, patchB, -1, j+1)
43+ continue
44+ }
45+ patchA := a[patchB.Matching]
46+ if patchB.ContentSha == patchA.ContentSha {
47+ out += outputPairHeader(patchA, patchB, patchB.Matching+1, patchA.Matching+1)
48+ }
49+ }
50+ return out
51+}
52+
53+func outputPairHeader(a *PatchRange, b *PatchRange, aIndex, bIndex int) string {
54+ if a == nil {
55+ return fmt.Sprintf("-: ------- > %d: %s %s\n", bIndex, truncateSha(b.CommitSha), b.Title)
56+ }
57+ if b == nil {
58+ return fmt.Sprintf("%d: %s < -: ------- %s\n", aIndex, truncateSha(a.CommitSha), a.Title)
59+ }
60+ return fmt.Sprintf("%d: %s = %d: %s %s\n", aIndex, truncateSha(a.CommitSha), bIndex, truncateSha(b.CommitSha), a.Title)
61+}
62+
63+func RangeDiff(a []*Patch, b []*Patch) string {
64+ aPatches := []*PatchRange{}
65+ for _, patch := range a {
66+ aPatches = append(aPatches, NewPatchRange(patch))
67+ }
68+ bPatches := []*PatchRange{}
69+ for _, patch := range b {
70+ bPatches = append(bPatches, NewPatchRange(patch))
71+ }
72+ findExactMatches(aPatches, bPatches)
73+ getCorrespondences(aPatches, bPatches, RANGE_DIFF_CREATION_FACTOR_DEFAULT)
74+ return output(aPatches, bPatches)
75+}
76+
77+func findExactMatches(a []*PatchRange, b []*PatchRange) {
78+ for i, patchA := range a {
79+ for j, patchB := range b {
80+ if patchA.ContentSha == patchB.ContentSha {
81+ patchA.Matching = j
82+ patchB.Matching = i
83+ }
84+ }
85+ }
86+}
87+
88+func createMatrix(rows, cols int) [][]int {
89+ mat := make([][]int, rows)
90+ for i := range mat {
91+ mat[i] = make([]int, cols)
92+ }
93+ return mat
94+}
95+
96+func diffsize(a *PatchRange, b *PatchRange) int {
97+ dmp := diffmatchpatch.New()
98+ diffs := dmp.DiffMain(a.Diff, b.Diff, false)
99+ return len(dmp.DiffPrettyText(diffs))
100+}
101+
102+func getCorrespondences(a []*PatchRange, b []*PatchRange, creationFactor int) {
103+ n := len(a) + len(b)
104+ fmt.Println("rows", len(a), "cols", len(b))
105+ cost := createMatrix(n, n)
106+
107+ for i, patchA := range a {
108+ var c int
109+ for j, patchB := range b {
110+ if patchA.Matching == j {
111+ c = 0
112+ } else if patchA.Matching == -1 && patchB.Matching == -1 {
113+ c = diffsize(patchA, patchB)
114+ } else {
115+ c = COST_MAX
116+ }
117+ cost[i][j] = c
118+ }
119+ }
120+
121+ for j, patchB := range b {
122+ creationCost := (patchB.DiffSize * creationFactor) / 100
123+ if patchB.Matching >= 0 {
124+ creationCost = math.MaxInt32
125+ }
126+ for i := len(a); i < n; i++ {
127+ cost[i][j] = creationCost
128+ }
129+ }
130+
131+ for i := len(a); i < n; i++ {
132+ for j := len(b); j < n; j++ {
133+ cost[i][j] = 0
134+ }
135+ }
136+
137+ assignment := computeAssignment(cost, n, n)
138+ for i, j := range assignment {
139+ if i < len(a) && j < len(b) {
140+ a[i].Matching = j
141+ b[j].Matching = i
142+ }
143+ }
144+
145+ fmt.Println("cost", cost, "assignment", assignment)
146+}
147+
148+// computeAssignment assigns patches using the Hungarian algorithm.
149+func computeAssignment(costMatrix [][]int, m, n int) []int {
150+ u := make([]int, m+1) // potential for workers
151+ v := make([]int, n+1) // potential for jobs
152+ p := make([]int, n+1) // job assignment
153+ way := make([]int, n+1)
154+
155+ for i := 1; i <= m; i++ {
156+ links := make([]int, n+1)
157+ minV := make([]int, n+1)
158+ used := make([]bool, n+1)
159+ for j := 0; j <= n; j++ {
160+ minV[j] = math.MaxInt32
161+ used[j] = false
162+ }
163+
164+ j0 := 0
165+ p[0] = i
166+
167+ for {
168+ used[j0] = true
169+ i0 := p[j0]
170+ delta := math.MaxInt32
171+ j1 := 0
172+
173+ for j := 1; j <= n; j++ {
174+ if !used[j] {
175+ cur := costMatrix[i0-1][j-1] - u[i0] - v[j]
176+ if cur < minV[j] {
177+ minV[j] = cur
178+ links[j] = j0
179+ }
180+ if minV[j] < delta {
181+ delta = minV[j]
182+ j1 = j
183+ }
184+ }
185+ }
186+
187+ for j := 0; j <= n; j++ {
188+ if used[j] {
189+ u[p[j]] += delta
190+ v[j] -= delta
191+ } else {
192+ minV[j] -= delta
193+ }
194+ }
195+
196+ j0 = j1
197+ if p[j0] == 0 {
198+ break
199+ }
200+ }
201+
202+ for {
203+ j1 := way[j0]
204+ p[j0] = p[j1]
205+ j0 = j1
206+ if j0 == 0 {
207+ break
208+ }
209+ }
210+ }
211+
212+ assignment := make([]int, m)
213+ for j := 1; j <= n; j++ {
214+ if p[j] > 0 {
215+ assignment[p[j]-1] = j - 1
216+ }
217+ }
218+ return assignment
219+}
+276 -0 range_diff_test.go #
......@@ -0,0 +1,276 @@
1+package git
2+
3+import (
4+ "fmt"
5+ "testing"
6+
7+ "github.com/picosh/git-pr/fixtures"
8+)
9+
10+func bail(err error) {
11+ if err != nil {
12+ panic(bail)
13+ }
14+}
15+
16+func cmp(afile, bfile string) string {
17+ a, err := fixtures.Fixtures.Open(afile)
18+ bail(err)
19+ b, err := fixtures.Fixtures.Open(bfile)
20+ bail(err)
21+ aPatches, err := ParsePatchset(a)
22+ bail(err)
23+ bPatches, err := ParsePatchset(b)
24+ bail(err)
25+ actual := RangeDiff(aPatches, bPatches)
26+ return actual
27+}
28+
29+func fail(expected, actual string) string {
30+ return fmt.Sprintf("expected:[%s] actual:[%s]", expected, actual)
31+}
32+
33+// https://git.kernel.org/tree/t/t3206-range-diff.sh?id=d19b6cd2dd72dc811f19df4b32c7ed223256c3ee
34+
35+// simple A..B A..C (unmodified)
36+/*
37+ 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/
38+ 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/
39+ 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/
40+ 4: $(test_oid t4) = 4: $(test_oid u4) s/12/B/
41+*/
42+func TestRangeDiffUnmodified(t *testing.T) {
43+ actual := cmp("a_b.patch", "a_c.patch")
44+ expected := "1: 33c682a = 1: 1668484 chore: add torch and create random tensor\n"
45+ if expected != actual {
46+ t.Fatalf(fail(expected, actual))
47+ }
48+}
49+
50+// trivial reordering
51+/*
52+ 1: $(test_oid t1) = 1: $(test_oid r1) s/5/A/
53+ 3: $(test_oid t3) = 2: $(test_oid r2) s/11/B/
54+ 4: $(test_oid t4) = 3: $(test_oid r3) s/12/B/
55+ 2: $(test_oid t2) = 4: $(test_oid r4) s/4/A/
56+*/
57+func TestRangeDiffTrivialReordering(t *testing.T) {
58+ actual := cmp("a_b_reorder.patch", "a_c_reorder.patch")
59+ expected := `2: 22dde12 = 1: 7dbb94c docs: readme
60+1: 33c682a = 2: ad17587 chore: add torch and create random tensor
61+`
62+ if expected != actual {
63+ t.Fatalf(fail(expected, actual))
64+ }
65+}
66+
67+// removed commit
68+/*
69+ 1: $(test_oid t1) = 1: $(test_oid d1) s/5/A/
70+ 2: $(test_oid t2) < -: $(test_oid __) s/4/A/
71+ 3: $(test_oid t3) = 2: $(test_oid d2) s/11/B/
72+ 4: $(test_oid t4) = 3: $(test_oid d3) s/12/B/
73+*/
74+func TestRangeDiffRemovedCommit(t *testing.T) {
75+ actual := cmp("a_b_reorder.patch", "a_c_rm_commit.patch")
76+ expected := `1: 33c682a < -: ------- chore: add torch and create random tensor
77+2: 22dde12 = 1: 7dbb94c docs: readme
78+`
79+ if expected != actual {
80+ t.Fatalf(fail(expected, actual))
81+ }
82+}
83+
84+// added commit
85+/*
86+ 1: $(test_oid t1) = 1: $(test_oid a1) s/5/A/
87+ 2: $(test_oid t2) = 2: $(test_oid a2) s/4/A/
88+ -: $(test_oid __) > 3: $(test_oid a3) s/6/A/
89+ 3: $(test_oid t3) = 4: $(test_oid a4) s/11/B/
90+ 4: $(test_oid t4) = 5: $(test_oid a5) s/12/B/
91+*/
92+func TestRangeDiffAddedCommit(t *testing.T) {
93+ actual := cmp("a_b_reorder.patch", "a_c_added_commit.patch")
94+ expected := `1: 33c682a = 1: 33c682a chore: add torch and create random tensor
95+2: 22dde12 = 2: 22dde12 docs: readme
96+-: ------- > 3: b248060 chore: make tensor 6x6
97+`
98+ if expected != actual {
99+ t.Fatalf(fail(expected, actual))
100+ }
101+}
102+
103+// changed commit
104+/*
105+ 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/
106+ 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/
107+ 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/
108+ @@ file: A
109+ 9
110+ 10
111+ -11
112+ -+B
113+ ++BB
114+ 12
115+ 13
116+ 14
117+ 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/
118+ @@ file
119+ @@ file: A
120+ 9
121+ 10
122+ - B
123+ + BB
124+ -12
125+ +B
126+ 13
127+*/
128+func TestRangeDiffChangedCommit(t *testing.T) {
129+ actual := cmp("a_b_reorder.patch", "a_c_changed_commit.patch")
130+ fp, err := fixtures.Fixtures.ReadFile("expected_commit_changed.txt")
131+ if err != nil {
132+ t.Fatalf("file not found")
133+ }
134+ expected := string(fp)
135+ if expected != actual {
136+ t.Fatalf(fail(expected, actual))
137+ }
138+}
139+
140+// renamed file
141+/*
142+ 1: $(test_oid t1) = 1: $(test_oid n1) s/5/A/
143+ 2: $(test_oid t2) ! 2: $(test_oid n2) s/4/A/
144+ @@ Metadata
145+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
146+ Z
147+ Z ## Commit message ##
148+ - s/4/A/
149+ + s/4/A/ + rename file
150+ Z
151+ - ## file ##
152+ + ## file => renamed-file ##
153+ Z@@
154+ Z 1
155+ Z 2
156+ 3: $(test_oid t3) ! 3: $(test_oid n3) s/11/B/
157+ @@ Metadata
158+ Z ## Commit message ##
159+ Z s/11/B/
160+ Z
161+ - ## file ##
162+ -@@ file: A
163+ + ## renamed-file ##
164+ +@@ renamed-file: A
165+ Z 8
166+ Z 9
167+ Z 10
168+ 4: $(test_oid t4) ! 4: $(test_oid n4) s/12/B/
169+ @@ Metadata
170+ Z ## Commit message ##
171+ Z s/12/B/
172+ Z
173+ - ## file ##
174+ -@@ file: A
175+ + ## renamed-file ##
176+ +@@ renamed-file: A
177+ Z 9
178+ Z 10
179+ Z B
180+*/
181+// func TestRangeDiffRenamedFile(t *testing.T) {}
182+
183+// file with mode only change
184+/*
185+ 1: $(test_oid t2) ! 1: $(test_oid o1) s/4/A/
186+ @@ Metadata
187+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
188+ Z
189+ Z ## Commit message ##
190+ - s/4/A/
191+ + s/4/A/ + add other-file
192+ Z
193+ Z ## file ##
194+ Z@@
195+ @@ file
196+ Z A
197+ Z 6
198+ Z 7
199+ +
200+ + ## other-file (new) ##
201+ 2: $(test_oid t3) ! 2: $(test_oid o2) s/11/B/
202+ @@ Metadata
203+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
204+ Z
205+ Z ## Commit message ##
206+ - s/11/B/
207+ + s/11/B/ + mode change other-file
208+ Z
209+ Z ## file ##
210+ Z@@ file: A
211+ @@ file: A
212+ Z 12
213+ Z 13
214+ Z 14
215+ +
216+ + ## other-file (mode change 100644 => 100755) ##
217+ 3: $(test_oid t4) = 3: $(test_oid o3) s/12/B/
218+*/
219+// func TestRangeDiffFileWithModeOnlyChange(t *testing.T) {}
220+
221+// file added and later removed
222+/*
223+ 1: $(test_oid t1) = 1: $(test_oid s1) s/5/A/
224+ 2: $(test_oid t2) ! 2: $(test_oid s2) s/4/A/
225+ @@ Metadata
226+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
227+ Z
228+ Z ## Commit message ##
229+ - s/4/A/
230+ + s/4/A/ + new-file
231+ Z
232+ Z ## file ##
233+ Z@@
234+ @@ file
235+ Z A
236+ Z 6
237+ Z 7
238+ +
239+ + ## new-file (new) ##
240+ 3: $(test_oid t3) ! 3: $(test_oid s3) s/11/B/
241+ @@ Metadata
242+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
243+ Z
244+ Z ## Commit message ##
245+ - s/11/B/
246+ + s/11/B/ + remove file
247+ Z
248+ Z ## file ##
249+ Z@@ file: A
250+ @@ file: A
251+ Z 12
252+ Z 13
253+ Z 14
254+ +
255+ + ## new-file (deleted) ##
256+ 4: $(test_oid t4) = 4: $(test_oid s4) s/12/B/
257+*/
258+// func TestRangeDiffFileAddedThenRemoved(t *testing.T) {}
259+
260+// changed message
261+/*
262+ 1: $(test_oid t1) = 1: $(test_oid m1) s/5/A/
263+ 2: $(test_oid t2) ! 2: $(test_oid m2) s/4/A/
264+ @@ Metadata
265+ Z ## Commit message ##
266+ Z s/4/A/
267+ Z
268+ + Also a silly comment here!
269+ +
270+ Z ## file ##
271+ Z@@
272+ Z 1
273+ 3: $(test_oid t3) = 3: $(test_oid m3) s/11/B/
274+ 4: $(test_oid t4) = 4: $(test_oid m4) s/12/B/
275+*/
276+// func TestRangeDiffChangedMessage(t *testing.T) {}
+3 -3 util.go #
......@@ -109,7 +109,7 @@ func patchToDiff(patch io.Reader) (string, error) {
109109 return str[idx:], nil
110110 }
111111
112-func parsePatchset(patchset io.Reader) ([]*Patch, error) {
112+func ParsePatchset(patchset io.Reader) ([]*Patch, error) {
113113 patches := []*Patch{}
114114 buf := new(strings.Builder)
115115 _, err := io.Copy(buf, patchset)
......@@ -154,6 +154,7 @@ func parsePatchset(patchset io.Reader) ([]*Patch, error) {
154154 ContentSha: contentSha,
155155 RawText: patchStr,
156156 BaseCommitSha: sql.NullString{String: baseCommit},
157+ Files: diffFiles,
157158 })
158159 }
159160
......@@ -172,12 +173,11 @@ func calcContentSha(diffFiles []*gitdiff.File, header *gitdiff.PatchHeader) stri
172173 authorEmail = header.Author.Email
173174 }
174175 content := fmt.Sprintf(
175- "%s\n%s\n%s\n%s\n%s\n",
176+ "%s\n%s\n%s\n%s\n",
176177 header.Title,
177178 header.Body,
178179 authorName,
179180 authorEmail,
180- header.AuthorDate,
181181 )
182182 for _, diff := range diffFiles {
183183 // we need to ignore diffs with base commit because that depends
+1 -1 util_test.go #
......@@ -15,7 +15,7 @@ func TestParsePatchsetWithCover(t *testing.T) {
1515 if err != nil {
1616 t.Fatalf(err.Error())
1717 }
18- actual, err := parsePatchset(file)
18+ actual, err := ParsePatchset(file)
1919 if err != nil {
2020 t.Fatalf(err.Error())
2121 }
Back to top