Merge branch 'lf/ref-is-hidden-namespace'
authorJeff King <peff@peff.net>
Fri, 20 Nov 2015 11:56:11 +0000 (06:56 -0500)
committerJeff King <peff@peff.net>
Fri, 20 Nov 2015 11:56:11 +0000 (06:56 -0500)
Extend transfer.hideRefs to work better with use of namespaces.

* lf/ref-is-hidden-namespace:
t5509: add basic tests for hideRefs
hideRefs: add support for matching full refs
upload-pack: strip refs before calling ref_is_hidden()
config.txt: document the semantics of hideRefs with namespaces

13 files changed:
Documentation/RelNotes/2.6.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.7.0.txt
Documentation/git-checkout.txt
Documentation/git.txt
builtin/checkout.c
builtin/count-objects.c
builtin/gc.c
cache.h
http.c
http.h
path.c
sha1_file.c
t/t5304-prune.sh
diff --git a/Documentation/RelNotes/2.6.3.txt b/Documentation/RelNotes/2.6.3.txt
new file mode 100644 (file)
index 0000000..fc6fe17
--- /dev/null
@@ -0,0 +1,111 @@
+Git v2.6.3 Release Notes
+========================
+
+Fixes since v2.6.2
+------------------
+
+ * The error message from "git blame --contents --reverse" incorrectly
+   talked about "--contents --children".
+
+ * "git merge-file" tried to signal how many conflicts it found, which
+   obviously would not work well when there are too many of them.
+
+ * The name-hash subsystem that is used to cope with case insensitive
+   filesystems keeps track of directories and their on-filesystem
+   cases for all the paths in the index by holding a pointer to a
+   randomly chosen cache entry that is inside the directory (for its
+   ce->ce_name component).  This pointer was not updated even when the
+   cache entry was removed from the index, leading to use after free.
+   This was fixed by recording the path for each directory instead of
+   borrowing cache entries and restructuring the API somewhat.
+
+ * When the "git am" command was reimplemented in C, "git am -3" had a
+   small regression where it is aborted in its error handling codepath
+   when underlying merge-recursive failed in some ways.
+
+ * The synopsis text and the usage string of subcommands that read
+   list of things from the standard input are often shown as if they
+   only take input from a file on a filesystem, which was misleading.
+
+ * A couple of commands still showed "[options]" in their usage string
+   to note where options should come on their command line, but we
+   spell that "[<options>]" in most places these days.
+
+ * The submodule code has been taught to work better with separate
+   work trees created via "git worktree add".
+
+ * When "git gc --auto" is backgrounded, its diagnosis message is
+   lost.  It now is saved to a file in $GIT_DIR and is shown next time
+   the "gc --auto" is run.
+
+ * Work around "git p4" failing when the P4 depot records the contents
+   in UTF-16 without UTF-16 BOM.
+
+ * Recent update to "rebase -i" that tries to sanity check the edited
+   insn sheet before it uses it has become too picky on Windows where
+   CRLF left by the editor is turned into a trailing CR on the line
+   read via the "read" built-in command.
+
+ * "git clone --dissociate" runs a big "git repack" process at the
+   end, and it helps to close file descriptors that are open on the
+   packs and their idx files before doing so on filesystems that
+   cannot remove a file that is still open.
+
+ * Correct "git p4 --detect-labels" so that it does not fail to create
+   a tag that points at a commit that is also being imported.
+
+ * The internal stripspace() function has been moved to where it
+   logically belongs to, i.e. strbuf API, and the command line parser
+   of "git stripspace" has been updated to use the parse_options API.
+
+ * Prepare for Git on-disk repository representation to undergo
+   backward incompatible changes by introducing a new repository
+   format version "1", with an extension mechanism.
+
+ * "git gc" used to barf when a symbolic ref has gone dangling
+   (e.g. the branch that used to be your upstream's default when you
+   cloned from it is now gone, and you did "fetch --prune").
+
+ * The normalize_ceiling_entry() function does not muck with the end
+   of the path it accepts, and the real world callers do rely on that,
+   but a test insisted that the function drops a trailing slash.
+
+ * "git gc" is safe to run anytime only because it has the built-in
+   grace period to protect young objects.  In order to run with no
+   grace period, the user must make sure that the repository is
+   quiescent.
+
+ * A recent "filter-branch --msg-filter" broke skipping of the commit
+   object header, which is fixed.
+
+ * "git --literal-pathspecs add -u/-A" without any command line
+   argument misbehaved ever since Git 2.0.
+
+ * Merging a branch that removes a path and another that changes the
+   mode bits on the same path should have conflicted at the path, but
+   it didn't and silently favoured the removal.
+
+ * "git imap-send" did not compile well with older version of cURL library.
+
+ * The linkage order of libraries was wrong in places around libcurl.
+
+ * It was not possible to use a repository-lookalike created by "git
+   worktree add" as a local source of "git clone".
+
+ * When "git send-email" wanted to talk over Net::SMTP::SSL,
+   Net::Cmd::datasend() did not like to be fed too many bytes at the
+   same time and failed to send messages.  Send the payload one line
+   at a time to work around the problem.
+
+ * We peek objects from submodule's object store by linking it to the
+   list of alternate object databases, but the code to do so forgot to
+   correctly initialize the list.
+
+ * "git status --branch --short" accessed beyond the constant string
+   "HEAD", which has been corrected.
+
+ * "git daemon" uses "run_command()" without "finish_command()", so it
+   needs to release resources itself, which it forgot to do.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
index 7facc02e0b00759f7d4190e704b11f7aa59ae226..ca2c24bea259ba531449829f5a6fec80c0bf53b6 100644 (file)
@@ -61,6 +61,11 @@ UI, Workflows & Features
  * "git blame" learnt to take "--first-parent" and "--reverse" at the
    same time when it makes sense.
 
+ * "git checkout" did not follow the usual "--[no-]progress"
+   convention and implemented only "--quiet" that is essentially
+   a superset of "--no-progress".  Extend the command to support the
+   usual "--[no-]progress".
+
 
 Performance, Internal Implementation, Development Support etc.
 
@@ -331,6 +336,11 @@ notes for details).
    not even exist or may be a directory.
    (merge cfe2d4b da/difftool later to maint).
 
+ * A Range: request can be responded with a full response and when
+   asked properly libcurl knows how to strip the result down to the
+   requested range.  However, we were hand-crafting a range request
+   and it did not kick in.
+
  * Code clean-up, minor fixes etc.
    (merge 15ed07d jc/rerere later to maint).
    (merge e7a7401 pt/pull-builtin later to maint).
index e269fb110835305633ccafa6aa87cf1f425f7b8c..5e5273e073c351a3c845043a69916a1773cefd94 100644 (file)
@@ -107,6 +107,12 @@ OPTIONS
 --quiet::
        Quiet, suppress feedback messages.
 
+--[no-]progress::
+       Progress status is reported on the standard error stream
+       by default when it is attached to a terminal, unless `--quiet`
+       is specified. This flag enables progress reporting even if not
+       attached to a terminal, regardless of `--quiet`.
+
 -f::
 --force::
        When switching branches, proceed even if the index or the
index 4585103f996c0e68753520ad5064a1a9879054c8..c2e2a94e754fb0f831f1604634901d4c155784af 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.6.2/git.html[documentation for release 2.6.2]
+* link:v2.6.3/git.html[documentation for release 2.6.3]
 
 * release notes for
+  link:RelNotes/2.6.3.txt[2.6.3],
   link:RelNotes/2.6.2.txt[2.6.2],
   link:RelNotes/2.6.1.txt[2.6.1],
   link:RelNotes/2.6.0.txt[2.6].
index bc703c0f5ed9644b2380ed1f2e20b47238c80e5a..e346f521b0b1c197a3a883cb040080048b970ebb 100644 (file)
@@ -37,6 +37,7 @@ struct checkout_opts {
        int overwrite_ignore;
        int ignore_skipworktree;
        int ignore_other_worktrees;
+       int show_progress;
 
        const char *new_branch;
        const char *new_branch_force;
@@ -417,7 +418,7 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
        opts.reset = 1;
        opts.merge = 1;
        opts.fn = oneway_merge;
-       opts.verbose_update = !o->quiet && isatty(2);
+       opts.verbose_update = o->show_progress;
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
        parse_tree(tree);
@@ -501,7 +502,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge && old->commit;
-               topts.verbose_update = !opts->quiet && isatty(2);
+               topts.verbose_update = opts->show_progress;
                topts.fn = twoway_merge;
                if (opts->overwrite_ignore) {
                        topts.dir = xcalloc(1, sizeof(*topts.dir));
@@ -1156,6 +1157,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
                                N_("second guess 'git checkout <no-such-branch>'")),
                OPT_BOOL(0, "ignore-other-worktrees", &opts.ignore_other_worktrees,
                         N_("do not check if another worktree is holding the given ref")),
+               OPT_BOOL(0, "progress", &opts.show_progress, N_("force progress reporting")),
                OPT_END(),
        };
 
@@ -1163,6 +1165,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        memset(&new, 0, sizeof(new));
        opts.overwrite_ignore = 1;
        opts.prefix = prefix;
+       opts.show_progress = -1;
 
        gitmodules_config();
        git_config(git_checkout_config, &opts);
@@ -1172,6 +1175,13 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
 
+       if (opts.show_progress < 0) {
+               if (opts.quiet)
+                       opts.show_progress = 0;
+               else
+                       opts.show_progress = isatty(2);
+       }
+
        if (conflict_style) {
                opts.merge = 1; /* implied */
                git_xmerge_config("merge.conflictstyle", conflict_style, NULL);
index ad0c79954aa0dfb8b9918500d08dd841d19d4ab3..ba9291944f7752a0b7c671cd4d63309a15ba5df2 100644 (file)
@@ -15,9 +15,31 @@ static int verbose;
 static unsigned long loose, packed, packed_loose;
 static off_t loose_size;
 
-static void real_report_garbage(const char *desc, const char *path)
+static const char *bits_to_msg(unsigned seen_bits)
+{
+       switch (seen_bits) {
+       case 0:
+               return "no corresponding .idx or .pack";
+       case PACKDIR_FILE_GARBAGE:
+               return "garbage found";
+       case PACKDIR_FILE_PACK:
+               return "no corresponding .idx";
+       case PACKDIR_FILE_IDX:
+               return "no corresponding .pack";
+       case PACKDIR_FILE_PACK|PACKDIR_FILE_IDX:
+       default:
+               return NULL;
+       }
+}
+
+static void real_report_garbage(unsigned seen_bits, const char *path)
 {
        struct stat st;
+       const char *desc = bits_to_msg(seen_bits);
+
+       if (!desc)
+               return;
+
        if (!stat(path, &st))
                size_garbage += st.st_size;
        warning("%s: %s", desc, path);
@@ -27,7 +49,7 @@ static void real_report_garbage(const char *desc, const char *path)
 static void loose_garbage(const char *path)
 {
        if (verbose)
-               report_garbage("garbage found", path);
+               report_garbage(PACKDIR_FILE_GARBAGE, path);
 }
 
 static int count_loose(const unsigned char *sha1, const char *path, void *data)
index df3e454447ea4e4e34c6a7eac7ef54df1d614df6..c583aad6ec2896c8a6ad3b35671e92a3c0478bcd 100644 (file)
@@ -46,6 +46,22 @@ static struct argv_array rerere = ARGV_ARRAY_INIT;
 static struct tempfile pidfile;
 static struct lock_file log_lock;
 
+static struct string_list pack_garbage = STRING_LIST_INIT_DUP;
+
+static void clean_pack_garbage(void)
+{
+       int i;
+       for (i = 0; i < pack_garbage.nr; i++)
+               unlink_or_warn(pack_garbage.items[i].string);
+       string_list_clear(&pack_garbage, 0);
+}
+
+static void report_pack_garbage(unsigned seen_bits, const char *path)
+{
+       if (seen_bits == PACKDIR_FILE_IDX)
+               string_list_append(&pack_garbage, path);
+}
+
 static void git_config_date_string(const char *key, const char **output)
 {
        if (git_config_get_string_const(key, output))
@@ -416,6 +432,11 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
                return error(FAILED_RUN, rerere.argv[0]);
 
+       report_garbage = report_pack_garbage;
+       reprepare_packed_git();
+       if (pack_garbage.nr > 0)
+               clean_pack_garbage();
+
        if (auto_gc && too_many_loose_objects())
                warning(_("There are too many unreachable loose objects; "
                        "run 'git prune' to remove them."));
diff --git a/cache.h b/cache.h
index 3ba0b8f3d7a86eac8839bb175b0291b76013d263..736abc03a4b2bde987077440453e253150a584f7 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1289,8 +1289,11 @@ struct pack_entry {
 
 extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
 
-/* A hook for count-objects to report invalid files in pack directory */
-extern void (*report_garbage)(const char *desc, const char *path);
+/* A hook to report invalid files in pack directory */
+#define PACKDIR_FILE_PACK 1
+#define PACKDIR_FILE_IDX 2
+#define PACKDIR_FILE_GARBAGE 4
+extern void (*report_garbage)(unsigned seen_bits, const char *path);
 
 extern void prepare_packed_git(void);
 extern void reprepare_packed_git(void);
diff --git a/http.c b/http.c
index 7da76edda16abea8a53299f2770ad2dce55c1b60..42f29ce0aaf7aac1e81849cf733e8ea92738f5b0 100644 (file)
--- a/http.c
+++ b/http.c
@@ -30,7 +30,6 @@ static CURL *curl_default;
 #endif
 
 #define PREV_BUF_SIZE 4096
-#define RANGE_HEADER_SIZE 30
 
 char curl_errorstr[CURL_ERROR_SIZE];
 
@@ -681,6 +680,7 @@ struct active_request_slot *get_active_slot(void)
        curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
+       curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);
 #ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
        curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
 #endif
@@ -1173,6 +1173,13 @@ static const char *get_accept_language(void)
        return cached_accept_language;
 }
 
+static void http_opt_request_remainder(CURL *curl, off_t pos)
+{
+       char buf[128];
+       xsnprintf(buf, sizeof(buf), "%"PRIuMAX"-", (uintmax_t)pos);
+       curl_easy_setopt(curl, CURLOPT_RANGE, buf);
+}
+
 /* http_request() targets */
 #define HTTP_REQUEST_STRBUF    0
 #define HTTP_REQUEST_FILE      1
@@ -1198,14 +1205,11 @@ static int http_request(const char *url,
                curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
 
                if (target == HTTP_REQUEST_FILE) {
-                       long posn = ftell(result);
+                       off_t posn = ftello(result);
                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
                                         fwrite);
-                       if (posn > 0) {
-                               strbuf_addf(&buf, "Range: bytes=%ld-", posn);
-                               headers = curl_slist_append(headers, buf.buf);
-                               strbuf_reset(&buf);
-                       }
+                       if (posn > 0)
+                               http_opt_request_remainder(slot->curl, posn);
                } else
                        curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
                                         fwrite_buffer);
@@ -1515,10 +1519,6 @@ void release_http_pack_request(struct http_pack_request *preq)
                fclose(preq->packfile);
                preq->packfile = NULL;
        }
-       if (preq->range_header != NULL) {
-               curl_slist_free_all(preq->range_header);
-               preq->range_header = NULL;
-       }
        preq->slot = NULL;
        free(preq->url);
        free(preq);
@@ -1581,8 +1581,7 @@ int finish_http_pack_request(struct http_pack_request *preq)
 struct http_pack_request *new_http_pack_request(
        struct packed_git *target, const char *base_url)
 {
-       long prev_posn = 0;
-       char range[RANGE_HEADER_SIZE];
+       off_t prev_posn = 0;
        struct strbuf buf = STRBUF_INIT;
        struct http_pack_request *preq;
 
@@ -1614,16 +1613,13 @@ struct http_pack_request *new_http_pack_request(
         * If there is data present from a previous transfer attempt,
         * resume where it left off
         */
-       prev_posn = ftell(preq->packfile);
+       prev_posn = ftello(preq->packfile);
        if (prev_posn>0) {
                if (http_is_verbose)
                        fprintf(stderr,
                                "Resuming fetch of pack %s at byte %ld\n",
                                sha1_to_hex(target->sha1), prev_posn);
-               xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
-               preq->range_header = curl_slist_append(NULL, range);
-               curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
-                       preq->range_header);
+               http_opt_request_remainder(preq->slot->curl, prev_posn);
        }
 
        return preq;
@@ -1672,9 +1668,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
        int prevlocal;
        char prev_buf[PREV_BUF_SIZE];
        ssize_t prev_read = 0;
-       long prev_posn = 0;
-       char range[RANGE_HEADER_SIZE];
-       struct curl_slist *range_header = NULL;
+       off_t prev_posn = 0;
        struct http_object_request *freq;
 
        freq = xcalloc(1, sizeof(*freq));
@@ -1780,10 +1774,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
                        fprintf(stderr,
                                "Resuming fetch of object %s at byte %ld\n",
                                hex, prev_posn);
-               xsnprintf(range, sizeof(range), "Range: bytes=%ld-", prev_posn);
-               range_header = curl_slist_append(range_header, range);
-               curl_easy_setopt(freq->slot->curl,
-                                CURLOPT_HTTPHEADER, range_header);
+               http_opt_request_remainder(freq->slot->curl, prev_posn);
        }
 
        return freq;
diff --git a/http.h b/http.h
index 49afe39279d02785f3567aad2fec55c623a53d5f..4f97b60b5c8abdf5ab0610382a6d6fa289df2605 100644 (file)
--- a/http.h
+++ b/http.h
@@ -190,7 +190,6 @@ struct http_pack_request {
        struct packed_git **lst;
        FILE *packfile;
        char tmpfile[PATH_MAX];
-       struct curl_slist *range_header;
        struct active_request_slot *slot;
 };
 
diff --git a/path.c b/path.c
index c740c4ff9403bc92df4c439839bd5596ac62e48d..f28ace2963bb3f0f76af0e363add22ed73a5a2c9 100644 (file)
--- a/path.c
+++ b/path.c
@@ -363,7 +363,7 @@ void report_linked_checkout_garbage(void)
                strbuf_setlen(&sb, len);
                strbuf_addstr(&sb, path);
                if (file_exists(sb.buf))
-                       report_garbage("unused in linked checkout", sb.buf);
+                       report_garbage(PACKDIR_FILE_GARBAGE, sb.buf);
        }
        strbuf_release(&sb);
 }
index c5b31de9aa579dde37e5345d207995416f261eed..3d56746a9be12e78c2b5262948bd411acf3230a2 100644 (file)
@@ -1217,27 +1217,16 @@ void install_packed_git(struct packed_git *pack)
        packed_git = pack;
 }
 
-void (*report_garbage)(const char *desc, const char *path);
+void (*report_garbage)(unsigned seen_bits, const char *path);
 
 static void report_helper(const struct string_list *list,
                          int seen_bits, int first, int last)
 {
-       const char *msg;
-       switch (seen_bits) {
-       case 0:
-               msg = "no corresponding .idx or .pack";
-               break;
-       case 1:
-               msg = "no corresponding .idx";
-               break;
-       case 2:
-               msg = "no corresponding .pack";
-               break;
-       default:
+       if (seen_bits == (PACKDIR_FILE_PACK|PACKDIR_FILE_IDX))
                return;
-       }
+
        for (; first < last; first++)
-               report_garbage(msg, list->items[first].string);
+               report_garbage(seen_bits, list->items[first].string);
 }
 
 static void report_pack_garbage(struct string_list *list)
@@ -1260,7 +1249,7 @@ static void report_pack_garbage(struct string_list *list)
                if (baselen == -1) {
                        const char *dot = strrchr(path, '.');
                        if (!dot) {
-                               report_garbage("garbage found", path);
+                               report_garbage(PACKDIR_FILE_GARBAGE, path);
                                continue;
                        }
                        baselen = dot - path + 1;
@@ -1332,7 +1321,7 @@ static void prepare_packed_git_one(char *objdir, int local)
                    ends_with(de->d_name, ".keep"))
                        string_list_append(&garbage, path.buf);
                else
-                       report_garbage("garbage found", path.buf);
+                       report_garbage(PACKDIR_FILE_GARBAGE, path.buf);
        }
        closedir(dir);
        report_pack_garbage(&garbage);
index 023d7c6f7b6008536cbd83b1873f0b00b9148bbd..def203c7243c099e1359b9a0c44f22a07c06cb37 100755 (executable)
@@ -219,6 +219,7 @@ test_expect_success 'gc: prune old objects after local clone' '
 
 test_expect_success 'garbage report in count-objects -v' '
        test_when_finished "rm -f .git/objects/pack/fake*" &&
+       test_when_finished "rm -f .git/objects/pack/foo*" &&
        : >.git/objects/pack/foo &&
        : >.git/objects/pack/foo.bar &&
        : >.git/objects/pack/foo.keep &&
@@ -244,6 +245,26 @@ EOF
        test_cmp expected actual
 '
 
+test_expect_success 'clean pack garbage with gc' '
+       test_when_finished "rm -f .git/objects/pack/fake*" &&
+       test_when_finished "rm -f .git/objects/pack/foo*" &&
+       : >.git/objects/pack/foo.keep &&
+       : >.git/objects/pack/foo.pack &&
+       : >.git/objects/pack/fake.idx &&
+       : >.git/objects/pack/fake2.keep &&
+       : >.git/objects/pack/fake2.idx &&
+       : >.git/objects/pack/fake3.keep &&
+       git gc &&
+       git count-objects -v 2>stderr &&
+       grep "^warning:" stderr | sort >actual &&
+       cat >expected <<\EOF &&
+warning: no corresponding .idx or .pack: .git/objects/pack/fake3.keep
+warning: no corresponding .idx: .git/objects/pack/foo.keep
+warning: no corresponding .idx: .git/objects/pack/foo.pack
+EOF
+       test_cmp expected actual
+'
+
 test_expect_success 'prune .git/shallow' '
        SHA1=`echo hi|git commit-tree HEAD^{tree}` &&
        echo $SHA1 >.git/shallow &&