Fix working directory errno handling when unlinking a directory
[gitweb.git] / diff-lib.c
index 6abb981534bf032d50e28eb3a14033c1b6546762..7531e20c784c44c0b5d3ecb2057638874a09ce6c 100644 (file)
@@ -142,18 +142,34 @@ static int queue_diff(struct diff_options *o,
        }
 }
 
+/*
+ * Does the path name a blob in the working tree, or a directory
+ * in the working tree?
+ */
 static int is_in_index(const char *path)
 {
-       int len = strlen(path);
-       int pos = cache_name_pos(path, len);
-       char c;
-
-       if (pos < 0)
-               return 0;
-       if (strncmp(active_cache[pos]->name, path, len))
-               return 0;
-       c = active_cache[pos]->name[len];
-       return c == '\0' || c == '/';
+       int len, pos;
+       struct cache_entry *ce;
+
+       len = strlen(path);
+       while (path[len-1] == '/')
+               len--;
+       if (!len)
+               return 1; /* "." */
+       pos = cache_name_pos(path, len);
+       if (0 <= pos)
+               return 1;
+       pos = -1 - pos;
+       while (pos < active_nr) {
+               ce = active_cache[pos++];
+               if (ce_namelen(ce) <= len ||
+                   strncmp(ce->name, path, len) ||
+                   (ce->name[len] > '/'))
+                       break; /* path cannot be a prefix */
+               if (ce->name[len] == '/')
+                       return 1;
+       }
+       return 0;
 }
 
 static int handle_diff_files_args(struct rev_info *revs,
@@ -170,8 +186,10 @@ static int handle_diff_files_args(struct rev_info *revs,
                else if (!strcmp(argv[1], "--theirs"))
                        revs->max_count = 3;
                else if (!strcmp(argv[1], "-n") ||
-                               !strcmp(argv[1], "--no-index"))
+                               !strcmp(argv[1], "--no-index")) {
                        revs->max_count = -2;
+                       revs->diffopt.exit_with_status = 1;
+               }
                else if (!strcmp(argv[1], "-q"))
                        *silent = 1;
                else
@@ -237,6 +255,7 @@ int setup_diff_no_index(struct rev_info *revs,
                        break;
                } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) {
                        i = argc - 3;
+                       revs->diffopt.exit_with_status = 1;
                        break;
                }
        if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) &&
@@ -321,6 +340,9 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                struct cache_entry *ce = active_cache[i];
                int changed;
 
+               if (revs->diffopt.quiet && revs->diffopt.has_changes)
+                       break;
+
                if (!ce_path_match(ce, revs->prune_data))
                        continue;
 
@@ -562,6 +584,9 @@ static int diff_cache(struct rev_info *revs,
                struct cache_entry *ce = *ac;
                int same = (entries > 1) && ce_same_name(ce, ac[1]);
 
+               if (revs->diffopt.quiet && revs->diffopt.has_changes)
+                       break;
+
                if (!ce_path_match(ce, pathspec))
                        goto skip_entry;