Merge branch 'cw/log-updates-for-all-refs-really'
authorJunio C Hamano <gitster@pobox.com>
Fri, 3 Feb 2017 19:25:19 +0000 (11:25 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 3 Feb 2017 19:25:19 +0000 (11:25 -0800)
The "core.logAllRefUpdates" that used to be boolean has been
enhanced to take 'always' as well, to record ref updates to refs
other than the ones that are expected to be updated (i.e. branches,
remote-tracking branches and notes).

* cw/log-updates-for-all-refs-really:
doc: add note about ignoring '--no-create-reflog'
update-ref: add test cases for bare repository
refs: add option core.logAllRefUpdates = always
config: add markup to core.logAllRefUpdates doc

1  2 
Documentation/config.txt
Documentation/git-tag.txt
builtin/checkout.c
cache.h
refs/files-backend.c
t/t7004-tag.sh
diff --combined Documentation/config.txt
index fc78139c21009f6991b8bed4c56509a8a2ab2c43,d1fab67ca6ef72e42c0f06360509bf26224dbd27..fc5a28a3204b5c3d23cbce43679d5b04f3ff957b
@@@ -170,9 -170,6 +170,9 @@@ The position of any attributes with res
  be turned off by prefixing them with `no` or `no-` (e.g., `noreverse`,
  `no-ul`, etc).
  +
 +An empty color string produces no color effect at all. This can be used
 +to avoid coloring specific elements without disabling color entirely.
 ++
  For git's pre-defined color slots, the attributes are meant to be reset
  at the beginning of each item in the colored output. So setting
  `color.decorate.branch` to `black` will paint that branch name in a
@@@ -520,10 -517,12 +520,12 @@@ core.logAllRefUpdates:
        "`$GIT_DIR/logs/<ref>`", by appending the new and old
        SHA-1, the date/time and the reason of the update, but
        only when the file exists.  If this configuration
-       variable is set to true, missing "`$GIT_DIR/logs/<ref>`"
+       variable is set to `true`, missing "`$GIT_DIR/logs/<ref>`"
        file is automatically created for branch heads (i.e. under
-       refs/heads/), remote refs (i.e. under refs/remotes/),
-       note refs (i.e. under refs/notes/), and the symbolic ref HEAD.
+       `refs/heads/`), remote refs (i.e. under `refs/remotes/`),
+       note refs (i.e. under `refs/notes/`), and the symbolic ref `HEAD`.
+       If it is set to `always`, then a missing reflog is automatically
+       created for any ref under `refs/`.
  +
  This information can be used to determine what commit
  was the tip of a branch "2 days ago".
@@@ -2039,10 -2038,6 +2041,10 @@@ log.follow:
        i.e. it cannot be used to follow multiple files and does not work well
        on non-linear history.
  
 +log.graphColors::
 +      A list of colors, separated by commas, that can be used to draw
 +      history lines in `git log --graph`.
 +
  log.showRoot::
        If true, the initial commit will be shown as a big creation event.
        This is equivalent to a diff against an empty tree.
index 8e70c5b6a4117034eb55969bd0a8d0702ae75d71,1d2e9a05f68e8248d129489125080e4c3f70bf27..525737a5d891bb4a8b4df92c26a20550a927a0b9
@@@ -15,7 -15,7 +15,7 @@@ SYNOPSI
  'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
        [--column[=<options>] | --no-column] [--create-reflog] [--sort=<key>]
        [--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
 -'git tag' -v <tagname>...
 +'git tag' -v [--format=<format>] <tagname>...
  
  DESCRIPTION
  -----------
@@@ -150,7 -150,11 +150,11 @@@ This option is only applicable when lis
        'strip' removes both whitespace and commentary.
  
  --create-reflog::
-       Create a reflog for the tag.
+       Create a reflog for the tag. To globally enable reflogs for tags, see
+       `core.logAllRefUpdates` in linkgit:git-config[1].
+       The negated form `--no-create-reflog` only overrides an earlier
+       `--create-reflog`, but currently does not negate the setting of
+       `core.logallrefupdates`.
  
  <tagname>::
        The name of the tag to create, delete, or describe.
diff --combined builtin/checkout.c
index 80d5e389813bed951b63ae5bd8e4347af4da53df,569912c3ab9051c5e5a40d3625c194c23d769993..f174f503033ea7f1274fc8f09c49c0ae378c9eee
@@@ -56,8 -56,8 +56,8 @@@ static int post_checkout_hook(struct co
                              int changed)
  {
        return run_hook_le(NULL, "post-checkout",
 -                         sha1_to_hex(old ? old->object.oid.hash : null_sha1),
 -                         sha1_to_hex(new ? new->object.oid.hash : null_sha1),
 +                         oid_to_hex(old ? &old->object.oid : &null_oid),
 +                         oid_to_hex(new ? &new->object.oid : &null_oid),
                           changed ? "1" : "0", NULL);
        /* "new" can be NULL when checking out from the index before
           a commit exists. */
@@@ -612,22 -612,25 +612,25 @@@ static void update_refs_for_switch(cons
        const char *old_desc, *reflog_msg;
        if (opts->new_branch) {
                if (opts->new_orphan_branch) {
-                       if (opts->new_branch_log && !log_all_ref_updates) {
+                       char *refname;
+                       refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
+                       if (opts->new_branch_log &&
+                           !should_autocreate_reflog(refname)) {
                                int ret;
-                               char *refname;
                                struct strbuf err = STRBUF_INIT;
  
-                               refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
                                ret = safe_create_reflog(refname, 1, &err);
-                               free(refname);
                                if (ret) {
                                        fprintf(stderr, _("Can not do reflog for '%s': %s\n"),
                                                opts->new_orphan_branch, err.buf);
                                        strbuf_release(&err);
+                                       free(refname);
                                        return;
                                }
                                strbuf_release(&err);
                        }
+                       free(refname);
                }
                else
                        create_branch(opts->new_branch, new->name,
diff --combined cache.h
index e26566a8ec3f9aae6547da4303ad62c013146208,96eeaaf7fb22ccd9b3d565b351f2b6478b1df4a5..61fc86e6d7199518555632a0b0b584471b9083a8
+++ b/cache.h
@@@ -507,12 -507,9 +507,12 @@@ extern int is_nonbare_repository_dir(st
  #define READ_GITFILE_ERR_NO_PATH 6
  #define READ_GITFILE_ERR_NOT_A_REPO 7
  #define READ_GITFILE_ERR_TOO_LARGE 8
 +extern void read_gitfile_error_die(int error_code, const char *path, const char *dir);
  extern const char *read_gitfile_gently(const char *path, int *return_error_code);
  #define read_gitfile(path) read_gitfile_gently((path), NULL)
 -extern const char *resolve_gitdir(const char *suspect);
 +extern const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
 +#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
 +
  extern void set_git_work_tree(const char *tree);
  
  #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
@@@ -577,26 -574,7 +577,26 @@@ extern int verify_path(const char *path
  extern int index_dir_exists(struct index_state *istate, const char *name, int namelen);
  extern void adjust_dirname_case(struct index_state *istate, char *name);
  extern struct cache_entry *index_file_exists(struct index_state *istate, const char *name, int namelen, int igncase);
 +
 +/*
 + * Searches for an entry defined by name and namelen in the given index.
 + * If the return value is positive (including 0) it is the position of an
 + * exact match. If the return value is negative, the negated value minus 1
 + * is the position where the entry would be inserted.
 + * Example: The current index consists of these files and its stages:
 + *
 + *   b#0, d#0, f#1, f#3
 + *
 + * index_name_pos(&index, "a", 1) -> -1
 + * index_name_pos(&index, "b", 1) ->  0
 + * index_name_pos(&index, "c", 1) -> -2
 + * index_name_pos(&index, "d", 1) ->  1
 + * index_name_pos(&index, "e", 1) -> -3
 + * index_name_pos(&index, "f", 1) -> -3
 + * index_name_pos(&index, "g", 1) -> -5
 + */
  extern int index_name_pos(const struct index_state *, const char *name, int namelen);
 +
  #define ADD_CACHE_OK_TO_ADD 1         /* Ok to add */
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
  #define ADD_CACHE_SKIP_DFCHECK 4      /* Ok to skip DF conflict checks */
  #define ADD_CACHE_KEEP_CACHE_TREE 32  /* Do not invalidate cache-tree */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
 +
 +/* Remove entry, return true if there are more entries to go. */
  extern int remove_index_entry_at(struct index_state *, int pos);
 +
  extern void remove_marked_cache_entries(struct index_state *istate);
  extern int remove_file_from_index(struct index_state *, const char *path);
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_IGNORE_ERRORS       4
  #define ADD_CACHE_IGNORE_REMOVAL 8
  #define ADD_CACHE_INTENT 16
 +/*
 + * These two are used to add the contents of the file at path
 + * to the index, marking the working tree up-to-date by storing
 + * the cached stat info in the resulting cache entry.  A caller
 + * that has already run lstat(2) on the path can call
 + * add_to_index(), and all others can call add_file_to_index();
 + * the latter will do necessary lstat(2) internally before
 + * calling the former.
 + */
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
 +
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, unsigned int refresh_options);
  extern int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
  extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
@@@ -695,7 -660,6 +695,6 @@@ extern int minimum_abbrev, default_abbr
  extern int ignore_case;
  extern int assume_unchanged;
  extern int prefer_symlink_refs;
- extern int log_all_ref_updates;
  extern int warn_ambiguous_refs;
  extern int warn_on_object_refname_ambiguity;
  extern const char *apply_default_whitespace;
@@@ -763,6 -727,14 +762,14 @@@ enum hide_dotfiles_type 
  };
  extern enum hide_dotfiles_type hide_dotfiles;
  
+ enum log_refs_config {
+       LOG_REFS_UNSET = -1,
+       LOG_REFS_NONE = 0,
+       LOG_REFS_NORMAL,
+       LOG_REFS_ALWAYS
+ };
+ extern enum log_refs_config log_all_ref_updates;
  enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
@@@ -1104,7 -1076,6 +1111,7 @@@ const char *real_path(const char *path)
  const char *real_path_if_valid(const char *path);
  char *real_pathdup(const char *path);
  const char *absolute_path(const char *path);
 +char *absolute_pathdup(const char *path);
  const char *remove_leading_path(const char *in, const char *prefix);
  const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
  int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
@@@ -1178,19 -1149,6 +1185,19 @@@ extern int finalize_object_file(const c
  
  extern int has_sha1_pack(const unsigned char *sha1);
  
 +/*
 + * Open the loose object at path, check its sha1, and return the contents,
 + * type, and size. If the object is a blob, then "contents" may return NULL,
 + * to allow streaming of large blobs.
 + *
 + * Returns 0 on success, negative on error (details may be written to stderr).
 + */
 +int read_loose_object(const char *path,
 +                    const unsigned char *expected_sha1,
 +                    enum object_type *type,
 +                    unsigned long *size,
 +                    void **contents);
 +
  /*
   * Return true iff we have an object named sha1, whether local or in
   * an alternate object database, and whether packed or loose.  This
diff --combined refs/files-backend.c
index 8ee2aba39f2b0bae36e66bc65610b429543bc1d8,14b17a63f855a203a34dc8ce78ae11beadf77e61..c041d4ba21a8fe70eb6d8277358e7e3f29a69bfb
@@@ -697,7 -697,7 +697,7 @@@ static int cache_ref_iterator_peel(stru
  
        if (peel_entry(entry, 0))
                return -1;
 -      hashcpy(peeled->hash, entry->u.value.peeled.hash);
 +      oidcpy(peeled, &entry->u.value.peeled);
        return 0;
  }
  
@@@ -2682,7 -2682,7 +2682,7 @@@ static int files_rename_ref(struct ref_
        }
  
        flag = log_all_ref_updates;
-       log_all_ref_updates = 0;
+       log_all_ref_updates = LOG_REFS_NONE;
        if (write_ref_to_lockfile(lock, orig_sha1, &err) ||
            commit_ref_update(refs, lock, orig_sha1, NULL, &err)) {
                error("unable to write current sha1 into %s: %s", oldrefname, err.buf);
@@@ -2835,8 -2835,8 +2835,8 @@@ static int log_ref_write_1(const char *
  {
        int logfd, result, oflags = O_APPEND | O_WRONLY;
  
-       if (log_all_ref_updates < 0)
-               log_all_ref_updates = !is_bare_repository();
+       if (log_all_ref_updates == LOG_REFS_UNSET)
+               log_all_ref_updates = is_bare_repository() ? LOG_REFS_NONE : LOG_REFS_NORMAL;
  
        result = log_ref_setup(refname, logfile, err, flags & REF_FORCE_CREATE_REFLOG);
  
diff --combined t/t7004-tag.sh
index b676b90c7dfd8bf743e788f07aedc2a4a8053540,1bf622de23cd7ee70a15d32c696ed31dcc799718..072e6c6b88447f21e89a0087d894ae8ab2868ad7
@@@ -71,6 -71,7 +71,7 @@@ test_expect_success 'creating a tag fo
  
  # commit used in the tests, test_tick is also called here to freeze the date:
  test_expect_success 'creating a tag using default HEAD should succeed' '
+       test_config core.logAllRefUpdates true &&
        test_tick &&
        echo foo >foo &&
        git add foo &&
@@@ -90,6 -91,13 +91,13 @@@ test_expect_success '--create-reflog do
        test_must_fail git reflog exists refs/tags/mytag
  '
  
+ test_expect_success 'option core.logAllRefUpdates=always creates reflog' '
+       test_when_finished "git tag -d tag_with_reflog" &&
+       test_config core.logAllRefUpdates always &&
+       git tag tag_with_reflog &&
+       git reflog exists refs/tags/tag_with_reflog
+ '
  test_expect_success 'listing all tags if one exists should succeed' '
        git tag -l &&
        git tag
@@@ -871,22 -879,6 +879,22 @@@ test_expect_success GPG 'verifying a fo
        test_must_fail git tag -v forged-tag
  '
  
 +test_expect_success 'verifying a proper tag with --format pass and format accordingly' '
 +      cat >expect <<-\EOF
 +      tagname : signed-tag
 +      EOF &&
 +      git tag -v --format="tagname : %(tag)" "signed-tag" >actual &&
 +      test_cmp expect actual
 +'
 +
 +test_expect_success 'verifying a forged tag with --format fail and format accordingly' '
 +      cat >expect <<-\EOF
 +      tagname : forged-tag
 +      EOF &&
 +      test_must_fail git tag -v --format="tagname : %(tag)" "forged-tag" >actual &&
 +      test_cmp expect actual
 +'
 +
  # blank and empty messages for signed tags:
  
  get_tag_header empty-signed-tag $commit commit $time >expect