Merge branch 'fg/exclude-bq'
authorJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2009 23:41:39 +0000 (15:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2009 23:41:39 +0000 (15:41 -0800)
* fg/exclude-bq:
Support "\" in non-wildcard exclusion entries

1  2 
dir.c
t/t3001-ls-files-others-exclude.sh
diff --combined dir.c
index cfd1ea587d9cce825e238ca81ea99b752543dada,04a4b9861e03739df5c048448cd5c0be28b400db..2245749b3fe74f793bd1997d2238883abe61fc07
--- 1/dir.c
--- 2/dir.c
+++ b/dir.c
@@@ -52,6 -52,11 +52,6 @@@ int common_prefix(const char **pathspec
        return prefix;
  }
  
 -static inline int special_char(unsigned char c1)
 -{
 -      return !c1 || c1 == '*' || c1 == '[' || c1 == '?' || c1 == '\\';
 -}
 -
  /*
   * Does 'match' matches the given name?
   * A match is found if
@@@ -75,7 -80,7 +75,7 @@@ static int match_one(const char *match
        for (;;) {
                unsigned char c1 = *match;
                unsigned char c2 = *name;
 -              if (special_char(c1))
 +              if (c1 == '\0' || is_glob_special(c1))
                        break;
                if (c1 != c2)
                        return 0;
   * and a mark is left in seen[] array for pathspec element that
   * actually matched anything.
   */
 -int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
 +int match_pathspec(const char **pathspec, const char *name, int namelen,
 +              int prefix, char *seen)
  {
 -      int retval;
 -      const char *match;
 +      int i, retval = 0;
 +
 +      if (!pathspec)
 +              return 1;
  
        name += prefix;
        namelen -= prefix;
  
 -      for (retval = 0; (match = *pathspec++) != NULL; seen++) {
 +      for (i = 0; pathspec[i] != NULL; i++) {
                int how;
 -              if (retval && *seen == MATCHED_EXACTLY)
 +              const char *match = pathspec[i] + prefix;
 +              if (seen && seen[i] == MATCHED_EXACTLY)
                        continue;
 -              match += prefix;
                how = match_one(match, name, namelen);
                if (how) {
                        if (retval < how)
                                retval = how;
 -                      if (*seen < how)
 -                              *seen = how;
 +                      if (seen && seen[i] < how)
 +                              seen[i] = how;
                }
        }
        return retval;
  
  static int no_wildcard(const char *string)
  {
-       return string[strcspn(string, "*?[{")] == '\0';
+       return string[strcspn(string, "*?[{\\")] == '\0';
  }
  
  void add_exclude(const char *string, const char *base,
@@@ -385,7 -387,7 +385,7 @@@ static struct dir_entry *dir_entry_new(
        return ent;
  }
  
 -struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
 +static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len)
  {
        if (cache_name_exists(pathname, len, ignore_case))
                return NULL;
        return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
  }
  
 -struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
 +static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
  {
        if (cache_name_pos(pathname, len) >= 0)
                return NULL;
@@@ -588,8 -590,10 +588,8 @@@ static int read_directory_recursive(str
                        int len, dtype;
                        int exclude;
  
 -                      if ((de->d_name[0] == '.') &&
 -                          (de->d_name[1] == 0 ||
 -                           !strcmp(de->d_name + 1, ".") ||
 -                           !strcmp(de->d_name + 1, "git")))
 +                      if (is_dot_or_dotdot(de->d_name) ||
 +                           !strcmp(de->d_name, ".git"))
                                continue;
                        len = strlen(de->d_name);
                        /* Ignore overly long pathnames! */
@@@ -676,12 -680,17 +676,12 @@@ static int cmp_name(const void *p1, con
   */
  static int simple_length(const char *match)
  {
 -      const char special[256] = {
 -              [0] = 1, ['?'] = 1,
 -              ['\\'] = 1, ['*'] = 1,
 -              ['['] = 1
 -      };
        int len = -1;
  
        for (;;) {
                unsigned char c = *match++;
                len++;
 -              if (special[c])
 +              if (c == '\0' || is_glob_special(c))
                        return len;
        }
  }
@@@ -718,12 -727,8 +718,12 @@@ static void free_simplify(struct path_s
  
  int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
  {
 -      struct path_simplify *simplify = create_simplify(pathspec);
 +      struct path_simplify *simplify;
 +
 +      if (has_symlink_leading_path(strlen(path), path))
 +              return dir->nr;
  
 +      simplify = create_simplify(pathspec);
        read_directory_recursive(dir, path, base, baselen, 0, simplify);
        free_simplify(simplify);
        qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
@@@ -780,25 -785,6 +780,25 @@@ int is_inside_dir(const char *dir
        return get_relative_cwd(buffer, sizeof(buffer), dir) != NULL;
  }
  
 +int is_empty_dir(const char *path)
 +{
 +      DIR *dir = opendir(path);
 +      struct dirent *e;
 +      int ret = 1;
 +
 +      if (!dir)
 +              return 0;
 +
 +      while ((e = readdir(dir)) != NULL)
 +              if (!is_dot_or_dotdot(e->d_name)) {
 +                      ret = 0;
 +                      break;
 +              }
 +
 +      closedir(dir);
 +      return ret;
 +}
 +
  int remove_dir_recursively(struct strbuf *path, int only_empty)
  {
        DIR *dir = opendir(path->buf);
        len = path->len;
        while ((e = readdir(dir)) != NULL) {
                struct stat st;
 -              if ((e->d_name[0] == '.') &&
 -                  ((e->d_name[1] == 0) ||
 -                   ((e->d_name[1] == '.') && e->d_name[2] == 0)))
 -                      continue; /* "." and ".." */
 +              if (is_dot_or_dotdot(e->d_name))
 +                      continue;
  
                strbuf_setlen(path, len);
                strbuf_addstr(path, e->d_name);
index 85aef12a113fed8164a085a19ce5c794ab96ff6f,6a1711374579082000e95e39e4f6c0d572d11cd4..c65bca838881938e2f924cfe62b2c303dbd5b1cd
@@@ -19,6 -19,9 +19,9 @@@ d
      >$dir/a.$i
    done
  done
+ >"#ignore1"
+ >"#ignore2"
+ >"#hidden"
  
  cat >expect <<EOF
  a.2
@@@ -42,6 -45,9 +45,9 @@@ three/a.
  EOF
  
  echo '.gitignore
+ \#ignore1
+ \#ignore2*
+ \#hid*n
  output
  expect
  .gitignore
@@@ -79,9 -85,10 +85,10 @@@ test_expect_success 
         >output &&
       test_cmp expect output'
  
- cat > excludes-file << EOF
+ cat > excludes-file <<\EOF
  *.[1-8]
  e*
+ \#*
  EOF
  
  git config core.excludesFile excludes-file
@@@ -140,10 -147,4 +147,10 @@@ test_expect_success 'trailing slash in 
  
  '
  
 +test_expect_success 'negated exclude matches can override previous ones' '
 +
 +      git ls-files --others --exclude="a.*" --exclude="!a.1" >output &&
 +      grep "^a.1" output
 +'
 +
  test_done