Reduce the number of connects when fetching
[gitweb.git] / diff-lib.c
index 7531e20c784c44c0b5d3ecb2057638874a09ce6c..d85d8f34ba055ad7e02bf5d61ae4a675ce0be1d3 100644 (file)
@@ -24,7 +24,7 @@ static int read_directory(const char *path, struct path_list *list)
 
        while ((e = readdir(dir)))
                if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
-                       path_list_insert(xstrdup(e->d_name), list);
+                       path_list_insert(e->d_name, list);
 
        closedir(dir);
        return 0;
@@ -121,7 +121,7 @@ static int queue_diff(struct diff_options *o,
        } else {
                struct diff_filespec *d1, *d2;
 
-               if (o->reverse_diff) {
+               if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
                        unsigned tmp;
                        const char *tmp_c;
                        tmp = mode1; mode1 = mode2; mode2 = tmp;
@@ -173,9 +173,10 @@ static int is_in_index(const char *path)
 }
 
 static int handle_diff_files_args(struct rev_info *revs,
-               int argc, const char **argv, int *silent)
+                                 int argc, const char **argv,
+                                 unsigned int *options)
 {
-       *silent = 0;
+       *options = 0;
 
        /* revs->max_count == -2 means --no-index */
        while (1 < argc && argv[1][0] == '-') {
@@ -188,10 +189,11 @@ static int handle_diff_files_args(struct rev_info *revs,
                else if (!strcmp(argv[1], "-n") ||
                                !strcmp(argv[1], "--no-index")) {
                        revs->max_count = -2;
-                       revs->diffopt.exit_with_status = 1;
+                       DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
+                       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
                }
                else if (!strcmp(argv[1], "-q"))
-                       *silent = 1;
+                       *options |= DIFF_SILENT_ON_REMOVED;
                else
                        return error("invalid option: %s", argv[1]);
                argv++; argc--;
@@ -204,8 +206,10 @@ static int handle_diff_files_args(struct rev_info *revs,
                 */
                read_cache();
                if (!is_in_index(revs->diffopt.paths[0]) ||
-                                       !is_in_index(revs->diffopt.paths[1]))
+                                       !is_in_index(revs->diffopt.paths[1])) {
                        revs->max_count = -2;
+                       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
+               }
        }
 
        /*
@@ -227,7 +231,7 @@ static int handle_diff_files_args(struct rev_info *revs,
 static int is_outside_repo(const char *path, int nongit, const char *prefix)
 {
        int i;
-       if (nongit || !strcmp(path, "-") || path[0] == '/')
+       if (nongit || !strcmp(path, "-") || is_absolute_path(path))
                return 1;
        if (prefixcmp(path, "../"))
                return 0;
@@ -255,7 +259,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;
+                       DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);
                        break;
                }
        if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) &&
@@ -293,18 +297,21 @@ int setup_diff_no_index(struct rev_info *revs,
        else
                revs->diffopt.paths = argv + argc - 2;
        revs->diffopt.nr_paths = 2;
+       DIFF_OPT_SET(&revs->diffopt, NO_INDEX);
        revs->max_count = -2;
+       if (diff_setup_done(&revs->diffopt) < 0)
+               die("diff_setup_done failed");
        return 0;
 }
 
 int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 {
-       int silent_on_removed;
+       unsigned int options;
 
-       if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
+       if (handle_diff_files_args(revs, argc, argv, &options))
                return -1;
 
-       if (revs->max_count == -2) {
+       if (DIFF_OPT_TST(&revs->diffopt, NO_INDEX)) {
                if (revs->diffopt.nr_paths != 2)
                        return error("need two files/directories with --no-index");
                if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
@@ -323,13 +330,16 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
                perror("read_cache");
                return -1;
        }
-       return run_diff_files(revs, silent_on_removed);
+       return run_diff_files(revs, options);
 }
 
-int run_diff_files(struct rev_info *revs, int silent_on_removed)
+int run_diff_files(struct rev_info *revs, unsigned int option)
 {
        int entries, i;
        int diff_unmerged_stage = revs->max_count;
+       int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
+       unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
+                             ? CE_MATCH_RACY_IS_DIRTY : 0);
 
        if (diff_unmerged_stage < 0)
                diff_unmerged_stage = 2;
@@ -340,7 +350,8 @@ 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)
+               if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
+                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
                        break;
 
                if (!ce_path_match(ce, revs->prune_data))
@@ -373,7 +384,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                                        continue;
                        }
                        else
-                               dpath->mode = canon_mode(st.st_mode);
+                               dpath->mode = ntohl(ce_mode_from_stat(ce, st.st_mode));
 
                        while (i < entries) {
                                struct cache_entry *nce = active_cache[i];
@@ -390,8 +401,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                                        int mode = ntohl(nce->ce_mode);
                                        num_compare_stages++;
                                        hashcpy(dpath->parent[stage-2].sha1, nce->sha1);
-                                       dpath->parent[stage-2].mode =
-                                               canon_mode(mode);
+                                       dpath->parent[stage-2].mode = ntohl(ce_mode_from_stat(nce, mode));
                                        dpath->parent[stage-2].status =
                                                DIFF_STATUS_MODIFIED;
                                }
@@ -436,19 +446,11 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                                       ce->sha1, ce->name, NULL);
                        continue;
                }
-               changed = ce_match_stat(ce, &st, 0);
-               if (!changed && !revs->diffopt.find_copies_harder)
+               changed = ce_match_stat(ce, &st, ce_option);
+               if (!changed && !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                        continue;
                oldmode = ntohl(ce->ce_mode);
-
-               newmode = canon_mode(st.st_mode);
-               if (!trust_executable_bit &&
-                   S_ISREG(newmode) && S_ISREG(oldmode) &&
-                   ((newmode ^ oldmode) == 0111))
-                       newmode = oldmode;
-               else if (!has_symlinks &&
-                   S_ISREG(newmode) && S_ISLNK(oldmode))
-                       newmode = oldmode;
+               newmode = ntohl(ce_mode_from_stat(ce, st.st_mode));
                diff_change(&revs->diffopt, oldmode, newmode,
                            ce->sha1, (changed ? null_sha1 : ce->sha1),
                            ce->name, NULL);
@@ -564,7 +566,7 @@ static int show_modified(struct rev_info *revs,
 
        oldmode = old->ce_mode;
        if (mode == oldmode && !hashcmp(sha1, old->sha1) &&
-           !revs->diffopt.find_copies_harder)
+           !DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                return 0;
 
        mode = ntohl(mode);
@@ -584,7 +586,8 @@ 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)
+               if (DIFF_OPT_TST(&revs->diffopt, QUIET) &&
+                       DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
                        break;
 
                if (!ce_path_match(ce, pathspec))
@@ -673,7 +676,7 @@ int run_diff_index(struct rev_info *revs, int cached)
        const char *tree_name;
        int match_missing = 0;
 
-       /* 
+       /*
         * Backward compatibility wart - "diff-index -m" does
         * not mean "do not ignore merges", but totally different.
         */