diffcore-pickaxe.con commit git-merge-tree: generalize the "traverse <n> trees in sync" functionality (164dcb9)
   1/*
   2 * Copyright (C) 2005 Junio C Hamano
   3 */
   4#include "cache.h"
   5#include "diff.h"
   6#include "diffcore.h"
   7
   8static unsigned int contains(struct diff_filespec *one,
   9                             const char *needle, unsigned long len)
  10{
  11        unsigned int cnt;
  12        unsigned long offset, sz;
  13        const char *data;
  14        if (diff_populate_filespec(one, 0))
  15                return 0;
  16
  17        sz = one->size;
  18        data = one->data;
  19        cnt = 0;
  20
  21        /* Yes, I've heard of strstr(), but the thing is *data may
  22         * not be NUL terminated.  Sue me.
  23         */
  24        for (offset = 0; offset + len <= sz; offset++) {
  25                /* we count non-overlapping occurrences of needle */
  26                if (!memcmp(needle, data + offset, len)) {
  27                        offset += len - 1;
  28                        cnt++;
  29                }
  30        }
  31        return cnt;
  32}
  33
  34void diffcore_pickaxe(const char *needle, int opts)
  35{
  36        struct diff_queue_struct *q = &diff_queued_diff;
  37        unsigned long len = strlen(needle);
  38        int i, has_changes;
  39        struct diff_queue_struct outq;
  40        outq.queue = NULL;
  41        outq.nr = outq.alloc = 0;
  42
  43        if (opts & DIFF_PICKAXE_ALL) {
  44                /* Showing the whole changeset if needle exists */
  45                for (i = has_changes = 0; !has_changes && i < q->nr; i++) {
  46                        struct diff_filepair *p = q->queue[i];
  47                        if (!DIFF_FILE_VALID(p->one)) {
  48                                if (!DIFF_FILE_VALID(p->two))
  49                                        continue; /* ignore unmerged */
  50                                /* created */
  51                                if (contains(p->two, needle, len))
  52                                        has_changes++;
  53                        }
  54                        else if (!DIFF_FILE_VALID(p->two)) {
  55                                if (contains(p->one, needle, len))
  56                                        has_changes++;
  57                        }
  58                        else if (!diff_unmodified_pair(p) &&
  59                                 contains(p->one, needle, len) !=
  60                                 contains(p->two, needle, len))
  61                                has_changes++;
  62                }
  63                if (has_changes)
  64                        return; /* not munge the queue */
  65
  66                /* otherwise we will clear the whole queue
  67                 * by copying the empty outq at the end of this
  68                 * function, but first clear the current entries
  69                 * in the queue.
  70                 */
  71                for (i = 0; i < q->nr; i++)
  72                        diff_free_filepair(q->queue[i]);
  73        }
  74        else 
  75                /* Showing only the filepairs that has the needle */
  76                for (i = 0; i < q->nr; i++) {
  77                        struct diff_filepair *p = q->queue[i];
  78                        has_changes = 0;
  79                        if (!DIFF_FILE_VALID(p->one)) {
  80                                if (!DIFF_FILE_VALID(p->two))
  81                                        ; /* ignore unmerged */
  82                                /* created */
  83                                else if (contains(p->two, needle, len))
  84                                        has_changes = 1;
  85                        }
  86                        else if (!DIFF_FILE_VALID(p->two)) {
  87                                if (contains(p->one, needle, len))
  88                                        has_changes = 1;
  89                        }
  90                        else if (!diff_unmodified_pair(p) &&
  91                                 contains(p->one, needle, len) !=
  92                                 contains(p->two, needle, len))
  93                                has_changes = 1;
  94
  95                        if (has_changes)
  96                                diff_q(&outq, p);
  97                        else
  98                                diff_free_filepair(p);
  99                }
 100
 101        free(q->queue);
 102        *q = outq;
 103        return;
 104}