summaryrefslogtreecommitdiff
path: root/apply.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-23 21:38:49 (GMT)
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-23 21:38:49 (GMT)
commit46979f567bde4c299fa18fdc72180361511b0057 (patch)
tree5b1d74e7804455c6b34a972cf2a49c1a2fec6000 /apply.c
parent5e224a2ed01facb1233474dd169307f499e70257 (diff)
downloadgit-46979f567bde4c299fa18fdc72180361511b0057.zip
git-46979f567bde4c299fa18fdc72180361511b0057.tar.gz
git-46979f567bde4c299fa18fdc72180361511b0057.tar.bz2
git-apply: improve error detection and messages
In particular, give line numbers when detecting corrupt patches. This makes the tool a lot more friendly (indeed, much more so than regular "patch", I think).
Diffstat (limited to 'apply.c')
-rw-r--r--apply.c116
1 files changed, 74 insertions, 42 deletions
diff --git a/apply.c b/apply.c
index 536b068..05f921a 100644
--- a/apply.c
+++ b/apply.c
@@ -21,6 +21,8 @@
static int merge_patch = 1;
static const char apply_usage[] = "git-apply <patch>";
+static int linenr = 1;
+
#define CHUNKSIZE (8192)
static void *read_patch_file(int fd, unsigned long *sizep)
@@ -77,7 +79,7 @@ static int parse_git_header(char *line, unsigned int size)
{
unsigned long offset, len;
- for (offset = 0 ; size > 0 ; offset += len, size -= len, line += len) {
+ for (offset = 0 ; size > 0 ; offset += len, size -= len, line += len, linenr++) {
len = linelen(line, size);
if (!len)
break;
@@ -104,11 +106,60 @@ static int parse_git_header(char *line, unsigned int size)
return offset ? :-1;
}
+static int parse_num(const char *line, int len, int offset, const char *expect, unsigned long *p)
+{
+ char *ptr;
+ int digits, ex;
+
+ if (offset < 0 || offset >= len)
+ return -1;
+ line += offset;
+ len -= offset;
+
+ if (!isdigit(*line))
+ return -1;
+ *p = strtoul(line, &ptr, 10);
+
+ digits = ptr - line;
+
+ offset += digits;
+ line += digits;
+ len -= digits;
+
+ ex = strlen(expect);
+ if (ex > len)
+ return -1;
+ if (memcmp(line, expect, ex))
+ return -1;
+
+ return offset + ex;
+}
+
+/*
+ * Parse a unified diff fragment header of the
+ * form "@@ -a,b +c,d @@"
+ */
+static int parse_fragment_header(char *line, int len, unsigned long *pos)
+{
+ int offset;
+
+ if (!len || line[len-1] != '\n')
+ return -1;
+
+ /* Figure out the number of lines in a fragment */
+ offset = parse_num(line, len, 4, ",", pos);
+ offset = parse_num(line, len, offset, " +", pos+1);
+ offset = parse_num(line, len, offset, ",", pos+2);
+ offset = parse_num(line, len, offset, " @@", pos+3);
+
+ return offset;
+}
+
static int find_header(char *line, unsigned long size, int *hdrsize)
{
unsigned long offset, len;
- for (offset = 0; size > 0; offset += len, size -= len, line += len) {
+ for (offset = 0; size > 0; offset += len, size -= len, line += len, linenr++) {
unsigned long nextlen;
len = linelen(line, size);
@@ -118,6 +169,19 @@ static int find_header(char *line, unsigned long size, int *hdrsize)
/* Testing this early allows us to take a few shortcuts.. */
if (len < 6)
continue;
+
+ /*
+ * Make sure we don't find any unconnected patch fragmants.
+ * That's a sign that we didn't find a header, and that a
+ * patch has become corrupted/broken up.
+ */
+ if (!memcmp("@@ -", line, 4)) {
+ unsigned long pos[4];
+ if (parse_fragment_header(line, len, pos) < 0)
+ continue;
+ error("patch fragment without header at line %d: %.*s", linenr, len-1, line);
+ }
+
if (size < len + 6)
break;
@@ -149,40 +213,12 @@ static int find_header(char *line, unsigned long size, int *hdrsize)
/* Ok, we'll consider it a patch */
*hdrsize = len + nextlen;
+ linenr += 2;
return offset;
}
return -1;
}
-static int parse_num(const char *line, int len, int offset, const char *expect, unsigned long *p)
-{
- char *ptr;
- int digits, ex;
-
- if (offset < 0 || offset >= len)
- return -1;
- line += offset;
- len -= offset;
-
- if (!isdigit(*line))
- return -1;
- *p = strtoul(line, &ptr, 10);
-
- digits = ptr - line;
-
- offset += digits;
- line += digits;
- len -= digits;
-
- ex = strlen(expect);
- if (ex > len)
- return -1;
- if (memcmp(line, expect, ex))
- return -1;
-
- return offset + ex;
-}
-
/*
* Parse a unified diff. Note that this really needs
* to parse each fragment separately, since the only
@@ -193,23 +229,19 @@ static int parse_num(const char *line, int len, int offset, const char *expect,
static int apply_fragment(char *line, unsigned long size)
{
int len = linelen(line, size), offset;
- unsigned long oldpos, oldlines, newpos, newlines;
+ unsigned long pos[4], oldlines, newlines;
- if (!len || line[len-1] != '\n')
- return -1;
-
- /* Figure out the number of lines in a fragment */
- offset = parse_num(line, len, 4, ",", &oldpos);
- offset = parse_num(line, len, offset, " +", &oldlines);
- offset = parse_num(line, len, offset, ",", &newpos);
- offset = parse_num(line, len, offset, " @@", &newlines);
+ offset = parse_fragment_header(line, len, pos);
if (offset < 0)
return -1;
+ oldlines = pos[1];
+ newlines = pos[3];
/* Parse the thing.. */
line += len;
size -= len;
- for (offset = len; size > 0; offset += len, size -= len, line += len) {
+ linenr++;
+ for (offset = len; size > 0; offset += len, size -= len, line += len, linenr++) {
if (!oldlines && !newlines)
break;
len = linelen(line, size);
@@ -240,7 +272,7 @@ static int apply_single_patch(char *line, unsigned long size)
while (size > 4 && !memcmp(line, "@@ -", 4)) {
int len = apply_fragment(line, size);
if (len <= 0)
- die("corrupt patch");
+ die("corrupt patch at line %d", linenr);
printf("applying fragment:\n%.*s\n\n", len, line);