From d55acb518764c11504b9d9ebaa41a19e5e85578a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 21 Aug 2013 11:40:59 +1000 Subject: [PATCH] Preserve per-hunk "comment" field. Each diff/patch hunk can have a comment, often a function name extract with "diff -p". Preserver that comment and display it when we print hunk headers, particularly in the browser. Signed-off-by: NeilBrown --- Makefile | 2 +- extract.c | 29 ++++++++++++++++++++++++----- split.c | 7 ++++--- tests/linux/inode-fullpatch/diff | 12 ++++++------ tests/linux/inode-fullpatch/rediff | 12 ++++++------ vpatch.c | 4 ++-- wiggle.c | 4 ++-- wiggle.h | 12 +++++++----- 8 files changed, 52 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index 850d681..c64c804 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,6 @@ v : version cat version demo.patch: force - diff -ru demo.orig demo.patched | sed 's/demo.patched/demo/' > demo.patch + diff -rup demo.orig demo.patched | sed 's/demo.patched/demo/' > demo.patch force: diff --git a/extract.c b/extract.c index 940de27..f469685 100644 --- a/extract.c +++ b/extract.c @@ -67,12 +67,14 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2) int a, b, c, d; int lineno = 0; char before[100], after[100]; + char func[100]; f1->body = f2->body = NULL; r1.body = xmalloc(f.len); r2.body = xmalloc(f.len); r1.len = r2.len = 0; + func[0] = 0; cp = f.body; end = f.body+f.len; @@ -86,7 +88,7 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2) lineno++; switch (state) { case 0: - if (sscanf(cp, "@@ -%s +%s @@", before, after) == 2) { + if (sscanf(cp, "@@ -%99s +%99s @@%99[^\n]", before, after, func) >= 2) { int ok = 1; if (sscanf(before, "%d,%d", &a, &b) == 2) acnt = b; @@ -111,15 +113,28 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2) } else if (sscanf(cp, "--- %d,%d ----", &c, &d) == 2) { bcnt = d-c+1; state = 2; - } + } else + sscanf(cp, "***************%99[^\n]", func); + skip_eol(&cp, end); if (state == 1 || state == 3) { + char *f; char buf[20]; buf[0] = 0; chunks++; - sprintf(buf+1, "%5d %5d %5d\n", chunks, a, acnt); - memcpy(r1.body+r1.len, buf, 20); - r1.len += 20; + sprintf(buf+1, "%5d %5d %5d", chunks, a, acnt); + memcpy(r1.body+r1.len, buf, 18); + r1.len += 18; + f = func; + while (*f == ' ') + f++; + if (*f) { + r1.body[r1.len++] = ' '; + strcpy(r1.body + r1.len, f); + r1.len += strlen(f); + } + r1.body[r1.len++] = '\n'; + r1.body[r1.len++] = '\0'; } if (state == 2 || state == 3) { char buf[20]; @@ -128,6 +143,8 @@ int split_patch(struct stream f, struct stream *f1, struct stream *f2) memcpy(r2.body+r2.len, buf, 20); r2.len += 20; } + if (state) + func[0] = 0; break; case 1: if ((*cp == ' ' || *cp == '!' || *cp == '-' || *cp == '+') @@ -316,6 +333,8 @@ int split_merge(struct stream f, struct stream *f1, struct stream *f2, struct st break; } } + if (cp > end) + abort(); *f1 = r1; *f2 = r2; *f3 = r3; diff --git a/split.c b/split.c index ba2cb26..7bc68a1 100644 --- a/split.c +++ b/split.c @@ -33,7 +33,7 @@ * A line is any string that ends with \n * * As a special case to allow proper aligning of multiple chunks - * in a patch, a word starting \0 will include 20 chars with a newline + * in a patch, a word starting \0 will include 20+ chars with a newline * second from the end. * * We make two passes through the stream. @@ -67,9 +67,10 @@ static int split_internal(char *start, char *end, int type, } start = cp; - if (*cp == '\0' && cp+19 < end && cp[18] == '\n') { + if (*cp == '\0' && cp+19 < end) { /* special word */ - cp += 20; + cp += 19; + cp += strlen(cp) + 1; } else switch (type & ByMask) { case ByLine: diff --git a/tests/linux/inode-fullpatch/diff b/tests/linux/inode-fullpatch/diff index d2a8b0d..f02bccf 100644 --- a/tests/linux/inode-fullpatch/diff +++ b/tests/linux/inode-fullpatch/diff @@ -469,7 +469,7 @@ - if (gfp_mask & __GFP_FS) - prune_icache(nr); - } -+*** 470,6 **** 1 ++*** 470,6 **** 1 static int shrink_icache_memory(int nr, | return inodes_stat.<<<--nr_unused-->>><<<++nr_inodes++>>>; } @@ -488,7 +488,7 @@ - prefetch(node->next); - inode = hlist_entry(node, struct inode, i_hash); - if (inode->i_sb != sb) -+*** 492,6 **** 2 ++*** 492,6 **** 2 static struct inode * find_inode(struct continue; if (!test(inode, data)) continue; @@ -510,7 +510,7 @@ - prefetch(node->next); - inode = list_entry(node, struct inode, i_hash); - if (inode->i_ino != ino) -+*** 517,6 **** 3 ++*** 517,6 **** 3 static struct inode * find_inode_fast(st continue; if (inode->i_sb != sb) continue; @@ -943,7 +943,7 @@ -} - -void generic_delete_inode(struct inode *inode) -+*** 949,7 **** 4 ++*** 949,7 **** 4 void generic_delete_inode(struct inode * { struct super_operations *op = inode->i_sb->s_op; @@ -963,7 +963,7 @@ - if (!is_bad_inode(inode)) - DQUOT_INIT(inode); - /* s_op->delete_inode internally recalls clear_inode() */ -+*** 968,6 **** 5 ++*** 968,6 **** 5 void generic_delete_inode(struct inode * delete(inode); } else clear_inode(inode); @@ -1237,7 +1237,7 @@ - goto repeat; - } - remove_wait_queue(wq, &wait); -|<<<-- __set_current_state(-->>><<<++*** 1219,6 **** 6 +|<<<-- __set_current_state(-->>><<<++*** 1219,6 **** 6 repeat: | current->state = ++>>>TASK_RUNNING<<<--)-->>>; } diff --git a/tests/linux/inode-fullpatch/rediff b/tests/linux/inode-fullpatch/rediff index ea080cf..d3ce126 100644 --- a/tests/linux/inode-fullpatch/rediff +++ b/tests/linux/inode-fullpatch/rediff @@ -1,4 +1,4 @@ -@@ -470,6 +470,7 @@ +@@ -470,6 +470,7 @@ static int shrink_icache_memory(int nr, return inodes_stat.nr_inodes; } @@ -6,7 +6,7 @@ /* * Called with the inode lock held. * NOTE: we are not increasing the inode-refcount, you must call __iget() -@@ -492,6 +493,11 @@ +@@ -492,6 +493,11 @@ static struct inode * find_inode(struct continue; if (!test(inode, data)) continue; @@ -18,7 +18,7 @@ break; } return inode; -@@ -517,6 +523,11 @@ +@@ -517,6 +523,11 @@ static struct inode * find_inode_fast(st continue; if (inode->i_sb != sb) continue; @@ -30,7 +30,7 @@ break; } return inode; -@@ -949,7 +960,6 @@ +@@ -949,7 +960,6 @@ void generic_delete_inode(struct inode * { struct super_operations *op = inode->i_sb->s_op; @@ -38,7 +38,7 @@ list_del_init(&inode->i_list); inode->i_state|=I_FREEING; inodes_stat.nr_inodes--; -@@ -968,6 +978,10 @@ +@@ -968,6 +978,10 @@ void generic_delete_inode(struct inode * delete(inode); } else clear_inode(inode); @@ -49,7 +49,7 @@ if (inode->i_state != I_CLEAR) BUG(); destroy_inode(inode); -@@ -1219,6 +1233,21 @@ +@@ -1219,6 +1233,21 @@ repeat: current->state = TASK_RUNNING; } diff --git a/vpatch.c b/vpatch.c index 1c1f52a..5082f0e 100644 --- a/vpatch.c +++ b/vpatch.c @@ -1039,14 +1039,14 @@ static void draw_mside(int mode, int row, int offset, int start, int cols, if (col < start) col = start; if (e.start && e.start[0] == 0) { - char b[40]; + char b[100]; struct elmnt e1; if (pos.p.s == 2 && m[pos.p.m].type == Extraneous) { int A, B, C, D, E, F; e1 = fb.list[m[pos.p.m].b + pos.p.o]; sscanf(e1.start+1, "%d %d %d", &A, &B, &C); sscanf(e.start+1, "%d %d %d", &D, &E, &F); - sprintf(b, "@@ -%d,%d +%d,%d @@\n", B, C, E, F); + snprintf(b, sizeof(b), "@@ -%d,%d +%d,%d @@%s", B, C, E, F, e1.start+18); (void)attrset(a_sep); } else { (void)attrset(visible(mode, m, &pos)); diff --git a/wiggle.c b/wiggle.c index ad89929..a9e9e0d 100644 --- a/wiggle.c +++ b/wiggle.c @@ -132,7 +132,7 @@ void printword(FILE *f, struct elmnt e) else { int a, b, c; sscanf(e.start+1, "%d %d %d", &a, &b, &c); - fprintf(f, "*** %d,%d **** %d\n", b, c, a); + fprintf(f, "*** %d,%d **** %d%s", b, c, a, e.start+18); } } @@ -141,7 +141,7 @@ static void printsep(struct elmnt e1, struct elmnt e2) int a, b, c, d, e, f; sscanf(e1.start+1, "%d %d %d", &a, &b, &c); sscanf(e2.start+1, "%d %d %d", &d, &e, &f); - printf("@@ -%d,%d +%d,%d @@\n", b, c, e, f); + printf("@@ -%d,%d +%d,%d @@%s", b, c, e, f, e1.start+18); } static int extract(int argc, char *argv[], int ispatch, int which) diff --git a/wiggle.h b/wiggle.h index 87f4c4d..2e9fb50 100644 --- a/wiggle.h +++ b/wiggle.h @@ -43,8 +43,8 @@ struct stream { * 'start' points into a 'body' in a stream. * When a stream is made of 'diff' hunks, there is a special * elmnt at the start of each hunk which starts with '\0' and - * records the line offsets of the hunk. These are 20 bytes long. - * "\0\d{5} \d{5} \d{5}\n\0" + * records the line offsets of the hunk. These are 20+ bytes long. + * "\0\d{5} \d{5} \d{5}{SP funcname}?\n\0" * The 3 numbers are: chunk number, starting line, number if lines. * An element with len==0 marks EOF. */ @@ -58,8 +58,10 @@ static inline int match(struct elmnt *a, struct elmnt *b) { return a->hash == b->hash && - a->len == b->len && - strncmp(a->start, b->start, a->len) == 0; + ((a->start[0] == 0 && b->start[0] == 0) + || + (a->len == b->len && + strncmp(a->start, b->start, a->len) == 0)); } /* end-of-line is important for narrowing conflicts. @@ -69,7 +71,7 @@ static inline int match(struct elmnt *a, struct elmnt *b) */ static inline int ends_line(struct elmnt e) { - if (e.len == 20 && e.start[0] == 0) + if (e.len >= 20 && e.start[0] == 0) return 1; return e.len && e.start[e.plen-1] == '\n'; } -- 2.39.5