| 108 | } |
| 109 | |
| 110 | func (p *parser) ParseTraditionalFileHeader() (*File, error) { |
| 111 | const shortestValidFragHeader = "@@ -1 +1 @@\n" |
| 112 | const ( |
| 113 | oldPrefix = "--- " |
| 114 | newPrefix = "+++ " |
| 115 | ) |
| 116 | |
| 117 | oldLine, newLine := p.Line(0), p.Line(1) |
| 118 | |
| 119 | if !strings.HasPrefix(oldLine, oldPrefix) || !strings.HasPrefix(newLine, newPrefix) { |
| 120 | return nil, nil |
| 121 | } |
| 122 | // heuristic: only a file header if followed by a (probable) fragment header |
| 123 | if len(p.Line(2)) < len(shortestValidFragHeader) || !strings.HasPrefix(p.Line(2), "@@ -") { |
| 124 | return nil, nil |
| 125 | } |
| 126 | |
| 127 | // advance past the first two lines so parser is after the header |
| 128 | // no EOF check needed because we know there are >=3 valid lines |
| 129 | if err := p.Next(); err != nil { |
| 130 | return nil, err |
| 131 | } |
| 132 | if err := p.Next(); err != nil { |
| 133 | return nil, err |
| 134 | } |
| 135 | |
| 136 | oldName, _, err := parseName(oldLine[len(oldPrefix):], '\t', 0) |
| 137 | if err != nil { |
| 138 | return nil, p.Errorf(0, "file header: %v", err) |
| 139 | } |
| 140 | |
| 141 | newName, _, err := parseName(newLine[len(newPrefix):], '\t', 0) |
| 142 | if err != nil { |
| 143 | return nil, p.Errorf(1, "file header: %v", err) |
| 144 | } |
| 145 | |
| 146 | f := &File{} |
| 147 | switch { |
| 148 | case oldName == devNull || hasEpochTimestamp(oldLine): |
| 149 | f.IsNew = true |
| 150 | f.NewName = newName |
| 151 | case newName == devNull || hasEpochTimestamp(newLine): |
| 152 | f.IsDelete = true |
| 153 | f.OldName = oldName |
| 154 | default: |
| 155 | // if old name is a prefix of new name, use that instead |
| 156 | // this avoids picking variants like "file.bak" or "file~" |
| 157 | if strings.HasPrefix(newName, oldName) { |
| 158 | f.OldName = oldName |
| 159 | f.NewName = oldName |
| 160 | } else { |
| 161 | f.OldName = newName |
| 162 | f.NewName = newName |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | return f, nil |
| 167 | } |