Merge branch 'jk/maint-commit-v-strip' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 3 Dec 2008 07:47:25 +0000 (23:47 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Dec 2008 07:47:25 +0000 (23:47 -0800)
* jk/maint-commit-v-strip:
commit: Fix stripping of patch in verbose mode.

42 files changed:
Documentation/RelNotes-1.6.0.4.txt
Documentation/RelNotes-1.6.0.5.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-check-attr.txt
Documentation/git-cherry-pick.txt
Documentation/git-commit.txt
Documentation/git-pack-objects.txt
Documentation/git-repack.txt
Documentation/git-svn.txt
Documentation/gitcore-tutorial.txt
Documentation/gitglossary.txt
Documentation/urls-remotes.txt
Documentation/user-manual.txt
RelNotes
builtin-checkout.c
builtin-diff.c
builtin-fast-export.c
builtin-gc.c
builtin-ls-files.c
builtin-pack-objects.c
builtin-read-tree.c
builtin-tag.c
cache.h
compat/mingw.c
contrib/completion/git-completion.bash
contrib/fast-import/git-p4
date.c
generate-cmdlist.sh
git-repack.sh
git-request-pull.sh
read-cache.c
remote.c
revision.c
sha1_file.c
t/t4020-diff-external.sh
t/t5300-pack-object.sh
t/t5516-fetch-push.sh
t/t7004-tag.sh
t/t7700-repack.sh [new file with mode: 0755]
t/t7701-repack-unpack-unreachable.sh
t/t9301-fast-export.sh
xdiff/xprepare.c
index fba3f30a89e22474ec3df358441cd79d29ff2bec..d522661d315c3aab445bf3aa123bbd0abd9db251 100644 (file)
@@ -30,7 +30,7 @@ Fixes since v1.6.0.3
 * 'git status' incorrectly reported a submodule directory as an untracked
   directory.
 
-* 'git svn' used deprecated 'git-foo' form of subcommand invocaition.
+* 'git svn' used deprecated 'git-foo' form of subcommand invocation.
 
 * 'git update-ref -d' to remove a reference did not honor --no-deref option.
 
diff --git a/Documentation/RelNotes-1.6.0.5.txt b/Documentation/RelNotes-1.6.0.5.txt
new file mode 100644 (file)
index 0000000..1dc101c
--- /dev/null
@@ -0,0 +1,43 @@
+GIT v1.6.0.5 Release Notes
+==========================
+
+Fixes since v1.6.0.4
+--------------------
+
+* 'git checkout' used to crash when your HEAD was pointing at a deleted
+  branch.
+
+* 'git checkout' from an un-checked-out state did not allow switching out
+  of the current branch.
+
+* 'git diff' always allowed GIT_EXTERNAL_DIFF and --no-ext-diff was no-op for
+  the command.
+
+* 'git fast-export' did not export all tags.
+
+* 'git ls-files --with-tree=<tree>' did not work with options other
+  than -c, most notably with -m.
+
+* 'git pack-objects' did not make its best effort to honor --max-pack-size
+  option when a single first object already busted the given limit and
+  placed many objects in a single pack.
+
+* 'git-p4' fast import frontend was too eager to trigger its keyword expansion
+  logic, even on a keyword-looking string that does not have closing '$' on the
+  same line.
+
+* 'git push $there' when the remote $there is defined in $GIT_DIR/branches/$there
+  behaves more like what cg-push from Cogito used to work.
+
+* 'git tag' did not complain when given mutually incompatible set of options.
+
+* 'make check' cannot be run without sparse; people may have meant to say
+  'make test' instead, so suggest that.
+
+* Many unsafe call to sprintf() style varargs functions are corrected.
+
+* Also contains quite a few documentation updates.
+
+--
+O=v1.6.0.4-39-g27f6496
+
index 87b028fbc1817c9c641e5fe03aab641e3bd5eb63..113d9d1438891b51d11f2fee2764c88e69024921 100644 (file)
@@ -561,9 +561,6 @@ color.status.<slot>::
        to red). The values of these variables may be specified as in
        color.branch.<slot>.
 
-commit.template::
-       Specify a file to use as the template for new commit messages.
-
 color.ui::
        When set to `always`, always use colors in all git commands which
        are capable of colored output. When false (or `never`), never. When
@@ -571,6 +568,9 @@ color.ui::
        terminal. When more specific variables of color.* are set, they always
        take precedence over this setting. Defaults to false.
 
+commit.template::
+       Specify a file to use as the template for new commit messages.
+
 diff.autorefreshindex::
        When using 'git-diff' to compare with work tree
        files, do not consider stat-only change as changed.
@@ -682,18 +682,6 @@ gc.rerereunresolved::
        kept for this many days when 'git-rerere gc' is run.
        The default is 15 days.  See linkgit:git-rerere[1].
 
-rerere.autoupdate::
-       When set to true, `git-rerere` updates the index with the
-       resulting contents after it cleanly resolves conflicts using
-       previously recorded resolution.  Defaults to false.
-
-rerere.enabled::
-       Activate recording of resolved conflicts, so that identical
-       conflict hunks can be resolved automatically, should they
-       be encountered again.  linkgit:git-rerere[1] command is by
-       default enabled if you create `rr-cache` directory under
-       `$GIT_DIR`, but can be disabled by setting this option to false.
-
 gitcvs.enabled::
        Whether the CVS server interface is enabled for this repository.
        See linkgit:git-cvsserver[1].
@@ -852,6 +840,10 @@ i18n.logOutputEncoding::
        Character encoding the commit messages are converted to when
        running 'git-log' and friends.
 
+imap::
+       The configuration variables in the 'imap' section are described
+       in linkgit:git-imap-send[1].
+
 instaweb.browser::
        Specify the program that will be used to browse your working
        repository in gitweb. See linkgit:git-instaweb[1].
@@ -887,8 +879,6 @@ man.viewer::
        Specify the programs that may be used to display help in the
        'man' format. See linkgit:git-help[1].
 
-include::merge-config.txt[]
-
 man.<tool>.cmd::
        Specify the command to invoke the specified man viewer. The
        specified command is evaluated in shell with the man page
@@ -898,6 +888,8 @@ man.<tool>.path::
        Override the path for the given tool that may be used to
        display help in the 'man' format. See linkgit:git-help[1].
 
+include::merge-config.txt[]
+
 mergetool.<tool>.path::
        Override the path for the given tool.  This is useful in case
        your tool is not in the PATH.
@@ -1006,6 +998,28 @@ pull.octopus::
 pull.twohead::
        The default merge strategy to use when pulling a single branch.
 
+receive.fsckObjects::
+       If it is set to true, git-receive-pack will check all received
+       objects. It will abort in the case of a malformed object or a
+       broken link. The result of an abort are only dangling objects.
+       Defaults to false.
+
+receive.unpackLimit::
+       If the number of objects received in a push is below this
+       limit then the objects will be unpacked into loose object
+       files. However if the number of received objects equals or
+       exceeds this limit then the received pack will be stored as
+       a pack, after adding any missing delta bases.  Storing the
+       pack from a push can make the push operation complete faster,
+       especially on slow filesystems.  If not set, the value of
+       `transfer.unpackLimit` is used instead.
+
+receive.denyNonFastForwards::
+       If set to true, git-receive-pack will deny a ref update which is
+       not a fast forward. Use this to prevent such an update via a push,
+       even if that push is forced. This configuration variable is
+       set when initializing a shared repository.
+
 remote.<name>.url::
        The URL of a remote repository.  See linkgit:git-fetch[1] or
        linkgit:git-push[1].
@@ -1055,6 +1069,18 @@ repack.usedeltabaseoffset::
        "false" and repack. Access from old git versions over the
        native protocol are unaffected by this option.
 
+rerere.autoupdate::
+       When set to true, `git-rerere` updates the index with the
+       resulting contents after it cleanly resolves conflicts using
+       previously recorded resolution.  Defaults to false.
+
+rerere.enabled::
+       Activate recording of resolved conflicts, so that identical
+       conflict hunks can be resolved automatically, should they
+       be encountered again.  linkgit:git-rerere[1] command is by
+       default enabled if you create `rr-cache` directory under
+       `$GIT_DIR`, but can be disabled by setting this option to false.
+
 showbranch.default::
        The default set of branches for linkgit:git-show-branch[1].
        See linkgit:git-show-branch[1].
@@ -1091,6 +1117,11 @@ tar.umask::
        archiving user's umask will be used instead.  See umask(2) and
        linkgit:git-archive[1].
 
+transfer.unpackLimit::
+       When `fetch.unpackLimit` or `receive.unpackLimit` are
+       not set, the value of this variable is used instead.
+       The default value is 100.
+
 url.<base>.insteadOf::
        Any URL that starts with this value will be rewritten to
        start, instead, with <base>. In cases where some site serves a
@@ -1119,37 +1150,6 @@ user.signingkey::
        unchanged to gpg's --local-user parameter, so you may specify a key
        using any method that gpg supports.
 
-imap::
-       The configuration variables in the 'imap' section are described
-       in linkgit:git-imap-send[1].
-
-receive.fsckObjects::
-       If it is set to true, git-receive-pack will check all received
-       objects. It will abort in the case of a malformed object or a
-       broken link. The result of an abort are only dangling objects.
-       Defaults to false.
-
-receive.unpackLimit::
-       If the number of objects received in a push is below this
-       limit then the objects will be unpacked into loose object
-       files. However if the number of received objects equals or
-       exceeds this limit then the received pack will be stored as
-       a pack, after adding any missing delta bases.  Storing the
-       pack from a push can make the push operation complete faster,
-       especially on slow filesystems.  If not set, the value of
-       `transfer.unpackLimit` is used instead.
-
-receive.denyNonFastForwards::
-       If set to true, git-receive-pack will deny a ref update which is
-       not a fast forward. Use this to prevent such an update via a push,
-       even if that push is forced. This configuration variable is
-       set when initializing a shared repository.
-
-transfer.unpackLimit::
-       When `fetch.unpackLimit` or `receive.unpackLimit` are
-       not set, the value of this variable is used instead.
-       The default value is 100.
-
 web.browser::
        Specify a web browser that may be used by some commands.
        Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]
index 4b3c2b0b06e9821124759d0cc6240d0a1953d2fa..043274b1b71cb9fbced92fabca16acc4453f6458 100644 (file)
@@ -3,7 +3,7 @@ git-check-attr(1)
 
 NAME
 ----
-git-check-attr - Display gitattributes information.
+git-check-attr - Display gitattributes information
 
 
 SYNOPSIS
index 837fb08b7971a8b948dd7d039bab4a3c2e54cac7..b764130d26eb750d2b5173dcc98366828e413046 100644 (file)
@@ -55,13 +55,12 @@ OPTIONS
 
 -n::
 --no-commit::
-       Usually the command automatically creates a commit with
-       a commit log message stating which commit was
-       cherry-picked.  This flag applies the change necessary
-       to cherry-pick the named commit to your working tree
-       and the index, but does not make the commit.  In addition,
-       when this option is used, your index does not have to match
-       the HEAD commit.  The cherry-pick is done against the
+       Usually the command automatically creates a commit.
+       This flag applies the change necessary to cherry-pick
+       the named commit to your working tree and the index,
+       but does not make the commit.  In addition, when this
+       option is used, your index does not have to match the
+       HEAD commit.  The cherry-pick is done against the
        beginning state of your index.
 +
 This is useful when cherry-picking more than one commits'
index 79be4f1c0086fd1193734412019feeef8b07d669..77604d021603fa7002e416356ae197648093b69d 100644 (file)
@@ -92,7 +92,7 @@ OPTIONS
 
 -s::
 --signoff::
-       Add Signed-off-by line by the commiter at the end of the commit
+       Add Signed-off-by line by the committer at the end of the commit
        log message.
 
 -n::
index 8c354bd47014825de71243d73158b6b080ecb350..7d4c1a75562de80aa80dfbfa665330b14ec948c6 100644 (file)
@@ -109,6 +109,11 @@ base-name::
        The default is unlimited, unless the config variable
        `pack.packSizeLimit` is set.
 
+--honor-pack-keep::
+       This flag causes an object already in a local pack that
+       has a .keep file to be ignored, even if it appears in the
+       standard input.
+
 --incremental::
        This flag causes an object already in a pack ignored
        even if it appears in the standard input.
@@ -116,7 +121,7 @@ base-name::
 --local::
        This flag is similar to `--incremental`; instead of
        ignoring all packed objects, it only ignores objects
-       that are packed and not in the local object store
+       that are packed and/or not in the local object store
        (i.e. borrowed from an alternate).
 
 --non-empty::
index bbe1485a97979830f883377c2dd55c6a90eb8a09..aaa88526291a26db55c7ebb0833faefda9c7e5a4 100644 (file)
@@ -38,12 +38,11 @@ OPTIONS
        dangling.
 
 -A::
-       Same as `-a`, but any unreachable objects in a previous
-       pack become loose, unpacked objects, instead of being
-       left in the old pack.  Unreachable objects are never
-       intentionally added to a pack, even when repacking.
-       When used with '-d', this option
-       prevents unreachable objects from being immediately
+       Same as `-a`, unless '-d' is used.  Then any unreachable
+       objects in a previous pack become loose, unpacked objects,
+       instead of being left in the old pack.  Unreachable objects
+       are never intentionally added to a pack, even when repacking.
+       This option prevents unreachable objects from being immediately
        deleted by way of being left in the old pack and then
        removed.  Instead, the loose unreachable objects
        will be pruned according to normal expiry rules
index 82d03b4ced9cb7e34feca325d0ac7b41923de976..5d6d30f764a7bca813295461104c8f6f46ad0e35 100644 (file)
@@ -109,7 +109,7 @@ COMMANDS
 
 This works similarly to `svn update` or 'git-pull' except that
 it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommiting with 'git-svn'.
+'git-merge' for ease of dcommitting with 'git-svn'.
 
 This accepts all options that 'git-svn fetch' and 'git-rebase'
 accept.  However, '--fetch-all' only fetches from the current
@@ -522,6 +522,8 @@ have each person clone that repository with 'git-clone':
        git remote add origin server:/pub/project
        git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
        git fetch
+# Create a local branch from one of the branches just fetched
+       git checkout -b master FETCH_HEAD
 # Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
        git svn init http://svn.example.com/project
 # Pull the latest changes from Subversion
index a417e592ac6a7ed72186dcfc241592ccdc25c9d2..61fc5d7be8effd65f24fccbcc42f86e6dbea6742 100644 (file)
@@ -1690,8 +1690,10 @@ to follow, not easier.
 
 SEE ALSO
 --------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:everyday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday git],
 link:user-manual.html[The Git User's Manual]
 
 GIT
index 565719ed5f8516e17229ec11bbec5e1354580397..d77a45aed678522344d58498f1ee20ca14e0895e 100644 (file)
@@ -16,8 +16,10 @@ include::glossary-content.txt[]
 
 SEE ALSO
 --------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:everyday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday git],
 link:user-manual.html[The Git User's Manual]
 
 GIT
index 504ae8a53bca42d7c9ec560b65ddfe14699387a4..41ec7774f481fd2d70492be4ab2b5e0bf887fc0b 100644 (file)
@@ -68,13 +68,22 @@ This file should have the following format:
 ------------
 
 `<url>` is required; `#<head>` is optional.
-When you do not provide a refspec on the command line,
-git will use the following refspec, where `<head>` defaults to `master`,
-and `<repository>` is the name of this file
-you provided in the command line.
+
+Depending on the operation, git will use one of the following
+refspecs, if you don't provide one on the command line.
+`<branch>` is the name of this file in `$GIT_DIR/branches` and
+`<head>` defaults to `master`.
+
+git fetch uses:
+
+------------
+       refs/heads/<head>:refs/heads/<branch>
+------------
+
+git push uses:
 
 ------------
-       refs/heads/<head>:<repository>
+       HEAD:refs/heads/<head>
 ------------
 
 
index 08d1310bf5fc5590ada1ee5b2af77d361ff4d874..b6533fa206a37aaccbb9f78712839e31ac94856e 100644 (file)
@@ -536,7 +536,7 @@ $ git bisect skip
 -------------------------------------------------
 
 In this case, though, git may not eventually be able to tell the first
-bad one between some first skipped commits and a latter bad commit.
+bad one between some first skipped commits and a later bad commit.
 
 There are also ways to automate the bisecting process if you have a
 test script that can tell a good from a bad commit. See
@@ -4560,4 +4560,3 @@ Alternates, clone -reference, etc.
 More on recovery from repository corruption.  See:
        http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
        http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
-       http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
index f9eb5528732ad3d45b5f685728b5f8943d435522..ebf508f2d7ccb5b3c32dd298dfbfcd243a006947 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.6.0.4.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.0.5.txt
\ No newline at end of file
index 05eee4ecc71d7a20d9faf59c849d3c693ae4cc8d..c107fd643a452edb016f7ad867d4b2a555d9abaf 100644 (file)
@@ -269,8 +269,7 @@ static int merge_working_tree(struct checkout_opts *opts,
                }
 
                /* 2-way merge to the new branch */
-               topts.initial_checkout = (!active_nr &&
-                                         (old->commit == new->commit));
+               topts.initial_checkout = is_cache_unborn();
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge;
@@ -422,7 +421,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
        if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
                describe_detached_head("Previous HEAD position was", old.commit);
 
-       if (!old.commit) {
+       if (!old.commit && !opts->force) {
                if (!opts->quiet) {
                        fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
                        fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
index d5fe775fc135c0905cabec6731104009ca3bfef3..26cf6785918300f3a0998a1811adb71ec6ec7b73 100644 (file)
@@ -290,6 +290,9 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        /* Otherwise, we are doing the usual "git" diff */
        rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
 
+       /* Default to let external be used */
+       DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+
        if (nongit)
                die("Not a git repository");
        argc = setup_revisions(argc, argv, &rev, NULL);
@@ -298,7 +301,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                if (diff_setup_done(&rev.diffopt) < 0)
                        die("diff_setup_done failed");
        }
-       DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+
        DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
 
        /*
index 7c93eb878d7da87b39959fb9599e4b7b6b81570b..7d5d57ad7568b8c0bf7396cdbd581c67ab4600e2 100644 (file)
@@ -354,7 +354,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
                case OBJ_TAG:
                        tag = (struct tag *)e->item;
                        while (tag && tag->object.type == OBJ_TAG) {
-                               string_list_insert(full_name, extra_refs)->util = tag;
+                               string_list_append(full_name, extra_refs)->util = tag;
                                tag = (struct tag *)tag->tagged;
                        }
                        if (!tag)
@@ -374,7 +374,7 @@ static void get_tags_and_duplicates(struct object_array *pending,
                }
                if (commit->util)
                        /* more than one name for the same object */
-                       string_list_insert(full_name, extra_refs)->util = commit;
+                       string_list_append(full_name, extra_refs)->util = commit;
                else
                        commit->util = full_name;
        }
index fac200e0b08360625afc81b02913128c9b87f486..53a0d43b679889dd8659fa6bdd6007f2a5967cc5 100644 (file)
@@ -134,19 +134,9 @@ static int too_many_packs(void)
 
        prepare_packed_git();
        for (cnt = 0, p = packed_git; p; p = p->next) {
-               char path[PATH_MAX];
-               size_t len;
-               int keep;
-
                if (!p->pack_local)
                        continue;
-               len = strlen(p->pack_name);
-               if (PATH_MAX <= len + 1)
-                       continue; /* oops, give up */
-               memcpy(path, p->pack_name, len-5);
-               memcpy(path + len - 5, ".keep", 6);
-               keep = access(p->pack_name, F_OK) && (errno == ENOENT);
-               if (keep)
+               if (p->pack_keep)
                        continue;
                /*
                 * Perhaps check the size of the pack and count only
index b48327db950e5d8a54045f4956fa92b7879227bc..f72eb854756f602e4d114964f4585bc5a8c55e20 100644 (file)
@@ -227,6 +227,8 @@ static void show_files(struct dir_struct *dir, const char *prefix)
                        int dtype = ce_to_dtype(ce);
                        if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
                                continue;
+                       if (ce->ce_flags & CE_UPDATE)
+                               continue;
                        err = lstat(ce->name, &st);
                        if (show_deleted && err)
                                show_ce_entry(tag_removed, ce);
@@ -329,7 +331,7 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix)
        if (prefix) {
                static const char *(matchbuf[2]);
                matchbuf[0] = prefix;
-               matchbuf [1] = NULL;
+               matchbuf[1] = NULL;
                match = matchbuf;
        } else
                match = NULL;
index b0dddbee4f93de462090218554e1b1b6d1038c34..4411a480c1067f6841181e838ffba54edbec823f 100644 (file)
@@ -71,6 +71,7 @@ static int reuse_delta = 1, reuse_object = 1;
 static int keep_unreachable, unpack_unreachable, include_tag;
 static int local;
 static int incremental;
+static int ignore_packed_keep;
 static int allow_ofs_delta;
 static const char *base_name;
 static int progress = 1;
@@ -245,8 +246,16 @@ static unsigned long write_object(struct sha1file *f,
        type = entry->type;
 
        /* write limit if limited packsize and not first object */
-       limit = pack_size_limit && nr_written ?
-                       pack_size_limit - write_offset : 0;
+       if (!pack_size_limit || !nr_written)
+               limit = 0;
+       else if (pack_size_limit <= write_offset)
+               /*
+                * the earlier object did not fit the limit; avoid
+                * mistaking this with unlimited (i.e. limit = 0).
+                */
+               limit = 1;
+       else
+               limit = pack_size_limit - write_offset;
 
        if (!entry->delta)
                usable_delta = 0;       /* no delta */
@@ -690,6 +699,9 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
                return 0;
        }
 
+       if (!exclude && local && has_loose_object_nonlocal(sha1))
+               return 0;
+
        for (p = packed_git; p; p = p->next) {
                off_t offset = find_pack_entry_one(sha1, p);
                if (offset) {
@@ -703,6 +715,8 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
                                return 0;
                        if (local && !p->pack_local)
                                return 0;
+                       if (ignore_packed_keep && p->pack_local && p->pack_keep)
+                               return 0;
                }
        }
 
@@ -2042,6 +2056,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                        incremental = 1;
                        continue;
                }
+               if (!strcmp("--honor-pack-keep", arg)) {
+                       ignore_packed_keep = 1;
+                       continue;
+               }
                if (!prefixcmp(arg, "--compression=")) {
                        char *end;
                        int level = strtoul(arg+14, &end, 0);
index 0706c958181c54aeb18d91f6e3dbe7c9f572b94d..38fef34d3fb6c24ab89043951f1ecf6c96e9bf51 100644 (file)
@@ -206,7 +206,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
                        break;
                case 2:
                        opts.fn = twoway_merge;
-                       opts.initial_checkout = !active_nr;
+                       opts.initial_checkout = is_cache_unborn();
                        break;
                case 3:
                default:
index 843e9ac056c88bb2c9a8c6ded464096a99f13aff..11b91b3c3b2289d396c72067f7b3ded2ec6a0b64 100644 (file)
@@ -344,7 +344,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        const char *object_ref, *tag;
        struct ref_lock *lock;
 
-       int annotate = 0, sign = 0, force = 0, lines = 0,
+       int annotate = 0, sign = 0, force = 0, lines = -1,
                list = 0, delete = 0, verify = 0;
        const char *msgfile = NULL, *keyid = NULL;
        struct msg_arg msg = { 0, STRBUF_INIT };
@@ -380,9 +380,19 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        }
        if (sign)
                annotate = 1;
+       if (argc == 0 && !(delete || verify))
+               list = 1;
 
+       if ((annotate || msg.given || msgfile || force) &&
+           (list || delete || verify))
+               usage_with_options(git_tag_usage, options);
+
+       if (list + delete + verify > 1)
+               usage_with_options(git_tag_usage, options);
        if (list)
-               return list_tags(argv[0], lines);
+               return list_tags(argv[0], lines == -1 ? 0 : lines);
+       if (lines != -1)
+               die("-n option is only allowed with -l.");
        if (delete)
                return for_each_tag_name(argv, delete_tag);
        if (verify)
@@ -407,11 +417,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                }
        }
 
-       if (argc == 0) {
-               if (annotate)
-                       usage_with_options(git_tag_usage, options);
-               return list_tags(NULL, lines);
-       }
        tag = argv[0];
 
        object_ref = argc == 2 ? argv[1] : "HEAD";
diff --git a/cache.h b/cache.h
index a1e4982cd424ec5c3695c2221583bca1bd861614..d1cd6aaf738f94930b94ebbee303fc267064e2ac 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -255,6 +255,7 @@ static inline void remove_name_hash(struct cache_entry *ce)
 
 #define read_cache() read_index(&the_index)
 #define read_cache_from(path) read_index_from(&the_index, (path))
+#define is_cache_unborn() is_index_unborn(&the_index)
 #define read_cache_unmerged() read_index_unmerged(&the_index)
 #define write_cache(newfd, cache, entries) write_index(&the_index, (newfd))
 #define discard_cache() discard_index(&the_index)
@@ -360,6 +361,7 @@ extern int init_db(const char *template_dir, unsigned int flags);
 /* Initialize and use the cache information */
 extern int read_index(struct index_state *);
 extern int read_index_from(struct index_state *, const char *path);
+extern int is_index_unborn(struct index_state *);
 extern int read_index_unmerged(struct index_state *);
 extern int write_index(const struct index_state *, int newfd);
 extern int discard_index(struct index_state *);
@@ -565,6 +567,7 @@ extern int move_temp_to_file(const char *tmpfile, const char *filename);
 
 extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
 extern int has_sha1_file(const unsigned char *sha1);
+extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
 extern int has_pack_file(const unsigned char *sha1);
 extern int has_pack_index(const unsigned char *sha1);
@@ -671,7 +674,8 @@ extern struct packed_git {
        int index_version;
        time_t mtime;
        int pack_fd;
-       int pack_local;
+       unsigned pack_local:1,
+                pack_keep:1;
        unsigned char sha1[20];
        /* something like ".git/objects/pack/xxxxx.pack" */
        char pack_name[FLEX_ARRAY]; /* more */
index 772cad510d5d260fdf33b4f7d6ff79f9f3367b05..45733f9e04eb87409a896898cb5a92b37e87a920 100644 (file)
@@ -865,6 +865,8 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
 #undef rename
 int mingw_rename(const char *pold, const char *pnew)
 {
+       DWORD attrs;
+
        /*
         * Try native rename() first to get errno right.
         * It is based on MoveFile(), which cannot overwrite existing files.
@@ -876,12 +878,19 @@ int mingw_rename(const char *pold, const char *pnew)
        if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
                return 0;
        /* TODO: translate more errors */
-       if (GetLastError() == ERROR_ACCESS_DENIED) {
-               DWORD attrs = GetFileAttributes(pnew);
-               if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+       if (GetLastError() == ERROR_ACCESS_DENIED &&
+           (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
+               if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
                        errno = EISDIR;
                        return -1;
                }
+               if ((attrs & FILE_ATTRIBUTE_READONLY) &&
+                   SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
+                       if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+                               return 0;
+                       /* revert file attributes on failure */
+                       SetFileAttributes(pnew, attrs);
+               }
        }
        errno = EACCES;
        return -1;
index 39a1ce5a3979e6160b8450a0d9dd08ec6b6cd7a2..554a03ff4fbc61e8b02b6010c9ffb9fad632f195 100755 (executable)
@@ -650,21 +650,12 @@ _git_branch ()
 
 _git_bundle ()
 {
-       local mycword="$COMP_CWORD"
-       case "${COMP_WORDS[0]}" in
-       git)
-               local cmd="${COMP_WORDS[2]}"
-               mycword="$((mycword-1))"
-               ;;
-       git-bundle*)
-               local cmd="${COMP_WORDS[1]}"
-               ;;
-       esac
-       case "$mycword" in
-       1)
+       local cmd="${COMP_WORDS[2]}"
+       case "$COMP_CWORD" in
+       2)
                __gitcomp "create list-heads verify unbundle"
                ;;
-       2)
+       3)
                # looking for a file
                ;;
        *)
@@ -812,12 +803,7 @@ _git_fetch ()
                        __gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
                        ;;
                *)
-                       local remote
-                       case "${COMP_WORDS[0]}" in
-                       git-fetch) remote="${COMP_WORDS[1]}" ;;
-                       git)       remote="${COMP_WORDS[2]}" ;;
-                       esac
-                       __gitcomp "$(__git_refs2 "$remote")"
+                       __gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
                        ;;
                esac
        fi
@@ -1060,12 +1046,7 @@ _git_pull ()
        if [ "$COMP_CWORD" = 2 ]; then
                __gitcomp "$(__git_remotes)"
        else
-               local remote
-               case "${COMP_WORDS[0]}" in
-               git-pull)  remote="${COMP_WORDS[1]}" ;;
-               git)       remote="${COMP_WORDS[2]}" ;;
-               esac
-               __gitcomp "$(__git_refs "$remote")"
+               __gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
        fi
 }
 
@@ -1078,19 +1059,13 @@ _git_push ()
        else
                case "$cur" in
                *:*)
-                       local remote
-                       case "${COMP_WORDS[0]}" in
-                       git-push)  remote="${COMP_WORDS[1]}" ;;
-                       git)       remote="${COMP_WORDS[2]}" ;;
-                       esac
-
                        local pfx=""
                        case "$COMP_WORDBREAKS" in
                        *:*) : great ;;
                        *)   pfx="${cur%%:*}:" ;;
                        esac
 
-                       __gitcomp "$(__git_refs "$remote")" "$pfx" "${cur#*:}"
+                       __gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
                        ;;
                +*)
                        __gitcomp "$(__git_refs)" + "${cur#+}"
@@ -1369,7 +1344,7 @@ _git_revert ()
                return
                ;;
        esac
-       COMPREPLY=()
+       __gitcomp "$(__git_refs)"
 }
 
 _git_rm ()
@@ -1591,7 +1566,7 @@ _git_tag ()
        -m|-F)
                COMPREPLY=()
                ;;
-       -*|tag|git-tag)
+       -*|tag)
                if [ $f = 1 ]; then
                        __gitcomp "$(__git_tags)"
                else
index 46136d49bf99f61a5c85a548bec055742ed140f8..2b122d3f5159d9a8206e16be9db7aca7dfe89bb6 100755 (executable)
@@ -963,7 +963,7 @@ class P4Sync(Command):
             if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'):
                 text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text)
             elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'):
-                text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text)
+                text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text)
 
             contents[stat['depotFile']] = text
 
diff --git a/date.c b/date.c
index 35a52576c53e5e1406d40ed4402b8834a29b9f0e..950b88fdcf74f550a582684f1702ffb58c62c7f9 100644 (file)
--- a/date.c
+++ b/date.c
@@ -402,6 +402,15 @@ static int match_multi_number(unsigned long num, char c, const char *date, char
        return end - date;
 }
 
+/* Have we filled in any part of the time/date yet? */
+static inline int nodate(struct tm *tm)
+{
+       return tm->tm_year < 0 &&
+               tm->tm_mon < 0 &&
+               tm->tm_mday < 0 &&
+               !(tm->tm_hour | tm->tm_min | tm->tm_sec);
+}
+
 /*
  * We've seen a digit. Time? Year? Date?
  */
@@ -418,7 +427,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
         * more than 8 digits. This is because we don't want to rule out
         * numbers like 20070606 as a YYYYMMDD date.
         */
-       if (num >= 100000000) {
+       if (num >= 100000000 && nodate(tm)) {
                time_t time = num;
                if (gmtime_r(&time, tm)) {
                        *tm_gmt = 1;
@@ -462,6 +471,13 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
                return n;
        }
 
+       /*
+        * Ignore lots of numerals. We took care of 4-digit years above.
+        * Days or months must be one or two digits.
+        */
+       if (n > 2)
+               return n;
+
        /*
         * NOTE! We will give precedence to day-of-month over month or
         * year numbers in the 1-12 range. So 05 is always "mday 5",
@@ -488,10 +504,6 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
 
        if (num > 0 && num < 32) {
                tm->tm_mday = num;
-       } else if (num > 1900) {
-               tm->tm_year = num - 1900;
-       } else if (num > 70) {
-               tm->tm_year = num;
        } else if (num > 0 && num < 13) {
                tm->tm_mon = num-1;
        }
@@ -823,7 +835,9 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num)
                }
        }
 
-       *num = number;
+       /* Accept zero-padding only for small numbers ("Dec 02", never "Dec 0002") */
+       if (date[0] != '0' || end - date <= 2)
+               *num = number;
        return end;
 }
 
index a2913c2a2cd1ec158157ada3e2deb666892b734b..75c68d948fd3105272f893ff2f901007519f62f5 100755 (executable)
@@ -14,7 +14,7 @@ sort |
 while read cmd
 do
      sed -n '
-     /NAME/,/git-'"$cmd"'/H
+     /^NAME/,/git-'"$cmd"'/H
      ${
             x
             s/.*git-'"$cmd"' - \(.*\)/  {"'"$cmd"'", "\1"},/
index d39eb6cea6174ac65f1cc13c98e4abeab3a90903..458a497af810c7bb188a5aafb80c32aa0bc05264 100755 (executable)
@@ -71,19 +71,17 @@ case ",$all_into_one," in
                                existing="$existing $e"
                        fi
                done
-       fi
-       if test -z "$args"
-       then
-               args='--unpacked --incremental'
-       elif test -n "$unpack_unreachable"
-       then
-               args="$args $unpack_unreachable"
+               if test -n "$args" -a -n "$unpack_unreachable" -a \
+                       -n "$remove_redundant"
+               then
+                       args="$args $unpack_unreachable"
+               fi
        fi
        ;;
 esac
 
 args="$args $local $quiet $no_reuse$extra"
-names=$(git pack-objects --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
        exit 1
 if [ -z "$names" ]; then
        if test -z "$quiet"; then
index 073a314c8043e0ff30afde65e012e356ff0d186f..a2cf5b82150a77fd9ddb775fea1bc8d5e8ee7392 100755 (executable)
@@ -4,9 +4,9 @@
 # This file is licensed under the GPL v2, or a later version
 # at the discretion of Linus Torvalds.
 
-USAGE='<commit> <url> [<head>]'
-LONG_USAGE='Summarizes the changes since <commit> to the standard output,
-and includes <url> in the message generated.'
+USAGE='<start> <url> [<end>]'
+LONG_USAGE='Summarizes the changes between two commits to the standard output,
+and includes the given URL in the generated summary.'
 SUBDIRECTORY_OK='Yes'
 OPTIONS_SPEC=
 . git-sh-setup
index 967f483f783693eff4fd4e252dae7a0cc8b12ada..525d138e90c524d08ef3d9755f1a2486c34adc39 100644 (file)
@@ -1239,6 +1239,11 @@ int read_index_from(struct index_state *istate, const char *path)
        die("index file corrupt");
 }
 
+int is_index_unborn(struct index_state *istate)
+{
+       return (!istate->cache_nr && !istate->alloc && !istate->timestamp);
+}
+
 int discard_index(struct index_state *istate)
 {
        istate->cache_nr = 0;
index 7688f3b04d197007bce64a2bcc54c0b62c0b5922..91f1b7cd81f5461b13c2553bf3dd3e4b5c76ab14 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -298,6 +298,17 @@ static void read_branches_file(struct remote *remote)
        }
        add_url_alias(remote, p);
        add_fetch_refspec(remote, strbuf_detach(&branch, 0));
+       /*
+        * Cogito compatible push: push current HEAD to remote #branch
+        * (master if missing)
+        */
+       strbuf_init(&branch, 0);
+       strbuf_addstr(&branch, "HEAD");
+       if (frag)
+               strbuf_addf(&branch, ":refs/heads/%s", frag);
+       else
+               strbuf_addstr(&branch, ":refs/heads/master");
+       add_push_refspec(remote, strbuf_detach(&branch, 0));
        remote->fetch_tags = 1; /* always auto-follow */
 }
 
index 270294af8321c0b81f720db0f36e8f7f9eddbc88..45fd7a366055d254529c53b21a06c6340427fa49 100644 (file)
@@ -968,7 +968,7 @@ static void add_ignore_packed(struct rev_info *revs, const char *name)
        int num = ++revs->num_ignore_packed;
 
        revs->ignore_packed = xrealloc(revs->ignore_packed,
-                                      sizeof(const char **) * (num + 1));
+                                      sizeof(const char *) * (num + 1));
        revs->ignore_packed[num-1] = name;
        revs->ignore_packed[num] = NULL;
 }
index 12fc767ee57103739e568a959981ca559417ecf4..c35469d488596bd1279c06bc391d744565f35e59 100644 (file)
@@ -410,23 +410,30 @@ void prepare_alt_odb(void)
        read_info_alternates(get_object_directory(), 0);
 }
 
-static int has_loose_object(const unsigned char *sha1)
+static int has_loose_object_local(const unsigned char *sha1)
 {
        char *name = sha1_file_name(sha1);
-       struct alternate_object_database *alt;
+       return !access(name, F_OK);
+}
 
-       if (!access(name, F_OK))
-               return 1;
+int has_loose_object_nonlocal(const unsigned char *sha1)
+{
+       struct alternate_object_database *alt;
        prepare_alt_odb();
        for (alt = alt_odb_list; alt; alt = alt->next) {
-               name = alt->name;
-               fill_sha1_path(name, sha1);
+               fill_sha1_path(alt->name, sha1);
                if (!access(alt->base, F_OK))
                        return 1;
        }
        return 0;
 }
 
+static int has_loose_object(const unsigned char *sha1)
+{
+       return has_loose_object_local(sha1) ||
+              has_loose_object_nonlocal(sha1);
+}
+
 static unsigned int pack_used_ctr;
 static unsigned int pack_mmap_calls;
 static unsigned int peak_pack_open_windows;
@@ -828,6 +835,11 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
                return NULL;
        }
        memcpy(p->pack_name, path, path_len);
+
+       strcpy(p->pack_name + path_len, ".keep");
+       if (!access(p->pack_name, F_OK))
+               p->pack_keep = 1;
+
        strcpy(p->pack_name + path_len, ".pack");
        if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
                free(p);
@@ -2220,7 +2232,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
        memcpy(buffer, filename, dirlen);
        strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
        fd = mkstemp(buffer);
-       if (fd < 0 && dirlen) {
+       if (fd < 0 && dirlen && errno == ENOENT) {
                /* Make sure the directory exists */
                memcpy(buffer, filename, dirlen);
                buffer[dirlen-1] = 0;
@@ -2246,7 +2258,7 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
        filename = sha1_file_name(sha1);
        fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
        if (fd < 0) {
-               if (errno == EPERM)
+               if (errno == EACCES)
                        return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
                else
                        return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno));
index 637b4e19d52e81cf1472a4ed9dcfb0c9ff00da2b..22ef7d44b08ac7ec20e799a194e27205c794c290 100755 (executable)
@@ -43,6 +43,13 @@ test_expect_success 'GIT_EXTERNAL_DIFF environment should apply only to diff' '
 
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
+
+       GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff |
+       grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'diff attribute' '
 
        git config diff.parrot.command echo &&
@@ -68,6 +75,13 @@ test_expect_success 'diff attribute should apply only to diff' '
 
 '
 
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+       git diff --no-ext-diff |
+       grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'diff attribute' '
 
        git config --unset diff.parrot.command &&
@@ -94,6 +108,13 @@ test_expect_success 'diff attribute should apply only to diff' '
 
 '
 
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+       git diff --no-ext-diff |
+       grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'no diff with -diff' '
        echo >.gitattributes "file -diff" &&
        git diff | grep Binary
index 3a0ef8759c9d7a55b95c56ca38cd3c37ac2432fa..2852a0326546f50f0cbefb4d5621c889b52f33c9 100755 (executable)
@@ -375,4 +375,10 @@ test_expect_success 'index-pack with --strict' '
        )
 '
 
+test_expect_success 'tolerate absurdly small packsizelimit' '
+       git config pack.packSizeLimit 2 &&
+       packname_9=$(git pack-objects test-9 <obj-list) &&
+       test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
+'
+
 test_done
index 598664ce7fa1747436c0a66d13e464398cac5674..f9e878022a93657a8b8d81339670f4d910392755 100755 (executable)
@@ -494,4 +494,54 @@ test_expect_success 'allow deleting an invalid remote ref' '
 
 '
 
+test_expect_success 'fetch with branches' '
+       mk_empty &&
+       git branch second $the_first_commit &&
+       git checkout second &&
+       echo ".." > testrepo/.git/branches/branch1 &&
+       (cd testrepo &&
+               git fetch branch1 &&
+               r=$(git show-ref -s --verify refs/heads/branch1) &&
+               test "z$r" = "z$the_commit" &&
+               test 1 = $(git for-each-ref refs/heads | wc -l)
+       ) &&
+       git checkout master
+'
+
+test_expect_success 'fetch with branches containing #' '
+       mk_empty &&
+       echo "..#second" > testrepo/.git/branches/branch2 &&
+       (cd testrepo &&
+               git fetch branch2 &&
+               r=$(git show-ref -s --verify refs/heads/branch2) &&
+               test "z$r" = "z$the_first_commit" &&
+               test 1 = $(git for-each-ref refs/heads | wc -l)
+       ) &&
+       git checkout master
+'
+
+test_expect_success 'push with branches' '
+       mk_empty &&
+       git checkout second &&
+       echo "testrepo" > .git/branches/branch1 &&
+       git push branch1 &&
+       (cd testrepo &&
+               r=$(git show-ref -s --verify refs/heads/master) &&
+               test "z$r" = "z$the_first_commit" &&
+               test 1 = $(git for-each-ref refs/heads | wc -l)
+       )
+'
+
+test_expect_success 'push with branches containing #' '
+       mk_empty &&
+       echo "testrepo#branch3" > .git/branches/branch2 &&
+       git push branch2 &&
+       (cd testrepo &&
+               r=$(git show-ref -s --verify refs/heads/branch3) &&
+               test "z$r" = "z$the_first_commit" &&
+               test 1 = $(git for-each-ref refs/heads | wc -l)
+       ) &&
+       git checkout master
+'
+
 test_done
index 33cde705953acc9a30d8535da77fe0f90e2b3118..c616deb0d0315acc41da93a81145494bc9f455c1 100755 (executable)
@@ -1090,4 +1090,15 @@ test_expect_success 'filename for the message is relative to cwd' '
        git cat-file tag tag-from-subdir-2 | grep "in sub directory"
 '
 
+# mixing modes and options:
+
+test_expect_success 'mixing incompatibles modes and options is forbidden' '
+       test_must_fail git tag -a
+       test_must_fail git tag -l -v
+       test_must_fail git tag -n 100
+       test_must_fail git tag -l -m msg
+       test_must_fail git tag -l -F some file
+       test_must_fail git tag -v -s
+'
+
 test_done
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
new file mode 100755 (executable)
index 0000000..3f602ea
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='git repack works correctly'
+
+. ./test-lib.sh
+
+test_expect_success 'objects in packs marked .keep are not repacked' '
+       echo content1 > file1 &&
+       echo content2 > file2 &&
+       git add . &&
+       git commit -m initial_commit &&
+       # Create two packs
+       # The first pack will contain all of the objects except one
+       git rev-list --objects --all | grep -v file2 |
+               git pack-objects pack > /dev/null &&
+       # The second pack will contain the excluded object
+       packsha1=$(git rev-list --objects --all | grep file2 |
+               git pack-objects pack) &&
+       touch -r pack-$packsha1.pack pack-$packsha1.keep &&
+       objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
+               sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
+       mv pack-* .git/objects/pack/ &&
+       git repack -A -d -l &&
+       git prune-packed &&
+       for p in .git/objects/pack/*.idx; do
+               idx=$(basename $p)
+               test "pack-$packsha1.idx" = "$idx" && continue
+               if git verify-pack -v $p | egrep "^$objsha1"; then
+                       found_duplicate_object=1
+                       echo "DUPLICATE OBJECT FOUND"
+                       break
+               fi
+       done &&
+       test -z "$found_duplicate_object"
+'
+
+test_expect_success 'loose objects in alternate ODB are not repacked' '
+       mkdir alt_objects &&
+       echo `pwd`/alt_objects > .git/objects/info/alternates &&
+       echo content3 > file3 &&
+       objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
+       git add file3 &&
+       git commit -m commit_file3 &&
+       git repack -a -d -l &&
+       git prune-packed &&
+       for p in .git/objects/pack/*.idx; do
+               if git verify-pack -v $p | egrep "^$objsha1"; then
+                       found_duplicate_object=1
+                       echo "DUPLICATE OBJECT FOUND"
+                       break
+               fi
+       done &&
+       test -z "$found_duplicate_object"
+'
+
+test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
+       mkdir alt_objects/pack
+       mv .git/objects/pack/* alt_objects/pack &&
+       git repack -a &&
+       myidx=$(ls -1 .git/objects/pack/*.idx) &&
+       test -f "$myidx" &&
+       for p in alt_objects/pack/*.idx; do
+               git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+       done | while read sha1 rest; do
+               if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+                       echo "Missing object in local pack: $sha1"
+                       return 1
+               fi
+       done
+'
+
+test_done
+
index 531dac060a761f3383b3bee15444345a66e2f13b..9813f113a2deebceec34a3e5f73ca2bd352deab1 100755 (executable)
@@ -8,7 +8,7 @@ fsha1=
 csha1=
 tsha1=
 
-test_expect_success '-A option leaves unreachable objects unpacked' '
+test_expect_success '-A with -d option leaves unreachable objects unpacked' '
        echo content > file1 &&
        git add . &&
        git commit -m initial_commit &&
@@ -58,7 +58,7 @@ compare_mtimes ()
                ' -- "$@"
 }
 
-test_expect_success 'unpacked objects receive timestamp of pack file' '
+test_expect_success '-A without -d option leaves unreachable objects packed' '
        fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
        fsha1path=".git/objects/$fsha1path" &&
        csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
@@ -75,7 +75,19 @@ test_expect_success 'unpacked objects receive timestamp of pack file' '
        git branch -D transient_branch &&
        sleep 1 &&
        git repack -A -l &&
-       compare_mtimes "$packfile" "$fsha1path" "$csha1path" "$tsha1path"
+       test ! -f "$fsha1path" &&
+       test ! -f "$csha1path" &&
+       test ! -f "$tsha1path" &&
+       git show $fsha1 &&
+       git show $csha1 &&
+       git show $tsha1
+'
+
+test_expect_success 'unpacked objects receive timestamp of pack file' '
+       tmppack=".git/objects/pack/tmp_pack" &&
+       ln "$packfile" "$tmppack" &&
+       git repack -A -l -d &&
+       compare_mtimes "$tmppack" "$fsha1path" "$csha1path" "$tsha1path"
 '
 
 test_done
index c19b4a2bab586b21da43c7a838ba85626f913568..638c858dc7b640fdff4af5902ed79c95e9d9d040 100755 (executable)
@@ -231,4 +231,12 @@ test_expect_success 'fast-export -C -C | fast-import' '
 
 '
 
+test_expect_success 'fast-export | fast-import when master is tagged' '
+
+       git tag -m msg last &&
+       git fast-export -C -C --signed-tags=strip --all > output &&
+       test $(grep -c "^tag " output) = 3
+
+'
+
 test_done
index e87ab57c652b56b1a684e2a0a56885c1d1b27ef7..a43aa72cd088af07b13a6bc8de304ecc178047e5 100644 (file)
 #include "xinclude.h"
 
 
-
 #define XDL_KPDIS_RUN 4
 #define XDL_MAX_EQLIMIT 1024
-
+#define XDL_SIMSCAN_WINDOW 100
 
 
 typedef struct s_xdlclass {
@@ -312,6 +311,18 @@ void xdl_free_env(xdfenv_t *xe) {
 static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
        long r, rdis0, rpdis0, rdis1, rpdis1;
 
+       /*
+        * Limits the window the is examined during the similar-lines
+        * scan. The loops below stops when dis[i - r] == 1 (line that
+        * has no match), but there are corner cases where the loop
+        * proceed all the way to the extremities by causing huge
+        * performance penalties in case of big files.
+        */
+       if (i - s > XDL_SIMSCAN_WINDOW)
+               s = i - XDL_SIMSCAN_WINDOW;
+       if (e - i > XDL_SIMSCAN_WINDOW)
+               e = i + XDL_SIMSCAN_WINDOW;
+
        /*
         * Scans the lines before 'i' to find a run of lines that either
         * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).