Merge branch 'jk/maint-add-ignored-dir' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 24 Mar 2010 23:24:03 +0000 (16:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 24 Mar 2010 23:24:03 +0000 (16:24 -0700)
* jk/maint-add-ignored-dir:
  tests for "git add ignored-dir/file" without -f
  dir: fix COLLECT_IGNORED on excluded prefixes
  t0050: mark non-working test as such

1  2 
dir.c

diff --combined dir.c
index 133c333df61be37e7908f77367f63c85cfc9c548,14ac91a7bbdecc8406a675c766a6c922a70608fe..cb83332a261f97026f9c6273afb162245944dec7
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -200,35 -200,11 +200,35 @@@ void add_exclude(const char *string, co
        which->excludes[which->nr++] = x;
  }
  
 -static int add_excludes_from_file_1(const char *fname,
 -                                  const char *base,
 -                                  int baselen,
 -                                  char **buf_p,
 -                                  struct exclude_list *which)
 +static void *read_skip_worktree_file_from_index(const char *path, size_t *size)
 +{
 +      int pos, len;
 +      unsigned long sz;
 +      enum object_type type;
 +      void *data;
 +      struct index_state *istate = &the_index;
 +
 +      len = strlen(path);
 +      pos = index_name_pos(istate, path, len);
 +      if (pos < 0)
 +              return NULL;
 +      if (!ce_skip_worktree(istate->cache[pos]))
 +              return NULL;
 +      data = read_sha1_file(istate->cache[pos]->sha1, &type, &sz);
 +      if (!data || type != OBJ_BLOB) {
 +              free(data);
 +              return NULL;
 +      }
 +      *size = xsize_t(sz);
 +      return data;
 +}
 +
 +int add_excludes_from_file_to_list(const char *fname,
 +                                 const char *base,
 +                                 int baselen,
 +                                 char **buf_p,
 +                                 struct exclude_list *which,
 +                                 int check_index)
  {
        struct stat st;
        int fd, i;
        char *buf, *entry;
  
        fd = open(fname, O_RDONLY);
 -      if (fd < 0 || fstat(fd, &st) < 0)
 -              goto err;
 -      size = xsize_t(st.st_size);
 -      if (size == 0) {
 -              close(fd);
 -              return 0;
 +      if (fd < 0 || fstat(fd, &st) < 0) {
 +              if (0 <= fd)
 +                      close(fd);
 +              if (!check_index ||
 +                  (buf = read_skip_worktree_file_from_index(fname, &size)) == NULL)
 +                      return -1;
 +              if (size == 0) {
 +                      free(buf);
 +                      return 0;
 +              }
 +              if (buf[size-1] != '\n') {
 +                      buf = xrealloc(buf, size+1);
 +                      buf[size++] = '\n';
 +              }
        }
 -      buf = xmalloc(size+1);
 -      if (read_in_full(fd, buf, size) != size)
 -      {
 -              free(buf);
 -              goto err;
 +      else {
 +              size = xsize_t(st.st_size);
 +              if (size == 0) {
 +                      close(fd);
 +                      return 0;
 +              }
 +              buf = xmalloc(size+1);
 +              if (read_in_full(fd, buf, size) != size) {
 +                      free(buf);
 +                      close(fd);
 +                      return -1;
 +              }
 +              buf[size++] = '\n';
 +              close(fd);
        }
 -      close(fd);
  
        if (buf_p)
                *buf_p = buf;
 -      buf[size++] = '\n';
        entry = buf;
        for (i = 0; i < size; i++) {
                if (buf[i] == '\n') {
                }
        }
        return 0;
 -
 - err:
 -      if (0 <= fd)
 -              close(fd);
 -      return -1;
  }
  
  void add_excludes_from_file(struct dir_struct *dir, const char *fname)
  {
 -      if (add_excludes_from_file_1(fname, "", 0, NULL,
 -                                   &dir->exclude_list[EXC_FILE]) < 0)
 +      if (add_excludes_from_file_to_list(fname, "", 0, NULL,
 +                                         &dir->exclude_list[EXC_FILE], 0) < 0)
                die("cannot use %s as an exclude file", fname);
  }
  
@@@ -334,9 -300,9 +334,9 @@@ static void prep_exclude(struct dir_str
                memcpy(dir->basebuf + current, base + current,
                       stk->baselen - current);
                strcpy(dir->basebuf + stk->baselen, dir->exclude_per_dir);
 -              add_excludes_from_file_1(dir->basebuf,
 -                                       dir->basebuf, stk->baselen,
 -                                       &stk->filebuf, el);
 +              add_excludes_from_file_to_list(dir->basebuf,
 +                                             dir->basebuf, stk->baselen,
 +                                             &stk->filebuf, el, 1);
                dir->exclude_stack = stk;
                current = stk->baselen;
        }
  /* Scan the list and let the last match determine the fate.
   * Return 1 for exclude, 0 for include and -1 for undecided.
   */
 -static int excluded_1(const char *pathname,
 -                    int pathlen, const char *basename, int *dtype,
 -                    struct exclude_list *el)
 +int excluded_from_list(const char *pathname,
 +                     int pathlen, const char *basename, int *dtype,
 +                     struct exclude_list *el)
  {
        int i;
  
                        int to_exclude = x->to_exclude;
  
                        if (x->flags & EXC_FLAG_MUSTBEDIR) {
 +                              if (!dtype) {
 +                                      if (!prefixcmp(pathname, exclude))
 +                                              return to_exclude;
 +                                      else
 +                                              continue;
 +                              }
                                if (*dtype == DT_UNKNOWN)
                                        *dtype = get_dtype(NULL, pathname, pathlen);
                                if (*dtype != DT_DIR)
@@@ -422,8 -382,8 +422,8 @@@ int excluded(struct dir_struct *dir, co
  
        prep_exclude(dir, pathname, basename-pathname);
        for (st = EXC_CMDL; st <= EXC_FILE; st++) {
 -              switch (excluded_1(pathname, pathlen, basename,
 -                                 dtype_p, &dir->exclude_list[st])) {
 +              switch (excluded_from_list(pathname, pathlen, basename,
 +                                         dtype_p, &dir->exclude_list[st])) {
                case 0:
                        return 0;
                case 1:
@@@ -594,13 -554,29 +594,29 @@@ static int simplify_away(const char *pa
        return 0;
  }
  
- static int in_pathspec(const char *path, int len, const struct path_simplify *simplify)
+ /*
+  * This function tells us whether an excluded path matches a
+  * list of "interesting" pathspecs. That is, whether a path matched
+  * by any of the pathspecs could possibly be ignored by excluding
+  * the specified path. This can happen if:
+  *
+  *   1. the path is mentioned explicitly in the pathspec
+  *
+  *   2. the path is a directory prefix of some element in the
+  *      pathspec
+  */
+ static int exclude_matches_pathspec(const char *path, int len,
+               const struct path_simplify *simplify)
  {
        if (simplify) {
                for (; simplify->path; simplify++) {
                        if (len == simplify->len
                            && !memcmp(path, simplify->path, len))
                                return 1;
+                       if (len < simplify->len
+                           && simplify->path[len] == '/'
+                           && !memcmp(path, simplify->path, len))
+                               return 1;
                }
        }
        return 0;
@@@ -678,7 -654,7 +694,7 @@@ static enum path_treatment treat_one_pa
  {
        int exclude = excluded(dir, path, &dtype);
        if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
-           && in_pathspec(path, *len, simplify))
+           && exclude_matches_pathspec(path, *len, simplify))
                dir_add_ignored(dir, path, *len);
  
        /*
@@@ -1044,7 -1020,7 +1060,7 @@@ int remove_path(const char *name
                slash = dirs + (slash - name);
                do {
                        *slash = '\0';
 -              } while (rmdir(dirs) && (slash = strrchr(dirs, '/')));
 +              } while (rmdir(dirs) == 0 && (slash = strrchr(dirs, '/')));
                free(dirs);
        }
        return 0;