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