Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2005 Junio C Hamano |
| 3 | */ |
| 4 | #include "cache.h" |
| 5 | #include "diff.h" |
| 6 | #include "diffcore.h" |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 7 | |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 8 | static unsigned int contains(struct diff_filespec *one, |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 9 | const char *needle, unsigned long len, |
| 10 | regex_t *regexp) |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 11 | { |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 12 | unsigned int cnt; |
René Scharfe | ce163c7 | 2009-03-03 00:00:55 +0100 | [diff] [blame] | 13 | unsigned long sz; |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 14 | const char *data; |
Junio C Hamano | f0c6b2a | 2005-05-27 15:56:38 -0700 | [diff] [blame] | 15 | if (diff_populate_filespec(one, 0)) |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 16 | return 0; |
Jeff King | e1b1611 | 2007-01-25 23:48:58 -0500 | [diff] [blame] | 17 | if (!len) |
| 18 | return 0; |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 19 | |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 20 | sz = one->size; |
| 21 | data = one->data; |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 22 | cnt = 0; |
| 23 | |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 24 | if (regexp) { |
| 25 | regmatch_t regmatch; |
| 26 | int flags = 0; |
| 27 | |
René Scharfe | 50fd699 | 2009-03-16 19:38:42 +0100 | [diff] [blame] | 28 | assert(data[sz] == '\0'); |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 29 | while (*data && !regexec(regexp, data, 1, ®match, flags)) { |
| 30 | flags |= REG_NOTBOL; |
René Scharfe | 50fd699 | 2009-03-16 19:38:42 +0100 | [diff] [blame] | 31 | data += regmatch.rm_eo; |
| 32 | if (*data && regmatch.rm_so == regmatch.rm_eo) |
| 33 | data++; |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 34 | cnt++; |
| 35 | } |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 36 | |
| 37 | } else { /* Classic exact string match */ |
René Scharfe | ce163c7 | 2009-03-03 00:00:55 +0100 | [diff] [blame] | 38 | while (sz) { |
| 39 | const char *found = memmem(data, sz, needle, len); |
| 40 | if (!found) |
| 41 | break; |
| 42 | sz -= found - data + len; |
| 43 | data = found + len; |
| 44 | cnt++; |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 45 | } |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 46 | } |
Junio C Hamano | a0cb940 | 2007-05-07 01:24:27 -0700 | [diff] [blame] | 47 | diff_free_filespec_data(one); |
Junio C Hamano | 2002eed | 2005-07-23 16:35:25 -0700 | [diff] [blame] | 48 | return cnt; |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 49 | } |
| 50 | |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 51 | void diffcore_pickaxe(const char *needle, int opts) |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 52 | { |
Junio C Hamano | 38c6f78 | 2005-05-21 19:40:36 -0700 | [diff] [blame] | 53 | struct diff_queue_struct *q = &diff_queued_diff; |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 54 | unsigned long len = strlen(needle); |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 55 | int i, has_changes; |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 56 | regex_t regex, *regexp = NULL; |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 57 | struct diff_queue_struct outq; |
| 58 | outq.queue = NULL; |
| 59 | outq.nr = outq.alloc = 0; |
| 60 | |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 61 | if (opts & DIFF_PICKAXE_REGEX) { |
| 62 | int err; |
| 63 | err = regcomp(®ex, needle, REG_EXTENDED | REG_NEWLINE); |
| 64 | if (err) { |
| 65 | /* The POSIX.2 people are surely sick */ |
| 66 | char errbuf[1024]; |
| 67 | regerror(err, ®ex, errbuf, 1024); |
| 68 | regfree(®ex); |
| 69 | die("invalid pickaxe regex: %s", errbuf); |
| 70 | } |
| 71 | regexp = ®ex; |
| 72 | } |
| 73 | |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 74 | if (opts & DIFF_PICKAXE_ALL) { |
| 75 | /* Showing the whole changeset if needle exists */ |
| 76 | for (i = has_changes = 0; !has_changes && i < q->nr; i++) { |
| 77 | struct diff_filepair *p = q->queue[i]; |
| 78 | if (!DIFF_FILE_VALID(p->one)) { |
| 79 | if (!DIFF_FILE_VALID(p->two)) |
| 80 | continue; /* ignore unmerged */ |
| 81 | /* created */ |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 82 | if (contains(p->two, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 83 | has_changes++; |
| 84 | } |
| 85 | else if (!DIFF_FILE_VALID(p->two)) { |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 86 | if (contains(p->one, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 87 | has_changes++; |
| 88 | } |
| 89 | else if (!diff_unmodified_pair(p) && |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 90 | contains(p->one, needle, len, regexp) != |
| 91 | contains(p->two, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 92 | has_changes++; |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 93 | } |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 94 | if (has_changes) |
| 95 | return; /* not munge the queue */ |
| 96 | |
| 97 | /* otherwise we will clear the whole queue |
| 98 | * by copying the empty outq at the end of this |
| 99 | * function, but first clear the current entries |
| 100 | * in the queue. |
| 101 | */ |
| 102 | for (i = 0; i < q->nr; i++) |
| 103 | diff_free_filepair(q->queue[i]); |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 104 | } |
Junio C Hamano | a6080a0 | 2007-06-07 00:04:01 -0700 | [diff] [blame] | 105 | else |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 106 | /* Showing only the filepairs that has the needle */ |
| 107 | for (i = 0; i < q->nr; i++) { |
| 108 | struct diff_filepair *p = q->queue[i]; |
| 109 | has_changes = 0; |
| 110 | if (!DIFF_FILE_VALID(p->one)) { |
| 111 | if (!DIFF_FILE_VALID(p->two)) |
| 112 | ; /* ignore unmerged */ |
| 113 | /* created */ |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 114 | else if (contains(p->two, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 115 | has_changes = 1; |
| 116 | } |
| 117 | else if (!DIFF_FILE_VALID(p->two)) { |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 118 | if (contains(p->one, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 119 | has_changes = 1; |
| 120 | } |
| 121 | else if (!diff_unmodified_pair(p) && |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 122 | contains(p->one, needle, len, regexp) != |
| 123 | contains(p->two, needle, len, regexp)) |
Junio C Hamano | 367cec1 | 2005-05-27 15:55:28 -0700 | [diff] [blame] | 124 | has_changes = 1; |
| 125 | |
| 126 | if (has_changes) |
| 127 | diff_q(&outq, p); |
| 128 | else |
| 129 | diff_free_filepair(p); |
| 130 | } |
| 131 | |
Petr Baudis | d01d8c6 | 2006-03-29 02:16:33 +0200 | [diff] [blame] | 132 | if (opts & DIFF_PICKAXE_REGEX) { |
| 133 | regfree(®ex); |
| 134 | } |
| 135 | |
Junio C Hamano | 52e9578 | 2005-05-21 02:40:01 -0700 | [diff] [blame] | 136 | free(q->queue); |
| 137 | *q = outq; |
| 138 | return; |
| 139 | } |