Select the types of activity you want to include in your feed.
Return preamble content when parsing files
This allows callers to provide patches with commit or email headers and then retrieve that leading content for additional parsing without having to identify where the first file in the patch starts.
···88 "strings"
99)
10101111-// Parse parses a patch with changes for one or more files. Any content
1212-// preceding the first file header is ignored. If an error occurs while
1313-// parsing, files will contain all files parsed before the error.
1414-func Parse(r io.Reader) ([]*File, error) {
1111+// Parse parses a patch with changes to one or more files. Any content before
1212+// the first file is returned as the second value. If an error occurs while
1313+// parsing, it returns all files parsed before the error.
1414+func Parse(r io.Reader) ([]*File, string, error) {
1515 p := &parser{r: bufio.NewReader(r)}
1616 if err := p.Next(); err != nil {
1717 if err == io.EOF {
1818- return nil, nil
1818+ return nil, "", nil
1919 }
2020- return nil, err
2020+ return nil, "", err
2121 }
22222323- // TODO(bkeyes): capture non-file lines in between files
2424-2323+ var preamble string
2524 var files []*File
2625 for {
2727- file, err := p.ParseNextFileHeader()
2626+ file, pre, err := p.ParseNextFileHeader()
2827 if err != nil {
2929- return files, err
2828+ return files, preamble, err
3029 }
3130 if file == nil {
3231 break
···3837 } {
3938 n, err := fn(file)
4039 if err != nil {
4141- return files, err
4040+ return files, preamble, err
4241 }
4342 if n > 0 {
4443 break
4544 }
4645 }
4747- // file has fragment(s) from above or the patch is empty or invalid
4646+4747+ if len(files) == 0 {
4848+ preamble = pre
4949+ }
4850 files = append(files, file)
4951 }
50525151- return files, nil
5353+ return files, preamble, nil
5254}
53555456// TODO(bkeyes): consider exporting the parser type with configuration
···7173 lines [3]string
7274}
73757474-// ParseNextFileHeader finds and parses the next file header in the stream. It
7575-// returns nil if no headers are found before the end of the stream.
7676-func (p *parser) ParseNextFileHeader() (*File, error) {
7676+// ParseNextFileHeader finds and parses the next file header in the stream. If
7777+// a header is found, it returns a file and all input before the header. It
7878+// returns nil if no headers are found before the end of the input.
7979+func (p *parser) ParseNextFileHeader() (*File, string, error) {
8080+ var preamble strings.Builder
7781 var file *File
7882 for {
7983 // check for disconnected fragment headers (corrupt patch)
···8387 goto NextLine
8488 }
8589 if frag != nil {
8686- return nil, p.Errorf(-1, "patch fragment without file header: %s", frag.Header())
9090+ return nil, "", p.Errorf(-1, "patch fragment without file header: %s", frag.Header())
8791 }
88928993 // check for a git-generated patch
9094 file, err = p.ParseGitFileHeader()
9195 if err != nil {
9292- return nil, err
9696+ return nil, "", err
9397 }
9498 if file != nil {
9595- return file, nil
9999+ return file, preamble.String(), nil
96100 }
9710198102 // check for a "traditional" patch
99103 file, err = p.ParseTraditionalFileHeader()
100104 if err != nil {
101101- return nil, err
105105+ return nil, "", err
102106 }
103107 if file != nil {
104104- return file, nil
108108+ return file, preamble.String(), nil
105109 }
106110107111 NextLine:
112112+ preamble.WriteString(p.Line(0))
108113 if err := p.Next(); err != nil {
109114 if err == io.EOF {
110115 break
111116 }
112112- return nil, err
117117+ return nil, "", err
113118 }
114119 }
115115- return nil, nil
120120+ return nil, "", nil
116121}
117122118123// ParseTextFragments parses text fragments until the next file header or the
···22Author: Morton Haypenny <mhaypenny@example.com>
33Date: Tue Apr 2 22:55:40 2019 -0700
4455- A single file with multiple fragments.
55+ A file with multiple fragments.
6677 The content is arbitrary.
88