Evil Merge branch 'jc/status' (early part) into js/diff-ni
authorJunio C Hamano <junkio@cox.net>
Sat, 24 Feb 2007 10:20:13 +0000 (02:20 -0800)
committerJunio C Hamano <junkio@cox.net>
Sat, 24 Feb 2007 10:20:13 +0000 (02:20 -0800)
* 'jc/status' (early part):
run_diff_{files,index}(): update calling convention.
update-index: do not die too early in a read-only repository.
git-status: do not be totally useless in a read-only repository.

This is to resolve semantic conflict (which is not textual) that
changes the calling convention of run_diff_files() early.

1  2 
builtin-diff.c
builtin-update-index.c
diff-lib.c
diff --combined builtin-diff.c
index 54bbf025d94d7925312b39f22766b6def4c0212b,12d11f0c555d2ba80b2f14d4a43c13733574330e..45faa2067a7f15286216c0323de0bf0ed5ef0f4c
@@@ -25,6 -25,44 +25,6 @@@ struct blobinfo 
  static const char builtin_diff_usage[] =
  "git-diff <options> <rev>{0,2} -- <path>*";
  
 -static int builtin_diff_files(struct rev_info *revs,
 -                            int argc, const char **argv)
 -{
 -      int silent = 0;
 -      while (1 < argc) {
 -              const char *arg = argv[1];
 -              if (!strcmp(arg, "--base"))
 -                      revs->max_count = 1;
 -              else if (!strcmp(arg, "--ours"))
 -                      revs->max_count = 2;
 -              else if (!strcmp(arg, "--theirs"))
 -                      revs->max_count = 3;
 -              else if (!strcmp(arg, "-q"))
 -                      silent = 1;
 -              else
 -                      usage(builtin_diff_usage);
 -              argv++; argc--;
 -      }
 -      /*
 -       * Make sure there are NO revision (i.e. pending object) parameter,
 -       * specified rev.max_count is reasonable (0 <= n <= 3), and
 -       * there is no other revision filtering parameter.
 -       */
 -      if (revs->pending.nr ||
 -          revs->min_age != -1 ||
 -          revs->max_age != -1 ||
 -          3 < revs->max_count)
 -              usage(builtin_diff_usage);
 -      if (revs->max_count < 0 &&
 -          (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
 -              revs->combine_merges = revs->dense_combined_merges = 1;
 -      if (read_cache() < 0) {
 -              perror("read_cache");
 -              return -1;
 -      }
 -      return run_diff_files(revs, silent);
 -}
 -
  static void stuff_change(struct diff_options *opt,
                         unsigned old_mode, unsigned new_mode,
                         const unsigned char *old_sha1,
@@@ -117,6 -155,10 +117,10 @@@ static int builtin_diff_index(struct re
            revs->max_count != -1 || revs->min_age != -1 ||
            revs->max_age != -1)
                usage(builtin_diff_usage);
+       if (read_cache() < 0) {
+               perror("read_cache");
+               return -1;
+       }
        return run_diff_index(revs, cached);
  }
  
@@@ -184,7 -226,6 +188,7 @@@ int cmd_diff(int argc, const char **arg
        int ents = 0, blobs = 0, paths = 0;
        const char *path = NULL;
        struct blobinfo blob[2];
 +      int nongit = 0;
  
        /*
         * We could get N tree-ish in the rev.pending_objects list.
         * Other cases are errors.
         */
  
 +      prefix = setup_git_directory_gently(&nongit);
        git_config(git_diff_ui_config);
        init_revisions(&rev, prefix);
  
        if (!ents) {
                switch (blobs) {
                case 0:
 -                      return builtin_diff_files(&rev, argc, argv);
 +                      return run_diff_files_cmd(&rev, argc, argv);
                        break;
                case 1:
                        if (paths != 1)
diff --combined builtin-update-index.c
index 772aaba7bbfded782cd9c0adbc4199fdac0de642,3fbdc67b8880a7d1b46e39d1b7d03c00d65b1408..65246dad8d075de3f77454494c419000288c9ed2
@@@ -109,17 -109,16 +109,17 @@@ static int add_file_to_cache(const cha
        ce->ce_flags = htons(namelen);
        fill_stat_cache_info(ce, &st);
  
 -      ce->ce_mode = create_ce_mode(st.st_mode);
 -      if (!trust_executable_bit) {
 +      if (trust_executable_bit)
 +              ce->ce_mode = create_ce_mode(st.st_mode);
 +      else {
                /* If there is an existing entry, pick the mode bits
                 * from it, otherwise assume unexecutable.
                 */
 +              struct cache_entry *ent;
                int pos = cache_name_pos(path, namelen);
 -              if (0 <= pos)
 -                      ce->ce_mode = active_cache[pos]->ce_mode;
 -              else if (S_ISREG(st.st_mode))
 -                      ce->ce_mode = create_ce_mode(S_IFREG | 0666);
 +
 +              ent = (0 <= pos) ? active_cache[pos] : NULL;
 +              ce->ce_mode = ce_mode_from_stat(ent, st.st_mode);
        }
  
        if (index_path(ce->sha1, path, &st, !info_only))
@@@ -487,6 -486,7 +487,7 @@@ int cmd_update_index(int argc, const ch
        int prefix_length = prefix ? strlen(prefix) : 0;
        char set_executable_bit = 0;
        unsigned int refresh_flags = 0;
+       int lock_error = 0;
        struct lock_file *lock_file;
  
        git_config(git_default_config);
        /* We can't free this memory, it becomes part of a linked list parsed atexit() */
        lock_file = xcalloc(1, sizeof(struct lock_file));
  
-       newfd = hold_lock_file_for_update(lock_file, get_index_file(), 1);
+       newfd = hold_lock_file_for_update(lock_file, get_index_file(), 0);
+       if (newfd < 0)
+               lock_error = errno;
  
        entries = read_cache();
        if (entries < 0)
  
   finish:
        if (active_cache_changed) {
+               if (newfd < 0) {
+                       if (refresh_flags & REFRESH_QUIET)
+                               exit(128);
+                       die("unable to create '%s.lock': %s",
+                           get_index_file(), strerror(lock_error));
+               }
                if (write_cache(newfd, active_cache, active_nr) ||
                    close(newfd) || commit_lock_file(lock_file))
                        die("Unable to write new index file");
diff --combined diff-lib.c
index a9b5149d1ba57d9721e0ee5aff71dcd7c1c6cf73,278ba79ee633b8109be2083597d43286c0ae08d8..1d184422a5e8645684702e239051948ca386d318
  #include "diffcore.h"
  #include "revision.h"
  #include "cache-tree.h"
 +#include "path-list.h"
  
  /*
   * diff-files
   */
  
 +static int read_directory(const char *path, struct path_list *list)
 +{
 +      DIR *dir;
 +      struct dirent *e;
 +
 +      if (!(dir = opendir(path)))
 +              return error("Could not open directory %s", path);
 +
 +      while ((e = readdir(dir)))
 +              if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
 +                      path_list_insert(xstrdup(e->d_name), list);
 +
 +      closedir(dir);
 +      return 0;
 +}
 +
 +static int queue_diff(struct diff_options *o,
 +              const char *name1, const char *name2)
 +{
 +      struct stat st;
 +      int mode1 = 0, mode2 = 0;
 +
 +      if (name1) {
 +              if (stat(name1, &st))
 +                      return error("Could not access '%s'", name1);
 +              mode1 = st.st_mode;
 +      }
 +      if (name2) {
 +              if (stat(name2, &st))
 +                      return error("Could not access '%s'", name1);
 +              mode2 = st.st_mode;
 +      }
 +
 +      if (mode1 && mode2 && S_ISDIR(mode1) != S_ISDIR(mode2))
 +              return error("file/directory conflict: %s, %s", name1, name2);
 +
 +      if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
 +              char buffer1[PATH_MAX], buffer2[PATH_MAX];
 +              struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
 +              int len1 = 0, len2 = 0, i1, i2, ret = 0;
 +
 +              if (name1 && read_directory(name1, &p1))
 +                      return -1;
 +              if (name2 && read_directory(name2, &p2)) {
 +                      path_list_clear(&p1, 0);
 +                      return -1;
 +              }
 +
 +              if (name1) {
 +                      len1 = strlen(name1);
 +                      if (len1 > 0 && name1[len1 - 1] == '/')
 +                              len1--;
 +                      memcpy(buffer1, name1, len1);
 +                      buffer1[len1++] = '/';
 +              }
 +
 +              if (name2) {
 +                      len2 = strlen(name2);
 +                      if (len2 > 0 && name2[len2 - 1] == '/')
 +                              len2--;
 +                      memcpy(buffer2, name2, len2);
 +                      buffer2[len2++] = '/';
 +              }
 +
 +              for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
 +                      const char *n1, *n2;
 +                      int comp;
 +
 +                      if (i1 == p1.nr)
 +                              comp = 1;
 +                      else if (i2 == p2.nr)
 +                              comp = -1;
 +                      else
 +                              comp = strcmp(p1.items[i1].path,
 +                                      p2.items[i2].path);
 +
 +                      if (comp > 0)
 +                              n1 = NULL;
 +                      else {
 +                              n1 = buffer1;
 +                              strncpy(buffer1 + len1, p1.items[i1++].path,
 +                                              PATH_MAX - len1);
 +                      }
 +
 +                      if (comp < 0)
 +                              n2 = NULL;
 +                      else {
 +                              n2 = buffer2;
 +                              strncpy(buffer2 + len2, p2.items[i2++].path,
 +                                              PATH_MAX - len2);
 +                      }
 +
 +                      ret = queue_diff(o, n1, n2);
 +              }
 +              path_list_clear(&p1, 0);
 +              path_list_clear(&p2, 0);
 +
 +              return ret;
 +      } else {
 +              struct diff_filespec *d1, *d2;
 +
 +              if (o->reverse_diff) {
 +                      unsigned tmp;
 +                      const char *tmp_c;
 +                      tmp = mode1; mode1 = mode2; mode2 = tmp;
 +                      tmp_c = name1; name1 = name2; name2 = tmp_c;
 +              }
 +
 +              if (!name1)
 +                      name1 = "/dev/null";
 +              if (!name2)
 +                      name2 = "/dev/null";
 +              d1 = alloc_filespec(name1);
 +              d2 = alloc_filespec(name2);
 +              fill_filespec(d1, null_sha1, mode1);
 +              fill_filespec(d2, null_sha1, mode2);
 +
 +              diff_queue(&diff_queued_diff, d1, d2);
 +              return 0;
 +      }
 +}
 +
 +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 == '/';
 +}
 +
 +static int handle_diff_files_args(struct rev_info *revs,
 +              int argc, const char **argv, int *silent)
 +{
 +      *silent = 0;
 +
 +      /* revs->max_count == -2 means --no-index */
 +      while (1 < argc && argv[1][0] == '-') {
 +              if (!strcmp(argv[1], "--base"))
 +                      revs->max_count = 1;
 +              else if (!strcmp(argv[1], "--ours"))
 +                      revs->max_count = 2;
 +              else if (!strcmp(argv[1], "--theirs"))
 +                      revs->max_count = 3;
 +              else if (!strcmp(argv[1], "-n") ||
 +                              !strcmp(argv[1], "--no-index"))
 +                      revs->max_count = -2;
 +              else if (!strcmp(argv[1], "-q"))
 +                      *silent = 1;
 +              else
 +                      return error("invalid option: %s", argv[1]);
 +              argv++; argc--;
 +      }
 +
 +      if (revs->max_count == -1 && revs->diffopt.nr_paths == 2) {
 +              /*
 +               * If two files are specified, and at least one is untracked,
 +               * default to no-index.
 +               */
 +              read_cache();
 +              if (!is_in_index(revs->diffopt.paths[0]) ||
 +                                      !is_in_index(revs->diffopt.paths[1]))
 +                      revs->max_count = -2;
 +      }
 +
 +      /*
 +       * Make sure there are NO revision (i.e. pending object) parameter,
 +       * rev.max_count is reasonable (0 <= n <= 3),
 +       * there is no other revision filtering parameters.
 +       */
 +      if (revs->pending.nr || revs->max_count > 3 ||
 +          revs->min_age != -1 || revs->max_age != -1)
 +              return error("no revision allowed with diff-files");
 +
 +      if (revs->max_count == -1 &&
 +          (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
 +              revs->combine_merges = revs->dense_combined_merges = 1;
 +
 +      return 0;
 +}
 +
 +int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
 +{
 +      int silent_on_removed;
 +
 +      if (handle_diff_files_args(revs, argc, argv, &silent_on_removed))
 +              return -1;
 +
 +      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]);
 +              diffcore_std(&revs->diffopt);
 +              diff_flush(&revs->diffopt);
 +              return 0;
 +      }
 +
++      if (read_cache() < 0) {
++              perror("read_cache");
++              return -1;
++      }
 +      return run_diff_files(revs, silent_on_removed);
 +}
 +
  int run_diff_files(struct rev_info *revs, int silent_on_removed)
  {
        int entries, i;
  
        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;
@@@ -377,7 -166,9 +377,7 @@@ static int get_stat_data(struct cache_e
                }
                changed = ce_match_stat(ce, &st, 0);
                if (changed) {
 -                      mode = create_ce_mode(st.st_mode);
 -                      if (!trust_executable_bit && S_ISREG(st.st_mode))
 -                              mode = ce->ce_mode;
 +                      mode = ce_mode_from_stat(ce, st.st_mode);
                        sha1 = no_sha1;
                }
        }
@@@ -559,10 -350,6 +559,6 @@@ int run_diff_index(struct rev_info *rev
        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;