Merge branch 'jk/log-missing-default-HEAD'
authorJunio C Hamano <gitster@pobox.com>
Wed, 2 Sep 2015 19:50:08 +0000 (12:50 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Sep 2015 19:50:10 +0000 (12:50 -0700)
"git init empty && git -C empty log" said "bad default revision 'HEAD'",
which was found to be a bit confusing to new users.

* jk/log-missing-default-HEAD:
log: diagnose empty HEAD more clearly

1  2 
revision.c
t/t4202-log.sh
diff --combined revision.c
index 5350139599d7d9fe542423ab9042962b75821dae,734494abe6af2288e2f0bf6ad31eb5b74db9ea9c..af2a18ed7485ea83170409ce55f81473ee606221
  #include "commit-slab.h"
  #include "dir.h"
  #include "cache-tree.h"
 +#include "bisect.h"
  
  volatile show_early_output_fn_t show_early_output;
  
 +static const char *term_bad;
 +static const char *term_good;
 +
  char *path_name(const struct name_path *path, const char *name)
  {
        const struct name_path *p;
@@@ -365,8 -361,8 +365,8 @@@ static int everybody_uninteresting(stru
                list = list->next;
                if (commit->object.flags & UNINTERESTING)
                        continue;
 -              if (interesting_cache)
 -                      *interesting_cache = commit;
 +
 +              *interesting_cache = commit;
                return 0;
        }
        return 1;
@@@ -821,7 -817,7 +821,7 @@@ static int add_parents_to_list(struct r
                        parent = parent->next;
                        if (p)
                                p->object.flags |= UNINTERESTING;
 -                      if (parse_commit(p) < 0)
 +                      if (parse_commit_gently(p, 1) < 0)
                                continue;
                        if (p->parents)
                                mark_parents_uninteresting(p);
        for (parent = commit->parents; parent; parent = parent->next) {
                struct commit *p = parent->item;
  
 -              if (parse_commit(p) < 0)
 +              if (parse_commit_gently(p, revs->ignore_missing_links) < 0)
                        return -1;
                if (revs->show_source && !p->util)
                        p->util = commit->util;
@@@ -1222,8 -1218,7 +1222,8 @@@ int ref_excluded(struct string_list *re
        return 0;
  }
  
 -static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int handle_one_ref(const char *path, const struct object_id *oid,
 +                        int flag, void *cb_data)
  {
        struct all_refs_cb *cb = cb_data;
        struct object *object;
        if (ref_excluded(cb->all_revs->ref_excludes, path))
            return 0;
  
 -      object = get_reference(cb->all_revs, path, sha1, cb->all_flags);
 +      object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags);
        add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
 -      add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags);
 +      add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags);
        return 0;
  }
  
@@@ -1297,8 -1292,7 +1297,8 @@@ static int handle_one_reflog_ent(unsign
        return 0;
  }
  
 -static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 +static int handle_one_reflog(const char *path, const struct object_id *oid,
 +                           int flag, void *cb_data)
  {
        struct all_refs_cb *cb = cb_data;
        cb->warned_bad_reflog = 0;
  void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
  {
        struct all_refs_cb cb;
 +
        cb.all_revs = revs;
        cb.all_flags = flags;
        for_each_reflog(handle_one_reflog, &cb);
@@@ -2000,10 -1993,10 +2000,10 @@@ static int handle_revision_opt(struct r
        } else if (!strcmp(arg, "--full-history")) {
                revs->simplify_history = 0;
        } else if (!strcmp(arg, "--relative-date")) {
 -              revs->date_mode = DATE_RELATIVE;
 +              revs->date_mode.type = DATE_RELATIVE;
                revs->date_mode_explicit = 1;
        } else if ((argcount = parse_long_opt("date", argv, &optarg))) {
 -              revs->date_mode = parse_date_format(optarg);
 +              parse_date_format(optarg, &revs->date_mode);
                revs->date_mode_explicit = 1;
                return argcount;
        } else if (!strcmp(arg, "--log-size")) {
@@@ -2080,23 -2073,14 +2080,23 @@@ void parse_revision_opt(struct rev_inf
        ctx->argc -= n;
  }
  
 +static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) {
 +      struct strbuf bisect_refs = STRBUF_INIT;
 +      int status;
 +      strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
 +      status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data);
 +      strbuf_release(&bisect_refs);
 +      return status;
 +}
 +
  static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
  {
 -      return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data);
 +      return for_each_bisect_ref(submodule, fn, cb_data, term_bad);
  }
  
  static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data)
  {
 -      return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data);
 +      return for_each_bisect_ref(submodule, fn, cb_data, term_good);
  }
  
  static int handle_revision_pseudo_opt(const char *submodule,
                handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
                clear_ref_exclusion(&revs->ref_excludes);
        } else if (!strcmp(arg, "--bisect")) {
 +              read_bisect_terms(&term_bad, &term_good);
                handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
                handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
                revs->bisect = 1;
        return 1;
  }
  
+ static void NORETURN diagnose_missing_default(const char *def)
+ {
+       unsigned char sha1[20];
+       int flags;
+       const char *refname;
+       refname = resolve_ref_unsafe(def, 0, sha1, &flags);
+       if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
+               die(_("your current branch appears to be broken"));
+       skip_prefix(refname, "refs/heads/", &refname);
+       die(_("your current branch '%s' does not have any commits yet"),
+           refname);
+ }
  /*
   * Parse revision information, filling in the "rev_info" structure,
   * and removing the used arguments from the argument list.
@@@ -2316,7 -2314,7 +2331,7 @@@ int setup_revisions(int argc, const cha
                struct object *object;
                struct object_context oc;
                if (get_sha1_with_context(revs->def, 0, sha1, &oc))
-                       die("bad default revision '%s'", revs->def);
+                       diagnose_missing_default(revs->def);
                object = get_reference(revs, revs->def, sha1, 0);
                add_pending_object_with_mode(revs, object, revs->def, oc.mode);
        }
diff --combined t/t4202-log.sh
index 35d2d7c22152e1735293dea1d47488ed5331c6b2,19277dd3618019a97ef0631cc4a808f5e5bcc653..6ede0692f6de9f2da011dd8b7361bfc53aba7253
@@@ -146,30 -146,7 +146,30 @@@ test_expect_success 'git log --follow' 
        actual=$(git log --follow --pretty="format:%s" ichi) &&
        expect=$(echo third ; echo second ; echo initial) &&
        verbose test "$actual" = "$expect"
 +'
 +
 +test_expect_success 'git config log.follow works like --follow' '
 +      test_config log.follow true &&
 +      actual=$(git log --pretty="format:%s" ichi) &&
 +      expect=$(echo third ; echo second ; echo initial) &&
 +      verbose test "$actual" = "$expect"
 +'
  
 +test_expect_success 'git config log.follow does not die with multiple paths' '
 +      test_config log.follow true &&
 +      git log --pretty="format:%s" ichi ein
 +'
 +
 +test_expect_success 'git config log.follow does not die with no paths' '
 +      test_config log.follow true &&
 +      git log --
 +'
 +
 +test_expect_success 'git config log.follow is overridden by --no-follow' '
 +      test_config log.follow true &&
 +      actual=$(git log --no-follow --pretty="format:%s" ichi) &&
 +      expect="third" &&
 +      verbose test "$actual" = "$expect"
  '
  
  cat > expect << EOF
@@@ -894,4 -871,18 +894,18 @@@ test_expect_success 'log --graph --no-w
        test_must_fail git log --graph --no-walk
  '
  
+ test_expect_success 'log diagnoses bogus HEAD' '
+       git init empty &&
+       test_must_fail git -C empty log 2>stderr &&
+       test_i18ngrep does.not.have.any.commits stderr &&
+       echo 1234abcd >empty/.git/refs/heads/master &&
+       test_must_fail git -C empty log 2>stderr &&
+       test_i18ngrep broken stderr &&
+       echo "ref: refs/heads/invalid.lock" >empty/.git/HEAD &&
+       test_must_fail git -C empty log 2>stderr &&
+       test_i18ngrep broken stderr &&
+       test_must_fail git -C empty log --default totally-bogus 2>stderr &&
+       test_i18ngrep broken stderr
+ '
  test_done