this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improve fragment validation, track context lines

Track leading and trailing context lines because it's easy and Git
includes this information in the fragment type. Add validation for when
the fragment does not agree with the header or with the new/deleted
state of the file.

+37 -3
+3
gitdiff/gitdiff.go
··· 39 39 LinesAdded int64 40 40 LinesDeleted int64 41 41 42 + LeadingContext int64 43 + TrailingContext int64 44 + 42 45 Lines []FragmentLine 43 46 } 44 47
+34 -3
gitdiff/parser.go
··· 107 107 // ParseFragments parses fragments until the next file header or the end of the 108 108 // stream and attaches them to the given file. 109 109 func (p *parser) ParseFragments(f *File) error { 110 - panic("TODO(bkeyes): unimplemented") 110 + for { 111 + frag, err := p.ParseFragment() 112 + if err != nil { 113 + return err 114 + } 115 + if frag == nil { 116 + // TODO(bkeyes): this could mean several things: 117 + // - binary patch 118 + // - reached the next file header 119 + // - reached the end of the patch 120 + return nil 121 + } 122 + 123 + lines := int64(len(frag.Lines) + 1) // +1 for the header 124 + if f.IsNew && frag.OldLines > 0 { 125 + return p.Errorf(-lines, "new file depends on old contents") 126 + } 127 + if f.IsDelete && frag.NewLines > 0 { 128 + return p.Errorf(-lines, "deleted file still has contents") 129 + } 130 + 131 + f.Fragments = append(f.Fragments, frag) 132 + } 111 133 } 112 134 113 135 // Next advances the parser by one line. It returns any error encountered while ··· 211 233 } 212 234 213 235 oldLines, newLines := frag.OldLines, frag.NewLines 214 - for oldLines > 0 && newLines > 0 { 236 + for oldLines > 0 || newLines > 0 { 215 237 line := p.Line(0) 216 238 switch line[0] { 217 239 case '\n': ··· 219 241 case ' ': 220 242 oldLines-- 221 243 newLines-- 244 + if frag.LinesAdded == 0 && frag.LinesDeleted == 0 { 245 + frag.LeadingContext++ 246 + } else { 247 + frag.TrailingContext++ 248 + } 222 249 frag.Lines = append(frag.Lines, FragmentLine{OpContext, line[1:]}) 223 250 case '-': 224 251 frag.LinesDeleted++ 225 252 oldLines-- 253 + frag.TrailingContext = 0 226 254 frag.Lines = append(frag.Lines, FragmentLine{OpDelete, line[1:]}) 227 255 case '+': 228 256 frag.LinesAdded++ 229 257 newLines-- 258 + frag.TrailingContext = 0 230 259 frag.Lines = append(frag.Lines, FragmentLine{OpAdd, line[1:]}) 231 260 default: 232 261 // this could be "\ No newline at end of file", which we allow ··· 246 275 } 247 276 } 248 277 249 - // TODO(bkeyes): verify stuff about the fragment 278 + if oldLines != 0 || newLines != 0 { 279 + return nil, p.Errorf(0, "invalid fragment: remaining lines: %d old, %d new", oldLines, newLines) 280 + } 250 281 251 282 return frag, nil 252 283 }