Merge branch 'sb/in-core-index-doc' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:32:11 +0000 (13:32 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:32:11 +0000 (13:32 -0800)
Documentation and in-code comments updates.

* sb/in-core-index-doc:
documentation: retire unfinished documentation
cache.h: document add_[file_]to_index
cache.h: document remove_index_entry_at
cache.h: document index_name_pos

33 files changed:
.travis.yml
Documentation/CodingGuidelines
Documentation/config.txt
Documentation/git-bisect.txt
Documentation/git-svn.txt
Makefile
archive-zip.c
builtin/blame.c
builtin/gc.c
builtin/pack-objects.c
builtin/repack.c
bulk-checkin.c
cache.h
compat/winansi.c
config.c
environment.c
exec_cmd.c
fast-import.c
git-rebase--interactive.sh
perl/Git/SVN/Ra.pm
remote.c
t/t1050-large.sh
t/t1514-rev-parse-push.sh
t/t5003-archive-zip.sh
t/t5310-pack-bitmaps.sh
t/t5315-pack-objects-compression.sh [new file with mode: 0755]
t/t6500-gc.sh
t/t7810-grep.sh
t/t8002-blame.sh
t/t8011-blame-split-file.sh [new file with mode: 0755]
t/t9301-fast-import-notes.sh
t/t9303-fast-import-compression.sh [new file with mode: 0755]
utf8.c
index 3843967a692d1642e43f536d5e2652b566ca554d..9c63c8c3f6807841df13161f76d476deca0d94fd 100644 (file)
@@ -75,20 +75,12 @@ before_install:
       popd
       ;;
     osx)
-      brew_force_set_latest_binary_hash () {
-        FORMULA=$1
-        SHA=$(brew fetch --force $FORMULA 2>&1 | grep ^SHA256: | cut -d ' ' -f 2)
-        sed -E -i.bak "s/sha256 \"[0-9a-f]{64}\"/sha256 \"$SHA\"/g" \
-          "$(brew --repository homebrew/homebrew-binary)/$FORMULA.rb"
-      }
       brew update --quiet
-      brew tap homebrew/binary --quiet
-      brew_force_set_latest_binary_hash perforce
-      brew_force_set_latest_binary_hash perforce-server
       # Uncomment this if you want to run perf tests:
       # brew install gnu-time
-      brew install git-lfs perforce-server perforce gettext
+      brew install git-lfs gettext
       brew link --force gettext
+      brew install caskroom/cask/perforce
       ;;
     esac;
     echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)";
index 4cd95da6b1e436c8764d51f17ea0446ca3bad73d..a4191aa3889000ed844678331e5fd7f9fc628ba4 100644 (file)
@@ -206,11 +206,38 @@ For C programs:
                x = 1;
        }
 
-   is frowned upon.  A gray area is when the statement extends
-   over a few lines, and/or you have a lengthy comment atop of
-   it.  Also, like in the Linux kernel, if there is a long list
-   of "else if" statements, it can make sense to add braces to
-   single line blocks.
+   is frowned upon. But there are a few exceptions:
+
+       - When the statement extends over a few lines (e.g., a while loop
+         with an embedded conditional, or a comment). E.g.:
+
+               while (foo) {
+                       if (x)
+                               one();
+                       else
+                               two();
+               }
+
+               if (foo) {
+                       /*
+                        * This one requires some explanation,
+                        * so we're better off with braces to make
+                        * it obvious that the indentation is correct.
+                        */
+                       doit();
+               }
+
+       - When there are multiple arms to a conditional and some of them
+         require braces, enclose even a single line block in braces for
+         consistency. E.g.:
+
+               if (foo) {
+                       doit();
+               } else {
+                       one();
+                       two();
+                       three();
+               }
 
  - We try to avoid assignments in the condition of an "if" statement.
 
index aba7568bcded1c5c35c779374e616282862b598c..1fee83ca42653b7ebd1074dc2b73aed66ad0a8c9 100644 (file)
@@ -783,10 +783,11 @@ core.sparseCheckout::
        linkgit:git-read-tree[1] for more information.
 
 core.abbrev::
-       Set the length object names are abbreviated to.  If unspecified,
-       many commands abbreviate to 7 hexdigits, which may not be enough
-       for abbreviated object names to stay unique for sufficiently long
-       time.
+       Set the length object names are abbreviated to.  If
+       unspecified or set to "auto", an appropriate value is
+       computed based on the approximate number of packed objects
+       in your repository, which hopefully is enough for
+       abbreviated object names to stay unique for some time.
 
 add.ignoreErrors::
 add.ignore-errors (deprecated)::
index 2bb9a577a2b4a4e95dcf950239c2ead8d424319f..bdd915a66b481dccf9ae6d601b5497ceb6b3b3d7 100644 (file)
@@ -18,8 +18,8 @@ on the subcommand:
 
  git bisect start [--term-{old,good}=<term> --term-{new,bad}=<term>]
                  [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
- git bisect (bad|new) [<rev>]
- git bisect (good|old) [<rev>...]
+ git bisect (bad|new|<term-new>) [<rev>]
+ git bisect (good|old|<term-old>) [<rev>...]
  git bisect terms [--term-good | --term-bad]
  git bisect skip [(<rev>|<range>)...]
  git bisect reset [<commit>]
index 5f9e65b0c4de117942babf0a14d255922d02b4ad..9bee9b0c4c53692bab569577d584797c0bd9e217 100644 (file)
@@ -664,13 +664,19 @@ creating the branch or tag.
        When retrieving svn commits into Git (as part of 'fetch', 'rebase', or
        'dcommit' operations), look for the first `From:` or `Signed-off-by:` line
        in the log message and use that as the author string.
++
+[verse]
+config key: svn.useLogAuthor
+
 --add-author-from::
        When committing to svn from Git (as part of 'commit-diff', 'set-tree' or 'dcommit'
        operations), if the existing log message doesn't already have a
        `From:` or `Signed-off-by:` line, append a `From:` line based on the
        Git commit's author string.  If you use this, then `--use-log-author`
        will retrieve a valid author string for all commits.
-
++
+[verse]
+config key: svn.addAuthorFrom
 
 ADVANCED OPTIONS
 ----------------
index f53fcc90d71b7e0ba95b94e9baf67d559085863c..76267262c155fa907cc6e806f8eb1ce1108e3a6a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2149,9 +2149,22 @@ endif
 po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
        $(QUIET_MSGFMT)mkdir -p $(dir $@) && $(MSGFMT) -o $@ $<
 
-FIND_SOURCE_FILES = ( git ls-files '*.[hcS]' 2>/dev/null || \
-                       $(FIND) . \( -name .git -type d -prune \) \
-                               -o \( -name '*.[hcS]' -type f -print \) )
+FIND_SOURCE_FILES = ( \
+       git ls-files \
+               '*.[hcS]' \
+               '*.sh' \
+               ':!*[tp][0-9][0-9][0-9][0-9]*' \
+               ':!contrib' \
+               2>/dev/null || \
+       $(FIND) . \
+               \( -name .git -type d -prune \) \
+               -o \( -name '[tp][0-9][0-9][0-9][0-9]*' -prune \) \
+               -o \( -name contrib -type d -prune \) \
+               -o \( -name build -type d -prune \) \
+               -o \( -name 'trash*' -type d -prune \) \
+               -o \( -name '*.[hcS]' -type f -print \) \
+               -o \( -name '*.sh' -type f -print \) \
+       )
 
 $(ETAGS_TARGET): FORCE
        $(RM) $(ETAGS_TARGET)
index 9db47357b02d4c33fc4e2d1edb8d948b2b3a496f..b429a8d974a02b06c9c6bc46850f4c9fae4a6d01 100644 (file)
@@ -554,11 +554,18 @@ static void dos_time(time_t *time, int *dos_date, int *dos_time)
        *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
 }
 
+static int archive_zip_config(const char *var, const char *value, void *data)
+{
+       return userdiff_config(var, value);
+}
+
 static int write_zip_archive(const struct archiver *ar,
                             struct archiver_args *args)
 {
        int err;
 
+       git_config(archive_zip_config, NULL);
+
        dos_time(&args->time, &zip_date, &zip_time);
 
        zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
index 4ddfadb71f7ef93958e2f236e166212e8b6bda2b..3aae19a0f91f90ec9191c8b3ec826d81c33b9ebe 100644 (file)
@@ -1700,13 +1700,23 @@ static void get_commit_info(struct commit *commit,
 }
 
 /*
+ * Write out any suspect information which depends on the path. This must be
+ * handled separately from emit_one_suspect_detail(), because a given commit
+ * may have changes in multiple paths. So this needs to appear each time
+ * we mention a new group.
+ *
  * To allow LF and other nonportable characters in pathnames,
  * they are c-style quoted as needed.
  */
-static void write_filename_info(const char *path)
+static void write_filename_info(struct origin *suspect)
 {
+       if (suspect->previous) {
+               struct origin *prev = suspect->previous;
+               printf("previous %s ", oid_to_hex(&prev->commit->object.oid));
+               write_name_quoted(prev->path, stdout, '\n');
+       }
        printf("filename ");
-       write_name_quoted(path, stdout, '\n');
+       write_name_quoted(suspect->path, stdout, '\n');
 }
 
 /*
@@ -1735,11 +1745,6 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
        printf("summary %s\n", ci.summary.buf);
        if (suspect->commit->object.flags & UNINTERESTING)
                printf("boundary\n");
-       if (suspect->previous) {
-               struct origin *prev = suspect->previous;
-               printf("previous %s ", oid_to_hex(&prev->commit->object.oid));
-               write_name_quoted(prev->path, stdout, '\n');
-       }
 
        commit_info_destroy(&ci);
 
@@ -1760,7 +1765,7 @@ static void found_guilty_entry(struct blame_entry *ent,
                       oid_to_hex(&suspect->commit->object.oid),
                       ent->s_lno + 1, ent->lno + 1, ent->num_lines);
                emit_one_suspect_detail(suspect, 0);
-               write_filename_info(suspect->path);
+               write_filename_info(suspect);
                maybe_flush_or_die(stdout, "stdout");
        }
        pi->blamed_lines += ent->num_lines;
@@ -1884,7 +1889,7 @@ static void emit_porcelain_details(struct origin *suspect, int repeat)
 {
        if (emit_one_suspect_detail(suspect, repeat) ||
            (suspect->commit->object.flags & MORE_THAN_ONE_PATH))
-               write_filename_info(suspect->path);
+               write_filename_info(suspect);
 }
 
 static void emit_porcelain(struct scoreboard *sb, struct blame_entry *ent,
@@ -2656,9 +2661,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        } else if (show_progress < 0)
                show_progress = isatty(2);
 
-       if (0 < abbrev)
+       if (0 < abbrev && abbrev < GIT_SHA1_HEXSZ)
                /* one more abbrev length is needed for the boundary commit */
                abbrev++;
+       else if (!abbrev)
+               abbrev = GIT_SHA1_HEXSZ;
 
        if (revs_file && read_ancestry(revs_file))
                die_errno("reading graft file '%s' failed", revs_file);
index 069950d0b417f5eb97cd756ae32df7a2fb13abce..331f2192607a4f7657750f4592193e6c0b8cea55 100644 (file)
@@ -191,6 +191,11 @@ static void add_repack_all_option(void)
        }
 }
 
+static void add_repack_incremental_option(void)
+{
+       argv_array_push(&repack, "--no-write-bitmap-index");
+}
+
 static int need_to_gc(void)
 {
        /*
@@ -208,7 +213,9 @@ static int need_to_gc(void)
         */
        if (too_many_packs())
                add_repack_all_option();
-       else if (!too_many_loose_objects())
+       else if (too_many_loose_objects())
+               add_repack_incremental_option();
+       else
                return 0;
 
        if (run_hook_le(NULL, "pre-auto-gc", NULL))
index 0fd52bd6b4b985b24d93ab7fb9887f57305b49fd..8841f8b366b4cee57d13a9086071351f849ddbba 100644 (file)
@@ -61,8 +61,6 @@ static int delta_search_threads;
 static int pack_to_stdout;
 static int num_preferred_base;
 static struct progress *progress_state;
-static int pack_compression_level = Z_DEFAULT_COMPRESSION;
-static int pack_compression_seen;
 
 static struct packed_git *reuse_packfile;
 static uint32_t reuse_packfile_objects;
@@ -2368,16 +2366,6 @@ static int git_pack_config(const char *k, const char *v, void *cb)
                depth = git_config_int(k, v);
                return 0;
        }
-       if (!strcmp(k, "pack.compression")) {
-               int level = git_config_int(k, v);
-               if (level == -1)
-                       level = Z_DEFAULT_COMPRESSION;
-               else if (level < 0 || level > Z_BEST_COMPRESSION)
-                       die("bad pack compression level %d", level);
-               pack_compression_level = level;
-               pack_compression_seen = 1;
-               return 0;
-       }
        if (!strcmp(k, "pack.deltacachesize")) {
                max_delta_cache_size = git_config_int(k, v);
                return 0;
@@ -2869,8 +2857,6 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 
        reset_pack_idx_option(&pack_idx_opts);
        git_config(git_pack_config, NULL);
-       if (!pack_compression_seen && core_compression_seen)
-               pack_compression_level = core_compression_level;
 
        progress = isatty(2);
        argc = parse_options(argc, argv, prefix, pack_objects_options,
index 80dd06b4a2a8b784ab96899cb150b13006d7e402..677bc7c81a2be11b287f3b05f91742216fbe1d51 100644 (file)
@@ -18,6 +18,12 @@ static const char *const git_repack_usage[] = {
        NULL
 };
 
+static const char incremental_bitmap_conflict_error[] = N_(
+"Incremental repacks are incompatible with bitmap indexes.  Use\n"
+"--no-write-bitmap-index or disable the pack.writebitmaps configuration."
+);
+
+
 static int repack_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "repack.usedeltabaseoffset")) {
@@ -206,6 +212,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        if (pack_kept_objects < 0)
                pack_kept_objects = write_bitmaps;
 
+       if (write_bitmaps && !(pack_everything & ALL_INTO_ONE))
+               die(_(incremental_bitmap_conflict_error));
+
        packdir = mkpathdup("%s/pack", get_object_directory());
        packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
 
index 4347f5c76aa72873eb5ccb090584428399f3159c..991b4a13e2491093ed9e9942ac116843973f65ff 100644 (file)
@@ -7,8 +7,6 @@
 #include "pack.h"
 #include "strbuf.h"
 
-static int pack_compression_level = Z_DEFAULT_COMPRESSION;
-
 static struct bulk_checkin_state {
        unsigned plugged:1;
 
diff --git a/cache.h b/cache.h
index b36b4fa31b3f123daf59d56064b59bef713ed9af..5c035dae57c4dfe710802021c4b4af6b6cb1ad8b 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -702,7 +702,7 @@ extern const char *git_attributes_file;
 extern const char *git_hooks_path;
 extern int zlib_compression_level;
 extern int core_compression_level;
-extern int core_compression_seen;
+extern int pack_compression_level;
 extern size_t packed_git_window_size;
 extern size_t packed_git_limit;
 extern size_t delta_base_cache_limit;
index 3c9ed3cfe07c1f3b58f5400af861fb8ae44c3fdb..82b89ab13767a5e562d4f41826d98bce0d704e1c 100644 (file)
@@ -494,19 +494,16 @@ static HANDLE swap_osfhnd(int fd, HANDLE new_handle)
         * It is because of this implicit close() that we created the
         * copy of the original.
         *
-        * Note that the OS can recycle HANDLE (numbers) just like it
-        * recycles fd (numbers), so we must update the cached value
-        * of "console".  You can use GetFileType() to see that
-        * handle and _get_osfhandle(fd) may have the same number
-        * value, but they refer to different actual files now.
+        * Note that we need to update the cached console handle to the
+        * duplicated one because the dup2() call will implicitly close
+        * the original one.
         *
         * Note that dup2() when given target := {0,1,2} will also
         * call SetStdHandle(), so we don't need to worry about that.
         */
-       dup2(new_fd, fd);
        if (console == handle)
                console = duplicate;
-       handle = INVALID_HANDLE_VALUE;
+       dup2(new_fd, fd);
 
        /* Close the temp fd.  This explicitly closes "new_handle"
         * (because it has been associated with it).
index 83fdecb1bc9f6f31bc625c79c1d3c12ba5b27f77..617b2e3cf4a9dcb61283ea797166d2bda812de6f 100644 (file)
--- a/config.c
+++ b/config.c
@@ -66,6 +66,8 @@ static struct key_value_info *current_config_kvi;
  */
 static enum config_scope current_parsing_scope;
 
+static int core_compression_seen;
+static int pack_compression_seen;
 static int zlib_compression_seen;
 
 /*
@@ -834,10 +836,16 @@ static int git_default_core_config(const char *var, const char *value)
        }
 
        if (!strcmp(var, "core.abbrev")) {
-               int abbrev = git_config_int(var, value);
-               if (abbrev < minimum_abbrev || abbrev > 40)
-                       return -1;
-               default_abbrev = abbrev;
+               if (!value)
+                       return config_error_nonbool(var);
+               if (!strcasecmp(value, "auto"))
+                       default_abbrev = -1;
+               else {
+                       int abbrev = git_config_int(var, value);
+                       if (abbrev < minimum_abbrev || abbrev > 40)
+                               return error("abbrev length out of range: %d", abbrev);
+                       default_abbrev = abbrev;
+               }
                return 0;
        }
 
@@ -865,6 +873,8 @@ static int git_default_core_config(const char *var, const char *value)
                core_compression_seen = 1;
                if (!zlib_compression_seen)
                        zlib_compression_level = level;
+               if (!pack_compression_seen)
+                       pack_compression_level = level;
                return 0;
        }
 
@@ -1125,6 +1135,18 @@ int git_default_config(const char *var, const char *value, void *dummy)
                pack_size_limit_cfg = git_config_ulong(var, value);
                return 0;
        }
+
+       if (!strcmp(var, "pack.compression")) {
+               int level = git_config_int(var, value);
+               if (level == -1)
+                       level = Z_DEFAULT_COMPRESSION;
+               else if (level < 0 || level > Z_BEST_COMPRESSION)
+                       die(_("bad pack compression level %d"), level);
+               pack_compression_level = level;
+               pack_compression_seen = 1;
+               return 0;
+       }
+
        /* Add other config variables here and to Documentation/config.txt. */
        return 0;
 }
@@ -2194,7 +2216,12 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
                        goto out_free;
                }
 
-               fstat(in_fd, &st);
+               if (fstat(in_fd, &st) == -1) {
+                       error_errno(_("fstat on %s failed"), config_filename);
+                       ret = CONFIG_INVALID_FILE;
+                       goto out_free;
+               }
+
                contents_sz = xsize_t(st.st_size);
                contents = xmmap_gently(NULL, contents_sz, PROT_READ,
                                        MAP_PRIVATE, in_fd, 0);
@@ -2396,7 +2423,7 @@ int git_config_rename_section_in_file(const char *config_filename,
 
        if (new_name && !section_name_is_ok(new_name)) {
                ret = error("invalid section name: %s", new_name);
-               goto out;
+               goto out_no_rollback;
        }
 
        if (!config_filename)
@@ -2411,10 +2438,13 @@ int git_config_rename_section_in_file(const char *config_filename,
 
        if (!(config_file = fopen(config_filename, "rb"))) {
                /* no config file means nothing to rename, no error */
-               goto unlock_and_out;
+               goto commit_and_out;
        }
 
-       fstat(fileno(config_file), &st);
+       if (fstat(fileno(config_file), &st) == -1) {
+               ret = error_errno(_("fstat on %s failed"), config_filename);
+               goto out;
+       }
 
        if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) {
                ret = error_errno("chmod on %s failed",
@@ -2470,11 +2500,13 @@ int git_config_rename_section_in_file(const char *config_filename,
                }
        }
        fclose(config_file);
-unlock_and_out:
+commit_and_out:
        if (commit_lock_file(lock) < 0)
                ret = error_errno("could not write config file %s",
                                  config_filename);
 out:
+       rollback_lock_file(lock);
+out_no_rollback:
        free(filename_buf);
        return ret;
 }
index 0935ec696e530e1b610c71eda0a0a7072d1d656f..4bce3eebfafa45d5781520781693029ffb317985 100644 (file)
@@ -34,7 +34,7 @@ const char *git_attributes_file;
 const char *git_hooks_path;
 int zlib_compression_level = Z_BEST_SPEED;
 int core_compression_level;
-int core_compression_seen;
+int pack_compression_level = Z_DEFAULT_COMPRESSION;
 int fsync_object_files;
 size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;
 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
index 19ac2146d0c49be8f5ef3739664dc3105544b4c2..fb94aeba9cef2893ea7173e5634640e596659474 100644 (file)
@@ -64,17 +64,19 @@ void git_set_argv_exec_path(const char *exec_path)
 /* Returns the highest-priority, location to look for git programs. */
 const char *git_exec_path(void)
 {
-       const char *env;
+       static char *cached_exec_path;
 
        if (argv_exec_path)
                return argv_exec_path;
 
-       env = getenv(EXEC_PATH_ENVIRONMENT);
-       if (env && *env) {
-               return env;
+       if (!cached_exec_path) {
+               const char *env = getenv(EXEC_PATH_ENVIRONMENT);
+               if (env && *env)
+                       cached_exec_path = xstrdup(env);
+               else
+                       cached_exec_path = system_path(GIT_EXEC_PATH);
        }
-
-       return system_path(GIT_EXEC_PATH);
+       return cached_exec_path;
 }
 
 static void add_path(struct strbuf *out, const char *path)
index cb545d7df514b73a5ad9358b614ea9b4751e3c1e..64fe602f0bb62c4848798d1bdb43a7be9ab5f523 100644 (file)
@@ -284,8 +284,6 @@ static unsigned long max_depth = 10;
 static off_t max_packsize;
 static int unpack_limit = 100;
 static int force_update;
-static int pack_compression_level = Z_DEFAULT_COMPRESSION;
-static int pack_compression_seen;
 
 /* Stats and misc. counters */
 static uintmax_t alloc_count;
@@ -2220,13 +2218,17 @@ static uintmax_t do_change_note_fanout(
                char *fullpath, unsigned int fullpath_len,
                unsigned char fanout)
 {
-       struct tree_content *t = root->tree;
+       struct tree_content *t;
        struct tree_entry *e, leaf;
        unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len;
        uintmax_t num_notes = 0;
        unsigned char sha1[20];
        char realpath[60];
 
+       if (!root->tree)
+               load_tree(root);
+       t = root->tree;
+
        for (i = 0; t && i < t->entry_count; i++) {
                e = t->entries[i];
                tmp_hex_sha1_len = hex_sha1_len + e->name->str_len;
@@ -2278,8 +2280,6 @@ static uintmax_t do_change_note_fanout(
                                leaf.tree);
                } else if (S_ISDIR(e->versions[1].mode)) {
                        /* This is a subdir that may contain note entries */
-                       if (!e->tree)
-                               load_tree(e);
                        num_notes += do_change_note_fanout(orig_root, e,
                                hex_sha1, tmp_hex_sha1_len,
                                fullpath, tmp_fullpath_len, fanout);
@@ -3381,15 +3381,6 @@ static void git_pack_config(void)
                if (max_depth > MAX_DEPTH)
                        max_depth = MAX_DEPTH;
        }
-       if (!git_config_get_int("pack.compression", &pack_compression_level)) {
-               if (pack_compression_level == -1)
-                       pack_compression_level = Z_DEFAULT_COMPRESSION;
-               else if (pack_compression_level < 0 ||
-                        pack_compression_level > Z_BEST_COMPRESSION)
-                       git_die_config("pack.compression",
-                                       "bad pack compression level %d", pack_compression_level);
-               pack_compression_seen = 1;
-       }
        if (!git_config_get_int("pack.indexversion", &indexversion_value)) {
                pack_idx_opts.version = indexversion_value;
                if (pack_idx_opts.version > 2)
@@ -3454,8 +3445,6 @@ int cmd_main(int argc, const char **argv)
        setup_git_directory();
        reset_pack_idx_option(&pack_idx_opts);
        git_pack_config();
-       if (!pack_compression_seen && core_compression_seen)
-               pack_compression_level = core_compression_level;
 
        alloc_objects(object_entry_alloc);
        strbuf_init(&command_buf, 0);
index 41fd374c725de1f42965b829c2bed5c48c92e19c..f5f58c483a5e229a6b62df6042fe42fb9d9de105 100644 (file)
@@ -425,7 +425,7 @@ update_squash_messages () {
        if test -f "$squash_msg"; then
                mv "$squash_msg" "$squash_msg".bak || exit
                count=$(($(sed -n \
-                       -e "1s/^$comment_char.*\([0-9][0-9]*\).*/\1/p" \
+                       -e "1s/^$comment_char[^0-9]*\([0-9][0-9]*\).*/\1/p" \
                        -e "q" < "$squash_msg".bak)+1))
                {
                        printf '%s\n' "$comment_char $(eval_ngettext \
index e7646968011234c09e1565577357a7678c015762..56ad9870bcfdfae68bd0fb5b57aa73e208bcb0fd 100644 (file)
@@ -606,7 +606,7 @@ sub minimize_url {
                        my $latest = $ra->get_latest_revnum;
                        $ra->get_log("", $latest, 0, 1, 0, 1, sub {});
                };
-       } while ($@ && ($c = shift @components));
+       } while ($@ && defined($c = shift @components));
 
        return canonicalize_url($url);
 }
index ad6c5424edab2ae15ac17bfcf12ac4ee93b5aa3f..d5eaec73742e74738c522cdc36ba9bf811b158b2 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1716,9 +1716,6 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
 {
        struct remote *remote;
 
-       if (!branch)
-               return error_buf(err, _("HEAD does not point to a branch"));
-
        remote = remote_get(pushremote_for_branch(branch, NULL));
        if (!remote)
                return error_buf(err,
@@ -1778,6 +1775,9 @@ static const char *branch_get_push_1(struct branch *branch, struct strbuf *err)
 
 const char *branch_get_push(struct branch *branch, struct strbuf *err)
 {
+       if (!branch)
+               return error_buf(err, _("HEAD does not point to a branch"));
+
        if (!branch->push_tracking_ref)
                branch->push_tracking_ref = branch_get_push_1(branch, err);
        return branch->push_tracking_ref;
index 096dbffecc3d51478b643bd2f4dee92f507e1c1a..6fd264cff0d6de1961656c2cd1193d8ce37e9a1f 100755 (executable)
@@ -5,6 +5,12 @@ test_description='adding and checking out large blobs'
 
 . ./test-lib.sh
 
+# This should be moved to test-lib.sh together with the
+# copy in t0021 after both topics have graduated to 'master'.
+file_size () {
+       perl -e 'print -s $ARGV[0]' "$1"
+}
+
 test_expect_success setup '
        # clone does not allow us to pass core.bigfilethreshold to
        # new repos, so set core.bigfilethreshold globally
@@ -17,6 +23,29 @@ test_expect_success setup '
        export GIT_ALLOC_LIMIT
 '
 
+# add a large file with different settings
+while read expect config
+do
+       test_expect_success "add with $config" '
+               test_when_finished "rm -f .git/objects/pack/pack-*.* .git/index" &&
+               git $config add large1 &&
+               sz=$(file_size .git/objects/pack/pack-*.pack) &&
+               case "$expect" in
+               small) test "$sz" -le 100000 ;;
+               large) test "$sz" -ge 100000 ;;
+               esac
+       '
+done <<\EOF
+large -c core.compression=0
+small -c core.compression=9
+large -c core.compression=0 -c pack.compression=0
+large -c core.compression=9 -c pack.compression=0
+small -c core.compression=0 -c pack.compression=9
+small -c core.compression=9 -c pack.compression=9
+large -c pack.compression=0
+small -c pack.compression=9
+EOF
+
 test_expect_success 'add a large file or two' '
        git add large1 huge large2 &&
        # make sure we got a single packfile and no loose objects
index 7214f5b33fa41fbb685e572ca24a0cb11337d251..623a32aa6e323d11267cb89af62d42c325a4dd75 100755 (executable)
@@ -60,4 +60,10 @@ test_expect_success '@{push} with push refspecs' '
        resolve topic@{push} refs/remotes/origin/magic/topic
 '
 
+test_expect_success 'resolving @{push} fails with a detached HEAD' '
+       git checkout HEAD^0 &&
+       test_when_finished "git checkout -" &&
+       test_must_fail git rev-parse @{push}
+'
+
 test_done
index 14744b2a4b1e646890176ec53970d36de6f8ec3b..55c78709978ff75cdbd794ee4c816dfd1eb55ef0 100755 (executable)
@@ -64,6 +64,12 @@ check_zip() {
                test_cmp_bin $original/nodiff.crlf $extracted/nodiff.crlf &&
                test_cmp_bin $original/nodiff.lf   $extracted/nodiff.lf
        "
+
+       test_expect_success UNZIP " validate that custom diff is unchanged " "
+               test_cmp_bin $original/custom.cr   $extracted/custom.cr &&
+               test_cmp_bin $original/custom.crlf $extracted/custom.crlf &&
+               test_cmp_bin $original/custom.lf   $extracted/custom.lf
+       "
 }
 
 test_expect_success \
@@ -78,6 +84,9 @@ test_expect_success \
      printf "text\r"   >a/nodiff.cr &&
      printf "text\r\n" >a/nodiff.crlf &&
      printf "text\n"   >a/nodiff.lf &&
+     printf "text\r"   >a/custom.cr &&
+     printf "text\r\n" >a/custom.crlf &&
+     printf "text\n"   >a/custom.lf &&
      printf "\0\r"     >a/binary.cr &&
      printf "\0\r\n"   >a/binary.crlf &&
      printf "\0\n"     >a/binary.lf &&
@@ -112,15 +121,20 @@ test_expect_success 'add files to repository' '
 test_expect_success 'setup export-subst and diff attributes' '
        echo "a/nodiff.* -diff" >>.git/info/attributes &&
        echo "a/diff.* diff" >>.git/info/attributes &&
+       echo "a/custom.* diff=custom" >>.git/info/attributes &&
+       git config diff.custom.binary true &&
        echo "substfile?" export-subst >>.git/info/attributes &&
        git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
                >a/substfile1
 '
 
-test_expect_success \
-    'create bare clone' \
-    'git clone --bare . bare.git &&
-     cp .git/info/attributes bare.git/info/attributes'
+test_expect_success 'create bare clone' '
+       git clone --bare . bare.git &&
+       cp .git/info/attributes bare.git/info/attributes &&
+       # Recreate our changes to .git/config rather than just copying it, as
+       # we do not want to clobber core.bare or other settings.
+       git -C bare.git config diff.custom.binary true
+'
 
 test_expect_success \
     'remove ignored file' \
index b4c7a6ff6b72d5d06ce9fb13bbd74590ff459a0b..424bec7d77c2b3761669230bf30030883ce4c230 100755 (executable)
@@ -118,12 +118,10 @@ test_expect_success 'fetch (partial bitmap)' '
        test_cmp expect actual
 '
 
-test_expect_success 'incremental repack cannot create bitmaps' '
+test_expect_success 'incremental repack fails when bitmaps are requested' '
        test_commit more-1 &&
-       find .git/objects/pack -name "*.bitmap" >expect &&
-       git repack -d &&
-       find .git/objects/pack -name "*.bitmap" >actual &&
-       test_cmp expect actual
+       test_must_fail git repack -d 2>err &&
+       test_i18ngrep "Incremental repacks are incompatible with bitmap" err
 '
 
 test_expect_success 'incremental repack can disable bitmaps' '
diff --git a/t/t5315-pack-objects-compression.sh b/t/t5315-pack-objects-compression.sh
new file mode 100755 (executable)
index 0000000..34c47da
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description='pack-object compression configuration'
+
+. ./test-lib.sh
+
+# This should be moved to test-lib.sh together with the
+# copy in t0021 after both topics have graduated to 'master'.
+file_size () {
+       perl -e 'print -s $ARGV[0]' "$1"
+}
+
+test_expect_success setup '
+       printf "%2000000s" X |
+       git hash-object -w --stdin >object-name &&
+       # make sure it resulted in a loose object
+       ob=$(sed -e "s/\(..\).*/\1/" object-name) &&
+       ject=$(sed -e "s/..\(.*\)/\1/" object-name) &&
+       test -f .git/objects/$ob/$ject
+'
+
+while read expect config
+do
+       test_expect_success "pack-objects with $config" '
+               test_when_finished "rm -f pack-*.*" &&
+               git $config pack-objects pack <object-name &&
+               sz=$(file_size pack-*.pack) &&
+               case "$expect" in
+               small) test "$sz" -le 100000 ;;
+               large) test "$sz" -ge 100000 ;;
+               esac
+       '
+done <<\EOF
+large -c core.compression=0
+small -c core.compression=9
+large -c core.compression=0 -c pack.compression=0
+large -c core.compression=9 -c pack.compression=0
+small -c core.compression=0 -c pack.compression=9
+small -c core.compression=9 -c pack.compression=9
+large -c pack.compression=0
+small -c pack.compression=9
+EOF
+
+test_done
index 5d7d4146179bb43184f74dd646aacbba11cc8c8b..1762dfa6a306ca672e3d3430b020f1b01a16da7e 100755 (executable)
@@ -43,4 +43,29 @@ test_expect_success 'gc is not aborted due to a stale symref' '
        )
 '
 
+test_expect_success 'auto gc with too many loose objects does not attempt to create bitmaps' '
+       test_config gc.auto 3 &&
+       test_config gc.autodetach false &&
+       test_config pack.writebitmaps true &&
+       # We need to create two object whose sha1s start with 17
+       # since this is what git gc counts.  As it happens, these
+       # two blobs will do so.
+       test_commit 263 &&
+       test_commit 410 &&
+       # Our first gc will create a pack; our second will create a second pack
+       git gc --auto &&
+       ls .git/objects/pack | sort >existing_packs &&
+       test_commit 523 &&
+       test_commit 790 &&
+
+       git gc --auto 2>err &&
+       test_i18ngrep ! "^warning:" err &&
+       ls .git/objects/pack/ | sort >post_packs &&
+       comm -1 -3 existing_packs post_packs >new &&
+       comm -2 -3 existing_packs post_packs >del &&
+       test_line_count = 0 del && # No packs are deleted
+       test_line_count = 2 new # There is one new pack and its .idx
+'
+
+
 test_done
index de2405ccba29016d2b83e16482bcfcbe70429e46..19f0108f8a2c67c518a92d996be7a335dbb69af2 100755 (executable)
@@ -39,6 +39,10 @@ test_expect_success setup '
                echo "a+bc"
                echo "abc"
        } >ab &&
+       {
+               echo d &&
+               echo 0
+       } >d0 &&
        echo vvv >v &&
        echo ww w >w &&
        echo x x xx x >x &&
@@ -1105,36 +1109,36 @@ test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =extended
 '
 
 test_expect_success 'grep -G -F -P -E pattern' '
-       >empty &&
-       test_must_fail git grep -G -F -P -E "a\x{2b}b\x{2a}c" ab >actual &&
-       test_cmp empty actual
+       echo "d0:d" >expected &&
+       git grep -G -F -P -E "[\d]" d0 >actual &&
+       test_cmp expected actual
 '
 
 test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =extended' '
-       >empty &&
-       test_must_fail git \
+       echo "d0:d" >expected &&
+       git \
                -c grep.patterntype=fixed \
                -c grep.patterntype=basic \
                -c grep.patterntype=perl \
                -c grep.patterntype=extended \
-               grep "a\x{2b}b\x{2a}c" ab >actual &&
-       test_cmp empty actual
+               grep "[\d]" d0 >actual &&
+       test_cmp expected actual
 '
 
 test_expect_success LIBPCRE 'grep -G -F -E -P pattern' '
-       echo "ab:a+b*c" >expected &&
-       git grep -G -F -E -P "a\x{2b}b\x{2a}c" ab >actual &&
+       echo "d0:0" >expected &&
+       git grep -G -F -E -P "[\d]" d0 >actual &&
        test_cmp expected actual
 '
 
 test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' '
-       echo "ab:a+b*c" >expected &&
+       echo "d0:0" >expected &&
        git \
                -c grep.patterntype=fixed \
                -c grep.patterntype=basic \
                -c grep.patterntype=extended \
                -c grep.patterntype=perl \
-               grep "a\x{2b}b\x{2a}c" ab >actual &&
+               grep "[\d]" d0 >actual &&
        test_cmp expected actual
 '
 
index ab79de95441f4f474525b48b14313f1d04172fce..380e1c1054de5d55a80cb558fea0791884ad7f38 100755 (executable)
@@ -86,4 +86,36 @@ test_expect_success 'blame with showEmail config true' '
        test_cmp expected_n result
 '
 
+test_expect_success 'set up abbrev tests' '
+       test_commit abbrev &&
+       sha1=$(git rev-parse --verify HEAD) &&
+       check_abbrev () {
+               expect=$1; shift
+               echo $sha1 | cut -c 1-$expect >expect &&
+               git blame "$@" abbrev.t >actual &&
+               perl -lne "/[0-9a-f]+/ and print \$&" <actual >actual.sha &&
+               test_cmp expect actual.sha
+       }
+'
+
+test_expect_success 'blame --abbrev=<n> works' '
+       # non-boundary commits get +1 for alignment
+       check_abbrev 31 --abbrev=30 HEAD &&
+       check_abbrev 30 --abbrev=30 ^HEAD
+'
+
+test_expect_success 'blame -l aligns regular and boundary commits' '
+       check_abbrev 40 -l HEAD &&
+       check_abbrev 39 -l ^HEAD
+'
+
+test_expect_success 'blame --abbrev=40 behaves like -l' '
+       check_abbrev 40 --abbrev=40 HEAD &&
+       check_abbrev 39 --abbrev=40 ^HEAD
+'
+
+test_expect_success '--no-abbrev works like --abbrev=40' '
+       check_abbrev 40 --no-abbrev
+'
+
 test_done
diff --git a/t/t8011-blame-split-file.sh b/t/t8011-blame-split-file.sh
new file mode 100755 (executable)
index 0000000..8311250
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+test_description='
+The general idea is that we have a single file whose lines come from
+multiple other files, and those individual files were modified in the same
+commits. That means that we will see the same commit in multiple contexts,
+and each one should be attributed to the correct file.
+
+Note that we need to use "blame -C" to find the commit for all lines. We will
+not bother testing that the non-C case fails to find it. That is how blame
+behaves now, but it is not a property we want to make sure is retained.
+'
+. ./test-lib.sh
+
+# help avoid typing and reading long strings of similar lines
+# in the tests below
+generate_expect () {
+       while read nr data
+       do
+               i=0
+               while test $i -lt $nr
+               do
+                       echo $data
+                       i=$((i + 1))
+               done
+       done
+}
+
+test_expect_success 'setup split file case' '
+       # use lines long enough to trigger content detection
+       test_seq 1000 1010 >one &&
+       test_seq 2000 2010 >two &&
+       git add one two &&
+       test_commit base &&
+
+       sed "6s/^/modified /" <one >one.tmp &&
+       mv one.tmp one &&
+       sed "6s/^/modified /" <two >two.tmp &&
+       mv two.tmp two &&
+       git add -u &&
+       test_commit modified &&
+
+       cat one two >combined &&
+       git add combined &&
+       git rm one two &&
+       test_commit combined
+'
+
+test_expect_success 'setup simulated porcelain' '
+       # This just reads porcelain-ish output and tries
+       # to output the value of a given field for each line (either by
+       # reading the field that accompanies this line, or referencing
+       # the information found last time the commit was mentioned).
+       cat >read-porcelain.pl <<-\EOF
+       my $field = shift;
+       while (<>) {
+               if (/^[0-9a-f]{40} /) {
+                       flush();
+                       $hash = $&;
+               } elsif (/^$field (.*)/) {
+                       $cache{$hash} = $1;
+               }
+       }
+       flush();
+
+       sub flush {
+               return unless defined $hash;
+               if (defined $cache{$hash}) {
+                       print "$cache{$hash}\n";
+               } else {
+                       print "NONE\n";
+               }
+       }
+       EOF
+'
+
+for output in porcelain line-porcelain
+do
+       test_expect_success "generate --$output output" '
+               git blame --root -C --$output combined >output
+       '
+
+       test_expect_success "$output output finds correct commits" '
+               generate_expect >expect <<-\EOF &&
+               5 base
+               1 modified
+               10 base
+               1 modified
+               5 base
+               EOF
+               perl read-porcelain.pl summary <output >actual &&
+               test_cmp expect actual
+       '
+
+       test_expect_success "$output output shows correct filenames" '
+               generate_expect >expect <<-\EOF &&
+               11 one
+               11 two
+               EOF
+               perl read-porcelain.pl filename <output >actual &&
+               test_cmp expect actual
+       '
+
+       test_expect_success "$output output shows correct previous pointer" '
+               generate_expect >expect <<-EOF &&
+               5 NONE
+               1 $(git rev-parse modified^) one
+               10 NONE
+               1 $(git rev-parse modified^) two
+               5 NONE
+               EOF
+               perl read-porcelain.pl previous <output >actual &&
+               test_cmp expect actual
+       '
+done
+
+test_done
index 83acf68bc3c19770eb690ece139892ca75329216..dadc70b7d5705d11437d40a701dd5079247e6357 100755 (executable)
@@ -483,6 +483,48 @@ test_expect_success 'verify that lots of notes trigger a fanout scheme' '
 
 '
 
+# Create another notes tree from the one above
+SP=" "
+cat >>input <<INPUT_END
+commit refs/heads/other_commits
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit #$(($num_commit + 1))
+COMMIT
+
+from refs/heads/many_commits
+M 644 inline file
+data <<EOF
+file contents in commit #$(($num_commit + 1))
+EOF
+
+commit refs/notes/other_notes
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+committing one more note on a tree imported from a previous notes tree
+COMMIT
+
+M 040000 $(git log --no-walk --format=%T refs/notes/many_notes)$SP
+N inline :$(($num_commit + 1))
+data <<EOF
+note for commit #$(($num_commit + 1))
+EOF
+INPUT_END
+
+test_expect_success 'verify that importing a notes tree respects the fanout scheme' '
+       git fast-import <input &&
+
+       # None of the entries in the top-level notes tree should be a full SHA1
+       git ls-tree --name-only refs/notes/other_notes |
+       while read path
+       do
+               if test $(expr length "$path") -ge 40
+               then
+                       return 1
+               fi
+       done
+'
+
 cat >>expect_non-note1 << EOF
 This is not a note, but rather a regular file residing in a notes tree
 EOF
diff --git a/t/t9303-fast-import-compression.sh b/t/t9303-fast-import-compression.sh
new file mode 100755 (executable)
index 0000000..856219f
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='compression setting of fast-import utility'
+. ./test-lib.sh
+
+# This should be moved to test-lib.sh together with the
+# copy in t0021 after both topics have graduated to 'master'.
+file_size () {
+       perl -e 'print -s $ARGV[0]' "$1"
+}
+
+import_large () {
+       (
+               echo blob
+               echo "data <<EOD"
+               printf "%2000000s\n" "$*"
+               echo EOD
+       ) | git "$@" fast-import
+}
+
+while read expect config
+do
+       test_expect_success "fast-import (packed) with $config" '
+               test_when_finished "rm -f .git/objects/pack/pack-*.*" &&
+               test_when_finished "rm -rf .git/objects/??" &&
+               import_large -c fastimport.unpacklimit=0 $config &&
+               sz=$(file_size .git/objects/pack/pack-*.pack) &&
+               case "$expect" in
+               small) test "$sz" -le 100000 ;;
+               large) test "$sz" -ge 100000 ;;
+               esac
+       '
+done <<\EOF
+large -c core.compression=0
+small -c core.compression=9
+large -c core.compression=0 -c pack.compression=0
+large -c core.compression=9 -c pack.compression=0
+small -c core.compression=0 -c pack.compression=9
+small -c core.compression=9 -c pack.compression=9
+large -c pack.compression=0
+small -c pack.compression=9
+EOF
+
+while read expect config
+do
+       test_expect_success "fast-import (loose) with $config" '
+               test_when_finished "rm -f .git/objects/pack/pack-*.*" &&
+               test_when_finished "rm -rf .git/objects/??" &&
+               import_large -c fastimport.unpacklimit=9 $config &&
+               sz=$(file_size .git/objects/??/????*) &&
+               case "$expect" in
+               small) test "$sz" -le 100000 ;;
+               large) test "$sz" -ge 100000 ;;
+               esac
+       '
+done <<\EOF
+large -c core.compression=0
+small -c core.compression=9
+large -c core.compression=0 -c core.loosecompression=0
+large -c core.compression=9 -c core.loosecompression=0
+small -c core.compression=0 -c core.loosecompression=9
+small -c core.compression=9 -c core.loosecompression=9
+large -c core.loosecompression=0
+small -c core.loosecompression=9
+EOF
+
+test_done
diff --git a/utf8.c b/utf8.c
index 00e10c86ad7ea7bcc2d53a90a2f608dd66d47462..0c8e011a58cae3c683851007ec81828ad8284471 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -489,6 +489,28 @@ char *reencode_string_iconv(const char *in, size_t insz, iconv_t conv, int *outs
        return out;
 }
 
+static const char *fallback_encoding(const char *name)
+{
+       /*
+        * Some platforms do not have the variously spelled variants of
+        * UTF-8, so let's fall back to trying the most official
+        * spelling. We do so only as a fallback in case the platform
+        * does understand the user's spelling, but not our official
+        * one.
+        */
+       if (is_encoding_utf8(name))
+               return "UTF-8";
+
+       /*
+        * Even though latin-1 is still seen in e-mail
+        * headers, some platforms only install ISO-8859-1.
+        */
+       if (!strcasecmp(name, "latin-1"))
+               return "ISO-8859-1";
+
+       return name;
+}
+
 char *reencode_string_len(const char *in, int insz,
                          const char *out_encoding, const char *in_encoding,
                          int *outsz)
@@ -501,17 +523,9 @@ char *reencode_string_len(const char *in, int insz,
 
        conv = iconv_open(out_encoding, in_encoding);
        if (conv == (iconv_t) -1) {
-               /*
-                * Some platforms do not have the variously spelled variants of
-                * UTF-8, so let's fall back to trying the most official
-                * spelling. We do so only as a fallback in case the platform
-                * does understand the user's spelling, but not our official
-                * one.
-                */
-               if (is_encoding_utf8(in_encoding))
-                       in_encoding = "UTF-8";
-               if (is_encoding_utf8(out_encoding))
-                       out_encoding = "UTF-8";
+               in_encoding = fallback_encoding(in_encoding);
+               out_encoding = fallback_encoding(out_encoding);
+
                conv = iconv_open(out_encoding, in_encoding);
                if (conv == (iconv_t) -1)
                        return NULL;