Merge branch 'jk/grep-binary-attribute' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 21 Feb 2012 22:57:05 +0000 (14:57 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 21 Feb 2012 22:57:05 +0000 (14:57 -0800)
* jk/grep-binary-attribute:
grep: pre-load userdiff drivers when threaded
grep: load file data after checking binary-ness
grep: respect diff attributes for binary-ness
grep: cache userdiff_driver in grep_source
grep: drop grep_buffer's "name" parameter
convert git-grep to use grep_source interface
grep: refactor the concept of "grep source" into an object
grep: move sha1-reading mutex into low-level code
grep: make locking flag global

1  2 
builtin/grep.c
revision.c
diff --combined builtin/grep.c
index 5c2ae94e5576f2e8af1f8509b789a67851db2598,e741aca18cc1c9c3e5cfef3db996d05956bedc2d..9fc3e95cc610c9df7d2b17eae59ac2c161443982
@@@ -29,25 -29,12 +29,12 @@@ static int use_threads = 1
  #define THREADS 8
  static pthread_t threads[THREADS];
  
- static void *load_sha1(const unsigned char *sha1, unsigned long *size,
-                      const char *name);
- static void *load_file(const char *filename, size_t *sz);
- enum work_type {WORK_SHA1, WORK_FILE};
  /* We use one producer thread and THREADS consumer
   * threads. The producer adds struct work_items to 'todo' and the
   * consumers pick work items from the same array.
   */
  struct work_item {
-       enum work_type type;
-       char *name;
-       /* if type == WORK_SHA1, then 'identifier' is a SHA1,
-        * otherwise type == WORK_FILE, and 'identifier' is a NUL
-        * terminated filename.
-        */
-       void *identifier;
+       struct grep_source source;
        char done;
        struct strbuf out;
  };
@@@ -85,21 -72,6 +72,6 @@@ static inline void grep_unlock(void
                pthread_mutex_unlock(&grep_mutex);
  }
  
- /* Used to serialize calls to read_sha1_file. */
- static pthread_mutex_t read_sha1_mutex;
- static inline void read_sha1_lock(void)
- {
-       if (use_threads)
-               pthread_mutex_lock(&read_sha1_mutex);
- }
- static inline void read_sha1_unlock(void)
- {
-       if (use_threads)
-               pthread_mutex_unlock(&read_sha1_mutex);
- }
  /* Signalled when a new work_item is added to todo. */
  static pthread_cond_t cond_add;
  
@@@ -113,7 -85,8 +85,8 @@@ static pthread_cond_t cond_result
  
  static int skip_first_line;
  
- static void add_work(enum work_type type, char *name, void *id)
+ static void add_work(struct grep_opt *opt, enum grep_source_type type,
+                    const char *name, const void *id)
  {
        grep_lock();
  
                pthread_cond_wait(&cond_write, &grep_mutex);
        }
  
-       todo[todo_end].type = type;
-       todo[todo_end].name = name;
-       todo[todo_end].identifier = id;
+       grep_source_init(&todo[todo_end].source, type, name, id);
+       if (opt->binary != GREP_BINARY_TEXT)
+               grep_source_load_driver(&todo[todo_end].source);
        todo[todo_end].done = 0;
        strbuf_reset(&todo[todo_end].out);
        todo_end = (todo_end + 1) % ARRAY_SIZE(todo);
@@@ -151,21 -124,6 +124,6 @@@ static struct work_item *get_work(void
        return ret;
  }
  
- static void grep_sha1_async(struct grep_opt *opt, char *name,
-                           const unsigned char *sha1)
- {
-       unsigned char *s;
-       s = xmalloc(20);
-       memcpy(s, sha1, 20);
-       add_work(WORK_SHA1, name, s);
- }
- static void grep_file_async(struct grep_opt *opt, char *name,
-                           const char *filename)
- {
-       add_work(WORK_FILE, name, xstrdup(filename));
- }
  static void work_done(struct work_item *w)
  {
        int old_done;
  
                        write_or_die(1, p, len);
                }
-               free(w->name);
-               free(w->identifier);
+               grep_source_clear(&w->source);
        }
  
        if (old_done != todo_done)
@@@ -216,25 -173,8 +173,8 @@@ static void *run(void *arg
                        break;
  
                opt->output_priv = w;
-               if (w->type == WORK_SHA1) {
-                       unsigned long sz;
-                       void* data = load_sha1(w->identifier, &sz, w->name);
-                       if (data) {
-                               hit |= grep_buffer(opt, w->name, data, sz);
-                               free(data);
-                       }
-               } else if (w->type == WORK_FILE) {
-                       size_t sz;
-                       void* data = load_file(w->identifier, &sz);
-                       if (data) {
-                               hit |= grep_buffer(opt, w->name, data, sz);
-                               free(data);
-                       }
-               } else {
-                       assert(0);
-               }
+               hit |= grep_source(opt, &w->source);
+               grep_source_clear_data(&w->source);
                work_done(w);
        }
        free_grep_patterns(arg);
@@@ -254,11 -194,12 +194,12 @@@ static void start_threads(struct grep_o
        int i;
  
        pthread_mutex_init(&grep_mutex, NULL);
-       pthread_mutex_init(&read_sha1_mutex, NULL);
+       pthread_mutex_init(&grep_read_mutex, NULL);
        pthread_mutex_init(&grep_attr_mutex, NULL);
        pthread_cond_init(&cond_add, NULL);
        pthread_cond_init(&cond_write, NULL);
        pthread_cond_init(&cond_result, NULL);
+       grep_use_locks = 1;
  
        for (i = 0; i < ARRAY_SIZE(todo); i++) {
                strbuf_init(&todo[i].out, 0);
@@@ -302,17 -243,16 +243,16 @@@ static int wait_all(void
        }
  
        pthread_mutex_destroy(&grep_mutex);
-       pthread_mutex_destroy(&read_sha1_mutex);
+       pthread_mutex_destroy(&grep_read_mutex);
        pthread_mutex_destroy(&grep_attr_mutex);
        pthread_cond_destroy(&cond_add);
        pthread_cond_destroy(&cond_write);
        pthread_cond_destroy(&cond_result);
+       grep_use_locks = 0;
  
        return hit;
  }
  #else /* !NO_PTHREADS */
- #define read_sha1_lock()
- #define read_sha1_unlock()
  
  static int wait_all(void)
  {
@@@ -374,21 -314,9 +314,9 @@@ static void *lock_and_read_sha1_file(co
  {
        void *data;
  
-       read_sha1_lock();
+       grep_read_lock();
        data = read_sha1_file(sha1, type, size);
-       read_sha1_unlock();
-       return data;
- }
- static void *load_sha1(const unsigned char *sha1, unsigned long *size,
-                      const char *name)
- {
-       enum object_type type;
-       void *data = lock_and_read_sha1_file(sha1, &type, size);
-       if (!data)
-               error(_("'%s': unable to read %s"), name, sha1_to_hex(sha1));
+       grep_read_unlock();
        return data;
  }
  
@@@ -396,7 -324,6 +324,6 @@@ static int grep_sha1(struct grep_opt *o
                     const char *filename, int tree_name_len)
  {
        struct strbuf pathbuf = STRBUF_INIT;
-       char *name;
  
        if (opt->relative && opt->prefix_length) {
                quote_path_relative(filename + tree_name_len, -1, &pathbuf,
                strbuf_addstr(&pathbuf, filename);
        }
  
-       name = strbuf_detach(&pathbuf, NULL);
  #ifndef NO_PTHREADS
        if (use_threads) {
-               grep_sha1_async(opt, name, sha1);
+               add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
+               strbuf_release(&pathbuf);
                return 0;
        } else
  #endif
        {
+               struct grep_source gs;
                int hit;
-               unsigned long sz;
-               void *data = load_sha1(sha1, &sz, name);
-               if (!data)
-                       hit = 0;
-               else
-                       hit = grep_buffer(opt, name, data, sz);
-               free(data);
-               free(name);
-               return hit;
-       }
- }
  
- static void *load_file(const char *filename, size_t *sz)
- {
-       struct stat st;
-       char *data;
-       int i;
+               grep_source_init(&gs, GREP_SOURCE_SHA1, pathbuf.buf, sha1);
+               strbuf_release(&pathbuf);
+               hit = grep_source(opt, &gs);
  
-       if (lstat(filename, &st) < 0) {
-       err_ret:
-               if (errno != ENOENT)
-                       error(_("'%s': %s"), filename, strerror(errno));
-               return NULL;
-       }
-       if (!S_ISREG(st.st_mode))
-               return NULL;
-       *sz = xsize_t(st.st_size);
-       i = open(filename, O_RDONLY);
-       if (i < 0)
-               goto err_ret;
-       data = xmalloc(*sz + 1);
-       if (st.st_size != read_in_full(i, data, *sz)) {
-               error(_("'%s': short read %s"), filename, strerror(errno));
-               close(i);
-               free(data);
-               return NULL;
+               grep_source_clear(&gs);
+               return hit;
        }
-       close(i);
-       data[*sz] = 0;
-       return data;
  }
  
  static int grep_file(struct grep_opt *opt, const char *filename)
  {
        struct strbuf buf = STRBUF_INIT;
-       char *name;
  
        if (opt->relative && opt->prefix_length)
                quote_path_relative(filename, -1, &buf, opt->prefix);
        else
                strbuf_addstr(&buf, filename);
-       name = strbuf_detach(&buf, NULL);
  
  #ifndef NO_PTHREADS
        if (use_threads) {
-               grep_file_async(opt, name, filename);
+               add_work(opt, GREP_SOURCE_FILE, buf.buf, filename);
+               strbuf_release(&buf);
                return 0;
        } else
  #endif
        {
+               struct grep_source gs;
                int hit;
-               size_t sz;
-               void *data = load_file(filename, &sz);
-               if (!data)
-                       hit = 0;
-               else
-                       hit = grep_buffer(opt, name, data, sz);
  
-               free(data);
-               free(name);
+               grep_source_init(&gs, GREP_SOURCE_FILE, buf.buf, filename);
+               strbuf_release(&buf);
+               hit = grep_source(opt, &gs);
+               grep_source_clear(&gs);
                return hit;
        }
  }
@@@ -615,10 -506,10 +506,10 @@@ static int grep_object(struct grep_opt 
                struct strbuf base;
                int hit, len;
  
-               read_sha1_lock();
+               grep_read_lock();
                data = read_object_with_reference(obj->sha1, tree_type,
                                                  &size, NULL);
-               read_sha1_unlock();
+               grep_read_unlock();
  
                if (!data)
                        die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1));
@@@ -1030,13 -921,10 +921,11 @@@ int cmd_grep(int argc, const char **arg
        use_threads = 0;
  #endif
  
-       opt.use_threads = use_threads;
  #ifndef NO_PTHREADS
        if (use_threads) {
 -              if (opt.pre_context || opt.post_context || opt.file_break ||
 -                  opt.funcbody)
 +              if (!(opt.name_only || opt.unmatch_name_only || opt.count)
 +                  && (opt.pre_context || opt.post_context ||
 +                      opt.file_break || opt.funcbody))
                        skip_first_line = 1;
                start_threads(&opt);
        }
diff --combined revision.c
index eb0be4206d2772e4d8eb11bfd164725529f915e7,89d3a8fafbe5d066a63c9b1f42113c7de5577c5c..18be62b3169095b908cb521cf9be211a9339029d
@@@ -416,7 -416,7 +416,7 @@@ static int rev_same_tree_as_empty(struc
  static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
  {
        struct commit_list **pp, *parent;
 -      int tree_changed = 0, tree_same = 0;
 +      int tree_changed = 0, tree_same = 0, nth_parent = 0;
  
        /*
         * If we don't do pruning, everything is interesting
        while ((parent = *pp) != NULL) {
                struct commit *p = parent->item;
  
 +              /*
 +               * Do not compare with later parents when we care only about
 +               * the first parent chain, in order to avoid derailing the
 +               * traversal to follow a side branch that brought everything
 +               * in the path we are limited to by the pathspec.
 +               */
 +              if (revs->first_parent_only && nth_parent++)
 +                      break;
                if (parse_commit(p) < 0)
                        die("cannot simplify commit %s (because of %s)",
                            sha1_to_hex(commit->object.sha1),
@@@ -2136,7 -2128,6 +2136,6 @@@ static int commit_match(struct commit *
        if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
                return 1;
        return grep_buffer(&opt->grep_filter,
-                          NULL, /* we say nothing, not even filename */
                           commit->buffer, strlen(commit->buffer));
  }