Code

Merge branch 'rs/maint-estimate-cache-size' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 1 Nov 2011 23:41:41 +0000 (16:41 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 1 Nov 2011 23:41:41 +0000 (16:41 -0700)
* rs/maint-estimate-cache-size:
  t7511: avoid use of reserved filename on Windows.

57 files changed:
Documentation/config.txt
Documentation/git-mergetool.txt
Documentation/git-read-tree.txt
Documentation/git-svn.txt
Documentation/git-update-index.txt
Documentation/technical/api-argv-array.txt [new file with mode: 0644]
Documentation/technical/api-sha1-array.txt [new file with mode: 0644]
Makefile
argv-array.c [new file with mode: 0644]
argv-array.h [new file with mode: 0644]
attr.c
bisect.c
builtin/check-attr.c
builtin/checkout.c
builtin/clone.c
builtin/fetch.c
builtin/mv.c
builtin/receive-pack.c
builtin/remote.c
cache.h
compat/mingw.c
compat/qsort.c
config.c
date.c
diff-lib.c
diff.c
environment.c
git-bisect.sh
git-mergetool.sh
git-pull.sh
git-rebase.sh
git-send-email.perl
gitweb/gitweb.perl
gitweb/static/js/javascript-detection.js
http.c
merge-recursive.c
notes-merge.c
quote.c
quote.h
remote-curl.c
remote.c
remote.h
run-command.c
show-index.c
submodule.c
t/t0003-attributes.sh
t/t0006-date.sh
t/t5505-remote.sh
t/t5510-fetch.sh
t/t7607-merge-overwrite.sh
t/t7609-merge-co-error-msgs.sh
t/t7610-mergetool.sh
t/t9159-git-svn-no-parent-mergeinfo.sh
templates/hooks--pre-commit.sample
transport-helper.c
unpack-trees.c
wt-status.c

index 0658ffb889320d408f2cad9214e138879059c766..eae75a39c0bcc779ed2c66ef6fa9b03a24a4a2fd 100644 (file)
@@ -147,7 +147,7 @@ advice.*::
 
 core.fileMode::
        If false, the executable bit differences between the index and
-       the working copy are ignored; useful on broken filesystems like FAT.
+       the working tree are ignored; useful on broken filesystems like FAT.
        See linkgit:git-update-index[1].
 +
 The default is true, except linkgit:git-clone[1] or linkgit:git-init[1]
@@ -179,7 +179,7 @@ is created.
 
 core.trustctime::
        If false, the ctime differences between the index and the
-       working copy are ignored; useful when the inode change time
+       working tree are ignored; useful when the inode change time
        is regularly modified by something outside Git (file system
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
@@ -292,7 +292,7 @@ core.ignoreStat::
        If true, commands which modify both the working tree and the index
        will mark the updated paths with the "assume unchanged" bit in the
        index. These marked files are then assumed to stay unchanged in the
-       working copy, until you mark them otherwise manually - Git will not
+       working tree, until you mark them otherwise manually - Git will not
        detect the file changes by lstat() calls. This is useful on systems
        where those are very slow, such as Microsoft Windows.
        See linkgit:git-update-index[1].
@@ -1453,7 +1453,8 @@ notes.rewriteRef::
        You may also specify this configuration several times.
 +
 Does not have a default value; you must configure this variable to
-enable note rewriting.
+enable note rewriting.  Set it to `refs/notes/commits` to enable
+rewriting for the default commit notes.
 +
 This setting can be overridden with the `GIT_NOTES_REWRITE_REF`
 environment variable, which must be a colon separated list of refs or
index 347091010995af95e43ced744b159b277bdb6cdc..2a49de7cfe5188b531bc02f1115e253bfa10e0e0 100644 (file)
@@ -17,9 +17,10 @@ Use `git mergetool` to run one of several merge utilities to resolve
 merge conflicts.  It is typically run after 'git merge'.
 
 If one or more <file> parameters are given, the merge tool program will
-be run to resolve differences on each file.  If no <file> names are
-specified, 'git mergetool' will run the merge tool program on every file
-with merge conflicts.
+be run to resolve differences on each file (skipping those without
+conflicts).  Specifying a directory will include all unresolved files in
+that path.  If no <file> names are specified, 'git mergetool' will run
+the merge tool program on every file with merge conflicts.
 
 OPTIONS
 -------
index c45d53c6e150479bd01bf3d643354348d8ce9273..5375549820bd6b9fecf3540b1e60ae50e74da0e6 100644 (file)
@@ -47,7 +47,7 @@ OPTIONS
 
 -i::
        Usually a merge requires the index file as well as the
-       files in the working tree are up to date with the
+       files in the working tree to be up to date with the
        current head commit, in order not to lose local
        changes.  This flag disables the check with the working
        tree and is meant to be used when creating a merge of
@@ -71,21 +71,21 @@ OPTIONS
 --aggressive::
        Usually a three-way merge by 'git read-tree' resolves
        the merge for really trivial cases and leaves other
-       cases unresolved in the index, so that Porcelains can
+       cases unresolved in the index, so that porcelains can
        implement different merge policies.  This flag makes the
-       command to resolve a few more cases internally:
+       command resolve a few more cases internally:
 +
 * when one side removes a path and the other side leaves the path
   unmodified.  The resolution is to remove that path.
 * when both sides remove a path.  The resolution is to remove that path.
-* when both sides adds a path identically.  The resolution
+* when both sides add a path identically.  The resolution
   is to add that path.
 
 --prefix=<prefix>/::
        Keep the current index contents, and read the contents
-       of named tree-ish under directory at `<prefix>`.  The
+       of the named tree-ish under the directory at `<prefix>`. The
        original index file cannot have anything at the path
-       `<prefix>` itself, and have nothing in `<prefix>/`
+       `<prefix>` itself, nor anything in the `<prefix>/`
        directory.  Note that the `<prefix>/` value must end
        with a slash.
 
@@ -379,45 +379,45 @@ have finished your work-in-progress), attempt the merge again.
 Sparse checkout
 ---------------
 
-"Sparse checkout" allows to sparsely populate working directory.
-It uses skip-worktree bit (see linkgit:git-update-index[1]) to tell
-Git whether a file on working directory is worth looking at.
+"Sparse checkout" allows populating the working directory sparsely.
+It uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell
+Git whether a file in the working directory is worth looking at.
 
-"git read-tree" and other merge-based commands ("git merge", "git
-checkout"...) can help maintaining skip-worktree bitmap and working
+'git read-tree' and other merge-based commands ('git merge', 'git
+checkout'...) can help maintaining the skip-worktree bitmap and working
 directory update. `$GIT_DIR/info/sparse-checkout` is used to
-define the skip-worktree reference bitmap. When "git read-tree" needs
-to update working directory, it will reset skip-worktree bit in index
+define the skip-worktree reference bitmap. When 'git read-tree' needs
+to update the working directory, it resets the skip-worktree bit in the index
 based on this file, which uses the same syntax as .gitignore files.
-If an entry matches a pattern in this file, skip-worktree will be
-set on that entry. Otherwise, skip-worktree will be unset.
+If an entry matches a pattern in this file, skip-worktree will not be
+set on that entry. Otherwise, skip-worktree will be set.
 
 Then it compares the new skip-worktree value with the previous one. If
-skip-worktree turns from unset to set, it will add the corresponding
-file back. If it turns from set to unset, that file will be removed.
+skip-worktree turns from set to unset, it will add the corresponding
+file back. If it turns from unset to set, that file will be removed.
 
 While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
-files are in. You can also specify what files are _not_ in, using
-negate patterns. For example, to remove file "unwanted":
+files are in, you can also specify what files are _not_ in, using
+negate patterns. For example, to remove the file `unwanted`:
 
 ----------------
-*
+/*
 !unwanted
 ----------------
 
-Another tricky thing is fully repopulating working directory when you
+Another tricky thing is fully repopulating the working directory when you
 no longer want sparse checkout. You cannot just disable "sparse
-checkout" because skip-worktree are still in the index and you working
-directory is still sparsely populated. You should re-populate working
+checkout" because skip-worktree bits are still in the index and your working
+directory is still sparsely populated. You should re-populate the working
 directory with the `$GIT_DIR/info/sparse-checkout` file content as
 follows:
 
 ----------------
-*
+/*
 ----------------
 
-Then you can disable sparse checkout. Sparse checkout support in "git
-read-tree" and similar commands is disabled by default. You need to
+Then you can disable sparse checkout. Sparse checkout support in 'git
+read-tree' and similar commands is disabled by default. You need to
 turn `core.sparseCheckout` on in order to have sparse checkout
 support.
 
index 08cad6d2b676642b37b5a871cd52617c4308a748..f977e8780b5e152b18d07a61fde8c2f86f98a0ce 100644 (file)
@@ -318,7 +318,7 @@ Any other arguments are passed directly to 'git log'
        Show what revision and author last modified each line of a file. The
        output of this mode is format-compatible with the output of
        `svn blame' by default. Like the SVN blame command,
-       local uncommitted changes in the working copy are ignored;
+       local uncommitted changes in the working tree are ignored;
        the version of the file in the HEAD revision is annotated. Unknown
        arguments are passed directly to 'git blame'.
 +
index d3931294d174e5c06adb81e428e31e00fbfa3b5e..a3081f4e237747dc858fd105302cbb9a489de41b 100644 (file)
@@ -264,7 +264,9 @@ tree files, you have to explicitly tell git about it by dropping
 "assume unchanged" bit, either before or after you modify them.
 
 In order to set "assume unchanged" bit, use `--assume-unchanged`
-option.  To unset, use `--no-assume-unchanged`.
+option.  To unset, use `--no-assume-unchanged`. To see which files
+have the "assume unchanged" bit set, use `git ls-files -v`
+(see linkgit:git-ls-files[1]).
 
 The command looks at `core.ignorestat` configuration variable.  When
 this is true, paths updated with `git update-index paths...` and
@@ -363,7 +365,8 @@ ctime for marking files processed) (see linkgit:git-config[1]).
 SEE ALSO
 --------
 linkgit:git-config[1],
-linkgit:git-add[1]
+linkgit:git-add[1],
+linkgit:git-ls-files[1]
 
 GIT
 ---
diff --git a/Documentation/technical/api-argv-array.txt b/Documentation/technical/api-argv-array.txt
new file mode 100644 (file)
index 0000000..49b3d52
--- /dev/null
@@ -0,0 +1,46 @@
+argv-array API
+==============
+
+The argv-array API allows one to dynamically build and store
+NULL-terminated lists.  An argv-array maintains the invariant that the
+`argv` member always points to a non-NULL array, and that the array is
+always NULL-terminated at the element pointed to by `argv[argc]`. This
+makes the result suitable for passing to functions expecting to receive
+argv from main(), or the link:api-run-command.html[run-command API].
+
+The link:api-string-list.html[string-list API] is similar, but cannot be
+used for these purposes; instead of storing a straight string pointer,
+it contains an item structure with a `util` field that is not compatible
+with the traditional argv interface.
+
+Each `argv_array` manages its own memory. Any strings pushed into the
+array are duplicated, and all memory is freed by argv_array_clear().
+
+Data Structures
+---------------
+
+`struct argv_array`::
+
+       A single array. This should be initialized by assignment from
+       `ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv`
+       member contains the actual array; the `argc` member contains the
+       number of elements in the array, not including the terminating
+       NULL.
+
+Functions
+---------
+
+`argv_array_init`::
+       Initialize an array. This is no different than assigning from
+       `ARGV_ARRAY_INIT`.
+
+`argv_array_push`::
+       Push a copy of a string onto the end of the array.
+
+`argv_array_pushf`::
+       Format a string and push it onto the end of the array. This is a
+       convenience wrapper combining `strbuf_addf` and `argv_array_push`.
+
+`argv_array_clear`::
+       Free all memory associated with the array and return it to the
+       initial, empty state.
diff --git a/Documentation/technical/api-sha1-array.txt b/Documentation/technical/api-sha1-array.txt
new file mode 100644 (file)
index 0000000..4a4bae8
--- /dev/null
@@ -0,0 +1,79 @@
+sha1-array API
+==============
+
+The sha1-array API provides storage and manipulation of sets of SHA1
+identifiers. The emphasis is on storage and processing efficiency,
+making them suitable for large lists. Note that the ordering of items is
+not preserved over some operations.
+
+Data Structures
+---------------
+
+`struct sha1_array`::
+
+       A single array of SHA1 hashes. This should be initialized by
+       assignment from `SHA1_ARRAY_INIT`.  The `sha1` member contains
+       the actual data. The `nr` member contains the number of items in
+       the set.  The `alloc` and `sorted` members are used internally,
+       and should not be needed by API callers.
+
+Functions
+---------
+
+`sha1_array_append`::
+       Add an item to the set. The sha1 will be placed at the end of
+       the array (but note that some operations below may lose this
+       ordering).
+
+`sha1_array_sort`::
+       Sort the elements in the array.
+
+`sha1_array_lookup`::
+       Perform a binary search of the array for a specific sha1.
+       If found, returns the offset (in number of elements) of the
+       sha1. If not found, returns a negative integer. If the array is
+       not sorted, this function has the side effect of sorting it.
+
+`sha1_array_clear`::
+       Free all memory associated with the array and return it to the
+       initial, empty state.
+
+`sha1_array_for_each_unique`::
+       Efficiently iterate over each unique element of the list,
+       executing the callback function for each one. If the array is
+       not sorted, this function has the side effect of sorting it.
+
+Examples
+--------
+
+-----------------------------------------
+void print_callback(const unsigned char sha1[20],
+                   void *data)
+{
+       printf("%s\n", sha1_to_hex(sha1));
+}
+
+void some_func(void)
+{
+       struct sha1_array hashes = SHA1_ARRAY_INIT;
+       unsigned char sha1[20];
+
+       /* Read objects into our set */
+       while (read_object_from_stdin(sha1))
+               sha1_array_append(&hashes, sha1);
+
+       /* Check if some objects are in our set */
+       while (read_object_from_stdin(sha1)) {
+               if (sha1_array_lookup(&hashes, sha1) >= 0)
+                       printf("it's in there!\n");
+
+       /*
+        * Print the unique set of objects. We could also have
+        * avoided adding duplicate objects in the first place,
+        * but we would end up re-sorting the array repeatedly.
+        * Instead, this will sort once and then skip duplicates
+        * in linear time.
+        */
+       sha1_array_for_each_unique(&hashes, print_callback, NULL);
+}
+-----------------------------------------
index 924749edae3b515b31a48bb3db85f44a40529b9d..71b853ffaf740aaba2415a18377326f37c27d584 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -505,6 +505,7 @@ VCSSVN_LIB=vcs-svn/lib.a
 
 LIB_H += advice.h
 LIB_H += archive.h
+LIB_H += argv-array.h
 LIB_H += attr.h
 LIB_H += blob.h
 LIB_H += builtin.h
@@ -586,6 +587,7 @@ LIB_OBJS += alloc.o
 LIB_OBJS += archive.o
 LIB_OBJS += archive-tar.o
 LIB_OBJS += archive-zip.o
+LIB_OBJS += argv-array.o
 LIB_OBJS += attr.o
 LIB_OBJS += base85.o
 LIB_OBJS += bisect.o
diff --git a/argv-array.c b/argv-array.c
new file mode 100644 (file)
index 0000000..a4e0420
--- /dev/null
@@ -0,0 +1,51 @@
+#include "cache.h"
+#include "argv-array.h"
+#include "strbuf.h"
+
+static const char *empty_argv_storage = NULL;
+const char **empty_argv = &empty_argv_storage;
+
+void argv_array_init(struct argv_array *array)
+{
+       array->argv = empty_argv;
+       array->argc = 0;
+       array->alloc = 0;
+}
+
+static void argv_array_push_nodup(struct argv_array *array, const char *value)
+{
+       if (array->argv == empty_argv)
+               array->argv = NULL;
+
+       ALLOC_GROW(array->argv, array->argc + 2, array->alloc);
+       array->argv[array->argc++] = value;
+       array->argv[array->argc] = NULL;
+}
+
+void argv_array_push(struct argv_array *array, const char *value)
+{
+       argv_array_push_nodup(array, xstrdup(value));
+}
+
+void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
+{
+       va_list ap;
+       struct strbuf v = STRBUF_INIT;
+
+       va_start(ap, fmt);
+       strbuf_vaddf(&v, fmt, ap);
+       va_end(ap);
+
+       argv_array_push_nodup(array, strbuf_detach(&v, NULL));
+}
+
+void argv_array_clear(struct argv_array *array)
+{
+       if (array->argv != empty_argv) {
+               int i;
+               for (i = 0; i < array->argc; i++)
+                       free((char **)array->argv[i]);
+               free(array->argv);
+       }
+       argv_array_init(array);
+}
diff --git a/argv-array.h b/argv-array.h
new file mode 100644 (file)
index 0000000..74dd2b1
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef ARGV_ARRAY_H
+#define ARGV_ARRAY_H
+
+extern const char **empty_argv;
+
+struct argv_array {
+       const char **argv;
+       int argc;
+       int alloc;
+};
+
+#define ARGV_ARRAY_INIT { empty_argv, 0, 0 }
+
+void argv_array_init(struct argv_array *);
+void argv_array_push(struct argv_array *, const char *);
+__attribute__((format (printf,2,3)))
+void argv_array_pushf(struct argv_array *, const char *fmt, ...);
+void argv_array_clear(struct argv_array *);
+
+#endif /* ARGV_ARRAY_H */
diff --git a/attr.c b/attr.c
index 33cb4e4d113cbb3816ba824cb06bf494a4bd9bc3..76b079f0f530e1372b2866f40cce21ec5266394c 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -11,6 +11,7 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "attr.h"
+#include "dir.h"
 
 const char git_attr__true[] = "(builtin)true";
 const char git_attr__false[] = "\0(builtin)false";
@@ -20,8 +21,6 @@ static const char git_attr__unknown[] = "(builtin)unknown";
 #define ATTR__UNSET NULL
 #define ATTR__UNKNOWN git_attr__unknown
 
-static const char *attributes_file;
-
 /* This is a randomly chosen prime. */
 #define HASHSIZE 257
 
@@ -494,14 +493,6 @@ static int git_attr_system(void)
        return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
 }
 
-static int git_attr_config(const char *var, const char *value, void *dummy)
-{
-       if (!strcmp(var, "core.attributesfile"))
-               return git_config_pathname(&attributes_file, var, value);
-
-       return 0;
-}
-
 static void bootstrap_attr_stack(void)
 {
        if (!attr_stack) {
@@ -521,9 +512,8 @@ static void bootstrap_attr_stack(void)
                        }
                }
 
-               git_config(git_attr_config, NULL);
-               if (attributes_file) {
-                       elem = read_attr_from_file(attributes_file, 1);
+               if (git_attributes_file) {
+                       elem = read_attr_from_file(git_attributes_file, 1);
                        if (elem) {
                                elem->origin = NULL;
                                elem->prev = attr_stack;
@@ -533,7 +523,7 @@ static void bootstrap_attr_stack(void)
 
                if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
                        elem = read_attr(GITATTRIBUTES_FILE, 1);
-                       elem->origin = strdup("");
+                       elem->origin = xstrdup("");
                        elem->prev = attr_stack;
                        attr_stack = elem;
                        debug_push(elem);
@@ -552,7 +542,6 @@ static void prepare_attr_stack(const char *path)
 {
        struct attr_stack *elem, *info;
        int dirlen, len;
-       struct strbuf pathbuf;
        const char *cp;
 
        cp = strrchr(path, '/');
@@ -561,8 +550,6 @@ static void prepare_attr_stack(const char *path)
        else
                dirlen = cp - path;
 
-       strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
-
        /*
         * At the bottom of the attribute stack is the built-in
         * set of attribute definitions, followed by the contents
@@ -607,27 +594,28 @@ static void prepare_attr_stack(const char *path)
         * Read from parent directories and push them down
         */
        if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
-               while (1) {
-                       char *cp;
+               struct strbuf pathbuf = STRBUF_INIT;
 
+               while (1) {
                        len = strlen(attr_stack->origin);
                        if (dirlen <= len)
                                break;
-                       strbuf_reset(&pathbuf);
-                       strbuf_add(&pathbuf, path, dirlen);
+                       cp = memchr(path + len + 1, '/', dirlen - len - 1);
+                       if (!cp)
+                               cp = path + dirlen;
+                       strbuf_add(&pathbuf, path, cp - path);
                        strbuf_addch(&pathbuf, '/');
-                       cp = strchr(pathbuf.buf + len + 1, '/');
-                       strcpy(cp + 1, GITATTRIBUTES_FILE);
+                       strbuf_addstr(&pathbuf, GITATTRIBUTES_FILE);
                        elem = read_attr(pathbuf.buf, 0);
-                       *cp = '\0';
-                       elem->origin = strdup(pathbuf.buf);
+                       strbuf_setlen(&pathbuf, cp - path);
+                       elem->origin = strbuf_detach(&pathbuf, NULL);
                        elem->prev = attr_stack;
                        attr_stack = elem;
                        debug_push(elem);
                }
-       }
 
-       strbuf_release(&pathbuf);
+               strbuf_release(&pathbuf);
+       }
 
        /*
         * Finally push the "info" one at the top of the stack.
@@ -644,7 +632,7 @@ static int path_matches(const char *pathname, int pathlen,
                /* match basename */
                const char *basename = strrchr(pathname, '/');
                basename = basename ? basename + 1 : pathname;
-               return (fnmatch(pattern, basename, 0) == 0);
+               return (fnmatch_icase(pattern, basename, 0) == 0);
        }
        /*
         * match with FNM_PATHNAME; the pattern has base implicitly
@@ -658,7 +646,7 @@ static int path_matches(const char *pathname, int pathlen,
                return 0;
        if (baselen != 0)
                baselen++;
-       return fnmatch(pattern, pathname + baselen, FNM_PATHNAME) == 0;
+       return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
 }
 
 static int macroexpand_one(int attr_nr, int rem);
index c7b7d7913dc444926b0260211e8bc3aa75eeffdb..de05bf824620324e42b7a27571ecd3e763cf7e8f 100644 (file)
--- a/bisect.c
+++ b/bisect.c
 #include "log-tree.h"
 #include "bisect.h"
 #include "sha1-array.h"
+#include "argv-array.h"
 
 static struct sha1_array good_revs;
 static struct sha1_array skipped_revs;
 
 static const unsigned char *current_bad_sha1;
 
-struct argv_array {
-       const char **argv;
-       int argv_nr;
-       int argv_alloc;
-};
-
 static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
 static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
@@ -405,21 +400,6 @@ struct commit_list *find_bisection(struct commit_list *list,
        return best;
 }
 
-static void argv_array_push(struct argv_array *array, const char *string)
-{
-       ALLOC_GROW(array->argv, array->argv_nr + 1, array->argv_alloc);
-       array->argv[array->argv_nr++] = string;
-}
-
-static void argv_array_push_sha1(struct argv_array *array,
-                                const unsigned char *sha1,
-                                const char *format)
-{
-       struct strbuf buf = STRBUF_INIT;
-       strbuf_addf(&buf, format, sha1_to_hex(sha1));
-       argv_array_push(array, strbuf_detach(&buf, NULL));
-}
-
 static int register_ref(const char *refname, const unsigned char *sha1,
                        int flags, void *cb_data)
 {
@@ -449,16 +429,10 @@ static void read_bisect_paths(struct argv_array *array)
                die_errno("Could not open file '%s'", filename);
 
        while (strbuf_getline(&str, fp, '\n') != EOF) {
-               char *quoted;
-               int res;
-
                strbuf_trim(&str);
-               quoted = strbuf_detach(&str, NULL);
-               res = sq_dequote_to_argv(quoted, &array->argv,
-                                        &array->argv_nr, &array->argv_alloc);
-               if (res)
+               if (sq_dequote_to_argv_array(str.buf, array))
                        die("Badly quoted content in file '%s': %s",
-                           filename, quoted);
+                           filename, str.buf);
        }
 
        strbuf_release(&str);
@@ -623,7 +597,7 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
                             const char *bad_format, const char *good_format,
                             int read_paths)
 {
-       struct argv_array rev_argv = { NULL, 0, 0 };
+       struct argv_array rev_argv = ARGV_ARRAY_INIT;
        int i;
 
        init_revisions(revs, prefix);
@@ -631,17 +605,17 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
        revs->commit_format = CMIT_FMT_UNSPECIFIED;
 
        /* rev_argv.argv[0] will be ignored by setup_revisions */
-       argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
-       argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
+       argv_array_push(&rev_argv, "bisect_rev_setup");
+       argv_array_pushf(&rev_argv, bad_format, sha1_to_hex(current_bad_sha1));
        for (i = 0; i < good_revs.nr; i++)
-               argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
-                                    good_format);
-       argv_array_push(&rev_argv, xstrdup("--"));
+               argv_array_pushf(&rev_argv, good_format,
+                                sha1_to_hex(good_revs.sha1[i]));
+       argv_array_push(&rev_argv, "--");
        if (read_paths)
                read_bisect_paths(&rev_argv);
-       argv_array_push(&rev_argv, NULL);
 
-       setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
+       setup_revisions(rev_argv.argc, rev_argv.argv, revs, NULL);
+       /* XXX leak rev_argv, as "revs" may still be pointing to it */
 }
 
 static void bisect_common(struct rev_info *revs)
index 708988a0e1a318fb737624f489d01e0686cd0611..abb11650fdd936d01210552b68739f2bff82ed06 100644 (file)
@@ -92,6 +92,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
        struct git_attr_check *check;
        int cnt, i, doubledash, filei;
 
+       git_config(git_default_config, NULL);
+
        argc = parse_options(argc, argv, prefix, check_attr_options,
                             check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
 
index 75dbe761361aa5f5dec2b7ed83556a7035868625..a7a493cecf08b20f32e4161dd5009fd2c3b97448 100644 (file)
@@ -19,6 +19,7 @@
 #include "ll-merge.h"
 #include "resolve-undo.h"
 #include "submodule.h"
+#include "argv-array.h"
 
 static const char * const checkout_usage[] = {
        "git checkout [options] <branch>",
@@ -592,24 +593,12 @@ static void update_refs_for_switch(struct checkout_opts *opts,
                report_tracking(new);
 }
 
-struct rev_list_args {
-       int argc;
-       int alloc;
-       const char **argv;
-};
-
-static void add_one_rev_list_arg(struct rev_list_args *args, const char *s)
-{
-       ALLOC_GROW(args->argv, args->argc + 1, args->alloc);
-       args->argv[args->argc++] = s;
-}
-
 static int add_one_ref_to_rev_list_arg(const char *refname,
                                       const unsigned char *sha1,
                                       int flags,
                                       void *cb_data)
 {
-       add_one_rev_list_arg(cb_data, refname);
+       argv_array_push(cb_data, refname);
        return 0;
 }
 
@@ -689,15 +678,14 @@ static void suggest_reattach(struct commit *commit, struct rev_info *revs)
  */
 static void orphaned_commit_warning(struct commit *commit)
 {
-       struct rev_list_args args = { 0, 0, NULL };
+       struct argv_array args = ARGV_ARRAY_INIT;
        struct rev_info revs;
 
-       add_one_rev_list_arg(&args, "(internal)");
-       add_one_rev_list_arg(&args, sha1_to_hex(commit->object.sha1));
-       add_one_rev_list_arg(&args, "--not");
+       argv_array_push(&args, "(internal)");
+       argv_array_push(&args, sha1_to_hex(commit->object.sha1));
+       argv_array_push(&args, "--not");
        for_each_ref(add_one_ref_to_rev_list_arg, &args);
-       add_one_rev_list_arg(&args, "--");
-       add_one_rev_list_arg(&args, NULL);
+       argv_array_push(&args, "--");
 
        init_revisions(&revs, NULL);
        if (setup_revisions(args.argc - 1, args.argv, &revs, NULL) != 1)
@@ -709,6 +697,7 @@ static void orphaned_commit_warning(struct commit *commit)
        else
                describe_detached_head(_("Previous HEAD position was"), commit);
 
+       argv_array_clear(&args);
        clear_commit_marks(commit, -1);
        for_each_ref(clear_commit_marks_from_one_ref, NULL);
 }
index 488f48e9a571fa9b958cd95b92808b44f4541982..efe8b6cce5a9f2ae40c6f69755debecfb6b501ca 100644 (file)
@@ -577,9 +577,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        if (0 <= option_verbosity) {
                if (option_bare)
-                       printf(_("Cloning into bare repository %s...\n"), dir);
+                       printf(_("Cloning into bare repository '%s'...\n"), dir);
                else
-                       printf(_("Cloning into %s...\n"), dir);
+                       printf(_("Cloning into '%s'...\n"), dir);
        }
        init_db(option_template, INIT_DB_QUIET);
        write_config(&option_config);
index e422ced9299521bb2e7f3c5ff59a434c8403a4ea..9d481f8ca9d9470311b356e9bd5356fa362ffd6a 100644 (file)
@@ -540,10 +540,10 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
        return ret;
 }
 
-static int prune_refs(struct transport *transport, struct ref *ref_map)
+static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
 {
        int result = 0;
-       struct ref *ref, *stale_refs = get_stale_heads(transport->remote, ref_map);
+       struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map);
        const char *dangling_msg = dry_run
                ? _("   (%s will become dangling)\n")
                : _("   (%s has become dangling)\n");
@@ -734,8 +734,31 @@ static int do_fetch(struct transport *transport,
                free_refs(ref_map);
                return 1;
        }
-       if (prune)
-               prune_refs(transport, ref_map);
+       if (prune) {
+               /* If --tags was specified, pretend the user gave us the canonical tags refspec */
+               if (tags == TAGS_SET) {
+                       const char *tags_str = "refs/tags/*:refs/tags/*";
+                       struct refspec *tags_refspec, *refspec;
+
+                       /* Copy the refspec and add the tags to it */
+                       refspec = xcalloc(ref_count + 1, sizeof(struct refspec));
+                       tags_refspec = parse_fetch_refspec(1, &tags_str);
+                       memcpy(refspec, refs, ref_count * sizeof(struct refspec));
+                       memcpy(&refspec[ref_count], tags_refspec, sizeof(struct refspec));
+                       ref_count++;
+
+                       prune_refs(refspec, ref_count, ref_map);
+
+                       ref_count--;
+                       /* The rest of the strings belong to fetch_one */
+                       free_refspec(1, tags_refspec);
+                       free(refspec);
+               } else if (ref_count) {
+                       prune_refs(refs, ref_count, ref_map);
+               } else {
+                       prune_refs(transport->remote->fetch, transport->remote->fetch_refspec_nr, ref_map);
+               }
+       }
        free_refs(ref_map);
 
        /* if neither --no-tags nor --tags was specified, do automated tag
@@ -918,7 +941,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
        atexit(unlock_pack);
        refspec = parse_fetch_refspec(ref_nr, refs);
        exit_code = do_fetch(transport, refspec, ref_nr);
-       free(refspec);
+       free_refspec(ref_nr, refspec);
        transport_disconnect(transport);
        transport = NULL;
        return exit_code;
index 40f33ca4d0e6d0bb1733e0544029c6f588d09b59..5efe6c5760c43d0059a940ab9d4610b97092c8bd 100644 (file)
@@ -29,7 +29,11 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
                        to_copy--;
                if (to_copy != length || base_name) {
                        char *it = xmemdupz(result[i], to_copy);
-                       result[i] = base_name ? strdup(basename(it)) : it;
+                       if (base_name) {
+                               result[i] = xstrdup(basename(it));
+                               free(it);
+                       } else
+                               result[i] = it;
                }
        }
        return get_pathspec(prefix, result);
index ae164da4d5a7b7a2c87937ba0983126586f1e646..af429e101777f1c5df09734433278cfb075e978c 100644 (file)
@@ -205,21 +205,15 @@ static int copy_to_sideband(int in, int out, void *arg)
        return 0;
 }
 
-static int run_receive_hook(struct command *commands, const char *hook_name)
+typedef int (*feed_fn)(void *, const char **, size_t *);
+static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state)
 {
-       static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4];
-       struct command *cmd;
        struct child_process proc;
        struct async muxer;
        const char *argv[2];
-       int have_input = 0, code;
-
-       for (cmd = commands; !have_input && cmd; cmd = cmd->next) {
-               if (!cmd->error_string)
-                       have_input = 1;
-       }
+       int code;
 
-       if (!have_input || access(hook_name, X_OK) < 0)
+       if (access(hook_name, X_OK) < 0)
                return 0;
 
        argv[0] = hook_name;
@@ -247,15 +241,13 @@ static int run_receive_hook(struct command *commands, const char *hook_name)
                return code;
        }
 
-       for (cmd = commands; cmd; cmd = cmd->next) {
-               if (!cmd->error_string) {
-                       size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
-                               sha1_to_hex(cmd->old_sha1),
-                               sha1_to_hex(cmd->new_sha1),
-                               cmd->ref_name);
-                       if (write_in_full(proc.in, buf, n) != n)
-                               break;
-               }
+       while (1) {
+               const char *buf;
+               size_t n;
+               if (feed(feed_state, &buf, &n))
+                       break;
+               if (write_in_full(proc.in, buf, n) != n)
+                       break;
        }
        close(proc.in);
        if (use_sideband)
@@ -263,6 +255,47 @@ static int run_receive_hook(struct command *commands, const char *hook_name)
        return finish_command(&proc);
 }
 
+struct receive_hook_feed_state {
+       struct command *cmd;
+       struct strbuf buf;
+};
+
+static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
+{
+       struct receive_hook_feed_state *state = state_;
+       struct command *cmd = state->cmd;
+
+       while (cmd && cmd->error_string)
+               cmd = cmd->next;
+       if (!cmd)
+               return -1; /* EOF */
+       strbuf_reset(&state->buf);
+       strbuf_addf(&state->buf, "%s %s %s\n",
+                   sha1_to_hex(cmd->old_sha1), sha1_to_hex(cmd->new_sha1),
+                   cmd->ref_name);
+       state->cmd = cmd->next;
+       if (bufp) {
+               *bufp = state->buf.buf;
+               *sizep = state->buf.len;
+       }
+       return 0;
+}
+
+static int run_receive_hook(struct command *commands, const char *hook_name)
+{
+       struct receive_hook_feed_state state;
+       int status;
+
+       strbuf_init(&state.buf, 0);
+       state.cmd = commands;
+       if (feed_receive_hook(&state, NULL, NULL))
+               return 0;
+       state.cmd = commands;
+       status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
+       strbuf_release(&state.buf);
+       return status;
+}
+
 static int run_update_hook(struct command *cmd)
 {
        static const char update_hook[] = "hooks/update";
index f2a9c26dc3494c0881ca3f91b44785c4b52caae7..e1285becffd768c88b4802425f0f5901cda83f06 100644 (file)
@@ -349,7 +349,8 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
                else
                        string_list_append(&states->tracked, abbrev_branch(ref->name));
        }
-       stale_refs = get_stale_heads(states->remote, fetch_map);
+       stale_refs = get_stale_heads(states->remote->fetch,
+                                    states->remote->fetch_refspec_nr, fetch_map);
        for (ref = stale_refs; ref; ref = ref->next) {
                struct string_list_item *item =
                        string_list_append(&states->stale, abbrev_branch(ref->name));
@@ -570,7 +571,7 @@ static int read_remote_branches(const char *refname,
        unsigned char orig_sha1[20];
        const char *symref;
 
-       strbuf_addf(&buf, "refs/remotes/%s", rename->old);
+       strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
        if (!prefixcmp(refname, buf.buf)) {
                item = string_list_append(rename->remote_branches, xstrdup(refname));
                symref = resolve_ref(refname, orig_sha1, 1, &flag);
@@ -621,10 +622,11 @@ static int mv(int argc, const char **argv)
                OPT_END()
        };
        struct remote *oldremote, *newremote;
-       struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
+       struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
+               old_remote_context = STRBUF_INIT;
        struct string_list remote_branches = STRING_LIST_INIT_NODUP;
        struct rename_info rename;
-       int i;
+       int i, refspec_updated = 0;
 
        if (argc != 3)
                usage_with_options(builtin_remote_rename_usage, options);
@@ -659,15 +661,25 @@ static int mv(int argc, const char **argv)
        strbuf_addf(&buf, "remote.%s.fetch", rename.new);
        if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
                return error("Could not remove config section '%s'", buf.buf);
+       strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
        for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
                char *ptr;
 
                strbuf_reset(&buf2);
                strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
-               ptr = strstr(buf2.buf, rename.old);
-               if (ptr)
-                       strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
-                                       rename.new, strlen(rename.new));
+               ptr = strstr(buf2.buf, old_remote_context.buf);
+               if (ptr) {
+                       refspec_updated = 1;
+                       strbuf_splice(&buf2,
+                                     ptr-buf2.buf + strlen(":refs/remotes/"),
+                                     strlen(rename.old), rename.new,
+                                     strlen(rename.new));
+               } else
+                       warning("Not updating non-default fetch respec\n"
+                               "\t%s\n"
+                               "\tPlease update the configuration manually if necessary.",
+                               buf2.buf);
+
                if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
                        return error("Could not append '%s'", buf.buf);
        }
@@ -685,6 +697,9 @@ static int mv(int argc, const char **argv)
                }
        }
 
+       if (!refspec_updated)
+               return 0;
+
        /*
         * First remove symrefs, then rename the rest, finally create
         * the new symrefs.
diff --git a/cache.h b/cache.h
index 607c2ea612889c46e81ae375b6985db18e529a8e..8d95fb25a2505a408aea4beba43409facb578213 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -589,6 +589,7 @@ extern int warn_ambiguous_refs;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
 extern const char *apply_default_ignorewhitespace;
+extern const char *git_attributes_file;
 extern int zlib_compression_level;
 extern int core_compression_level;
 extern int core_compression_seen;
index 6ef0cc4f99becd772a6fed1cfe2484a67b3a9000..8947418ce78faa3619779c12319c0dd99b1557d3 100644 (file)
@@ -1183,7 +1183,7 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
        }
        ai->ai_addrlen = sizeof(struct sockaddr_in);
        if (hints && (hints->ai_flags & AI_CANONNAME))
-               ai->ai_canonname = h ? strdup(h->h_name) : NULL;
+               ai->ai_canonname = h ? xstrdup(h->h_name) : NULL;
        else
                ai->ai_canonname = NULL;
 
index d93dce2cf8fa33bd1fbefe131d2e41a6b954da61..9574d537bd38d3aa72ee040b106456088ee16a07 100644 (file)
@@ -55,7 +55,7 @@ void git_qsort(void *b, size_t n, size_t s,
                msort_with_tmp(b, n, s, cmp, buf);
        } else {
                /* It's somewhat large, so malloc it.  */
-               char *tmp = malloc(size);
+               char *tmp = xmalloc(size);
                msort_with_tmp(b, n, s, cmp, tmp);
                free(tmp);
        }
index 4183f80262ea9f24e286295a2295f93459548b78..d3bcaa023d1f238d8fa9b2c416ae7448eff36d17 100644 (file)
--- a/config.c
+++ b/config.c
@@ -491,6 +491,9 @@ static int git_default_core_config(const char *var, const char *value)
                return 0;
        }
 
+       if (!strcmp(var, "core.attributesfile"))
+               return git_config_pathname(&git_attributes_file, var, value);
+
        if (!strcmp(var, "core.bare")) {
                is_bare_repository_cfg = git_config_bool(var, value);
                return 0;
diff --git a/date.c b/date.c
index 896fbb48060c673b8dc2f2aa6ea3de3c1042fbd2..353e0a5e53f13c36549e65452931f254de3423c4 100644 (file)
--- a/date.c
+++ b/date.c
@@ -552,23 +552,35 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
 static int match_tz(const char *date, int *offp)
 {
        char *end;
-       int offset = strtoul(date+1, &end, 10);
-       int min, hour;
-       int n = end - date - 1;
+       int hour = strtoul(date + 1, &end, 10);
+       int n = end - (date + 1);
+       int min = 0;
 
-       min = offset % 100;
-       hour = offset / 100;
+       if (n == 4) {
+               /* hhmm */
+               min = hour % 100;
+               hour = hour / 100;
+       } else if (n != 2) {
+               min = 99; /* random crap */
+       } else if (*end == ':') {
+               /* hh:mm? */
+               min = strtoul(end + 1, &end, 10);
+               if (end - (date + 1) != 5)
+                       min = 99; /* random crap */
+       } /* otherwise we parsed "hh" */
 
        /*
-        * Don't accept any random crap.. At least 3 digits, and
-        * a valid minute. We might want to check that the minutes
-        * are divisible by 30 or something too.
+        * Don't accept any random crap. Even though some places have
+        * offset larger than 12 hours (e.g. Pacific/Kiritimati is at
+        * UTC+14), there is something wrong if hour part is much
+        * larger than that. We might also want to check that the
+        * minutes are divisible by 15 or something too. (Offset of
+        * Kathmandu, Nepal is UTC+5:45)
         */
-       if (min < 60 && n > 2) {
-               offset = hour*60+min;
+       if (min < 60 && hour < 24) {
+               int offset = hour * 60 + min;
                if (*date == '-')
                        offset = -offset;
-
                *offp = offset;
        }
        return end - date;
index ebe751e72d0ca9db2f0a9d2576f3dc3f41ffc31d..62f4cd94cfbc4d3fe9e46c84f318af6624349a48 100644 (file)
@@ -289,7 +289,7 @@ static void show_new_file(struct rev_info *revs,
 
        /*
         * New file in the index: it might actually be different in
-        * the working copy.
+        * the working tree.
         */
        if (get_stat_data(new, &sha1, &mode, cached, match_missing,
            &dirty_submodule, &revs->diffopt) < 0)
diff --git a/diff.c b/diff.c
index 977ca7125b9acc603ce6c1d27c57a75c9d21fbdf..d922b77aef2da84824a8e14fc21961e36e6d2e36 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2274,6 +2274,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                memset(&xpp, 0, sizeof(xpp));
                memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = o->xdl_opts;
+               xecfg.ctxlen = o->context;
+               xecfg.interhunkctxlen = o->interhunkcontext;
                xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
                              &xpp, &xecfg);
        }
index e96edcfebc4174a5166c11e7a511ea792e7a2639..d60b73f6a5a88632a2a36140bf719484adec9f39 100644 (file)
@@ -29,6 +29,7 @@ const char *git_log_output_encoding;
 int shared_repository = PERM_UMASK;
 const char *apply_default_whitespace;
 const char *apply_default_ignorewhitespace;
+const char *git_attributes_file;
 int zlib_compression_level = Z_BEST_SPEED;
 int core_compression_level;
 int core_compression_seen;
index 2524060475ef369c0b9a4641aa88dc2ad6083da4..99efbe884528ffa730d6c0297e20d9de93d5ad9e 100755 (executable)
@@ -126,7 +126,8 @@ bisect_start() {
                start_head=$(cat "$GIT_DIR/BISECT_START")
                if test "z$mode" != "z--no-checkout"
                then
-                       git checkout "$start_head" --
+                       git checkout "$start_head" -- ||
+                       die "$(eval_gettext "Checking out '\$start_head' failed. Try 'git bisect reset <validbranch>'.")"
                fi
        else
                # Get rev from where we start.
index b6d463f0d057361ab5909209d24fc8fd383a3dbb..085e213a126e5864befc8e3436832ae3c587a624 100755 (executable)
@@ -342,64 +342,42 @@ merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo fa
 
 last_status=0
 rollup_status=0
-rerere=false
-
-files_to_merge() {
-    if test "$rerere" = true
-    then
-       git rerere remaining
-    else
-       git ls-files -u | sed -e 's/^[^ ]*      //' | sort -u
-    fi
-}
-
+files=
 
 if test $# -eq 0 ; then
     cd_to_toplevel
 
     if test -e "$GIT_DIR/MERGE_RR"
     then
-       rerere=true
-    fi
-
-    files=$(files_to_merge)
-    if test -z "$files" ; then
-       echo "No files need merging"
-       exit 0
+       files=$(git rerere remaining)
+    else
+       files=$(git ls-files -u | sed -e 's/^[^ ]*      //' | sort -u)
     fi
+else
+    files=$(git ls-files -u -- "$@" | sed -e 's/^[^    ]*      //' | sort -u)
+fi
 
-    # Save original stdin
-    exec 3<&0
+if test -z "$files" ; then
+    echo "No files need merging"
+    exit 0
+fi
 
-    printf "Merging:\n"
-    printf "$files\n"
+printf "Merging:\n"
+printf "$files\n"
 
-    files_to_merge |
-    while IFS= read i
-    do
-       if test $last_status -ne 0; then
-           prompt_after_failed_merge <&3 || exit 1
-       fi
-       printf "\n"
-       merge_file "$i" <&3
-       last_status=$?
-       if test $last_status -ne 0; then
-           rollup_status=1
-       fi
-    done
-else
-    while test $# -gt 0; do
-       if test $last_status -ne 0; then
-           prompt_after_failed_merge || exit 1
-       fi
-       printf "\n"
-       merge_file "$1"
-       last_status=$?
-       if test $last_status -ne 0; then
-           rollup_status=1
-       fi
-       shift
-    done
-fi
+IFS='
+'
+for i in $files
+do
+    if test $last_status -ne 0; then
+       prompt_after_failed_merge || exit 1
+    fi
+    printf "\n"
+    merge_file "$i"
+    last_status=$?
+    if test $last_status -ne 0; then
+       rollup_status=1
+    fi
+done
 
 exit $rollup_status
index 63da37bcc2730358140ae4b862040ed8fb0ed77e..902fc4adb4b95d27c6ba6c63f40108702dd93f11 100755 (executable)
@@ -11,7 +11,7 @@ OPTIONS_SPEC=
 . git-sh-setup
 . git-sh-i18n
 set_reflog_action "pull${1+ $*}"
-require_work_tree
+require_work_tree_exists
 cd_to_toplevel
 
 
index 6759702c573f51ac00bf1b5c8abccf252cb4ff1d..00ca7b99fef35e21d24af844e6dbaa92cab5834f 100755 (executable)
@@ -63,7 +63,7 @@ skip!              skip current patch and continue
 "
 . git-sh-setup
 set_reflog_action rebase
-require_work_tree
+require_work_tree_exists
 cd_to_toplevel
 
 LF='
index 98ab33aae7e35c2d288bc34ddb2bbc71f8a16cdd..5790744ae3fd89f83a229f964a5603df94e05c83 100755 (executable)
@@ -1079,7 +1079,7 @@ X-Mailer: git-send-email $gitversion
                                        $smtp_encryption = '';
                                        # Send EHLO again to receive fresh
                                        # supported commands
-                                       $smtp->hello();
+                                       $smtp->hello($smtp_domain);
                                } else {
                                        die "Server does not support STARTTLS! ".$smtp->message;
                                }
index 70a576a626ac67516af7b980c64ec33da6b7c19b..85d64b244dead86132de8a2a980cfbfc27c86494 100755 (executable)
@@ -1517,6 +1517,17 @@ sub esc_path {
        return $str;
 }
 
+# Sanitize for use in XHTML + application/xml+xhtm (valid XML 1.0)
+sub sanitize {
+       my $str = shift;
+
+       return undef unless defined $str;
+
+       $str = to_utf8($str);
+       $str =~ s|([[:cntrl:]])|($1 =~ /[\t\n\r]/ ? $1 : quot_cec($1))|eg;
+       return $str;
+}
+
 # Make control characters "printable", using character escape codes (CEC)
 sub quot_cec {
        my $cntrl = shift;
@@ -6484,7 +6495,8 @@ sub git_blob {
                        $nr++;
                        $line = untabify($line);
                        printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
-                              $nr, esc_attr(href(-replay => 1)), $nr, $nr, $syntax ? to_utf8($line) : esc_html($line, -nbsp=>1);
+                              $nr, esc_attr(href(-replay => 1)), $nr, $nr,
+                              $syntax ? sanitize($line) : esc_html($line, -nbsp=>1);
                }
        }
        close $fd
index 93dd2bdd91b2b4b851f4ddc3b806e58bde792d56..fa2596f77c645b87e79aceb242d6074d6b2764ea 100644 (file)
@@ -16,7 +16,7 @@
  * and other reasons to not add 'js=1' param at the end of link
  * @constant
  */
-var jsExceptionsRe = /[;?]js=[01]$/;
+var jsExceptionsRe = /[;?]js=[01](#.*)?$/;
 
 /**
  * Add '?js=1' or ';js=1' to the end of every link in the document
@@ -33,9 +33,9 @@ function fixLinks() {
        var allLinks = document.getElementsByTagName("a") || document.links;
        for (var i = 0, len = allLinks.length; i < len; i++) {
                var link = allLinks[i];
-               if (!jsExceptionsRe.test(link)) { // =~ /[;?]js=[01]$/;
-                       link.href +=
-                               (link.href.indexOf('?') === -1 ? '?' : ';') + 'js=1';
+               if (!jsExceptionsRe.test(link)) {
+                       link.href = link.href.replace(/(#|$)/,
+                               (link.href.indexOf('?') === -1 ? '?' : ';') + 'js=1$1');
                }
        }
 }
diff --git a/http.c b/http.c
index a59cac45d7a6c159e740cab9b20bb63ab91f7c48..fb3465f50c95ab9cb3e6fae1d1e594f6ae0b9c42 100644 (file)
--- a/http.c
+++ b/http.c
@@ -851,8 +851,13 @@ static int http_request(const char *url, void *result, int target, int options)
                                init_curl_http_auth(slot->curl);
                                ret = HTTP_REAUTH;
                        }
-               } else
+               } else {
+                       if (!curl_errorstr[0])
+                               strlcpy(curl_errorstr,
+                                       curl_easy_strerror(results.curl_result),
+                                       sizeof(curl_errorstr));
                        ret = HTTP_ERROR;
+               }
        } else {
                error("Unable to start HTTP request for %s", url);
                ret = HTTP_START_FAILED;
@@ -908,7 +913,7 @@ int http_error(const char *url, int ret)
 {
        /* http_request has already handled HTTP_START_FAILED. */
        if (ret != HTTP_START_FAILED)
-               error("%s while accessing %s\n", curl_errorstr, url);
+               error("%s while accessing %s", curl_errorstr, url);
 
        return ret;
 }
index 3efc04e04fd754de85fbab1dbafa7bffb2fa2854..c34a4f148b65cf81f28e2aed6c35e141e175b324 100644 (file)
@@ -390,7 +390,7 @@ static void record_df_conflict_files(struct merge_options *o,
                                     struct string_list *entries)
 {
        /* If there is a D/F conflict and the file for such a conflict
-        * currently exist in the working copy, we want to allow it to be
+        * currently exist in the working tree, we want to allow it to be
         * removed to make room for the corresponding directory if needed.
         * The files underneath the directories of such D/F conflicts will
         * be processed before the corresponding file involved in the D/F
index e1aaf43b438d0cfb6b7b0c723060a662a915bcea..baaf31f4aed4e4cfd967c278b7cfd4bee6a0ab30 100644 (file)
@@ -680,7 +680,7 @@ int notes_merge_commit(struct notes_merge_options *o,
         * Finally store the new commit object SHA1 into 'result_sha1'.
         */
        struct dir_struct dir;
-       const char *path = git_path(NOTES_MERGE_WORKTREE "/");
+       char *path = xstrdup(git_path(NOTES_MERGE_WORKTREE "/"));
        int path_len = strlen(path), i;
        const char *msg = strstr(partial_commit->buffer, "\n\n");
 
@@ -720,6 +720,7 @@ int notes_merge_commit(struct notes_merge_options *o,
                            result_sha1);
        OUTPUT(o, 4, "Finalized notes merge commit: %s",
               sha1_to_hex(result_sha1));
+       free(path);
        return 0;
 }
 
diff --git a/quote.c b/quote.c
index 532fd3b7b7a0c7b6766a7af742b0c7362f307221..911229fdf3caffe29a87aea76f38dc50863797d4 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "quote.h"
+#include "argv-array.h"
 
 int quote_path_fully = 1;
 
@@ -120,7 +121,9 @@ char *sq_dequote(char *arg)
        return sq_dequote_step(arg, NULL);
 }
 
-int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
+static int sq_dequote_to_argv_internal(char *arg,
+                                      const char ***argv, int *nr, int *alloc,
+                                      struct argv_array *array)
 {
        char *next = arg;
 
@@ -130,13 +133,27 @@ int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
                char *dequoted = sq_dequote_step(next, &next);
                if (!dequoted)
                        return -1;
-               ALLOC_GROW(*argv, *nr + 1, *alloc);
-               (*argv)[(*nr)++] = dequoted;
+               if (argv) {
+                       ALLOC_GROW(*argv, *nr + 1, *alloc);
+                       (*argv)[(*nr)++] = dequoted;
+               }
+               if (array)
+                       argv_array_push(array, dequoted);
        } while (next);
 
        return 0;
 }
 
+int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc)
+{
+       return sq_dequote_to_argv_internal(arg, argv, nr, alloc, NULL);
+}
+
+int sq_dequote_to_argv_array(char *arg, struct argv_array *array)
+{
+       return sq_dequote_to_argv_internal(arg, NULL, NULL, NULL, array);
+}
+
 /* 1 means: quote as octal
  * 0 means: quote as octal if (quote_path_fully)
  * -1 means: never quote
diff --git a/quote.h b/quote.h
index 024e21d80ceaa37ec1f893acc907a62092560d21..133155a48b4baa56cd70c07af8a477771f373105 100644 (file)
--- a/quote.h
+++ b/quote.h
@@ -40,12 +40,19 @@ extern char *sq_dequote(char *);
 
 /*
  * Same as the above, but can be used to unwrap many arguments in the
- * same string separated by space. "next" is changed to point to the
- * next argument that should be passed as first parameter. When there
- * is no more argument to be dequoted, "next" is updated to point to NULL.
+ * same string separated by space. Like sq_quote, it works in place,
+ * modifying arg and appending pointers into it to argv.
  */
 extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
 
+/*
+ * Same as above, but store the unquoted strings in an argv_array. We will
+ * still modify arg in place, but unlike sq_dequote_to_argv, the argv_array
+ * will duplicate and take ownership of the strings.
+ */
+struct argv_array;
+extern int sq_dequote_to_argv_array(char *arg, struct argv_array *);
+
 extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
 extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq);
 extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
index b8cf45a7dd439b83c80bcf7a397e1b8e34c70f67..0aa4bfed309d6c439fac4ff2a0df6a468307e7bf 100644 (file)
@@ -573,7 +573,14 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
 
        close(client.in);
        client.in = -1;
-       strbuf_read(&rpc->result, client.out, 0);
+       if (!err) {
+               strbuf_read(&rpc->result, client.out, 0);
+       } else {
+               char buf[4096];
+               for (;;)
+                       if (xread(client.out, buf, sizeof(buf)) <= 0)
+                               break;
+       }
 
        close(client.out);
        client.out = -1;
index b8ecfa5d9558e3824872ad6778fc344681cc8d5c..6ececc4a7703f6d54caf919b1162ed454b45a47e 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -828,59 +828,56 @@ static int match_name_with_pattern(const char *key, const char *name,
        return ret;
 }
 
-char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
-                    const char *name)
+static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
 {
        int i;
-       char *ret = NULL;
-       for (i = 0; i < nr_refspec; i++) {
-               struct refspec *refspec = refspecs + i;
-               if (refspec->pattern) {
-                       if (match_name_with_pattern(refspec->src, name,
-                                                   refspec->dst, &ret))
-                               return ret;
-               } else if (!strcmp(refspec->src, name))
-                       return strdup(refspec->dst);
-       }
-       return NULL;
-}
+       int find_src = !query->src;
 
-int remote_find_tracking(struct remote *remote, struct refspec *refspec)
-{
-       int find_src = refspec->src == NULL;
-       char *needle, **result;
-       int i;
+       if (find_src && !query->dst)
+               return error("query_refspecs: need either src or dst");
 
-       if (find_src) {
-               if (!refspec->dst)
-                       return error("find_tracking: need either src or dst");
-               needle = refspec->dst;
-               result = &refspec->src;
-       } else {
-               needle = refspec->src;
-               result = &refspec->dst;
-       }
+       for (i = 0; i < ref_count; i++) {
+               struct refspec *refspec = &refs[i];
+               const char *key = find_src ? refspec->dst : refspec->src;
+               const char *value = find_src ? refspec->src : refspec->dst;
+               const char *needle = find_src ? query->dst : query->src;
+               char **result = find_src ? &query->src : &query->dst;
 
-       for (i = 0; i < remote->fetch_refspec_nr; i++) {
-               struct refspec *fetch = &remote->fetch[i];
-               const char *key = find_src ? fetch->dst : fetch->src;
-               const char *value = find_src ? fetch->src : fetch->dst;
-               if (!fetch->dst)
+               if (!refspec->dst)
                        continue;
-               if (fetch->pattern) {
+               if (refspec->pattern) {
                        if (match_name_with_pattern(key, needle, value, result)) {
-                               refspec->force = fetch->force;
+                               query->force = refspec->force;
                                return 0;
                        }
                } else if (!strcmp(needle, key)) {
                        *result = xstrdup(value);
-                       refspec->force = fetch->force;
+                       query->force = refspec->force;
                        return 0;
                }
        }
        return -1;
 }
 
+char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
+                    const char *name)
+{
+       struct refspec query;
+
+       memset(&query, 0, sizeof(struct refspec));
+       query.src = (char *)name;
+
+       if (query_refspecs(refspecs, nr_refspec, &query))
+               return NULL;
+
+       return query.dst;
+}
+
+int remote_find_tracking(struct remote *remote, struct refspec *refspec)
+{
+       return query_refspecs(remote->fetch, remote->fetch_refspec_nr, refspec);
+}
+
 static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen,
                const char *name)
 {
@@ -1681,36 +1678,47 @@ struct ref *guess_remote_head(const struct ref *head,
 }
 
 struct stale_heads_info {
-       struct remote *remote;
        struct string_list *ref_names;
        struct ref **stale_refs_tail;
+       struct refspec *refs;
+       int ref_count;
 };
 
 static int get_stale_heads_cb(const char *refname,
        const unsigned char *sha1, int flags, void *cb_data)
 {
        struct stale_heads_info *info = cb_data;
-       struct refspec refspec;
-       memset(&refspec, 0, sizeof(refspec));
-       refspec.dst = (char *)refname;
-       if (!remote_find_tracking(info->remote, &refspec)) {
-               if (!((flags & REF_ISSYMREF) ||
-                   string_list_has_string(info->ref_names, refspec.src))) {
-                       struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
-                       hashcpy(ref->new_sha1, sha1);
-               }
+       struct refspec query;
+       memset(&query, 0, sizeof(struct refspec));
+       query.dst = (char *)refname;
+
+       if (query_refspecs(info->refs, info->ref_count, &query))
+               return 0; /* No matches */
+
+       /*
+        * If we did find a suitable refspec and it's not a symref and
+        * it's not in the list of refs that currently exist in that
+        * remote we consider it to be stale.
+        */
+       if (!((flags & REF_ISSYMREF) ||
+             string_list_has_string(info->ref_names, query.src))) {
+               struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
+               hashcpy(ref->new_sha1, sha1);
        }
+
+       free(query.src);
        return 0;
 }
 
-struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
+struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map)
 {
        struct ref *ref, *stale_refs = NULL;
        struct string_list ref_names = STRING_LIST_INIT_NODUP;
        struct stale_heads_info info;
-       info.remote = remote;
        info.ref_names = &ref_names;
        info.stale_refs_tail = &stale_refs;
+       info.refs = refs;
+       info.ref_count = ref_count;
        for (ref = fetch_map; ref; ref = ref->next)
                string_list_append(&ref_names, ref->name);
        sort_string_list(&ref_names);
index 9a30a9dba64825950f7a0448ad8b64581c0b8fae..f2541b5a29a552fb9fab736f5b47a545c2eee383 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -164,6 +164,6 @@ struct ref *guess_remote_head(const struct ref *head,
                              int all);
 
 /* Return refs which no longer exist on remote */
-struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map);
+struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map);
 
 #endif
index a2796c4caecc0fae6ea1a95b2c965b92d98f8a31..1c5104388429e50722769358d5d89948c55bb3aa 100644 (file)
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 #include "exec_cmd.h"
+#include "argv-array.h"
 
 static inline void close_pair(int fd[2])
 {
@@ -605,26 +606,23 @@ int finish_async(struct async *async)
 int run_hook(const char *index_file, const char *name, ...)
 {
        struct child_process hook;
-       const char **argv = NULL, *env[2];
+       struct argv_array argv = ARGV_ARRAY_INIT;
+       const char *p, *env[2];
        char index[PATH_MAX];
        va_list args;
        int ret;
-       size_t i = 0, alloc = 0;
 
        if (access(git_path("hooks/%s", name), X_OK) < 0)
                return 0;
 
        va_start(args, name);
-       ALLOC_GROW(argv, i + 1, alloc);
-       argv[i++] = git_path("hooks/%s", name);
-       while (argv[i-1]) {
-               ALLOC_GROW(argv, i + 1, alloc);
-               argv[i++] = va_arg(args, const char *);
-       }
+       argv_array_push(&argv, git_path("hooks/%s", name));
+       while ((p = va_arg(args, const char *)))
+               argv_array_push(&argv, p);
        va_end(args);
 
        memset(&hook, 0, sizeof(hook));
-       hook.argv = argv;
+       hook.argv = argv.argv;
        hook.no_stdin = 1;
        hook.stdout_to_stderr = 1;
        if (index_file) {
@@ -635,6 +633,6 @@ int run_hook(const char *index_file, const char *name, ...)
        }
 
        ret = run_command(&hook);
-       free(argv);
+       argv_array_clear(&argv);
        return ret;
 }
index 4c0ac138aff7b5add73e17fc9c3c4e409fd918e2..63f9da53237d4233bede66a28e4bcf27d5b44af1 100644 (file)
@@ -48,7 +48,7 @@ int main(int argc, char **argv)
                        unsigned char sha1[20];
                        uint32_t crc;
                        uint32_t off;
-               } *entries = malloc(nr * sizeof(entries[0]));
+               } *entries = xmalloc(nr * sizeof(entries[0]));
                for (i = 0; i < nr; i++)
                        if (fread(entries[i].sha1, 20, 1, stdin) != 1)
                                die("unable to read sha1 %u/%u", i, nr);
index 08756387e207700861cfa6dac039334ecd53c7a1..0b709bc2914335853e7525076f5e1d026d5dd779 100644 (file)
@@ -9,6 +9,7 @@
 #include "refs.h"
 #include "string-list.h"
 #include "sha1-array.h"
+#include "argv-array.h"
 
 static struct string_list config_name_for_path;
 static struct string_list config_fetch_recurse_submodules_for_name;
@@ -496,56 +497,26 @@ void check_for_new_submodule_commits(unsigned char new_sha1[20])
        sha1_array_append(&ref_tips_after_fetch, new_sha1);
 }
 
-struct argv_array {
-       const char **argv;
-       unsigned int argc;
-       unsigned int alloc;
-};
-
-static void init_argv(struct argv_array *array)
-{
-       array->argv = NULL;
-       array->argc = 0;
-       array->alloc = 0;
-}
-
-static void push_argv(struct argv_array *array, const char *value)
-{
-       ALLOC_GROW(array->argv, array->argc + 2, array->alloc);
-       array->argv[array->argc++] = xstrdup(value);
-       array->argv[array->argc] = NULL;
-}
-
-static void clear_argv(struct argv_array *array)
-{
-       int i;
-       for (i = 0; i < array->argc; i++)
-               free((char **)array->argv[i]);
-       free(array->argv);
-       init_argv(array);
-}
-
 static void add_sha1_to_argv(const unsigned char sha1[20], void *data)
 {
-       push_argv(data, sha1_to_hex(sha1));
+       argv_array_push(data, sha1_to_hex(sha1));
 }
 
 static void calculate_changed_submodule_paths(void)
 {
        struct rev_info rev;
        struct commit *commit;
-       struct argv_array argv;
+       struct argv_array argv = ARGV_ARRAY_INIT;
 
        /* No need to check if there are no submodules configured */
        if (!config_name_for_path.nr)
                return;
 
        init_revisions(&rev, NULL);
-       init_argv(&argv);
-       push_argv(&argv, "--"); /* argv[0] program name */
+       argv_array_push(&argv, "--"); /* argv[0] program name */
        sha1_array_for_each_unique(&ref_tips_after_fetch,
                                   add_sha1_to_argv, &argv);
-       push_argv(&argv, "--not");
+       argv_array_push(&argv, "--not");
        sha1_array_for_each_unique(&ref_tips_before_fetch,
                                   add_sha1_to_argv, &argv);
        setup_revisions(argv.argc, argv.argv, &rev, NULL);
@@ -573,7 +544,7 @@ static void calculate_changed_submodule_paths(void)
                }
        }
 
-       clear_argv(&argv);
+       argv_array_clear(&argv);
        sha1_array_clear(&ref_tips_before_fetch);
        sha1_array_clear(&ref_tips_after_fetch);
        initialized_fetch_ref_tips = 0;
index ae2f1da28fa55b92338d7dbcb6ef851b6ec40118..6946c4b82f9291f6618d49de2e3892a2c203d337 100755 (executable)
@@ -9,7 +9,7 @@ attr_check () {
        path="$1"
        expect="$2"
 
-       git check-attr test -- "$path" >actual 2>err &&
+       git $3 check-attr test -- "$path" >actual 2>err &&
        echo "$path: test: $2" >expect &&
        test_cmp expect actual &&
        test_line_count = 0 err
@@ -27,6 +27,7 @@ test_expect_success 'setup' '
                echo "onoff test -test"
                echo "offon -test test"
                echo "no notest"
+               echo "A/e/F test=A/e/F"
        ) >.gitattributes &&
        (
                echo "g test=a/g" &&
@@ -93,6 +94,62 @@ test_expect_success 'attribute test' '
 
 '
 
+test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' '
+
+       test_must_fail attr_check F f "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/F f "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/c/F f "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/G a/g "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" &&
+       test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" &&
+       test_must_fail attr_check oFfOn set "-c core.ignorecase=0" &&
+       attr_check NO unspecified "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
+       attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" &&
+       test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0"
+
+'
+
+test_expect_success 'attribute matching is case insensitive when core.ignorecase=1' '
+
+       attr_check F f "-c core.ignorecase=1" &&
+       attr_check a/F f "-c core.ignorecase=1" &&
+       attr_check a/c/F f "-c core.ignorecase=1" &&
+       attr_check a/G a/g "-c core.ignorecase=1" &&
+       attr_check a/B/g a/b/g "-c core.ignorecase=1" &&
+       attr_check a/b/G a/b/g "-c core.ignorecase=1" &&
+       attr_check a/b/H a/b/h "-c core.ignorecase=1" &&
+       attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=1" &&
+       attr_check oNoFf unset "-c core.ignorecase=1" &&
+       attr_check oFfOn set "-c core.ignorecase=1" &&
+       attr_check NO unspecified "-c core.ignorecase=1" &&
+       attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=1" &&
+       attr_check a/b/d/YES unspecified "-c core.ignorecase=1" &&
+       attr_check a/E/f "A/e/F" "-c core.ignorecase=1"
+
+'
+
+test_expect_success 'check whether FS is case-insensitive' '
+       mkdir junk &&
+       echo good >junk/CamelCase &&
+       echo bad >junk/camelcase &&
+       if test "$(cat junk/CamelCase)" != good
+       then
+               test_set_prereq CASE_INSENSITIVE_FS
+       fi
+'
+
+test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' '
+       test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" &&
+       test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" &&
+       attr_check A/b/h a/b/h "-c core.ignorecase=1" &&
+       attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" &&
+       attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1"
+'
+
 test_expect_success 'unnormalized paths' '
 
        attr_check ./f f &&
index f87abb5a0682d7a2fc7c3947789301c4157d331d..1d29810a7a94dad15645869c2f4f015a470fa622 100755 (executable)
@@ -40,6 +40,12 @@ check_parse 2008-02 bad
 check_parse 2008-02-14 bad
 check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000'
 check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500'
+check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015'
+check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -05' '2008-02-14 20:30:45 -0500'
+check_parse '2008-02-14 20:30:45 -:30' '2008-02-14 20:30:45 +0000'
+check_parse '2008-02-14 20:30:45 -05:00' '2008-02-14 20:30:45 -0500'
 check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 -0500' EST5
 
 check_approxidate() {
index 0d0222ea2ace733ffe3fbfbdee58520abcd40e92..e8af615e6dcdf365416ef9f71825c17a0d601186 100755 (executable)
@@ -631,6 +631,37 @@ test_expect_success 'rename a remote' '
 
 '
 
+test_expect_success 'rename does not update a non-default fetch refspec' '
+
+       git clone one four.one &&
+       (cd four.one &&
+        git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
+        git remote rename origin upstream &&
+        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
+        git rev-parse -q origin/master)
+
+'
+
+test_expect_success 'rename a remote with name part of fetch spec' '
+
+       git clone one four.two &&
+       (cd four.two &&
+        git remote rename origin remote &&
+        git remote rename remote upstream &&
+        test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*")
+
+'
+
+test_expect_success 'rename a remote with name prefix of other remote' '
+
+       git clone one four.three &&
+       (cd four.three &&
+        git remote add o git://example.com/repo.git &&
+        git remote rename o upstream &&
+        test "$(git rev-parse origin/master)" = "$(git rev-parse master)")
+
+'
+
 cat > remotes_origin << EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream
index 7e433b179f9fcb0b3ccdd0ec83c6ec850735e391..e0af4c4e62c40a563f692361944cc58e2c8e38e2 100755 (executable)
@@ -76,6 +76,56 @@ test_expect_success "fetch test for-merge" '
        cut -f -2 .git/FETCH_HEAD >actual &&
        test_cmp expected actual'
 
+test_expect_success 'fetch --prune on its own works as expected' '
+       cd "$D" &&
+       git clone . prune &&
+       cd prune &&
+       git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+
+       git fetch --prune origin &&
+       test_must_fail git rev-parse origin/extrabranch
+'
+
+test_expect_success 'fetch --prune with a branch name keeps branches' '
+       cd "$D" &&
+       git clone . prune-branch &&
+       cd prune-branch &&
+       git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+
+       git fetch --prune origin master &&
+       git rev-parse origin/extrabranch
+'
+
+test_expect_success 'fetch --prune with a namespace keeps other namespaces' '
+       cd "$D" &&
+       git clone . prune-namespace &&
+       cd prune-namespace &&
+
+       git fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&
+       git rev-parse origin/master
+'
+
+test_expect_success 'fetch --prune --tags does not delete the remote-tracking branches' '
+       cd "$D" &&
+       git clone . prune-tags &&
+       cd prune-tags &&
+       git fetch origin refs/heads/master:refs/tags/sometag &&
+
+       git fetch --prune --tags origin &&
+       git rev-parse origin/master &&
+       test_must_fail git rev-parse somebranch
+'
+
+test_expect_success 'fetch --prune --tags with branch does not delete other remote-tracking branches' '
+       cd "$D" &&
+       git clone . prune-tags-branch &&
+       cd prune-tags-branch &&
+       git fetch origin refs/heads/master:refs/remotes/origin/extrabranch &&
+
+       git fetch --prune --tags origin master &&
+       git rev-parse origin/extrabranch
+'
+
 test_expect_success 'fetch tags when there is no tags' '
 
     cd "$D" &&
index 72a8731d5e28d71577d0c53fc25a5ddc1d2ad6de..aa74184c31cd6b2bd2e0e566e6805e60eed7aff8 100755 (executable)
@@ -107,6 +107,7 @@ error: The following untracked working tree files would be overwritten by merge:
        sub
        sub2
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'will not overwrite untracked file in leading path' '
index c994836c53224dd0a8302f7a6ab63b35f8b493e3..0e4a682c6428a96af4d98bb7e24b0de7f4be865c 100755 (executable)
@@ -32,6 +32,7 @@ error: The following untracked working tree files would be overwritten by merge:
        three
        two
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'untracked files overwritten by merge (fast and non-fast forward)' '
@@ -56,6 +57,7 @@ Please, commit your changes or stash them before you can merge.
 error: The following untracked working tree files would be overwritten by merge:
        five
 Please move or remove them before you can merge.
+Aborting
 EOF
 
 test_expect_success 'untracked files or local changes ovewritten by merge' '
@@ -71,6 +73,7 @@ error: Your local changes to the following files would be overwritten by checkou
        rep/one
        rep/two
 Please, commit your changes or stash them before you can switch branches.
+Aborting
 EOF
 
 test_expect_success 'cannot switch branches because of local changes' '
@@ -92,6 +95,7 @@ error: Your local changes to the following files would be overwritten by checkou
        rep/one
        rep/two
 Please, commit your changes or stash them before you can switch branches.
+Aborting
 EOF
 
 test_expect_success 'not uptodate file porcelain checkout error' '
@@ -105,6 +109,7 @@ error: Updating the following directories would lose untracked files in it:
        rep
        rep2
 
+Aborting
 EOF
 
 test_expect_success 'not_uptodate_dir porcelain checkout error' '
index cbc08e32761c6e35a3eb25519873e74218fd441a..4aab2a75b8ef5836a58f30b6c27a8eec4a733afc 100755 (executable)
@@ -16,6 +16,7 @@ Testing basic merge tool invocation'
 test_expect_success 'setup' '
     git config rerere.enabled true &&
     echo master >file1 &&
+    echo master spaced >"spaced name" &&
     echo master file11 >file11 &&
     echo master file12 >file12 &&
     echo master file13 >file13 &&
@@ -30,13 +31,14 @@ test_expect_success 'setup' '
        git commit -m "Add foo"
     ) &&
     git submodule add git://example.com/submod submod &&
-    git add file1 file1[1-4] subdir/file3 .gitmodules submod &&
+    git add file1 "spaced name" file1[1-4] subdir/file3 .gitmodules submod &&
     git commit -m "add initial versions" &&
 
     git checkout -b branch1 master &&
     git submodule update -N &&
     echo branch1 change >file1 &&
     echo branch1 newfile >file2 &&
+    echo branch1 spaced >"spaced name" &&
     echo branch1 change file11 >file11 &&
     echo branch1 change file13 >file13 &&
     echo branch1 sub >subdir/file3 &&
@@ -47,7 +49,7 @@ test_expect_success 'setup' '
        git commit -m "Add bar on branch1" &&
        git checkout -b submod-branch1
     ) &&
-    git add file1 file11 file13 file2 subdir/file3 submod &&
+    git add file1 "spaced name" file11 file13 file2 subdir/file3 submod &&
     git rm file12 &&
     git commit -m "branch1 changes" &&
 
@@ -55,6 +57,7 @@ test_expect_success 'setup' '
     git submodule update -N &&
     echo master updated >file1 &&
     echo master new >file2 &&
+    echo master updated spaced >"spaced name" &&
     echo master updated file12 >file12 &&
     echo master updated file14 >file14 &&
     echo master new sub >subdir/file3 &&
@@ -65,7 +68,7 @@ test_expect_success 'setup' '
        git commit -m "Add bar on master" &&
        git checkout -b submod-master
     ) &&
-    git add file1 file12 file14 file2 subdir/file3 submod &&
+    git add file1 "spaced name" file12 file14 file2 subdir/file3 submod &&
     git rm file11 &&
     git commit -m "master updates" &&
 
@@ -78,8 +81,8 @@ test_expect_success 'custom mergetool' '
     git checkout -b test1 branch1 &&
     git submodule update -N &&
     test_must_fail git merge master >/dev/null 2>&1 &&
-    ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
-    ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file1 ) &&
+    ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -97,6 +100,7 @@ test_expect_success 'mergetool crlf' '
     test_must_fail git merge master >/dev/null 2>&1 &&
     ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
@@ -126,7 +130,7 @@ test_expect_success 'mergetool on file in parent dir' '
     (
        cd subdir &&
        ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
-       ( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
+       ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) &&
        ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
        ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
        ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) &&
@@ -180,6 +184,24 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
     git reset --hard
 '
 
+test_expect_success 'mergetool takes partial path' '
+    git config rerere.enabled false &&
+    git checkout -b test12 branch1 &&
+    git submodule update -N &&
+    test_must_fail git merge master &&
+
+    #shouldnt need these lines
+    #( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+    #( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
+    #( yes "l" | git mergetool submod >/dev/null 2>&1 ) &&
+    #( yes "" | git mergetool file1 file2 >/dev/null 2>&1 ) &&
+
+    ( yes "" | git mergetool subdir ) &&
+
+    test "$(cat subdir/file3)" = "master new sub" &&
+    git reset --hard
+'
+
 test_expect_success 'deleted vs modified submodule' '
     git checkout -b test6 branch1 &&
     git submodule update -N &&
@@ -189,7 +211,7 @@ test_expect_success 'deleted vs modified submodule' '
     git checkout -b test6.a test6 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     rmdir submod && mv submod-movedaside submod &&
@@ -205,7 +227,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test ! -e submod &&
@@ -218,7 +240,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test6 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     test ! -e submod &&
@@ -233,7 +255,7 @@ test_expect_success 'deleted vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test6 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test "$(cat submod/bar)" = "master submodule" &&
@@ -256,7 +278,7 @@ test_expect_success 'file vs modified submodule' '
     git checkout -b test7.a branch1 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     rmdir submod && mv submod-movedaside submod &&
@@ -271,7 +293,7 @@ test_expect_success 'file vs modified submodule' '
     git checkout -b test7.b test7 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     git submodule update -N &&
@@ -286,7 +308,7 @@ test_expect_success 'file vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test7 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "r" | git mergetool submod ) &&
     test -d submod.orig &&
@@ -301,7 +323,7 @@ test_expect_success 'file vs modified submodule' '
     git submodule update -N &&
     test_must_fail git merge test7 &&
     test -n "$(git ls-files -u)" &&
-    ( yes "" | git mergetool file1 file2 subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) &&
     ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) &&
     ( yes "l" | git mergetool submod ) &&
     test "$(cat submod/bar)" = "master submodule" &&
@@ -388,7 +410,7 @@ test_expect_success 'directory vs modified submodule' '
     test "$(cat submod/file16)" = "not a submodule" &&
     rm -rf submod.orig &&
 
-    git reset --hard &&
+    git reset --hard >/dev/null 2>&1 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
     test ! -e submod.orig &&
@@ -400,7 +422,7 @@ test_expect_success 'directory vs modified submodule' '
     ( cd submod && git clean -f && git reset --hard ) &&
     git submodule update -N &&
     test "$(cat submod/bar)" = "master submodule" &&
-    git reset --hard && rm -rf submod-movedaside &&
+    git reset --hard >/dev/null 2>&1 && rm -rf submod-movedaside &&
 
     git checkout -b test11.c master &&
     git submodule update -N &&
@@ -410,7 +432,7 @@ test_expect_success 'directory vs modified submodule' '
     git submodule update -N &&
     test "$(cat submod/bar)" = "master submodule" &&
 
-    git reset --hard &&
+    git reset --hard >/dev/null 2>&1 &&
     git submodule update -N &&
     test_must_fail git merge test11 &&
     test -n "$(git ls-files -u)" &&
@@ -418,7 +440,7 @@ test_expect_success 'directory vs modified submodule' '
     ( yes "r" | git mergetool submod ) &&
     test "$(cat submod/file16)" = "not a submodule" &&
 
-    git reset --hard master &&
+    git reset --hard master >/dev/null 2>&1 &&
     ( cd submod && git clean -f && git reset --hard ) &&
     git submodule update -N
 '
index 85120b70db8cfb60b8d8c38f85a9038aa856468a..69e4815781c190207d406a4871a5dc5252690239 100755 (executable)
@@ -2,6 +2,14 @@
 test_description='git svn handling of root commits in merge ranges'
 . ./lib-git-svn.sh
 
+svn_ver="$(svn --version --quiet)"
+case $svn_ver in
+0.* | 1.[0-4].*)
+       skip_all="skipping git-svn test - SVN too old ($svn_ver)"
+       test_done
+       ;;
+esac
+
 test_expect_success 'test handling of root commits in merge ranges' '
        mkdir -p init/trunk init/branches init/tags &&
        echo "r1" > init/trunk/file.txt &&
index b187c4bb1f256e19c25f80dd64f3451ced77e123..18c48297652174ffae65b877dd131711a5746181 100755 (executable)
@@ -18,6 +18,9 @@ fi
 # If you want to allow non-ascii filenames set this variable to true.
 allownonascii=$(git config hooks.allownonascii)
 
+# Redirect output to stderr.
+exec 1>&2
+
 # Cross platform projects tend to avoid non-ascii filenames; prevent
 # them from being added to the repository. We exploit the fact that the
 # printable range starts at the space character and ends with tilde.
@@ -25,8 +28,8 @@ if [ "$allownonascii" != "true" ] &&
        # Note that the use of brackets around a tr range is ok here, (it's
        # even required, for portability to Solaris 10's /usr/bin/tr), since
        # the square bracket bytes happen to fall in the designated range.
-       test "$(git diff --cached --name-only --diff-filter=A -z $against |
-         LC_ALL=C tr -d '[ -~]\0')"
+       test $(git diff --cached --name-only --diff-filter=A -z $against |
+         LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 then
        echo "Error: Attempt to add a non-ascii file name."
        echo
@@ -43,4 +46,5 @@ then
        exit 1
 fi
 
+# If there are whitespace errors, print the offending file names and fail.
 exec git diff-index --check --cached $against --
index 4eab844d4abfa29ce53b6245a5821ee7be03641b..07131261fefeab2066636a7f83bce05796329a54 100644 (file)
@@ -183,7 +183,7 @@ static struct child_process *get_helper(struct transport *transport)
                        ALLOC_GROW(refspecs,
                                   refspec_nr + 1,
                                   refspec_alloc);
-                       refspecs[refspec_nr++] = strdup(capname + strlen("refspec "));
+                       refspecs[refspec_nr++] = xstrdup(capname + strlen("refspec "));
                } else if (!strcmp(capname, "connect")) {
                        data->connect = 1;
                } else if (!prefixcmp(capname, "export-marks ")) {
@@ -445,7 +445,7 @@ static int fetch_with_import(struct transport *transport,
                if (data->refspecs)
                        private = apply_refspecs(data->refspecs, data->refspec_nr, posn->name);
                else
-                       private = strdup(posn->name);
+                       private = xstrdup(posn->name);
                read_ref(private, posn->old_sha1);
                free(private);
        }
index 670b46473883505c39c5353c65e0eeb93aec21c3..237aed8c766638c55d8d6b870c86ef2ad13a74d3 100644 (file)
@@ -159,7 +159,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
                string_list_clear(rejects, 0);
        }
        if (something_displayed)
-               printf("Aborting\n");
+               fprintf(stderr, "Aborting\n");
 }
 
 /*
index 8836a527d0b1980bd4ebdd50b3225f7ce37ccf79..70fdb76ff2b5100c6d20f9f3b758e1ac8df314e1 100644 (file)
@@ -396,7 +396,7 @@ static void wt_status_collect_changes_worktree(struct wt_status *s)
        if (s->ignore_submodule_arg) {
                DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);
                handle_ignore_submodules_arg(&rev.diffopt, s->ignore_submodule_arg);
-    }
+       }
        rev.diffopt.format_callback = wt_status_collect_changed_cb;
        rev.diffopt.format_callback_data = s;
        init_pathspec(&rev.prune_data, s->pathspec);