Merge git://git.bogomips.org/git-svn
authorJunio C Hamano <gitster@pobox.com>
Fri, 27 Dec 2013 22:58:35 +0000 (14:58 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 27 Dec 2013 22:58:35 +0000 (14:58 -0800)
* git://git.bogomips.org/git-svn:
git-svn: workaround for a bug in svn serf backend

32 files changed:
Documentation/git-pack-objects.txt
Documentation/git-push.txt
Documentation/git-rebase.txt
Documentation/git.txt
builtin/cat-file.c
builtin/diff.c
builtin/push.c
builtin/rev-parse.c
contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
contrib/remote-helpers/git-remote-bzr
contrib/remote-helpers/git-remote-hg
contrib/remote-helpers/test-hg.sh
csum-file.c
csum-file.h
diff-no-index.c
diff.c
diff.h
git-difftool--helper.sh
git-pull.sh
git-rebase.sh
pack-write.c
pack.h
remote.c
remote.h
t/perf/p4001-diff-no-index.sh [new file with mode: 0755]
t/t1006-cat-file.sh
t/t1506-rev-parse-diagnosis.sh
t/t3400-rebase.sh
t/t4020-diff-external.sh
t/t4053-diff-no-index.sh
t/t5302-pack-index.sh
t/t5516-fetch-push.sh
index d94edcd4b4fdd8bd57150bd0ad8f870a45e0249c..cdab9ed503a5adaace14b06863f31347725d06db 100644 (file)
@@ -51,8 +51,7 @@ base-name::
        <base-name> to determine the name of the created file.
        When this option is used, the two files are written in
        <base-name>-<SHA-1>.{pack,idx} files.  <SHA-1> is a hash
-       of the sorted object names to make the resulting filename
-       based on the pack content, and written to the standard
+       based on the pack content and is written to the standard
        output of the command.
 
 --stdout::
index 9eec74091097c0ea5c9fea69a09eb63e3cebd8d9..2b7f4f939f38626dbd796b808cc21285ad5c8c3d 100644 (file)
@@ -56,8 +56,13 @@ it can be any arbitrary "SHA-1 expression", such as `master~4` or
 +
 The <dst> tells which ref on the remote side is updated with this
 push. Arbitrary expressions cannot be used here, an actual ref must
-be named. If `:`<dst> is omitted, the same ref as <src> will be
-updated.
+be named.
+If `git push [<repository>]` without any `<refspec>` argument is set to
+update some ref at the destination with `<src>` with
+`remote.<repository>.push` configuration variable, `:<dst>` part can
+be omitted---such a push will update a ref that `<src>` normally updates
+without any `<refspec>` on the command line.  Otherwise, missing
+`:<dst>` means to update the same ref as the `<src>`.
 +
 The object referenced by <src> is used to update the <dst> reference
 on the remote side.  By default this is only allowed if <dst> is not
index 94e07fdab550dcac70734fb79724b00cf8d23edc..2889be6bdc4a1a243585e43def2e7416a9aa7038 100644 (file)
@@ -324,6 +324,16 @@ fresh commits so it can be remerged successfully without needing to "revert
 the reversion" (see the
 link:howto/revert-a-faulty-merge.html[revert-a-faulty-merge How-To] for details).
 
+--fork-point::
+--no-fork-point::
+       Use 'git merge-base --fork-point' to find a better common ancestor
+       between `upstream` and `branch` when calculating which commits have
+       have been introduced by `branch` (see linkgit:git-merge-base[1]).
++
+If no non-option arguments are given on the command line, then the default is
+`--fork-point @{u}` otherwise the `upstream` argument is interpreted literally
+unless the `--fork-point` option is specified.
+
 --ignore-whitespace::
 --whitespace=<option>::
        These flag are passed to the 'git apply' program
index cc0e5e2bfe66a0962283fd570c5e440e72b57813..aec372646ffc30f13b924159d47ade373fc44b87 100644 (file)
@@ -807,6 +807,15 @@ temporary file --- it is removed when 'GIT_EXTERNAL_DIFF' exits.
 +
 For a path that is unmerged, 'GIT_EXTERNAL_DIFF' is called with 1
 parameter, <path>.
++
+For each path 'GIT_EXTERNAL_DIFF' is called, two environment variables,
+'GIT_DIFF_PATH_COUNTER' and 'GIT_DIFF_PATH_TOTAL' are set.
+
+'GIT_DIFF_PATH_COUNTER'::
+       A 1-based counter incremented by one for every path.
+
+'GIT_DIFF_PATH_TOTAL'::
+       The total number of paths.
 
 other
 ~~~~~
index b2ca775a80f54fcceba344d5545fe3cb34ba0184..f8288c830cad215af63dd6d575c9bd4bf7aeaf6c 100644 (file)
@@ -193,25 +193,28 @@ static size_t expand_format(struct strbuf *sb, const char *start, void *data)
        return end - start + 1;
 }
 
-static void print_object_or_die(int fd, const unsigned char *sha1,
-                               enum object_type type, unsigned long size)
+static void print_object_or_die(int fd, struct expand_data *data)
 {
-       if (type == OBJ_BLOB) {
+       const unsigned char *sha1 = data->sha1;
+
+       assert(data->info.typep);
+
+       if (data->type == OBJ_BLOB) {
                if (stream_blob_to_fd(fd, sha1, NULL, 0) < 0)
                        die("unable to stream %s to stdout", sha1_to_hex(sha1));
        }
        else {
-               enum object_type rtype;
-               unsigned long rsize;
+               enum object_type type;
+               unsigned long size;
                void *contents;
 
-               contents = read_sha1_file(sha1, &rtype, &rsize);
+               contents = read_sha1_file(sha1, &type, &size);
                if (!contents)
                        die("object %s disappeared", sha1_to_hex(sha1));
-               if (rtype != type)
+               if (type != data->type)
                        die("object %s changed type!?", sha1_to_hex(sha1));
-               if (rsize != size)
-                       die("object %s change size!?", sha1_to_hex(sha1));
+               if (data->info.sizep && size != data->size)
+                       die("object %s changed size!?", sha1_to_hex(sha1));
 
                write_or_die(fd, contents, size);
                free(contents);
@@ -250,7 +253,7 @@ static int batch_one_object(const char *obj_name, struct batch_options *opt,
        strbuf_release(&buf);
 
        if (opt->print_contents) {
-               print_object_or_die(1, data->sha1, data->type, data->size);
+               print_object_or_die(1, data);
                write_or_die(1, "\n", 1);
        }
        return 0;
@@ -274,6 +277,13 @@ static int batch_objects(struct batch_options *opt)
        strbuf_expand(&buf, opt->format, expand_format, &data);
        data.mark_query = 0;
 
+       /*
+        * If we are printing out the object, then always fill in the type,
+        * since we will want to decide whether or not to stream.
+        */
+       if (opt->print_contents)
+               data.info.typep = &data.type;
+
        /*
         * We are going to call get_sha1 on a potentially very large number of
         * objects. In most large cases, these will be actual object sha1s. The
index fe0cc7f1b5b1451f267b1d9e24a6e40cd6e55325..0f247d24008a4dc7ba5958e716c13f7582a820f1 100644 (file)
@@ -16,6 +16,9 @@
 #include "submodule.h"
 #include "sha1-array.h"
 
+#define DIFF_NO_INDEX_EXPLICIT 1
+#define DIFF_NO_INDEX_IMPLICIT 2
+
 struct blobinfo {
        unsigned char sha1[20];
        const char *name;
@@ -259,7 +262,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        struct object_array ent = OBJECT_ARRAY_INIT;
        int blobs = 0, paths = 0;
        struct blobinfo blob[2];
-       int nongit;
+       int nongit = 0, no_index = 0;
        int result = 0;
 
        /*
@@ -285,14 +288,59 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
         * Other cases are errors.
         */
 
-       prefix = setup_git_directory_gently(&nongit);
-       gitmodules_config();
+       /* Were we asked to do --no-index explicitly? */
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "--")) {
+                       i++;
+                       break;
+               }
+               if (!strcmp(argv[i], "--no-index"))
+                       no_index = DIFF_NO_INDEX_EXPLICIT;
+               if (argv[i][0] != '-')
+                       break;
+       }
+
+       if (!no_index)
+               prefix = setup_git_directory_gently(&nongit);
+
+       /*
+        * Treat git diff with at least one path outside of the
+        * repo the same as if the command would have been executed
+        * outside of a git repository.  In this case it behaves
+        * the same way as "git diff --no-index <a> <b>", which acts
+        * as a colourful "diff" replacement.
+        */
+       if (nongit || ((argc == i + 2) &&
+                      (!path_inside_repo(prefix, argv[i]) ||
+                       !path_inside_repo(prefix, argv[i + 1]))))
+               no_index = DIFF_NO_INDEX_IMPLICIT;
+
+       if (!no_index)
+               gitmodules_config();
        git_config(git_diff_ui_config, NULL);
 
        init_revisions(&rev, prefix);
 
-       /* If this is a no-index diff, just run it and exit there. */
-       diff_no_index(&rev, argc, argv, nongit, prefix);
+       if (no_index && argc != i + 2) {
+               if (no_index == DIFF_NO_INDEX_IMPLICIT) {
+                       /*
+                        * There was no --no-index and there were not two
+                        * paths. It is possible that the user intended
+                        * to do an inside-repository operation.
+                        */
+                       fprintf(stderr, "Not a git repository\n");
+                       fprintf(stderr,
+                               "To compare two paths outside a working tree:\n");
+               }
+               /* Give the usage message for non-repository usage and exit. */
+               usagef("git diff %s <path> <path>",
+                      no_index == DIFF_NO_INDEX_EXPLICIT ?
+                      "--no-index" : "[--no-index]");
+
+       }
+       if (no_index)
+               /* If this is a no-index diff, just run it and exit there. */
+               diff_no_index(&rev, argc, argv, prefix);
 
        /* Otherwise, we are doing the usual "git" diff */
        rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
index a73982a30879f89be939034e462df68ee2c51c0b..0e50ddbb01342128d9118217118726000bdeaff6 100644 (file)
@@ -35,35 +35,75 @@ static void add_refspec(const char *ref)
        refspec[refspec_nr-1] = ref;
 }
 
-static void set_refspecs(const char **refs, int nr)
+static const char *map_refspec(const char *ref,
+                              struct remote *remote, struct ref *local_refs)
 {
+       struct ref *matched = NULL;
+
+       /* Does "ref" uniquely name our ref? */
+       if (count_refspec_match(ref, local_refs, &matched) != 1)
+               return ref;
+
+       if (remote->push) {
+               struct refspec query;
+               memset(&query, 0, sizeof(struct refspec));
+               query.src = matched->name;
+               if (!query_refspecs(remote->push, remote->push_refspec_nr, &query) &&
+                   query.dst) {
+                       struct strbuf buf = STRBUF_INIT;
+                       strbuf_addf(&buf, "%s%s:%s",
+                                   query.force ? "+" : "",
+                                   query.src, query.dst);
+                       return strbuf_detach(&buf, NULL);
+               }
+       }
+
+       if (push_default == PUSH_DEFAULT_UPSTREAM &&
+           !prefixcmp(matched->name, "refs/heads/")) {
+               struct branch *branch = branch_get(matched->name + 11);
+               if (branch->merge_nr == 1 && branch->merge[0]->src) {
+                       struct strbuf buf = STRBUF_INIT;
+                       strbuf_addf(&buf, "%s:%s",
+                                   ref, branch->merge[0]->src);
+                       return strbuf_detach(&buf, NULL);
+               }
+       }
+
+       return ref;
+}
+
+static void set_refspecs(const char **refs, int nr, const char *repo)
+{
+       struct remote *remote = NULL;
+       struct ref *local_refs = NULL;
        int i;
+
        for (i = 0; i < nr; i++) {
                const char *ref = refs[i];
                if (!strcmp("tag", ref)) {
-                       char *tag;
-                       int len;
+                       struct strbuf tagref = STRBUF_INIT;
                        if (nr <= ++i)
                                die(_("tag shorthand without <tag>"));
-                       len = strlen(refs[i]) + 11;
-                       if (deleterefs) {
-                               tag = xmalloc(len+1);
-                               strcpy(tag, ":refs/tags/");
-                       } else {
-                               tag = xmalloc(len);
-                               strcpy(tag, "refs/tags/");
+                       ref = refs[i];
+                       if (deleterefs)
+                               strbuf_addf(&tagref, ":refs/tags/%s", ref);
+                       else
+                               strbuf_addf(&tagref, "refs/tags/%s", ref);
+                       ref = strbuf_detach(&tagref, NULL);
+               } else if (deleterefs) {
+                       struct strbuf delref = STRBUF_INIT;
+                       if (strchr(ref, ':'))
+                               die(_("--delete only accepts plain target ref names"));
+                       strbuf_addf(&delref, ":%s", ref);
+                       ref = strbuf_detach(&delref, NULL);
+               } else if (!strchr(ref, ':')) {
+                       if (!remote) {
+                               /* lazily grab remote and local_refs */
+                               remote = remote_get(repo);
+                               local_refs = get_local_heads();
                        }
-                       strcat(tag, refs[i]);
-                       ref = tag;
-               } else if (deleterefs && !strchr(ref, ':')) {
-                       char *delref;
-                       int len = strlen(ref)+1;
-                       delref = xmalloc(len+1);
-                       strcpy(delref, ":");
-                       strcat(delref, ref);
-                       ref = delref;
-               } else if (deleterefs)
-                       die(_("--delete only accepts plain target ref names"));
+                       ref = map_refspec(ref, remote, local_refs);
+               }
                add_refspec(ref);
        }
 }
@@ -501,7 +541,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 
        if (argc > 0) {
                repo = argv[0];
-               set_refspecs(argv + 1, argc - 1);
+               set_refspecs(argv + 1, argc - 1, repo);
        }
 
        rc = do_push(repo, flags);
index 6e802fdeb8bce0f7fdce925f47fc239462f6a459..aaeb611a9729938251b1c679e35c446bb737ff4f 100644 (file)
@@ -286,6 +286,7 @@ static int try_difference(const char *arg)
                                exclude = n;
                        }
                }
+               *dotdot = '.';
                return 1;
        }
        *dotdot = '.';
@@ -309,8 +310,10 @@ static int try_parent_shorthands(const char *arg)
                return 0;
 
        *dotdot = 0;
-       if (get_sha1_committish(arg, sha1))
+       if (get_sha1_committish(arg, sha1)) {
+               *dotdot = '^';
                return 0;
+       }
 
        if (!parents_only)
                show_rev(NORMAL, sha1, arg);
@@ -319,6 +322,7 @@ static int try_parent_shorthands(const char *arg)
                show_rev(parents_only ? NORMAL : REVERSED,
                                parents->item->object.sha1, arg);
 
+       *dotdot = '^';
        return 1;
 }
 
@@ -488,6 +492,7 @@ N_("git rev-parse --parseopt [options] -- [<args>...]\n"
 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
        int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
+       int has_dashdash = 0;
        int output_prefix = 0;
        unsigned char sha1[20];
        const char *name = NULL;
@@ -501,6 +506,13 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
        if (argc > 1 && !strcmp("-h", argv[1]))
                usage(builtin_rev_parse_usage);
 
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "--")) {
+                       has_dashdash = 1;
+                       break;
+               }
+       }
+
        prefix = setup_git_directory();
        git_config(git_default_config, NULL);
        for (i = 1; i < argc; i++) {
@@ -788,6 +800,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                }
                if (verify)
                        die_no_single_rev(quiet);
+               if (has_dashdash)
+                       die("bad revision '%s'", arg);
                as_is = 1;
                if (!show_file(arg, output_prefix))
                        continue;
index 635c96bc563a21e98df181e3a179e50e0eaeadaa..2a317fca442a51dd6f47bfeeaa19bf32ed6e670f 100644 (file)
@@ -60,7 +60,7 @@
 #define gnome_keyring_memory_free gnome_keyring_free_password
 #define gnome_keyring_memory_strdup g_strdup
 
-static const chargnome_keyring_result_to_message(GnomeKeyringResult result)
+static const char *gnome_keyring_result_to_message(GnomeKeyringResult result)
 {
        switch (result) {
        case GNOME_KEYRING_RESULT_OK:
@@ -95,9 +95,9 @@ static const char* gnome_keyring_result_to_message(GnomeKeyringResult result)
 
 static void gnome_keyring_done_cb(GnomeKeyringResult result, gpointer user_data)
 {
-       gpointer *data = (gpointer*) user_data;
-       int *done = (int*) data[0];
-       GnomeKeyringResult *r = (GnomeKeyringResult*) data[1];
+       gpointer *data = (gpointer *)user_data;
+       int *done = (int *)data[0];
+       GnomeKeyringResult *r = (GnomeKeyringResult *)data[1];
 
        *r = result;
        *done = 1;
@@ -130,34 +130,30 @@ static GnomeKeyringResult gnome_keyring_item_delete_sync(const char *keyring, gu
 /*
  * This credential struct and API is simplified from git's credential.{h,c}
  */
-struct credential
-{
-       char          *protocol;
-       char          *host;
+struct credential {
+       char *protocol;
+       char *host;
        unsigned short port;
-       char          *path;
-       char          *username;
-       char          *password;
+       char *path;
+       char *username;
+       char *password;
 };
 
-#define CREDENTIAL_INIT \
-  { NULL,NULL,0,NULL,NULL,NULL }
+#define CREDENTIAL_INIT { NULL, NULL, 0, NULL, NULL, NULL }
 
-typedef int (*credential_op_cb)(struct credential*);
+typedef int (*credential_op_cb)(struct credential *);
 
-struct credential_operation
-{
-       char             *name;
+struct credential_operation {
+       char *name;
        credential_op_cb op;
 };
 
-#define CREDENTIAL_OP_END \
-  { NULL,NULL }
+#define CREDENTIAL_OP_END { NULL, NULL }
 
 /* ----------------- GNOME Keyring functions ----------------- */
 
 /* create a special keyring option string, if path is given */
-static charkeyring_object(struct credential *c)
+static char *keyring_object(struct credential *c)
 {
        if (!c->path)
                return NULL;
@@ -170,7 +166,7 @@ static char* keyring_object(struct credential *c)
 
 static int keyring_get(struct credential *c)
 {
-       charobject = NULL;
+       char *object = NULL;
        GList *entries;
        GnomeKeyringNetworkPasswordData *password_data;
        GnomeKeyringResult result;
@@ -204,7 +200,7 @@ static int keyring_get(struct credential *c)
        }
 
        /* pick the first one from the list */
-       password_data = (GnomeKeyringNetworkPasswordData *) entries->data;
+       password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
 
        gnome_keyring_memory_free(c->password);
        c->password = gnome_keyring_memory_strdup(password_data->password);
@@ -221,7 +217,7 @@ static int keyring_get(struct credential *c)
 static int keyring_store(struct credential *c)
 {
        guint32 item_id;
-       char  *object = NULL;
+       char *object = NULL;
        GnomeKeyringResult result;
 
        /*
@@ -262,7 +258,7 @@ static int keyring_store(struct credential *c)
 
 static int keyring_erase(struct credential *c)
 {
-       char  *object = NULL;
+       char *object = NULL;
        GList *entries;
        GnomeKeyringNetworkPasswordData *password_data;
        GnomeKeyringResult result;
@@ -298,22 +294,20 @@ static int keyring_erase(struct credential *c)
        if (result == GNOME_KEYRING_RESULT_CANCELLED)
                return EXIT_SUCCESS;
 
-       if (result != GNOME_KEYRING_RESULT_OK)
-       {
+       if (result != GNOME_KEYRING_RESULT_OK) {
                g_critical("%s", gnome_keyring_result_to_message(result));
                return EXIT_FAILURE;
        }
 
        /* pick the first one from the list (delete all matches?) */
-       password_data = (GnomeKeyringNetworkPasswordData *) entries->data;
+       password_data = (GnomeKeyringNetworkPasswordData *)entries->data;
 
        result = gnome_keyring_item_delete_sync(
                password_data->keyring, password_data->item_id);
 
        gnome_keyring_network_password_list_free(entries);
 
-       if (result != GNOME_KEYRING_RESULT_OK)
-       {
+       if (result != GNOME_KEYRING_RESULT_OK) {
                g_critical("%s", gnome_keyring_result_to_message(result));
                return EXIT_FAILURE;
        }
@@ -325,9 +319,8 @@ static int keyring_erase(struct credential *c)
  * Table with helper operation callbacks, used by generic
  * credential helper main function.
  */
-static struct credential_operation const credential_helper_ops[] =
-{
-       { "get",   keyring_get   },
+static struct credential_operation const credential_helper_ops[] = {
+       { "get",   keyring_get },
        { "store", keyring_store },
        { "erase", keyring_erase },
        CREDENTIAL_OP_END
@@ -353,24 +346,23 @@ static void credential_clear(struct credential *c)
 
 static int credential_read(struct credential *c)
 {
-       char    *buf;
+       char *buf;
        size_t line_len;
-       char   *key;
-       char   *value;
+       char *key;
+       char *value;
 
        key = buf = gnome_keyring_memory_alloc(1024);
 
-       while (fgets(buf, 1024, stdin))
-       {
+       while (fgets(buf, 1024, stdin)) {
                line_len = strlen(buf);
 
                if (line_len && buf[line_len-1] == '\n')
-                       buf[--line_len]='\0';
+                       buf[--line_len] = '\0';
 
                if (!line_len)
                        break;
 
-               value = strchr(buf,'=');
+               value = strchr(buf, '=');
                if (!value) {
                        g_warning("invalid credential line: %s", key);
                        gnome_keyring_memory_free(buf);
@@ -384,7 +376,7 @@ static int credential_read(struct credential *c)
                } else if (!strcmp(key, "host")) {
                        g_free(c->host);
                        c->host = g_strdup(value);
-                       value = strrchr(c->host,':');
+                       value = strrchr(c->host, ':');
                        if (value) {
                                *value++ = '\0';
                                c->port = atoi(value);
@@ -398,7 +390,8 @@ static int credential_read(struct credential *c)
                } else if (!strcmp(key, "password")) {
                        gnome_keyring_memory_free(c->password);
                        c->password = gnome_keyring_memory_strdup(value);
-                       while (*value) *value++ = '\0';
+                       while (*value)
+                               *value++ = '\0';
                }
                /*
                 * Ignore other lines; we don't know what they mean, but
@@ -429,16 +422,16 @@ static void credential_write(const struct credential *c)
 static void usage(const char *name)
 {
        struct credential_operation const *try_op = credential_helper_ops;
-       const char *basename = strrchr(name,'/');
+       const char *basename = strrchr(name, '/');
 
        basename = (basename) ? basename + 1 : name;
        fprintf(stderr, "usage: %s <", basename);
        while (try_op->name) {
-               fprintf(stderr,"%s",(try_op++)->name);
+               fprintf(stderr, "%s", (try_op++)->name);
                if (try_op->name)
-                       fprintf(stderr,"%s","|");
+                       fprintf(stderr, "%s", "|");
        }
-       fprintf(stderr,"%s",">\n");
+       fprintf(stderr, "%s", ">\n");
 }
 
 int main(int argc, char *argv[])
@@ -446,7 +439,7 @@ int main(int argc, char *argv[])
        int ret = EXIT_SUCCESS;
 
        struct credential_operation const *try_op = credential_helper_ops;
-       struct credential                  cred   = CREDENTIAL_INIT;
+       struct credential cred = CREDENTIAL_INIT;
 
        if (!argv[1]) {
                usage(argv[0]);
index 7e345320ada69f1cbb909130d406cf08ce9ae130..332aba784b8810120df8e1ddfafeb034a55337a3 100755 (executable)
@@ -883,6 +883,16 @@ def main(args):
     global branches, peers
     global transports
 
+    marks = None
+    is_tmp = False
+    gitdir = os.environ.get('GIT_DIR', None)
+
+    if len(args) < 3:
+        die('Not enough arguments.')
+
+    if not gitdir:
+        die('GIT_DIR not set')
+
     alias = args[1]
     url = args[2]
 
@@ -891,7 +901,6 @@ def main(args):
     blob_marks = {}
     parsed_refs = {}
     files_cache = {}
-    marks = None
     branches = {}
     peers = {}
     transports = []
@@ -899,11 +908,8 @@ def main(args):
     if alias[5:] == url:
         is_tmp = True
         alias = hashlib.sha1(alias).hexdigest()
-    else:
-        is_tmp = False
 
     prefix = 'refs/bzr/%s' % alias
-    gitdir = os.environ['GIT_DIR']
     dirname = os.path.join(gitdir, 'bzr', alias)
 
     if not is_tmp:
index 30402d55323488f7c2bc6599bbc4a471f2120b33..eb89ef67798e70fd77eff341e3dda5385d3cde48 100755 (executable)
@@ -415,6 +415,9 @@ def get_repo(url, alias):
         local_path = os.path.join(dirname, 'clone')
         if not os.path.exists(local_path):
             hg.share(myui, shared_path, local_path, update=False)
+        else:
+            # make sure the shared path is always up-to-date
+            util.writefile(os.path.join(local_path, '.hg', 'sharedpath'), hg_path)
 
         repo = hg.repository(myui, local_path)
         try:
@@ -537,7 +540,7 @@ def export_ref(repo, name, kind, head):
 
         print "commit %s" % ref
         print "mark :%d" % (note_mark)
-        print "committer remote-hg <> %s" % (ptime.strftime('%s %z'))
+        print "committer remote-hg <> %d %s" % (ptime.time(), gittz(ptime.timezone))
         desc = "Notes for %s\n" % (name)
         print "data %d" % (len(desc))
         print desc
@@ -1164,6 +1167,16 @@ def main(args):
     global dry_run
     global notes, alias
 
+    marks = None
+    is_tmp = False
+    gitdir = os.environ.get('GIT_DIR', None)
+
+    if len(args) < 3:
+        die('Not enough arguments.')
+
+    if not gitdir:
+        die('GIT_DIR not set')
+
     alias = args[1]
     url = args[2]
     peer = None
@@ -1184,16 +1197,12 @@ def main(args):
     if alias[4:] == url:
         is_tmp = True
         alias = hashlib.sha1(alias).hexdigest()
-    else:
-        is_tmp = False
 
-    gitdir = os.environ['GIT_DIR']
     dirname = os.path.join(gitdir, 'hg', alias)
     branches = {}
     bmarks = {}
     blob_marks = {}
     parsed_refs = {}
-    marks = None
     parsed_tags = {}
     filenodes = {}
     fake_bmark = None
index 347e812923a20652b964db6b820f8f08d6c0795f..5d128a5da9a1afd3bf441f58e75d4f02a64509d5 100755 (executable)
@@ -337,6 +337,17 @@ test_expect_success 'remote cloning' '
        check gitrepo HEAD zero
 '
 
+test_expect_success 'moving remote clone' '
+       test_when_finished "rm -rf gitrepo*" &&
+
+       (
+       git clone "hg::hgrepo" gitrepo &&
+       mv gitrepo gitrepo2 &&
+       cd gitrepo2 &&
+       git fetch
+       )
+'
+
 test_expect_success 'remote update bookmark' '
        test_when_finished "rm -rf gitrepo*" &&
 
@@ -444,6 +455,74 @@ test_expect_success 'remote new bookmark multiple branch head' '
 # cleanup previous stuff
 rm -rf hgrepo
 
+test_expect_success 'fetch special filenames' '
+       test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
+
+       LC_ALL=en_US.UTF-8
+       export LC_ALL
+
+       (
+       hg init hgrepo &&
+       cd hgrepo &&
+
+       echo test >> "æ rø" &&
+       hg add "æ rø" &&
+       echo test >> "ø~?" &&
+       hg add "ø~?" &&
+       hg commit -m add-utf-8 &&
+       echo test >> "æ rø" &&
+       hg commit -m test-utf-8 &&
+       hg rm "ø~?" &&
+       hg mv "æ rø" "ø~?" &&
+       hg commit -m hg-mv-utf-8
+       ) &&
+
+       (
+       git clone "hg::hgrepo" gitrepo &&
+       cd gitrepo &&
+       git -c core.quotepath=false ls-files > ../actual
+       ) &&
+       echo "ø~?" > expected &&
+       test_cmp expected actual
+'
+
+test_expect_success 'push special filenames' '
+       test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
+
+       mkdir -p tmp && cd tmp &&
+
+       LC_ALL=en_US.UTF-8
+       export LC_ALL
+
+       (
+       hg init hgrepo &&
+       cd hgrepo &&
+
+       echo one >> content &&
+       hg add content &&
+       hg commit -m one
+       ) &&
+
+       (
+       git clone "hg::hgrepo" gitrepo &&
+       cd gitrepo &&
+
+       echo test >> "æ rø" &&
+       git add "æ rø" &&
+       git commit -m utf-8 &&
+
+       git push
+       ) &&
+
+       (cd hgrepo &&
+       hg update &&
+       hg manifest > ../actual
+       ) &&
+
+       printf "content\næ rø\n" > expected &&
+       test_cmp expected actual
+'
+
 setup_big_push () {
        (
        hg init hgrepo &&
index 53f5375b6ca3368de6647cf5edcd7fb4dec79657..465971c7f303e29bf9501e6968da1ea71b5af76a 100644 (file)
@@ -11,7 +11,7 @@
 #include "progress.h"
 #include "csum-file.h"
 
-static void flush(struct sha1file *f, void *buf, unsigned int count)
+static void flush(struct sha1file *f, const void *buf, unsigned int count)
 {
        if (0 <= f->check_fd && count)  {
                unsigned char check_buffer[8192];
@@ -86,13 +86,13 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
        return fd;
 }
 
-int sha1write(struct sha1file *f, void *buf, unsigned int count)
+int sha1write(struct sha1file *f, const void *buf, unsigned int count)
 {
        while (count) {
                unsigned offset = f->offset;
                unsigned left = sizeof(f->buffer) - offset;
                unsigned nr = count > left ? left : count;
-               void *data;
+               const void *data;
 
                if (f->do_crc)
                        f->crc32 = crc32(f->crc32, buf, nr);
index 3b540bdc21d2edf8d3d6fc2b5e52cc840aa19395..9dedb038ea9c77a8fadac370e039f1672e948325 100644 (file)
@@ -34,7 +34,7 @@ extern struct sha1file *sha1fd(int fd, const char *name);
 extern struct sha1file *sha1fd_check(const char *name);
 extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
 extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
-extern int sha1write(struct sha1file *, void *, unsigned int);
+extern int sha1write(struct sha1file *, const void *, unsigned int);
 extern void sha1flush(struct sha1file *f);
 extern void crc32_begin(struct sha1file *);
 extern uint32_t crc32_end(struct sha1file *);
index 00a8eefde9aeb96592f5ed6455dbf5d3b16747c4..33e5982a1c61a5726580f40df0a07dadc7e2aaf1 100644 (file)
@@ -183,54 +183,12 @@ static int queue_diff(struct diff_options *o,
 
 void diff_no_index(struct rev_info *revs,
                   int argc, const char **argv,
-                  int nongit, const char *prefix)
+                  const char *prefix)
 {
        int i, prefixlen;
-       int no_index = 0;
        unsigned deprecated_show_diff_q_option_used = 0;
        const char *paths[2];
 
-       /* Were we asked to do --no-index explicitly? */
-       for (i = 1; i < argc; i++) {
-               if (!strcmp(argv[i], "--")) {
-                       i++;
-                       break;
-               }
-               if (!strcmp(argv[i], "--no-index"))
-                       no_index = 1;
-               if (argv[i][0] != '-')
-                       break;
-       }
-
-       if (!no_index && !nongit) {
-               /*
-                * Inside a git repository, without --no-index.  Only
-                * when a path outside the repository is given,
-                * e.g. "git diff /var/tmp/[12]", or "git diff
-                * Makefile /var/tmp/Makefile", allow it to be used as
-                * a colourful "diff" replacement.
-                */
-               if ((argc != i + 2) ||
-                   (path_inside_repo(prefix, argv[i]) &&
-                    path_inside_repo(prefix, argv[i+1])))
-                       return;
-       }
-       if (argc != i + 2) {
-               if (!no_index) {
-                       /*
-                        * There was no --no-index and there were not two
-                        * paths. It is possible that the user intended
-                        * to do an inside-repository operation.
-                        */
-                       fprintf(stderr, "Not a git repository\n");
-                       fprintf(stderr,
-                               "To compare two paths outside a working tree:\n");
-               }
-               /* Give the usage message for non-repository usage and exit. */
-               usagef("git diff %s <path> <path>",
-                      no_index ? "--no-index" : "[--no-index]");
-       }
-
        diff_setup(&revs->diffopt);
        for (i = 1; i < argc - 2; ) {
                int j;
diff --git a/diff.c b/diff.c
index b79432b1ec97909e20eb76fceb5530b2f7be647f..f99bc83b733acc7992c24c26f4465a669f7a4467 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2899,11 +2899,16 @@ static void run_external_diff(const char *pgm,
                              struct diff_filespec *one,
                              struct diff_filespec *two,
                              const char *xfrm_msg,
-                             int complete_rewrite)
+                             int complete_rewrite,
+                             struct diff_options *o)
 {
        const char *spawn_arg[10];
        int retval;
        const char **arg = &spawn_arg[0];
+       struct diff_queue_struct *q = &diff_queued_diff;
+       const char *env[3] = { NULL };
+       char env_counter[50];
+       char env_total[50];
 
        if (one && two) {
                struct diff_tempfile *temp_one, *temp_two;
@@ -2928,7 +2933,14 @@ static void run_external_diff(const char *pgm,
        }
        *arg = NULL;
        fflush(NULL);
-       retval = run_command_v_opt(spawn_arg, RUN_USING_SHELL);
+
+       env[0] = env_counter;
+       snprintf(env_counter, sizeof(env_counter), "GIT_DIFF_PATH_COUNTER=%d",
+                ++o->diff_path_counter);
+       env[1] = env_total;
+       snprintf(env_total, sizeof(env_total), "GIT_DIFF_PATH_TOTAL=%d", q->nr);
+
+       retval = run_command_v_opt_cd_env(spawn_arg, RUN_USING_SHELL, NULL, env);
        remove_tempfile();
        if (retval) {
                fprintf(stderr, "external diff died, stopping at %s.\n", name);
@@ -3042,7 +3054,7 @@ static void run_diff_cmd(const char *pgm,
 
        if (pgm) {
                run_external_diff(pgm, name, other, one, two, xfrm_msg,
-                                 complete_rewrite);
+                                 complete_rewrite, o);
                return;
        }
        if (one && two)
@@ -3317,6 +3329,8 @@ void diff_setup_done(struct diff_options *options)
                options->output_format = DIFF_FORMAT_NO_OUTPUT;
                DIFF_OPT_SET(options, EXIT_WITH_STATUS);
        }
+
+       options->diff_path_counter = 0;
 }
 
 static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)
diff --git a/diff.h b/diff.h
index 1c05b3a6bec6ce90a97efe366614d23133026b00..ce123fa06fee6fb6e5e76d6a92ea8284a5bbbcf1 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -164,6 +164,8 @@ struct diff_options {
        diff_prefix_fn_t output_prefix;
        int output_prefix_length;
        void *output_prefix_data;
+
+       int diff_path_counter;
 };
 
 enum color_diff {
@@ -330,7 +332,7 @@ extern int diff_flush_patch_id(struct diff_options *, unsigned char *);
 
 extern int diff_result_code(struct diff_options *, int);
 
-extern void diff_no_index(struct rev_info *, int, const char **, int, const char *);
+extern void diff_no_index(struct rev_info *, int, const char **, const char *);
 
 extern int index_differs_from(const char *def, int diff_flags);
 
index b00ed95dba9c035ee812d3a2d6db2d13a1944a33..7ef36b9482ccc4111f2c888bf5ccbaa2421a5875 100755 (executable)
@@ -40,7 +40,8 @@ launch_merge_tool () {
        # the user with the real $MERGED name before launching $merge_tool.
        if should_prompt
        then
-               printf "\nViewing: '%s'\n" "$MERGED"
+               printf "\nViewing (%s/%s): '%s'\n" "$GIT_DIFF_PATH_COUNTER" \
+                       "$GIT_DIFF_PATH_TOTAL" "$MERGED"
                if use_ext_cmd
                then
                        printf "Launch '%s' [Y/n]: " \
index 97716b885f8d52be465552458374698c4c78a51b..f210d0a14707c57d66baa2d098d0d2efdaaaf72e 100755 (executable)
@@ -229,15 +229,7 @@ test true = "$rebase" && {
        test -n "$curr_branch" &&
        . git-parse-remote &&
        remoteref="$(get_remote_merge_branch "$@" 2>/dev/null)" &&
-       oldremoteref="$(git rev-parse -q --verify "$remoteref")" &&
-       for reflog in $(git rev-list -g $remoteref 2>/dev/null)
-       do
-               if test "$reflog" = "$(git merge-base $reflog $curr_branch)"
-               then
-                       oldremoteref="$reflog"
-                       break
-               fi
-       done
+       oldremoteref=$(git merge-base --fork-point "$remoteref" $curr_branch)
 }
 orig_head=$(git rev-parse -q --verify HEAD)
 git fetch $verbosity $progress $dry_run $recurse_submodules --update-head-ok "$@" || exit 1
index 226752fbff62f4f27da95f7d711c898503fd7148..7185dc84387d6e20299fdda86800372445b9318e 100755 (executable)
@@ -14,6 +14,7 @@ git-rebase --continue | --abort | --skip | --edit-todo
 v,verbose!         display a diffstat of what changed upstream
 q,quiet!           be quiet. implies --no-stat
 autostash!         automatically stash/stash pop before and after
+fork-point         use 'merge-base --fork-point' to refine upstream
 onto=!             rebase onto given branch instead of upstream
 p,preserve-merges! try to recreate merges instead of ignoring them
 s,strategy=!       use the given merge strategy
@@ -66,6 +67,7 @@ verbose=
 diffstat=
 test "$(git config --bool rebase.stat)" = true && diffstat=t
 autostash="$(git config --bool rebase.autostash || echo false)"
+fork_point=auto
 git_am_opt=
 rebase_root=
 force_rebase=
@@ -260,6 +262,12 @@ do
        --no-autosquash)
                autosquash=
                ;;
+       --fork-point)
+               fork_point=t
+               ;;
+       --no-fork-point)
+               fork_point=
+               ;;
        -M|-m)
                do_merge=t
                ;;
@@ -437,6 +445,8 @@ then
                        error_on_missing_default_upstream "rebase" "rebase" \
                                "against" "git rebase <branch>"
                fi
+
+               test "$fork_point" = auto && fork_point=t
                ;;
        *)      upstream_name="$1"
                shift
@@ -522,6 +532,15 @@ case "$#" in
        ;;
 esac
 
+if test "$fork_point" = t
+then
+       new_upstream=$(git merge-base --fork-point "$upstream_name" "$switch_to")
+       if test -n "$new_upstream"
+       then
+               upstream=$new_upstream
+       fi
+fi
+
 if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
 then
        stash_sha1=$(git stash create "autostash") ||
index ca9e63be18f9333bf0f603ddb9ddd923588be0aa..ddc174e1adb9e1545b2815d8a1990e43f6fa2bfb 100644 (file)
@@ -44,14 +44,13 @@ static int need_large_offset(off_t offset, const struct pack_idx_option *opts)
  */
 const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects,
                           int nr_objects, const struct pack_idx_option *opts,
-                          unsigned char *sha1)
+                          const unsigned char *sha1)
 {
        struct sha1file *f;
        struct pack_idx_entry **sorted_by_sha, **list, **last;
        off_t last_obj_offset = 0;
        uint32_t array[256];
        int i, fd;
-       git_SHA_CTX ctx;
        uint32_t index_version;
 
        if (nr_objects) {
@@ -114,9 +113,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
        }
        sha1write(f, array, 256 * 4);
 
-       /* compute the SHA1 hash of sorted object names. */
-       git_SHA1_Init(&ctx);
-
        /*
         * Write the actual SHA1 entries..
         */
@@ -128,7 +124,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
                        sha1write(f, &offset, 4);
                }
                sha1write(f, obj->sha1, 20);
-               git_SHA1_Update(&ctx, obj->sha1, 20);
                if ((opts->flags & WRITE_IDX_STRICT) &&
                    (i && !hashcmp(list[-2]->sha1, obj->sha1)))
                        die("The same object %s appears twice in the pack",
@@ -178,7 +173,6 @@ const char *write_idx_file(const char *index_name, struct pack_idx_entry **objec
        sha1write(f, sha1, 20);
        sha1close(f, NULL, ((opts->flags & WRITE_IDX_VERIFY)
                            ? CSUM_CLOSE : CSUM_FSYNC));
-       git_SHA1_Final(sha1, &ctx);
        return index_name;
 }
 
diff --git a/pack.h b/pack.h
index aa6ee7d606f1d5336bff9a3067b44057c362e788..12d951659c16462cf2da6a43e2c4974b85e39712 100644 (file)
--- a/pack.h
+++ b/pack.h
@@ -76,7 +76,7 @@ struct pack_idx_entry {
 struct progress;
 typedef int (*verify_fn)(const unsigned char*, enum object_type, unsigned long, void*, int*);
 
-extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, unsigned char *sha1);
+extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, const struct pack_idx_option *, const unsigned char *sha1);
 extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
 extern int verify_pack_index(struct packed_git *);
 extern int verify_pack(struct packed_git *, verify_fn fn, struct progress *, uint32_t);
index 709a9cbd26fea972a6781581a0c345c8e95a7f6d..a89efab5b766ba9374c3a09656b2d56593884c8e 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -852,7 +852,7 @@ static int match_name_with_pattern(const char *key, const char *name,
        return ret;
 }
 
-static int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
+int query_refspecs(struct refspec *refs, int ref_count, struct refspec *query)
 {
        int i;
        int find_src = !query->src;
@@ -986,9 +986,9 @@ void sort_ref_list(struct ref **l, int (*cmp)(const void *, const void *))
        *l = llist_mergesort(*l, ref_list_get_next, ref_list_set_next, cmp);
 }
 
-static int count_refspec_match(const char *pattern,
-                              struct ref *refs,
-                              struct ref **matched_ref)
+int count_refspec_match(const char *pattern,
+                       struct ref *refs,
+                       struct ref **matched_ref)
 {
        int patlen = strlen(pattern);
        struct ref *matched_weak = NULL;
index c07eb9950a15600f7fde7faa60570ea5a558fb60..00c6a76ef803005698e14d7f31eb4acd22b35649 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -128,6 +128,7 @@ struct ref *alloc_ref(const char *name);
 struct ref *copy_ref(const struct ref *ref);
 struct ref *copy_ref_list(const struct ref *ref);
 void sort_ref_list(struct ref **, int (*cmp)(const void *, const void *));
+extern int count_refspec_match(const char *, struct ref *refs, struct ref **matched_ref);
 int ref_compare_name(const void *, const void *);
 
 int check_ref_type(const struct ref *ref, int flags);
@@ -162,6 +163,7 @@ struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
 
 void free_refspec(int nr_refspec, struct refspec *refspec);
 
+extern int query_refspecs(struct refspec *specs, int nr, struct refspec *query);
 char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
                     const char *name);
 
diff --git a/t/perf/p4001-diff-no-index.sh b/t/perf/p4001-diff-no-index.sh
new file mode 100755 (executable)
index 0000000..683be69
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+test_description="Test diff --no-index performance"
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+test_checkout_worktree
+
+file1=$(git ls-files | tail -n 2 | head -1)
+file2=$(git ls-files | tail -n 1 | head -1)
+
+test_expect_success "empty files, so they take no time to diff" "
+       echo >$file1 &&
+       echo >$file2
+"
+
+test_perf "diff --no-index" "
+       git diff --no-index $file1 $file2 >/dev/null
+"
+
+test_done
index 8a1bc5c53281eb6f44c15d68dd0ae737bc0125f3..1687098355b710850a04769512320930d9b8b27b 100755 (executable)
@@ -85,6 +85,28 @@ $content"
                git cat-file --batch-check="%(objecttype) %(rest)" >actual &&
        test_cmp expect actual
     '
+
+    test -z "$content" ||
+    test_expect_success "--batch without type ($type)" '
+       {
+               echo "$size" &&
+               maybe_remove_timestamp "$content" $no_ts
+       } >expect &&
+       echo $sha1 | git cat-file --batch="%(objectsize)" >actual.full &&
+       maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
+       test_cmp expect actual
+    '
+
+    test -z "$content" ||
+    test_expect_success "--batch without size ($type)" '
+       {
+               echo "$type" &&
+               maybe_remove_timestamp "$content" $no_ts
+       } >expect &&
+       echo $sha1 | git cat-file --batch="%(objecttype)" >actual.full &&
+       maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual &&
+       test_cmp expect actual
+    '
 }
 
 hello_content="Hello World"
index f950c101287c2f05bbd70c1faffbcf2cda1edbee..613d9bfe1bbb153d1c2e647aee26a60e07a6af86 100755 (executable)
@@ -196,4 +196,28 @@ test_expect_success 'dotdot is not an empty set' '
        test_cmp expect actual
 '
 
+test_expect_success 'arg before dashdash must be a revision (missing)' '
+       test_must_fail git rev-parse foobar -- 2>stderr &&
+       test_i18ngrep "bad revision" stderr
+'
+
+test_expect_success 'arg before dashdash must be a revision (file)' '
+       >foobar &&
+       test_must_fail git rev-parse foobar -- 2>stderr &&
+       test_i18ngrep "bad revision" stderr
+'
+
+test_expect_success 'arg before dashdash must be a revision (ambiguous)' '
+       >foobar &&
+       git update-ref refs/heads/foobar HEAD &&
+       {
+               # we do not want to use rev-parse here, because
+               # we are testing it
+               cat .git/refs/heads/foobar &&
+               printf "%s\n" --
+       } >expect &&
+       git rev-parse foobar -- >actual &&
+       test_cmp expect actual
+'
+
 test_done
index ebf93b0695dfac37fc276e1f07377d858eb3e1da..998503db12eb115e8e160937d456dfd9cb46311f 100755 (executable)
@@ -134,12 +134,14 @@ test_expect_success 'fail when upstream arg is missing and not configured' '
        test_must_fail git rebase
 '
 
-test_expect_success 'default to @{upstream} when upstream arg is missing' '
+test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg' '
        git checkout -b default topic &&
        git config branch.default.remote . &&
        git config branch.default.merge refs/heads/master &&
        git rebase &&
-       test "$(git rev-parse default~1)" = "$(git rev-parse master)"
+       git rev-parse --verify master >expect &&
+       git rev-parse default~1 >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'rebase -q is quiet' '
index 8a309795c9c9654446d82c2e474e1ca08486e081..bcae35ac1c93aaf79032db5ee09fd2d3400101f5 100755 (executable)
@@ -193,6 +193,19 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
        GIT_EXTERNAL_DIFF=echo git diff
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF path counter/total' '
+       write_script external-diff.sh <<-\EOF &&
+       echo $GIT_DIFF_PATH_COUNTER of $GIT_DIFF_PATH_TOTAL >>counter.txt
+       EOF
+       >counter.txt &&
+       cat >expect <<-\EOF &&
+       1 of 2
+       2 of 2
+       EOF
+       GIT_EXTERNAL_DIFF=./external-diff.sh git diff &&
+       test_cmp expect counter.txt
+'
+
 test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
        touch file.ext &&
        git add file.ext &&
index 979e98398bebc21fe664ca4a19770e5b251bfc97..2ab3c487340569d7f2f8164776907ef30df2d415 100755 (executable)
@@ -29,4 +29,30 @@ test_expect_success 'git diff --no-index relative path outside repo' '
        )
 '
 
+test_expect_success 'git diff --no-index with broken index' '
+       (
+               cd repo &&
+               echo broken >.git/index &&
+               git diff --no-index a ../non/git/a
+       )
+'
+
+test_expect_success 'git diff outside repo with broken index' '
+       (
+               cd repo &&
+               git diff ../non/git/a ../non/git/b
+       )
+'
+
+test_expect_success 'git diff --no-index executed outside repo gives correct error message' '
+       (
+               GIT_CEILING_DIRECTORIES=$TRASH_DIRECTORY/non &&
+               export GIT_CEILING_DIRECTORIES &&
+               cd non/git &&
+               test_must_fail git diff --no-index a 2>actual.err &&
+               echo "usage: git diff --no-index <path> <path>" >expect.err &&
+               test_cmp expect.err actual.err
+       )
+'
+
 test_done
index fe82025d4a0dbae0cee3d0c3943617ede5b5c7a5..4bbb718751738c3e913c25160d0fff52d8350bba 100755 (executable)
@@ -174,11 +174,11 @@ test_expect_success \
 test_expect_success \
     '[index v1] 5) pack-objects happily reuses corrupted data' \
     'pack4=$(git pack-objects test-4 <obj-list) &&
-     test -f "test-4-${pack1}.pack"'
+     test -f "test-4-${pack4}.pack"'
 
 test_expect_success \
     '[index v1] 6) newly created pack is BAD !' \
-    'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
+    'test_must_fail git verify-pack -v "test-4-${pack4}.pack"'
 
 test_expect_success \
     '[index v2] 1) stream pack to repository' \
index 99c32d75391bb02fae779ad831879903abca5d25..926e7f6b979d4d1c69ecc9d280cd6de365627012 100755 (executable)
@@ -1126,6 +1126,81 @@ test_expect_success 'fetch follows tags by default' '
        test_cmp expect actual
 '
 
+test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' '
+       mk_test testrepo heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       git init --bare dst &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git branch next &&
+               git config remote.dst.url ../dst &&
+               git config remote.dst.push "+refs/heads/*:refs/remotes/src/*" &&
+               git push dst master &&
+               git show-ref refs/heads/master |
+               sed -e "s|refs/heads/|refs/remotes/src/|" >../dst/expect
+       ) &&
+       (
+               cd dst &&
+               test_must_fail git show-ref refs/heads/next &&
+               test_must_fail git show-ref refs/heads/master &&
+               git show-ref refs/remotes/src/master >actual
+       ) &&
+       test_cmp dst/expect dst/actual
+'
+
+test_expect_success 'with no remote.$name.push, it is not used as refmap' '
+       mk_test testrepo heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       git init --bare dst &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git branch next &&
+               git config remote.dst.url ../dst &&
+               git config push.default matching &&
+               git push dst master &&
+               git show-ref refs/heads/master >../dst/expect
+       ) &&
+       (
+               cd dst &&
+               test_must_fail git show-ref refs/heads/next &&
+               git show-ref refs/heads/master >actual
+       ) &&
+       test_cmp dst/expect dst/actual
+'
+
+test_expect_success 'with no remote.$name.push, upstream mapping is used' '
+       mk_test testrepo heads/master &&
+       rm -fr src dst &&
+       git init src &&
+       git init --bare dst &&
+       (
+               cd src &&
+               git pull ../testrepo master &&
+               git branch next &&
+               git config remote.dst.url ../dst &&
+               git config remote.dst.fetch "+refs/heads/*:refs/remotes/dst/*" &&
+               git config push.default upstream &&
+
+               git config branch.master.merge refs/heads/trunk &&
+               git config branch.master.remote dst &&
+
+               git push dst master &&
+               git show-ref refs/heads/master |
+               sed -e "s|refs/heads/master|refs/heads/trunk|" >../dst/expect
+       ) &&
+       (
+               cd dst &&
+               test_must_fail git show-ref refs/heads/master &&
+               test_must_fail git show-ref refs/heads/next &&
+               git show-ref refs/heads/trunk >actual
+       ) &&
+       test_cmp dst/expect dst/actual
+'
+
 test_expect_success 'push does not follow tags by default' '
        mk_test testrepo heads/master &&
        rm -fr src dst &&