Merge branch 'jc/lock-report-on-error'
authorJunio C Hamano <gitster@pobox.com>
Mon, 19 Dec 2016 22:45:35 +0000 (14:45 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 19 Dec 2016 22:45:35 +0000 (14:45 -0800)
Git 2.11 had a minor regression in "merge --ff-only" that competed
with another process that simultanously attempted to update the
index. We used to explain what went wrong with an error message,
but the new code silently failed. The error message has been
resurrected.

* jc/lock-report-on-error:
lockfile: LOCK_REPORT_ON_ERROR
hold_locked_index(): align error handling with hold_lockfile_for_update()
wt-status: implement opportunisitc index update correctly

1  2 
builtin/clone.c
builtin/commit.c
merge-recursive.c
sequencer.c
diff --combined builtin/clone.c
index e3cb8082f7e83b4f233d55bfba78417ebdada114,892bdbfe3f2752a89da69a86efcfa58ab59aee3f..5ef81927a629985aa4f0de6acba326f79747e7aa
@@@ -99,7 -99,7 +99,7 @@@ static struct option builtin_clone_opti
        OPT_STRING(0, "shallow-since", &option_since, N_("time"),
                    N_("create a shallow clone since a specific time")),
        OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"),
 -                      N_("deepen history of shallow clone by excluding rev")),
 +                      N_("deepen history of shallow clone, excluding rev")),
        OPT_BOOL(0, "single-branch", &option_single_branch,
                    N_("clone only one branch, HEAD or --branch")),
        OPT_BOOL(0, "shallow-submodules", &option_shallow_submodules,
@@@ -711,7 -711,7 +711,7 @@@ static int checkout(int submodule_progr
        setup_work_tree();
  
        lock_file = xcalloc(1, sizeof(struct lock_file));
-       hold_locked_index(lock_file, 1);
+       hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);
  
        memset(&opts, 0, sizeof opts);
        opts.update = 1;
diff --combined builtin/commit.c
index 0ed634b26caf862cae2e64cda30488d7b6377d3f,b910e760179a12032433ad20007d47a992a56255..711f96cc438c0125290a587a0187702121bc461d
@@@ -351,7 -351,7 +351,7 @@@ static const char *prepare_index(int ar
  
        if (interactive) {
                char *old_index_env = NULL;
-               hold_locked_index(&index_lock, 1);
+               hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
  
                refresh_cache_or_die(refresh_flags);
  
         * (B) on failure, rollback the real index.
         */
        if (all || (also && pathspec.nr)) {
-               hold_locked_index(&index_lock, 1);
+               hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
                add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
                refresh_cache_or_die(refresh_flags);
                update_main_cache_tree(WRITE_TREE_SILENT);
         * We still need to refresh the index here.
         */
        if (!only && !pathspec.nr) {
-               hold_locked_index(&index_lock, 1);
+               hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
                refresh_cache_or_die(refresh_flags);
                if (active_cache_changed
                    || !cache_tree_fully_valid(active_cache_tree))
        if (read_cache() < 0)
                die(_("cannot read the index"));
  
-       hold_locked_index(&index_lock, 1);
+       hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
        add_remove_files(&partial);
        refresh_cache(REFRESH_QUIET);
        update_main_cache_tree(WRITE_TREE_SILENT);
@@@ -790,7 -790,7 +790,7 @@@ static int prepare_to_commit(const cha
                strbuf_stripspace(&sb, 0);
  
        if (signoff)
 -              append_signoff(&sb, ignore_non_trailer(&sb), 0);
 +              append_signoff(&sb, ignore_non_trailer(sb.buf, sb.len), 0);
  
        if (fwrite(sb.buf, 1, sb.len, s->fp) < sb.len)
                die_errno(_("could not write commit template"));
@@@ -1206,8 -1206,10 +1206,8 @@@ static int parse_and_validate_options(i
  
        if (also + only + all + interactive > 1)
                die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
 -      if (argc == 0 && (also || (only && !amend)))
 +      if (argc == 0 && (also || (only && !amend && !allow_empty)))
                die(_("No paths with --include/--only does not make sense."));
 -      if (argc == 0 && only && amend)
 -              only_include_assumed = _("Clever... amending the last one with dirty index.");
        if (argc > 0 && !also && !only)
                only_include_assumed = _("Explicit paths specified without -i or -o; assuming --only paths...");
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
diff --combined merge-recursive.c
index 23d6992f4037b37a9c3e133001af16595e8da394,8442068716035b61a448514e3fa7957aed51a597..d3272094430ccd3914c8214df73ba8e11363cfa7
@@@ -235,8 -235,6 +235,8 @@@ static int add_cacheinfo(struct merge_o
                struct cache_entry *nce;
  
                nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
 +              if (!nce)
 +                      return err(o, _("addinfo_cache failed for path '%s'"), path);
                if (nce != ce)
                        ret = add_cache_entry(nce, options);
        }
@@@ -390,10 -388,12 +390,10 @@@ static struct string_list *get_unmerged
        return unmerged;
  }
  
 -static int string_list_df_name_compare(const void *a, const void *b)
 +static int string_list_df_name_compare(const char *one, const char *two)
  {
 -      const struct string_list_item *one = a;
 -      const struct string_list_item *two = b;
 -      int onelen = strlen(one->string);
 -      int twolen = strlen(two->string);
 +      int onelen = strlen(one);
 +      int twolen = strlen(two);
        /*
         * Here we only care that entries for D/F conflicts are
         * adjacent, in particular with the file of the D/F conflict
         * since in other cases any changes in their order due to
         * sorting cause no problems for us.
         */
 -      int cmp = df_name_compare(one->string, onelen, S_IFDIR,
 -                                two->string, twolen, S_IFDIR);
 +      int cmp = df_name_compare(one, onelen, S_IFDIR,
 +                                two, twolen, S_IFDIR);
        /*
         * Now that 'foo' and 'foo/bar' compare equal, we have to make sure
         * that 'foo' comes before 'foo/bar'.
@@@ -451,8 -451,8 +451,8 @@@ static void record_df_conflict_files(st
                string_list_append(&df_sorted_entries, next->string)->util =
                                   next->util;
        }
 -      qsort(df_sorted_entries.items, entries->nr, sizeof(*entries->items),
 -            string_list_df_name_compare);
 +      df_sorted_entries.cmp = string_list_df_name_compare;
 +      string_list_sort(&df_sorted_entries);
  
        string_list_clear(&o->df_conflict_file_set, 1);
        for (i = 0; i < df_sorted_entries.nr; i++) {
@@@ -664,13 -664,7 +664,13 @@@ static char *unique_path(struct merge_o
        return strbuf_detach(&newpath, NULL);
  }
  
 -static int dir_in_way(const char *path, int check_working_copy)
 +/**
 + * Check whether a directory in the index is in the way of an incoming
 + * file.  Return 1 if so.  If check_working_copy is non-zero, also
 + * check the working directory.  If empty_ok is non-zero, also return
 + * 0 in the case where the working-tree dir exists but is empty.
 + */
 +static int dir_in_way(const char *path, int check_working_copy, int empty_ok)
  {
        int pos;
        struct strbuf dirpath = STRBUF_INIT;
        }
  
        strbuf_release(&dirpath);
 -      return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode);
 +      return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode) &&
 +              !(empty_ok && is_empty_dir(path));
  }
  
  static int was_tracked(const char *path)
@@@ -1069,7 -1062,7 +1069,7 @@@ static int handle_change_delete(struct 
  {
        char *renamed = NULL;
        int ret = 0;
 -      if (dir_in_way(path, !o->call_depth)) {
 +      if (dir_in_way(path, !o->call_depth, 0)) {
                renamed = unique_path(o, path, a_oid ? o->branch1 : o->branch2);
        }
  
@@@ -1202,7 -1195,7 +1202,7 @@@ static int handle_file(struct merge_opt
                remove_file(o, 0, rename->path, 0);
                dst_name = unique_path(o, rename->path, cur_branch);
        } else {
 -              if (dir_in_way(rename->path, !o->call_depth)) {
 +              if (dir_in_way(rename->path, !o->call_depth, 0)) {
                        dst_name = unique_path(o, rename->path, cur_branch);
                        output(o, 1, _("%s is a directory in %s adding as %s instead"),
                               rename->path, other_branch, dst_name);
@@@ -1711,8 -1704,7 +1711,8 @@@ static int merge_content(struct merge_o
                         o->branch2 == rename_conflict_info->branch1) ?
                        pair1->two->path : pair1->one->path;
  
 -              if (dir_in_way(path, !o->call_depth))
 +              if (dir_in_way(path, !o->call_depth,
 +                             S_ISGITLINK(pair1->two->mode)))
                        df_conflict_remains = 1;
        }
        if (merge_file_special_markers(o, &one, &a, &b,
@@@ -1870,8 -1862,7 +1870,8 @@@ static int process_entry(struct merge_o
                        oid = b_oid;
                        conf = _("directory/file");
                }
 -              if (dir_in_way(path, !o->call_depth)) {
 +              if (dir_in_way(path, !o->call_depth,
 +                             S_ISGITLINK(a_mode))) {
                        char *new_path = unique_path(o, path, add_branch);
                        clean_merge = 0;
                        output(o, 1, _("CONFLICT (%s): There is a directory with name %s in %s. "
@@@ -2133,7 -2124,7 +2133,7 @@@ int merge_recursive_generic(struct merg
                }
        }
  
-       hold_locked_index(lock, 1);
+       hold_locked_index(lock, LOCK_DIE_ON_ERROR);
        clean = merge_recursive(o, head_commit, next_commit, ca,
                        result);
        if (clean < 0)
diff --combined sequencer.c
index 050e28bbc3d136509e8b7d909b27e9d954fa7754,7fc1e2a5df0ada4816dc3de97e8f6139fbabe635..28061dcb78b5db5711f77da1026c0cb81acee27b
@@@ -16,7 -16,6 +16,7 @@@
  #include "refs.h"
  #include "argv-array.h"
  #include "quote.h"
 +#include "trailer.h"
  
  #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
  
@@@ -57,6 -56,30 +57,6 @@@ static const char *get_todo_path(const 
        return git_path_todo_file();
  }
  
 -static int is_rfc2822_line(const char *buf, int len)
 -{
 -      int i;
 -
 -      for (i = 0; i < len; i++) {
 -              int ch = buf[i];
 -              if (ch == ':')
 -                      return 1;
 -              if (!isalnum(ch) && ch != '-')
 -                      break;
 -      }
 -
 -      return 0;
 -}
 -
 -static int is_cherry_picked_from_line(const char *buf, int len)
 -{
 -      /*
 -       * We only care that it looks roughly like (cherry picked from ...)
 -       */
 -      return len > strlen(cherry_picked_prefix) + 1 &&
 -              starts_with(buf, cherry_picked_prefix) && buf[len - 1] == ')';
 -}
 -
  /*
   * Returns 0 for non-conforming footer
   * Returns 1 for conforming footer
  static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
        int ignore_footer)
  {
 -      char prev;
 -      int i, k;
 -      int len = sb->len - ignore_footer;
 -      const char *buf = sb->buf;
 -      int found_sob = 0;
 -
 -      /* footer must end with newline */
 -      if (!len || buf[len - 1] != '\n')
 -              return 0;
 +      struct trailer_info info;
 +      int i;
 +      int found_sob = 0, found_sob_last = 0;
  
 -      prev = '\0';
 -      for (i = len - 1; i > 0; i--) {
 -              char ch = buf[i];
 -              if (prev == '\n' && ch == '\n') /* paragraph break */
 -                      break;
 -              prev = ch;
 -      }
 +      trailer_info_get(&info, sb->buf);
  
 -      /* require at least one blank line */
 -      if (prev != '\n' || buf[i] != '\n')
 +      if (info.trailer_start == info.trailer_end)
                return 0;
  
 -      /* advance to start of last paragraph */
 -      while (i < len - 1 && buf[i] == '\n')
 -              i++;
 -
 -      for (; i < len; i = k) {
 -              int found_rfc2822;
 -
 -              for (k = i; k < len && buf[k] != '\n'; k++)
 -                      ; /* do nothing */
 -              k++;
 +      for (i = 0; i < info.trailer_nr; i++)
 +              if (sob && !strncmp(info.trailers[i], sob->buf, sob->len)) {
 +                      found_sob = 1;
 +                      if (i == info.trailer_nr - 1)
 +                              found_sob_last = 1;
 +              }
  
 -              found_rfc2822 = is_rfc2822_line(buf + i, k - i - 1);
 -              if (found_rfc2822 && sob &&
 -                  !strncmp(buf + i, sob->buf, sob->len))
 -                      found_sob = k;
 +      trailer_info_release(&info);
  
 -              if (!(found_rfc2822 ||
 -                    is_cherry_picked_from_line(buf + i, k - i - 1)))
 -                      return 0;
 -      }
 -      if (found_sob == i)
 +      if (found_sob_last)
                return 3;
        if (found_sob)
                return 2;
@@@ -323,7 -370,7 +323,7 @@@ static int do_recursive_merge(struct co
        char **xopt;
        static struct lock_file index_lock;
  
-       hold_locked_index(&index_lock, 1);
+       hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
  
        read_cache();