Code

Handle core.symlinks=false case in merge-recursive.
[git.git] / diff-lib.c
index a9b5149d1ba57d9721e0ee5aff71dcd7c1c6cf73..f70888f8af57b3b7a695ecdbc19a3b8bc04c13b2 100644 (file)
@@ -43,7 +43,7 @@ static int queue_diff(struct diff_options *o,
        }
        if (name2) {
                if (stat(name2, &st))
-                       return error("Could not access '%s'", name1);
+                       return error("Could not access '%s'", name2);
                mode2 = st.st_mode;
        }
 
@@ -210,13 +210,22 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
        if (revs->max_count == -2) {
                if (revs->diffopt.nr_paths != 2)
                        return error("need two files/directories with --no-index");
-               queue_diff(&revs->diffopt, revs->diffopt.paths[0],
-                               revs->diffopt.paths[1]);
+               if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
+                               revs->diffopt.paths[1]))
+                       return -1;
                diffcore_std(&revs->diffopt);
                diff_flush(&revs->diffopt);
-               return 0;
+               /*
+                * The return code for --no-index imitates diff(1):
+                * 0 = no changes, 1 = changes, else error
+                */
+               return revs->diffopt.found_changes;
        }
 
+       if (read_cache() < 0) {
+               perror("read_cache");
+               return -1;
+       }
        return run_diff_files(revs, silent_on_removed);
 }
 
@@ -227,11 +236,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
 
        if (diff_unmerged_stage < 0)
                diff_unmerged_stage = 2;
-       entries = read_cache();
-       if (entries < 0) {
-               perror("read_cache");
-               return -1;
-       }
+       entries = active_nr;
        for (i = 0; i < entries; i++) {
                struct stat st;
                unsigned int oldmode, newmode;
@@ -248,17 +253,27 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
 
                        path_len = ce_namelen(ce);
 
-                       dpath = xmalloc (combine_diff_path_size (5, path_len));
+                       dpath = xmalloc(combine_diff_path_size(5, path_len));
                        dpath->path = (char *) &(dpath->parent[5]);
 
                        dpath->next = NULL;
                        dpath->len = path_len;
                        memcpy(dpath->path, ce->name, path_len);
                        dpath->path[path_len] = '\0';
-                       dpath->mode = 0;
                        hashclr(dpath->sha1);
                        memset(&(dpath->parent[0]), 0,
-                                       sizeof(struct combine_diff_parent)*5);
+                              sizeof(struct combine_diff_parent)*5);
+
+                       if (lstat(ce->name, &st) < 0) {
+                               if (errno != ENOENT && errno != ENOTDIR) {
+                                       perror(ce->name);
+                                       continue;
+                               }
+                               if (silent_on_removed)
+                                       continue;
+                       }
+                       else
+                               dpath->mode = canon_mode(st.st_mode);
 
                        while (i < entries) {
                                struct cache_entry *nce = active_cache[i];
@@ -331,6 +346,9 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
                    S_ISREG(newmode) && S_ISREG(oldmode) &&
                    ((newmode ^ oldmode) == 0111))
                        newmode = oldmode;
+               else if (!has_symlinks &&
+                   S_ISREG(newmode) && S_ISLNK(oldmode))
+                       newmode = oldmode;
                diff_change(&revs->diffopt, oldmode, newmode,
                            ce->sha1, (changed ? null_sha1 : ce->sha1),
                            ce->name, NULL);
@@ -559,10 +577,6 @@ int run_diff_index(struct rev_info *revs, int cached)
        if (!revs->ignore_merges)
                match_missing = 1;
 
-       if (read_cache() < 0) {
-               perror("read_cache");
-               return -1;
-       }
        mark_merge_entries();
 
        ent = revs->pending.objects[0].item;