Add HunkHeader to represent a single hunk of a file within a patch
[egit/charleso.git] / org.spearce.jgit / src / org / spearce / jgit / patch / HunkHeader.java
blobfc606c310713a77534700bd2811571e292768e46
1 /*
2 * Copyright (C) 2008, Google Inc.
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
8 * conditions are met:
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org.spearce.jgit.patch;
40 import static org.spearce.jgit.util.RawParseUtils.match;
41 import static org.spearce.jgit.util.RawParseUtils.nextLF;
42 import static org.spearce.jgit.util.RawParseUtils.parseBase10;
44 import org.spearce.jgit.util.MutableInteger;
46 /** Hunk header describing the layout of a single block of lines */
47 public class HunkHeader {
48 private final FileHeader file;
50 /** Offset within {@link #file}.buf to the "@@ -" line. */
51 final int startOffset;
53 /** Position 1 past the end of this hunk within {@link #file}'s buf. */
54 int endOffset;
56 /** First line number in the pre-image file where the hunk starts */
57 int oldStartLine;
59 /** Total number of pre-image lines this hunk covers (context + deleted) */
60 int oldLineCount;
62 /** First line number in the post-image file where the hunk starts */
63 int newStartLine;
65 /** Total number of post-image lines this hunk covers (context + inserted) */
66 int newLineCount;
68 /** Total number of lines of context appearing in this hunk */
69 int nContext;
71 /** Number of lines removed by this hunk */
72 int nDeleted;
74 /** Number of lines added by this hunk */
75 int nAdded;
77 HunkHeader(final FileHeader fh, final int offset) {
78 file = fh;
79 startOffset = offset;
82 /** @return header for the file this hunk applies to */
83 public FileHeader getFileHeader() {
84 return file;
87 /** @return first line number in the pre-image file where the hunk starts */
88 public int getOldStartLine() {
89 return oldStartLine;
92 /** @return total number of pre-image lines this hunk covers */
93 public int getOldLineCount() {
94 return oldLineCount;
97 /** @return first line number in the post-image file where the hunk starts */
98 public int getNewStartLine() {
99 return newStartLine;
102 /** @return Total number of post-image lines this hunk covers */
103 public int getNewLineCount() {
104 return newLineCount;
107 /** @return total number of lines of context appearing in this hunk */
108 public int getLinesContext() {
109 return nContext;
112 /** @return number of lines removed by this hunk */
113 public int getLinesDeleted() {
114 return nDeleted;
117 /** @return number of lines added by this hunk */
118 public int getLinesAdded() {
119 return nAdded;
122 void parseHeader() {
123 // Parse "@@ -236,9 +236,9 @@ protected boolean"
125 final byte[] buf = file.buf;
126 final MutableInteger ptr = new MutableInteger();
127 ptr.value = nextLF(buf, startOffset, ' ');
128 oldStartLine = -parseBase10(buf, ptr.value, ptr);
129 oldLineCount = parseBase10(buf, ptr.value + 1, ptr);
131 newStartLine = parseBase10(buf, ptr.value + 1, ptr);
132 newLineCount = parseBase10(buf, ptr.value + 1, ptr);
135 int parseBody() {
136 final byte[] buf = file.buf;
137 final int sz = buf.length;
138 int c = nextLF(buf, startOffset), last = c;
140 nDeleted = 0;
141 nAdded = 0;
143 SCAN: for (; c < sz; last = c, c = nextLF(buf, c)) {
144 switch (buf[c]) {
145 case ' ':
146 case '\n':
147 nContext++;
148 continue;
150 case '-':
151 nDeleted++;
152 continue;
154 case '+':
155 nAdded++;
156 continue;
158 case '\\': // Matches "\ No newline at end of file"
159 continue;
161 default:
162 break SCAN;
166 if (last < sz && nContext + nDeleted - 1 == oldLineCount
167 && nContext + nAdded == newLineCount
168 && match(buf, last, Patch.SIG_FOOTER) >= 0) {
169 // This is an extremely common occurrence of "corruption".
170 // Users add footers with their signatures after this mark,
171 // and git diff adds the git executable version number.
172 // Let it slide; the hunk otherwise looked sound.
174 nDeleted--;
175 return last;
178 if (nContext + nDeleted != oldLineCount
179 || nContext + nAdded != newLineCount) {
180 // TODO report on truncated hunk
183 return c;