@@ -7,8 +7,109 @@ import (
7
7
"bufio"
8
8
"fmt"
9
9
"io"
10
+ "strings"
10
11
)
11
12
13
+ type Commit struct {
14
+ CommitSha string
15
+ Content string
16
+ }
17
+
18
+ func EmitCommit (content string ) (Commit , bool ) {
19
+ tokens := strings .Split (content , " " )
20
+ if len (tokens ) < 2 {
21
+ return Commit {}, false
22
+ }
23
+ return Commit {
24
+ CommitSha : tokens [1 ],
25
+ Content : content ,
26
+ }, true
27
+ }
28
+
29
+ func (c Commit ) Equal (rhs Commit ) bool {
30
+ return c .CommitSha == rhs .CommitSha
31
+ }
32
+
33
+
34
+ type Patches struct {
35
+ FilesToSha map [* File ]string
36
+ ShaToFiles map [string ][]* File
37
+ ShaToCommit map [string ]Commit
38
+ }
39
+
40
+ func (p * Patches ) AppendFile (cmt Commit , file * File ) {
41
+ p .FilesToSha [file ] = cmt .CommitSha
42
+ p .ShaToFiles [cmt .CommitSha ] = append (p .ShaToFiles [cmt .CommitSha ], file )
43
+ p .ShaToCommit [cmt .CommitSha ] = cmt
44
+ }
45
+
46
+ func (p * Patches ) GetFiles (sha string ) ([]* File , bool ) {
47
+ files , ok := p .ShaToFiles [sha ]
48
+ return files , ok
49
+ }
50
+
51
+ func (p * Patches ) GetCommit (file * File ) (Commit , bool ) {
52
+ sha , ok := p .FilesToSha [file ]
53
+ if ! ok {
54
+ return Commit {}, false
55
+ }
56
+ cmt , ok := p .ShaToCommit [sha ]
57
+ if ! ok {
58
+ return Commit {}, false
59
+ }
60
+ return cmt , ok
61
+ }
62
+
63
+ func ParsePatch (r io.Reader ) ([]* File , * Patches , error ) {
64
+ p := newParser (r )
65
+ patches := & Patches {
66
+ FilesToSha : make (map [* File ]string ),
67
+ ShaToFiles : make (map [string ][]* File ),
68
+ ShaToCommit : make (map [string ]Commit ),
69
+ }
70
+ if err := p .Next (); err != nil {
71
+ if err == io .EOF {
72
+ return nil , patches , nil
73
+ }
74
+ return nil , patches , err
75
+ }
76
+
77
+ var files []* File
78
+ lastCommit := Commit {}
79
+ for {
80
+ file , pre , err := p .ParseNextFileHeader ()
81
+ if err != nil {
82
+ return files , patches , err
83
+ }
84
+ if file == nil {
85
+ break
86
+ }
87
+
88
+ for _ , fn := range []func (* File ) (int , error ){
89
+ p .ParseTextFragments ,
90
+ p .ParseBinaryFragments ,
91
+ } {
92
+ n , err := fn (file )
93
+ if err != nil {
94
+ return files , patches , err
95
+ }
96
+ if n > 0 {
97
+ break
98
+ }
99
+ }
100
+
101
+ files = append (files , file )
102
+ if cmt , ok := EmitCommit (pre ); ok {
103
+ patches .AppendFile (cmt , file )
104
+ lastCommit = cmt
105
+ } else {
106
+ patches .AppendFile (lastCommit , file )
107
+ }
108
+ }
109
+
110
+ return files , patches , nil
111
+ }
112
+
12
113
// Parse parses a patch with changes to one or more files. Any content before
13
114
// the first file is returned as the second value. If an error occurs while
14
115
// parsing, it returns all files parsed before the error.
0 commit comments