Code

Merge branch 'gb/idx'
authorJunio C Hamano <gitster@pobox.com>
Wed, 6 Jun 2007 04:36:51 +0000 (21:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Jun 2007 04:36:51 +0000 (21:36 -0700)
* gb/idx:
  Unify write_index_file functions

28 files changed:
.gitignore
Documentation/RelNotes-1.5.2.1.txt [new file with mode: 0644]
Documentation/RelNotes-1.5.3.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/cmd-list.perl
Documentation/git-am.txt
Documentation/git-applymbox.txt [deleted file]
Documentation/git-applypatch.txt [deleted file]
Documentation/git-fsck.txt
Documentation/git-mailinfo.txt
Documentation/git-submodule.txt [new file with mode: 0644]
Documentation/hooks.txt
Makefile
RelNotes
builtin-apply.c
builtin-fsck.c
diff.c
git-applymbox.sh [deleted file]
git-applypatch.sh [deleted file]
git-submodule.sh [new file with mode: 0755]
gitweb/gitweb.perl
grep.c
merge-recursive.c
t/t6024-recursive-merge.sh
t/t7400-submodule-basic.sh [new file with mode: 0755]
t/t9500-gitweb-standalone-no-errors.sh
xdiff-interface.c
xdiff-interface.h

index 4dc0c395fa7d6e7cff7588ee66c928c954cc014d..8e75c99d6f5e78965977f9734619689b1838ff52 100644 (file)
@@ -7,8 +7,6 @@ git-add--interactive
 git-am
 git-annotate
 git-apply
-git-applymbox
-git-applypatch
 git-archimport
 git-archive
 git-bisect
@@ -126,6 +124,7 @@ git-ssh-push
 git-ssh-upload
 git-status
 git-stripspace
+git-submodule
 git-svn
 git-svnimport
 git-symbolic-ref
@@ -152,6 +151,7 @@ test-delta
 test-dump-cache-tree
 test-genrandom
 test-match-trees
+test-sha1
 common-cmds.h
 *.tar.gz
 *.dsc
diff --git a/Documentation/RelNotes-1.5.2.1.txt b/Documentation/RelNotes-1.5.2.1.txt
new file mode 100644 (file)
index 0000000..ebf20e2
--- /dev/null
@@ -0,0 +1,53 @@
+GIT v1.5.2.1 Release Notes
+==========================
+
+Fixes since v1.5.2
+------------------
+
+* Bugfixes
+
+  - Temporary files that are used when invoking external diff
+    programs did not tolerate a long TMPDIR.
+
+  - git-daemon did not notice when it could not write into its
+    pid file.
+
+  - git-status did not honor core.excludesFile configuration like
+    git-add did.
+
+  - git-annotate did not work from a subdirectory while
+    git-blame did.
+
+  - git-cvsserver should have disabled access to a repository
+    with "gitcvs.pserver.enabled = false" set even when
+    "gitcvs.enabled = true" was set at the same time.  It
+    didn't.
+
+  - git-cvsimport did not work correctly in a repository with
+    its branch heads were packed with pack-refs.
+
+  - ident unexpansion to squash "$Id: xxx $" that is in the
+    repository copy removed incorrect number of bytes.
+
+  - git-svn misbehaved when the subversion repository did not
+    provide MD5 checksums for files.
+
+  - git rebase (and git am) misbehaved on commits that have '\n'
+    (literally backslash and en, not a linefeed) in the title.
+
+  - code to decode base85 used in binary patches had one error
+    return codepath wrong.
+
+  - RFC2047 Q encoding output by git-format-patch used '_' for a
+    space, which is not understood by some programs.  It uses =20
+    which is safer.
+
+  - git-fastimport --import-marks was broken; fixed.
+
+  - A lot of documentation updates, clarifications and fixes.
+
+--
+exec >/var/tmp/1
+O=v1.5.2-65-g996e2d6
+echo O=`git describe refs/heads/maint`
+git shortlog --no-merges $O..refs/heads/maint
diff --git a/Documentation/RelNotes-1.5.3.txt b/Documentation/RelNotes-1.5.3.txt
new file mode 100644 (file)
index 0000000..d111661
--- /dev/null
@@ -0,0 +1,109 @@
+GIT v1.5.3 Release Notes (draft)
+========================
+
+Updates since v1.5.2
+--------------------
+
+* An initial interation of Porcelain level superproject support
+  started to take shape.
+
+* Thee are a handful pack-objects changes to help you cope better with
+  repositories with pathologically large blobs in them.
+
+* New commands and options.
+
+  - "git-submodule" command helps you manage the projects from
+    the superproject that contain them.
+
+  - In addition to core.compression configuration option,
+    core.loosecompression and pack.compression options can
+    independently tweak zlib compression levels used for loose
+    and packed objects.
+
+  - "git-ls-tree -l" shows size of blobs pointed at by the
+    tree entries, similar to "/bin/ls -l".
+
+  - "git-rev-list" learned --regexp-ignore-case and
+    --extended-regexp options to tweak its matching logic used
+    for --grep fitering.
+
+  - "git-describe --contains" is a handier way to call more
+    obscure command "git-name-rev --tags".
+
+  - "git gc --aggressive" tells the command to spend more cycles
+    to optimize the repository harder.
+
+  - "git repack" can be told to split resulting packs to avoid
+    exceeding limit specified with "--max-pack-size".
+
+* Updated behavior of existing commands.
+
+  - "git push" pretends that you immediately fetched back from
+    the remote by updating corresponding remote tracking
+    branches if you have any.
+
+  - The diffstat given after a merge (or a pull) honors the
+    color.diff configuration.
+
+  - "git-apply --whitespace=strip" removes blank lines added at
+    the end of the file.
+
+  - fetch over git native protocols with -v shows connection
+    status, and the IP address of the other end, to help
+    diagnosing problems.
+
+  - core.legacyheaders is no more, although we still can read
+    objects created in a new loose object format.
+
+  - "git-mailsplit" (hence "git-am") can read from Maildir
+    formatted mailboxes.
+
+  - "git cvsserver" does not barf upon seeing "cvs login"
+    request.
+
+  - "pack-objects" honors "delta" attribute set in
+    .gitattributes.  It does not attempt to deltify blobs that
+    come from paths with delta attribute set to false.
+
+  - new-workdir script (in contrib) can now be used with a bare
+    repository.
+
+
+* Builds
+
+  -
+
+* Performance Tweaks
+
+  - git-pack-objects avoids re-deltification cost by caching
+    small enough delta results it creates while looking for the
+    best delta candidates.
+
+  - diff-delta code that is used for packing has been improved
+    to work better on big files.
+
+  - when there are more than one pack files in the repository,
+    the runtime used to try finding an object always from the
+    newest packfile; it now tries the same packfile as we found
+    the object requested the last time, which exploits the
+    locality of references.
+
+Fixes since v1.5.2
+------------------
+
+All of the fixes in v1.5.2 maintenance series are included in
+this release, unless otherwise noted.
+
+* Bugfixes
+
+  - ....  This has not
+    been backported to 1.5.2.x series, as it is rather an
+    intrusive change.
+
+
+--
+exec >/var/tmp/1
+O=v1.5.2-45-ged82edc
+O=v1.5.2-172-g1a8b769
+echo O=`git describe refs/heads/master`
+git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
index b94d9a816664333e0b1767c22d1639b8839cee24..b9baa1d3b4685859d6ad3530a64865cc054df7a3 100644 (file)
@@ -14,6 +14,8 @@ Checklist (and a short version for the impatient):
          commit message (or just use the option "-s" when
          committing) to confirm that you agree to the Developer's
          Certificate of Origin
+       - make sure that you have tests for the bug you are fixing
+       - make sure that the test suite passes after your commit
 
        Patch:
 
@@ -33,6 +35,8 @@ Checklist (and a short version for the impatient):
        - if you change, add, or remove a command line option or
          make some other user interface change, the associated
          documentation should be updated as well.
+       - if your name is not writable in ASCII, make sure that
+         you send off a message in the correct encoding.
 
 Long version:
 
@@ -239,7 +243,7 @@ One test you could do yourself if your MUA is set up correctly is:
     $ git fetch http://kernel.org/pub/scm/git/git.git master:test-apply
     $ git checkout test-apply
     $ git reset --hard
-    $ git applymbox a.patch
+    $ git am a.patch
 
 If it does not apply correctly, there can be various reasons.
 
@@ -247,7 +251,7 @@ If it does not apply correctly, there can be various reasons.
   does not have much to do with your MUA.  Please rebase the
   patch appropriately.
 
-* Your MUA corrupted your patch; applymbox would complain that
+* Your MUA corrupted your patch; "am" would complain that
   the patch does not apply.  Look at .dotest/ subdirectory and
   see what 'patch' file contains and check for the common
   corruption patterns mentioned above.
index 443802a9a3e4982c33f831217602ea600f0f2775..a181f753e0fefdeb036a826b8c0d0a5b54d0ae25 100755 (executable)
@@ -72,8 +72,6 @@ __DATA__
 git-add                                 mainporcelain
 git-am                                  mainporcelain
 git-annotate                            ancillaryinterrogators
-git-applymbox                           ancillaryinterrogators
-git-applypatch                          purehelpers
 git-apply                               plumbingmanipulators
 git-archimport                          foreignscminterface
 git-archive                             mainporcelain
@@ -180,6 +178,7 @@ git-ssh-fetch                           synchingrepositories
 git-ssh-upload                          synchingrepositories
 git-status                              mainporcelain
 git-stripspace                          purehelpers
+git-submodule                           mainporcelain
 git-svn                                 foreignscminterface
 git-svnimport                           foreignscminterface
 git-symbolic-ref                        plumbingmanipulators
index f78e5dc28d7a641a2c6db93ba74d95e45d175dd0..f3387f5d09959c1e94cb2e140d5ccc617b45ebb1 100644 (file)
@@ -127,8 +127,7 @@ is terminated before the first occurrence of such a line.
 
 When initially invoking it, you give it names of the mailboxes
 to crunch.  Upon seeing the first patch that does not apply, it
-aborts in the middle, just like 'git-applymbox' does.  You can
-recover from this in one of two ways:
+aborts in the middle,.  You can recover from this in one of two ways:
 
 . skip the current patch by re-running the command with '--skip'
   option.
@@ -145,7 +144,7 @@ names.
 
 SEE ALSO
 --------
-gitlink:git-applymbox[1], gitlink:git-applypatch[1], gitlink:git-apply[1].
+gitlink:git-apply[1].
 
 
 Author
diff --git a/Documentation/git-applymbox.txt b/Documentation/git-applymbox.txt
deleted file mode 100644 (file)
index ea919ba..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-git-applymbox(1)
-================
-
-NAME
-----
-git-applymbox - Apply a series of patches in a mailbox
-
-
-SYNOPSIS
---------
-'git-applymbox' [-u] [-k] [-q] [-m] ( -c .dotest/<num> | <mbox> ) [ <signoff> ]
-
-DESCRIPTION
------------
-Splits mail messages in a mailbox into commit log message,
-authorship information and patches, and applies them to the
-current branch.
-
-
-OPTIONS
--------
--q::
-       Apply patches interactively.  The user will be given
-       opportunity to edit the log message and the patch before
-       attempting to apply it.
-
--k::
-       Usually the program 'cleans up' the Subject: header line
-       to extract the title line for the commit log message,
-       among which (1) remove 'Re:' or 're:', (2) leading
-       whitespaces, (3) '[' up to ']', typically '[PATCH]', and
-       then prepends "[PATCH] ".  This flag forbids this
-       munging, and is most useful when used to read back 'git
-       format-patch -k' output.
-
--m::
-       Patches are applied with `git-apply` command, and unless
-       it cleanly applies without fuzz, the processing fails.
-       With this flag, if a tree that the patch applies cleanly
-       is found in a repository, the patch is applied to the
-       tree and then a 3-way merge between the resulting tree
-       and the current tree.
-
--u::
-       Pass `-u` flag to `git-mailinfo` (see gitlink:git-mailinfo[1]).
-       The proposed commit log message taken from the e-mail
-       are re-coded into UTF-8 encoding (configuration variable
-       `i18n.commitencoding` can be used to specify project's
-       preferred encoding if it is not UTF-8).  This used to be
-       optional but now it is the default.
-+
-Note that the patch is always used as-is without charset
-conversion, even with this flag.
-
--n::
-       Pass `-n` flag to `git-mailinfo` (see
-       gitlink:git-mailinfo[1]).
-
--c .dotest/<num>::
-       When the patch contained in an e-mail does not cleanly
-       apply, the command exits with an error message. The
-       patch and extracted message are found in .dotest/, and
-       you could re-run 'git applymbox' with '-c .dotest/<num>'
-       flag to restart the process after inspecting and fixing
-       them.
-
-<mbox>::
-       The name of the file that contains the e-mail messages
-       with patches.  This file should be in the UNIX mailbox
-       format.  See 'SubmittingPatches' document to learn about
-       the formatting convention for e-mail submission.
-
-<signoff>::
-       The name of the file that contains your "Signed-off-by"
-       line.  See 'SubmittingPatches' document to learn what
-       "Signed-off-by" line means.  You can also just say
-       'yes', 'true', 'me', or 'please' to use an automatically
-       generated "Signed-off-by" line based on your committer
-       identity.
-
-
-SEE ALSO
---------
-gitlink:git-am[1], gitlink:git-applypatch[1].
-
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
diff --git a/Documentation/git-applypatch.txt b/Documentation/git-applypatch.txt
deleted file mode 100644 (file)
index 451434a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-git-applypatch(1)
-=================
-
-NAME
-----
-git-applypatch - Apply one patch extracted from an e-mail
-
-
-SYNOPSIS
---------
-'git-applypatch' <msg> <patch> <info> [<signoff>]
-
-DESCRIPTION
------------
-This is usually not what an end user wants to run directly.  See
-gitlink:git-am[1] instead.
-
-Takes three files <msg>, <patch>, and <info> prepared from an
-e-mail message by 'git-mailinfo', and creates a commit.  It is
-usually not necessary to use this command directly.
-
-This command can run `applypatch-msg`, `pre-applypatch`, and
-`post-applypatch` hooks.  See link:hooks.html[hooks] for more
-information.
-
-
-OPTIONS
--------
-<msg>::
-       Commit log message (sans the first line, which comes
-       from e-mail Subject stored in <info>).
-
-<patch>::
-       The patch to apply.
-
-<info>::
-       Author and subject information extracted from e-mail,
-       used on "author" line and as the first line of the
-       commit log message.
-
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
index 8c68cf037259b3abc7ea16952d232b2fb2f07a25..ed6413a3c75625ea63a5ea140ae15b120997c9b4 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git-fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
-                [--full] [--strict] [<object>*]
+                [--full] [--strict] [--verbose] [<object>*]
 
 DESCRIPTION
 -----------
@@ -61,6 +61,9 @@ index file and all SHA1 references in .git/refs/* as heads.
        objects that triggers this check, but it is recommended
        to check new projects with this flag.
 
+--verbose::
+       Be chatty.
+
 It tests SHA1 and general object sanity, and it does full tracking of
 the resulting reachability and everything else. It prints out any
 corruption it finds (missing or bad objects), and if you use the
index 8eadcebfcf5c26c599cde0d939d1046de69f2335..16956951dd122698f7602b78c91be999348b61e4 100644 (file)
@@ -16,7 +16,7 @@ DESCRIPTION
 Reading a single e-mail message from the standard input, and
 writes the commit log message in <msg> file, and the patches in
 <patch> file.  The author name, e-mail and e-mail subject are
-written out to the standard output to be used by git-applypatch
+written out to the standard output to be used by git-am
 to create a commit.  It is usually not necessary to use this
 command directly.  See gitlink:git-am[1] instead.
 
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
new file mode 100644 (file)
index 0000000..cb0424f
--- /dev/null
@@ -0,0 +1,65 @@
+git-submodule(1)
+================
+
+NAME
+----
+git-submodule - Initialize, update or inspect submodules
+
+
+SYNOPSIS
+--------
+'git-submodule' [--quiet] [--cached] [status|init|update] [--] [<path>...]
+
+
+COMMANDS
+--------
+status::
+       Show the status of the submodules. This will print the SHA-1 of the
+       currently checked out commit for each submodule, along with the
+       submodule path and the output of gitlink:git-describe[1] for the
+       SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
+       initialized and `+` if the currently checked out submodule commit
+       does not match the SHA-1 found in the index of the containing
+       repository. This command is the default command for git-submodule.
+
+init::
+       Initialize the submodules, i.e. clone the git repositories specified
+       in the .gitmodules file and checkout the submodule commits specified
+       in the index of the containing repository. This will make the
+       submodules HEAD be detached.
+
+update::
+       Update the initialized submodules, i.e. checkout the submodule commits
+       specified in the index of the containing repository. This will make
+       the submodules HEAD be detached.
+
+
+OPTIONS
+-------
+-q, --quiet::
+       Only print error messages.
+
+--cached::
+       Display the SHA-1 stored in the index, not the SHA-1 of the currently
+       checked out submodule commit. This option is only valid for the
+       status command.
+
+<path>::
+       Path to submodule(s). When specified this will restrict the command
+       to only operate on the submodules found at the specified paths.
+
+FILES
+-----
+When cloning submodules, a .gitmodules file in the top-level directory
+of the containing repository is used to find the url of each submodule.
+This file should be formatted in the same way as $GIR_DIR/config. The key
+to each submodule url is "module.$path.url".
+
+
+AUTHOR
+------
+Written by Lars Hjemli <hjemli@gmail.com>
+
+GIT
+---
+Part of the gitlink:git[7] suite
index aabb9750fddbc28091c46780ccf7b835b62b04c7..6836477ca816a6caa860960c3456cfbbf5cd32f1 100644 (file)
@@ -12,11 +12,10 @@ This document describes the currently defined hooks.
 applypatch-msg
 --------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-applymbox`.  It takes a single
+This hook is invoked by `git-am` script.  It takes a single
 parameter, the name of the file that holds the proposed commit
 log message.  Exiting with non-zero status causes
-`git-applypatch` to abort before applying the patch.
+`git-am` to abort before applying the patch.
 
 The hook is allowed to edit the message file in place, and can
 be used to normalize the message into some project standard
@@ -29,8 +28,7 @@ The default 'applypatch-msg' hook, when enabled, runs the
 pre-applypatch
 --------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-applymbox`.  It takes no parameter,
+This hook is invoked by `git-am`.  It takes no parameter,
 and is invoked after the patch is applied, but before a commit
 is made.  Exiting with non-zero status causes the working tree
 after application of the patch not committed.
@@ -44,12 +42,11 @@ The default 'pre-applypatch' hook, when enabled, runs the
 post-applypatch
 ---------------
 
-This hook is invoked by `git-applypatch` script, which is
-typically invoked by `git-applymbox`.  It takes no parameter,
+This hook is invoked by `git-am`.  It takes no parameter,
 and is invoked after the patch is applied and a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-applypatch`.
+the outcome of `git-am`.
 
 pre-commit
 ----------
index cac0a4a2edc074d45d69665a68f23b9260847743..a11ff6054926a92e49939eb53ab342c90704b295 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -206,10 +206,10 @@ SCRIPT_SH = \
        git-repack.sh git-request-pull.sh git-reset.sh \
        git-sh-setup.sh \
        git-tag.sh git-verify-tag.sh \
-       git-applymbox.sh git-applypatch.sh git-am.sh \
+       git-am.sh \
        git-merge.sh git-merge-stupid.sh git-merge-octopus.sh \
        git-merge-resolve.sh git-merge-ours.sh \
-       git-lost-found.sh git-quiltimport.sh
+       git-lost-found.sh git-quiltimport.sh git-submodule.sh
 
 SCRIPT_PERL = \
        git-add--interactive.perl \
index c543b1d1eedf821fe1e8c31d902a719bfc6ffb20..0de5e663a2ba03a15eb6711079c6bff0cba023cb 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.5.2.txt
\ No newline at end of file
+Documentation/RelNotes-1.5.3.txt
\ No newline at end of file
index e71789803749b22a3ec041b2bce533957cea1c72..c6f736c14e4840bde2efd204e7f88a3556e9eed9 100644 (file)
@@ -55,7 +55,7 @@ static enum whitespace_eol {
 } new_whitespace = warn_on_whitespace;
 static int whitespace_error;
 static int squelch_whitespace_errors = 5;
-static int applied_after_stripping;
+static int applied_after_fixing_ws;
 static const char *patch_input_file;
 
 static void parse_whitespace_option(const char *option)
@@ -1657,7 +1657,7 @@ static int apply_line(char *output, const char *patch, int plen)
        if (add_nl_to_tail)
                output[plen++] = '\n';
        if (fixed)
-               applied_after_stripping++;
+               applied_after_fixing_ws++;
        return output + plen - buf;
 }
 
@@ -2884,18 +2884,17 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                                squelched == 1 ? "" : "s");
                }
                if (new_whitespace == error_on_whitespace)
-                       die("%d line%s add%s trailing whitespaces.",
+                       die("%d line%s add%s whitespace errors.",
                            whitespace_error,
                            whitespace_error == 1 ? "" : "s",
                            whitespace_error == 1 ? "s" : "");
-               if (applied_after_stripping)
+               if (applied_after_fixing_ws)
                        fprintf(stderr, "warning: %d line%s applied after"
-                               " stripping trailing whitespaces.\n",
-                               applied_after_stripping,
-                               applied_after_stripping == 1 ? "" : "s");
+                               " fixing whitespace errors.\n",
+                               applied_after_fixing_ws,
+                               applied_after_fixing_ws == 1 ? "" : "s");
                else if (whitespace_error)
-                       fprintf(stderr, "warning: %d line%s add%s trailing"
-                               " whitespaces.\n",
+                       fprintf(stderr, "warning: %d line%s add%s whitespace errors.\n",
                                whitespace_error,
                                whitespace_error == 1 ? "" : "s",
                                whitespace_error == 1 ? "s" : "");
index 9959818ceddf52ec24d9b24b0cade558f4d43070..bacae5dfa6e09602db59df256e5496f9f14e0d89 100644 (file)
@@ -20,6 +20,7 @@ static int check_strict;
 static int keep_cache_objects;
 static unsigned char head_sha1[20];
 static int errors_found;
+static int verbose;
 #define ERROR_OBJECT 01
 #define ERROR_REACHABLE 02
 
@@ -149,6 +150,9 @@ static void check_unreachable_object(struct object *obj)
 
 static void check_object(struct object *obj)
 {
+       if (verbose)
+               fprintf(stderr, "Checking %s\n", sha1_to_hex(obj->sha1));
+
        if (obj->flags & REACHABLE)
                check_reachable_object(obj);
        else
@@ -161,6 +165,9 @@ static void check_connectivity(void)
 
        /* Look up all the requirements, warn about missing objects.. */
        max = get_max_object_index();
+       if (verbose)
+               fprintf(stderr, "Checking connectivity (%d objects)\n", max);
+
        for (i = 0; i < max; i++) {
                struct object *obj = get_indexed_object(i);
 
@@ -229,6 +236,10 @@ static int fsck_tree(struct tree *item)
        const char *o_name;
        const unsigned char *o_sha1;
 
+       if (verbose)
+               fprintf(stderr, "Checking tree %s\n",
+                               sha1_to_hex(item->object.sha1));
+
        init_tree_desc(&desc, item->buffer, item->size);
 
        o_mode = 0;
@@ -317,6 +328,10 @@ static int fsck_commit(struct commit *commit)
        char *buffer = commit->buffer;
        unsigned char tree_sha1[20], sha1[20];
 
+       if (verbose)
+               fprintf(stderr, "Checking commit %s\n",
+                       sha1_to_hex(commit->object.sha1));
+
        if (memcmp(buffer, "tree ", 5))
                return objerror(&commit->object, "invalid format - expected 'tree' line");
        if (get_sha1_hex(buffer+5, tree_sha1) || buffer[45] != '\n')
@@ -345,6 +360,10 @@ static int fsck_tag(struct tag *tag)
 {
        struct object *tagged = tag->tagged;
 
+       if (verbose)
+               fprintf(stderr, "Checking tag %s\n",
+                       sha1_to_hex(tag->object.sha1));
+
        if (!tagged) {
                return objerror(&tag->object, "could not load tagged object");
        }
@@ -446,6 +465,9 @@ static void fsck_dir(int i, char *path)
        if (!dir)
                return;
 
+       if (verbose)
+               fprintf(stderr, "Checking directory %s\n", path);
+
        while ((de = readdir(dir)) != NULL) {
                char name[100];
                unsigned char sha1[20];
@@ -480,6 +502,10 @@ static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
 {
        struct object *obj;
 
+       if (verbose)
+               fprintf(stderr, "Checking reflog %s->%s\n",
+                       sha1_to_hex(osha1), sha1_to_hex(nsha1));
+
        if (!is_null_sha1(osha1)) {
                obj = lookup_object(osha1);
                if (obj) {
@@ -549,6 +575,10 @@ static void get_default_heads(void)
 static void fsck_object_dir(const char *path)
 {
        int i;
+
+       if (verbose)
+               fprintf(stderr, "Checking object directory\n");
+
        for (i = 0; i < 256; i++) {
                static char dir[4096];
                sprintf(dir, "%s/%02x", path, i);
@@ -564,6 +594,9 @@ static int fsck_head_link(void)
        int null_is_error = 0;
        const char *head_points_at = resolve_ref("HEAD", sha1, 0, &flag);
 
+       if (verbose)
+               fprintf(stderr, "Checking HEAD link\n");
+
        if (!head_points_at)
                return error("Invalid HEAD");
        if (!strcmp(head_points_at, "HEAD"))
@@ -586,6 +619,9 @@ static int fsck_cache_tree(struct cache_tree *it)
        int i;
        int err = 0;
 
+       if (verbose)
+               fprintf(stderr, "Checking cache tree\n");
+
        if (0 <= it->entry_count) {
                struct object *obj = parse_object(it->sha1);
                if (!obj) {
@@ -605,7 +641,7 @@ static int fsck_cache_tree(struct cache_tree *it)
 
 static const char fsck_usage[] =
 "git-fsck [--tags] [--root] [[--unreachable] [--cache] [--full] "
-"[--strict] <head-sha1>*]";
+"[--strict] [--verbose] <head-sha1>*]";
 
 int cmd_fsck(int argc, char **argv, const char *prefix)
 {
@@ -645,6 +681,10 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
                        check_strict = 1;
                        continue;
                }
+               if (!strcmp(arg, "--verbose")) {
+                       verbose = 1;
+                       continue;
+               }
                if (*arg == '-')
                        usage(fsck_usage);
        }
diff --git a/diff.c b/diff.c
index 508bc51ed59998be463fd429ee074654baaad76a..c57ac334141186d23f669bf71c897212a2b37c30 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1107,10 +1107,8 @@ static void setup_diff_attr_check(struct git_attr_check *check)
        check->attr = attr_diff;
 }
 
-#define FIRST_FEW_BYTES 8000
 static int file_is_binary(struct diff_filespec *one)
 {
-       unsigned long sz;
        struct git_attr_check attr_diff_check;
 
        setup_diff_attr_check(&attr_diff_check);
@@ -1127,10 +1125,7 @@ static int file_is_binary(struct diff_filespec *one)
                        return 0;
                diff_populate_filespec(one, 0);
        }
-       sz = one->size;
-       if (FIRST_FEW_BYTES < sz)
-               sz = FIRST_FEW_BYTES;
-       return !!memchr(one->data, 0, sz);
+       return buffer_is_binary(one->data, one->size);
 }
 
 static void builtin_diff(const char *name_a,
diff --git a/git-applymbox.sh b/git-applymbox.sh
deleted file mode 100755 (executable)
index c18e80f..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/bin/sh
-##
-## "dotest" is my stupid name for my patch-application script, which
-## I never got around to renaming after I tested it. We're now on the
-## second generation of scripts, still called "dotest".
-##
-## Update: Ryan Anderson finally shamed me into naming this "applymbox".
-##
-## You give it a mbox-format collection of emails, and it will try to
-## apply them to the kernel using "applypatch"
-##
-## The patch application may fail in the middle.  In which case:
-## (1) look at .dotest/patch and fix it up to apply
-## (2) re-run applymbox with -c .dotest/msg-number for the current one.
-## Pay a special attention to the commit log message if you do this and
-## use a Signoff_file, because applypatch wants to append the sign-off
-## message to msg-clean every time it is run.
-##
-## git-am is supposed to be the newer and better tool for this job.
-
-USAGE='[-u] [-k] [-q] [-m] (-c .dotest/<num> | mbox) [signoff]'
-. git-sh-setup
-
-git var GIT_COMMITTER_IDENT >/dev/null || exit
-
-keep_subject= query_apply= continue= utf8=-u resume=t
-while case "$#" in 0) break ;; esac
-do
-       case "$1" in
-       -u)     utf8=-u ;;
-       -n)     utf8=-n ;;
-       -k)     keep_subject=-k ;;
-       -q)     query_apply=t ;;
-       -c)     continue="$2"; resume=f; shift ;;
-       -m)     fall_back_3way=t ;;
-       -*)     usage ;;
-       *)      break ;;
-       esac
-       shift
-done
-
-case "$continue" in
-'')
-       rm -rf .dotest
-       mkdir .dotest
-       num_msgs=$(git-mailsplit "$1" .dotest) || exit 1
-       echo "$num_msgs patch(es) to process."
-       shift
-esac
-
-files=$(git-diff-index --cached --name-only HEAD) || exit
-if [ "$files" ]; then
-   echo "Dirty index: cannot apply patches (dirty: $files)" >&2
-   exit 1
-fi
-
-case "$query_apply" in
-t)     touch .dotest/.query_apply
-esac
-case "$fall_back_3way" in
-t)     : >.dotest/.3way
-esac
-case "$keep_subject" in
--k)    : >.dotest/.keep_subject
-esac
-
-signoff="$1"
-set x .dotest/0*
-shift
-while case "$#" in 0) break;; esac
-do
-    i="$1" 
-    case "$resume,$continue" in
-    f,$i)      resume=t;;
-    f,*)       shift
-               continue;;
-    *)
-           git-mailinfo $keep_subject $utf8 \
-               .dotest/msg .dotest/patch <$i >.dotest/info || exit 1
-           test -s .dotest/patch || {
-               echo "Patch is empty.  Was it split wrong?"
-               exit 1
-           }
-           git-stripspace < .dotest/msg > .dotest/msg-clean
-           ;;
-    esac
-    while :; # for fixing up and retry
-    do
-       git-applypatch .dotest/msg-clean .dotest/patch .dotest/info "$signoff"
-       case "$?" in
-       0)
-               # Remove the cleanly applied one to reduce clutter.
-               rm -f .dotest/$i
-               ;;
-       2)
-               # 2 is a special exit code from applypatch to indicate that
-               # the patch wasn't applied, but continue anyway 
-               ;;
-       *)
-               ret=$?
-               if test -f .dotest/.query_apply
-               then
-                       echo >&2 "* Patch failed."
-                       echo >&2 "* You could fix it up in your editor and"
-                       echo >&2 "  retry.  If you want to do so, say yes here"
-                       echo >&2 "  AFTER fixing .dotest/patch up."
-                       echo >&2 -n "Retry [y/N]? "
-                       read yesno
-                       case "$yesno" in
-                       [Yy]*)
-                               continue ;;
-                       esac
-               fi
-               exit $ret
-       esac
-       break
-    done
-    shift
-done
-# return to pristine
-rm -fr .dotest
diff --git a/git-applypatch.sh b/git-applypatch.sh
deleted file mode 100755 (executable)
index 8df2aee..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/bin/sh
-##
-## applypatch takes four file arguments, and uses those to
-## apply the unpacked patch (surprise surprise) that they
-## represent to the current tree.
-##
-## The arguments are:
-##     $1 - file with commit message
-##     $2 - file with the actual patch
-##     $3 - "info" file with Author, email and subject
-##     $4 - optional file containing signoff to add
-##
-
-USAGE='<msg> <patch> <info> [<signoff>]'
-. git-sh-setup
-
-case "$#" in 3|4) ;; *) usage ;; esac
-
-final=.dotest/final-commit
-##
-## If this file exists, we ask before applying
-##
-query_apply=.dotest/.query_apply
-
-## We do not munge the first line of the commit message too much
-## if this file exists.
-keep_subject=.dotest/.keep_subject
-
-## We do not attempt the 3-way merge fallback unless this file exists.
-fall_back_3way=.dotest/.3way
-
-MSGFILE=$1
-PATCHFILE=$2
-INFO=$3
-SIGNOFF=$4
-EDIT=${VISUAL:-${EDITOR:-vi}}
-
-export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$INFO")"
-export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$INFO")"
-export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$INFO")"
-export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$INFO")"
-
-if test '' != "$SIGNOFF"
-then
-       if test -f "$SIGNOFF"
-       then
-               SIGNOFF=`cat "$SIGNOFF"` || exit
-       elif case "$SIGNOFF" in yes | true | me | please) : ;; *) false ;; esac
-       then
-               SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
-                               s/>.*/>/
-                               s/^/Signed-off-by: /'
-               `
-       else
-               SIGNOFF=
-       fi
-       if test '' != "$SIGNOFF"
-       then
-               LAST_SIGNED_OFF_BY=`
-                       sed -ne '/^Signed-off-by: /p' "$MSGFILE" |
-                       tail -n 1
-               `
-               test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
-                   test '' = "$LAST_SIGNED_OFF_BY" && echo
-                   echo "$SIGNOFF"
-               } >>"$MSGFILE"
-       fi
-fi
-
-patch_header=
-test -f "$keep_subject" || patch_header='[PATCH] '
-
-{
-       echo "$patch_header$SUBJECT"
-       if test -s "$MSGFILE"
-       then
-               echo
-               cat "$MSGFILE"
-       fi
-} >"$final"
-
-interactive=yes
-test -f "$query_apply" || interactive=no
-
-while [ "$interactive" = yes ]; do
-       echo "Commit Body is:"
-       echo "--------------------------"
-       cat "$final"
-       echo "--------------------------"
-       printf "Apply? [y]es/[n]o/[e]dit/[a]ccept all "
-       read reply
-       case "$reply" in
-               y|Y) interactive=no;;
-               n|N) exit 2;;   # special value to tell dotest to keep going
-               e|E) "$EDIT" "$final";;
-               a|A) rm -f "$query_apply"
-                    interactive=no ;;
-       esac
-done
-
-if test -x "$GIT_DIR"/hooks/applypatch-msg
-then
-       "$GIT_DIR"/hooks/applypatch-msg "$final" || exit
-fi
-
-echo
-echo Applying "'$SUBJECT'"
-echo
-
-git-apply --index "$PATCHFILE" || {
-
-       # git-apply exits with status 1 when the patch does not apply,
-       # but it die()s with other failures, most notably upon corrupt
-       # patch.  In the latter case, there is no point to try applying
-       # it to another tree and do 3-way merge.
-       test $? = 1 || exit 1
-
-       test -f "$fall_back_3way" || exit 1
-
-       # Here if we know which revision the patch applies to,
-       # we create a temporary working tree and index, apply the
-       # patch, and attempt 3-way merge with the resulting tree.
-
-       O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
-       rm -fr .patch-merge-*
-
-       if git-apply -z --index-info "$PATCHFILE" \
-               >.patch-merge-index-info 2>/dev/null &&
-               GIT_INDEX_FILE=.patch-merge-tmp-index \
-               git-update-index -z --index-info <.patch-merge-index-info &&
-               GIT_INDEX_FILE=.patch-merge-tmp-index \
-               git-write-tree >.patch-merge-tmp-base &&
-               (
-                       mkdir .patch-merge-tmp-dir &&
-                       cd .patch-merge-tmp-dir &&
-                       GIT_INDEX_FILE="../.patch-merge-tmp-index" \
-                       GIT_OBJECT_DIRECTORY="$O_OBJECT" \
-                       git-apply $binary --index
-               ) <"$PATCHFILE"
-       then
-               echo Using index info to reconstruct a base tree...
-               mv .patch-merge-tmp-base .patch-merge-base
-               mv .patch-merge-tmp-index .patch-merge-index
-       else
-       (
-               N=10
-
-               # Otherwise, try nearby trees that can be used to apply the
-               # patch.
-               git-rev-list --max-count=$N HEAD
-
-               # or hoping the patch is against known tags...
-               git-ls-remote --tags .
-       ) |
-           while read base junk
-           do
-               # Try it if we have it as a tree.
-               git-cat-file tree "$base" >/dev/null 2>&1 || continue
-
-               rm -fr .patch-merge-tmp-* &&
-               mkdir .patch-merge-tmp-dir || break
-               (
-                       cd .patch-merge-tmp-dir &&
-                       GIT_INDEX_FILE=../.patch-merge-tmp-index &&
-                       GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
-                       export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
-                       git-read-tree "$base" &&
-                       git-apply --index &&
-                       mv ../.patch-merge-tmp-index ../.patch-merge-index &&
-                       echo "$base" >../.patch-merge-base
-               ) <"$PATCHFILE"  2>/dev/null && break
-           done
-       fi
-
-       test -f .patch-merge-index &&
-       his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) &&
-       orig_tree=$(cat .patch-merge-base) &&
-       rm -fr .patch-merge-* || exit 1
-
-       echo Falling back to patching base and 3-way merge using $orig_tree...
-
-       # This is not so wrong.  Depending on which base we picked,
-       # orig_tree may be wildly different from ours, but his_tree
-       # has the same set of wildly different changes in parts the
-       # patch did not touch, so resolve ends up canceling them,
-       # saying that we reverted all those changes.
-
-       if git-merge-resolve $orig_tree -- HEAD $his_tree
-       then
-               echo Done.
-       else
-               echo Failed to merge in the changes.
-               exit 1
-       fi
-}
-
-if test -x "$GIT_DIR"/hooks/pre-applypatch
-then
-       "$GIT_DIR"/hooks/pre-applypatch || exit
-fi
-
-tree=$(git-write-tree) || exit 1
-echo Wrote tree $tree
-parent=$(git-rev-parse --verify HEAD) &&
-commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
-echo Committed: $commit
-git-update-ref -m "applypatch: $SUBJECT" HEAD $commit $parent || exit
-
-if test -x "$GIT_DIR"/hooks/post-applypatch
-then
-       "$GIT_DIR"/hooks/post-applypatch
-fi
diff --git a/git-submodule.sh b/git-submodule.sh
new file mode 100755 (executable)
index 0000000..6ed5a6c
--- /dev/null
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# git-submodules.sh: init, update or list git submodules
+#
+# Copyright (c) 2007 Lars Hjemli
+
+USAGE='[--quiet] [--cached] [status|init|update] [--] [<path>...]'
+. git-sh-setup
+require_work_tree
+
+init=
+update=
+status=
+quiet=
+cached=
+
+#
+# print stuff on stdout unless -q was specified
+#
+say()
+{
+       if test -z "$quiet"
+       then
+               echo "$@"
+       fi
+}
+
+#
+# Run clone + checkout on missing submodules
+#
+# $@ = requested paths (default to all)
+#
+modules_init()
+{
+       git ls-files --stage -- "$@" | grep -e '^160000 ' |
+       while read mode sha1 stage path
+       do
+               # Skip submodule paths that already contain a .git directory.
+               # This will also trigger if $path is a symlink to a git
+               # repository
+               test -d "$path"/.git && continue
+
+               # If there already is a directory at the submodule path,
+               # expect it to be empty (since that is the default checkout
+               # action) and try to remove it.
+               # Note: if $path is a symlink to a directory the test will
+               # succeed but the rmdir will fail. We might want to fix this.
+               if test -d "$path"
+               then
+                       rmdir "$path" 2>/dev/null ||
+                       die "Directory '$path' exist, but is neither empty nor a git repository"
+               fi
+
+               test -e "$path" &&
+               die "A file already exist at path '$path'"
+
+               url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
+               test -z "$url" &&
+               die "No url found for submodule '$path' in .gitmodules"
+
+               # MAYBE FIXME: this would be the place to check GIT_CONFIG
+               # for a preferred url for this submodule, possibly like this:
+               #
+               # modname=$(GIT_CONFIG=.gitmodules git-config module."$path".name)
+               # alturl=$(git-config module."$modname".url)
+               #
+               # This would let the versioned .gitmodules file use the submodule
+               # path as key, while the unversioned GIT_CONFIG would use the
+               # logical modulename (if present) as key. But this would need
+               # another fallback mechanism if the module wasn't named.
+
+               git-clone -n "$url" "$path" ||
+               die "Clone of submodule '$path' failed"
+
+               (unset GIT_DIR && cd "$path" && git-checkout -q "$sha1") ||
+               die "Checkout of submodule '$path' failed"
+
+               say "Submodule '$path' initialized"
+       done
+}
+
+#
+# Checkout correct revision of each initialized submodule
+#
+# $@ = requested paths (default to all)
+#
+modules_update()
+{
+       git ls-files --stage -- "$@" | grep -e '^160000 ' |
+       while read mode sha1 stage path
+       do
+               if ! test -d "$path"/.git
+               then
+                       # Only mention uninitialized submodules when its
+                       # path have been specified
+                       test "$#" != "0" &&
+                       say "Submodule '$path' not initialized"
+                       continue;
+               fi
+               subsha1=$(unset GIT_DIR && cd "$path" &&
+                       git-rev-parse --verify HEAD) ||
+               die "Unable to find current revision of submodule '$path'"
+
+               if test "$subsha1" != "$sha1"
+               then
+                       (unset GIT_DIR && cd "$path" && git-fetch &&
+                               git-checkout -q "$sha1") ||
+                       die "Unable to checkout '$sha1' in submodule '$path'"
+
+                       say "Submodule '$path': checked out '$sha1'"
+               fi
+       done
+}
+
+#
+# List all registered submodules, prefixed with:
+#  - submodule not initialized
+#  + different revision checked out
+#
+# If --cached was specified the revision in the index will be printed
+# instead of the currently checked out revision.
+#
+# $@ = requested paths (default to all)
+#
+modules_list()
+{
+       git ls-files --stage -- "$@" | grep -e '^160000 ' |
+       while read mode sha1 stage path
+       do
+               if ! test -d "$path"/.git
+               then
+                       say "-$sha1 $path"
+                       continue;
+               fi
+               revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
+               if git diff-files --quiet -- "$path"
+               then
+                       say " $sha1 $path ($revname)"
+               else
+                       if test -z "$cached"
+                       then
+                               sha1=$(unset GIT_DIR && cd "$path" && git-rev-parse --verify HEAD)
+                               revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
+                       fi
+                       say "+$sha1 $path ($revname)"
+               fi
+       done
+}
+
+while case "$#" in 0) break ;; esac
+do
+       case "$1" in
+       init)
+               init=1
+               ;;
+       update)
+               update=1
+               ;;
+       status)
+               status=1
+               ;;
+       -q|--quiet)
+               quiet=1
+               ;;
+       --cached)
+               cached=1
+               ;;
+       --)
+               break
+               ;;
+       -*)
+               usage
+               ;;
+       *)
+               break
+               ;;
+       esac
+       shift
+done
+
+case "$init,$update,$status,$cached" in
+1,,,)
+       modules_init "$@"
+       ;;
+,1,,)
+       modules_update "$@"
+       ;;
+,,*,*)
+       modules_list "$@"
+       ;;
+*)
+       usage
+       ;;
+esac
index c3921cb0baf162b8294fe47b2fff749114f3061f..e92596c295576d20d76eef23c004e7d2a5db6a3a 100755 (executable)
@@ -94,6 +94,13 @@ our $default_text_plain_charset  = undef;
 # (relative to the current git repository)
 our $mimetypes_file = undef;
 
+# assume this charset if line contains non-UTF-8 characters;
+# it should be valid encoding (see Encoding::Supported(3pm) for list),
+# for which encoding all byte sequences are valid, for example
+# 'iso-8859-1' aka 'latin1' (it is decoded without checking, so it
+# could be even 'utf-8' for the old behavior)
+our $fallback_encoding = 'latin1';
+
 # You define site-wide feature defaults here; override them with
 # $GITWEB_CONFIG as necessary.
 our %feature = (
@@ -602,6 +609,20 @@ sub validate_refname {
        return $input;
 }
 
+# decode sequences of octets in utf8 into Perl's internal form,
+# which is utf-8 with utf8 flag set if needed.  gitweb writes out
+# in utf-8 thanks to "binmode STDOUT, ':utf8'" at beginning
+sub to_utf8 {
+       my $str = shift;
+       my $res;
+       eval { $res = decode_utf8($str, Encode::FB_CROAK); };
+       if (defined $res) {
+               return $res;
+       } else {
+               return decode($fallback_encoding, $str, Encode::FB_DEFAULT);
+       }
+}
+
 # quote unsafe chars, but keep the slash, even when it's not
 # correct, but quoted slashes look too horrible in bookmarks
 sub esc_param {
@@ -626,7 +647,7 @@ sub esc_html ($;%) {
        my $str = shift;
        my %opts = @_;
 
-       $str = decode_utf8($str);
+       $str = to_utf8($str);
        $str = $cgi->escapeHTML($str);
        if ($opts{'-nbsp'}) {
                $str =~ s/ /&nbsp;/g;
@@ -640,7 +661,7 @@ sub esc_path {
        my $str = shift;
        my %opts = @_;
 
-       $str = decode_utf8($str);
+       $str = to_utf8($str);
        $str = $cgi->escapeHTML($str);
        if ($opts{'-nbsp'}) {
                $str =~ s/ /&nbsp;/g;
@@ -925,7 +946,7 @@ sub format_subject_html {
 
        if (length($short) < length($long)) {
                return $cgi->a({-href => $href, -class => "list subject",
-                               -title => decode_utf8($long)},
+                               -title => to_utf8($long)},
                       esc_html($short) . $extra);
        } else {
                return $cgi->a({-href => $href, -class => "list subject"},
@@ -1239,7 +1260,7 @@ sub git_get_projects_list {
                        if (check_export_ok("$projectroot/$path")) {
                                my $pr = {
                                        path => $path,
-                                       owner => decode_utf8($owner),
+                                       owner => to_utf8($owner),
                                };
                                push @list, $pr;
                                (my $forks_path = $path) =~ s/\.git$//;
@@ -1269,7 +1290,7 @@ sub git_get_project_owner {
                        $pr = unescape($pr);
                        $ow = unescape($ow);
                        if ($pr eq $project) {
-                               $owner = decode_utf8($ow);
+                               $owner = to_utf8($ow);
                                last;
                        }
                }
@@ -1759,7 +1780,7 @@ sub get_file_owner {
        }
        my $owner = $gcos;
        $owner =~ s/[,;].*$//;
-       return decode_utf8($owner);
+       return to_utf8($owner);
 }
 
 ## ......................................................................
@@ -1842,7 +1863,7 @@ sub git_header_html {
 
        my $title = "$site_name";
        if (defined $project) {
-               $title .= " - " . decode_utf8($project);
+               $title .= " - " . to_utf8($project);
                if (defined $action) {
                        $title .= "/$action";
                        if (defined $file_name) {
@@ -2116,7 +2137,7 @@ sub git_print_page_path {
 
        print "<div class=\"page_path\">";
        print $cgi->a({-href => href(action=>"tree", hash_base=>$hb),
-                     -title => 'tree root'}, decode_utf8("[$project]"));
+                     -title => 'tree root'}, to_utf8("[$project]"));
        print " / ";
        if (defined $name) {
                my @dirname = split '/', $name;
@@ -2936,7 +2957,7 @@ sub git_project_list_body {
                ($pr->{'age'}, $pr->{'age_string'}) = @aa;
                if (!defined $pr->{'descr'}) {
                        my $descr = git_get_project_description($pr->{'path'}) || "";
-                       $pr->{'descr_long'} = decode_utf8($descr);
+                       $pr->{'descr_long'} = to_utf8($descr);
                        $pr->{'descr'} = chop_str($descr, 25, 5);
                }
                if (!defined $pr->{'owner'}) {
@@ -3981,7 +4002,7 @@ sub git_snapshot {
        my $git = git_cmd_str();
        my $name = $project;
        $name =~ s/\047/\047\\\047\047/g;
-       my $filename = decode_utf8(basename($project));
+       my $filename = to_utf8(basename($project));
        my $cmd;
        if ($suffix eq 'zip') {
                $filename .= "-$hash.$suffix";
diff --git a/grep.c b/grep.c
index fcc676230282e4c5bda4f9f97c5ae65c1a6beb30..f67d6716ea5f42c3384a7a4cb2eb973b02785fba 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "grep.h"
+#include "xdiff-interface.h"
 
 void append_grep_pattern(struct grep_opt *opt, const char *pat,
                         const char *origin, int no, enum grep_pat_token t)
@@ -232,17 +233,6 @@ static void show_line(struct grep_opt *opt, const char *bol, const char *eol,
        printf("%.*s\n", (int)(eol-bol), bol);
 }
 
-/*
- * NEEDSWORK: share code with diff.c
- */
-#define FIRST_FEW_BYTES 8000
-static int buffer_is_binary(const char *ptr, unsigned long size)
-{
-       if (FIRST_FEW_BYTES < size)
-               size = FIRST_FEW_BYTES;
-       return !!memchr(ptr, 0, size);
-}
-
 static int fixmatch(const char *pattern, char *line, regmatch_t *match)
 {
        char *hit = strstr(line, pattern);
index 8f72b2c079a68ac5cb9d1c90bb7b72fa779efb5f..4a82b741ae020376ac67b34d5fce86e8a87a3b5d 100644 (file)
@@ -680,6 +680,12 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 {
        xpparam_t xpp;
 
+       if (buffer_is_binary(orig->ptr, orig->size) ||
+                       buffer_is_binary(src1->ptr, src1->size) ||
+                       buffer_is_binary(src2->ptr, src2->size))
+               return error("Cannot merge binary files: %s vs. %s\n",
+                       name1, name2);
+
        memset(&xpp, 0, sizeof(xpp));
        return xdl_merge(orig,
                         src1, name1,
index a398556137205d9fb561746335a13330a5aeda54..058db9cc52521a9ba9e408c9455645d8adc4ba79 100755 (executable)
@@ -81,4 +81,18 @@ EOF
 
 test_expect_success "virtual trees were processed" "git diff expect out"
 
+git reset --hard
+test_expect_success 'refuse to merge binary files' '
+       printf "\0" > binary-file &&
+       git add binary-file &&
+       git commit -m binary &&
+       git checkout G &&
+       printf "\0\0" > binary-file &&
+       git add binary-file &&
+       git commit -m binary2 &&
+       ! git merge F > merge.out 2> merge.err &&
+       grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
+               merge.err
+'
+
 test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
new file mode 100755 (executable)
index 0000000..6274729
--- /dev/null
@@ -0,0 +1,143 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Lars Hjemli
+#
+
+test_description='Basic porcelain support for submodules
+
+This test tries to verify basic sanity of the init, update and status
+subcommands of git-submodule.
+'
+
+. ./test-lib.sh
+
+#
+# Test setup:
+#  -create a repository in directory lib
+#  -add a couple of files
+#  -add directory lib to 'superproject', this creates a DIRLINK entry
+#  -add a couple of regular files to enable testing of submodule filtering
+#  -mv lib subrepo
+#  -add an entry to .gitmodules for path 'lib'
+#
+test_expect_success 'Prepare submodule testing' '
+       mkdir lib &&
+       cd lib &&
+       git-init &&
+       echo a >a &&
+       git-add a &&
+       git-commit -m "submodule commit 1" &&
+       git-tag -a -m "rev-1" rev-1 &&
+       rev1=$(git-rev-parse HEAD) &&
+       if test -z "$rev1"
+       then
+               echo "[OOPS] submodule git-rev-parse returned nothing"
+               false
+       fi &&
+       cd .. &&
+       echo a >a &&
+       echo z >z &&
+       git-add a lib z &&
+       git-commit -m "super commit 1" &&
+       mv lib .subrepo &&
+       GIT_CONFIG=.gitmodules git-config module.lib.url ./.subrepo
+'
+
+test_expect_success 'status should only print one line' '
+       lines=$(git-submodule status | wc -l) &&
+       test $lines = 1
+'
+
+test_expect_success 'status should initially be "missing"' '
+       git-submodule status | grep "^-$rev1"
+'
+
+test_expect_success 'init should fail when path is used by a file' '
+       echo "hello" >lib &&
+       if git-submodule init
+       then
+               echo "[OOPS] init should have failed"
+               false
+       elif test -f lib && test "$(cat lib)" != "hello"
+       then
+               echo "[OOPS] init failed but lib file was molested"
+               false
+       else
+               rm lib
+       fi
+'
+
+test_expect_success 'init should fail when path is used by a nonempty directory' '
+       mkdir lib &&
+       echo "hello" >lib/a &&
+       if git-submodule init
+       then
+               echo "[OOPS] init should have failed"
+               false
+       elif test "$(cat lib/a)" != "hello"
+       then
+               echo "[OOPS] init failed but lib/a was molested"
+               false
+       else
+               rm lib/a
+       fi
+'
+
+test_expect_success 'init should work when path is an empty dir' '
+       rm -rf lib &&
+       mkdir lib &&
+       git-submodule init &&
+       head=$(cd lib && git-rev-parse HEAD) &&
+       if test -z "$head"
+       then
+               echo "[OOPS] Failed to obtain submodule head"
+               false
+       elif test "$head" != "$rev1"
+       then
+               echo "[OOPS] Submodule head is $head but should have been $rev1"
+               false
+       fi
+'
+
+test_expect_success 'status should be "up-to-date" after init' '
+       git-submodule status | grep "^ $rev1"
+'
+
+test_expect_success 'status should be "modified" after submodule commit' '
+       cd lib &&
+       echo b >b &&
+       git-add b &&
+       git-commit -m "submodule commit 2" &&
+       rev2=$(git-rev-parse HEAD) &&
+       cd .. &&
+       if test -z "$rev2"
+       then
+               echo "[OOPS] submodule git-rev-parse returned nothing"
+               false
+       fi &&
+       git-submodule status | grep "^+$rev2"
+'
+
+test_expect_success 'the --cached sha1 should be rev1' '
+       git-submodule --cached status | grep "^+$rev1"
+'
+
+test_expect_success 'update should checkout rev1' '
+       git-submodule update &&
+       head=$(cd lib && git-rev-parse HEAD) &&
+       if test -z "$head"
+       then
+               echo "[OOPS] submodule git-rev-parse returned nothing"
+               false
+       elif test "$head" != "$rev1"
+       then
+               echo "[OOPS] init did not checkout correct head"
+               false
+       fi
+'
+
+test_expect_success 'status should be "up-to-date" after update' '
+       git-submodule status | grep "^ $rev1"
+'
+
+test_done
index b92ab6331204ca40dd51b618623e5241ae08dd37..44ae503b992ee26023a19830039062e01be9aa57 100755 (executable)
@@ -487,4 +487,32 @@ test_expect_success \
        'gitweb_run "p=.git;a=atom"'
 test_debug 'cat gitweb.log'
 
+# ----------------------------------------------------------------------
+# encoding/decoding
+
+test_expect_success \
+       'encode(commit): utf8' \
+       '. ../t3901-utf8.txt &&
+        echo "UTF-8" >> file &&
+        git add file &&
+        git commit -F ../t3900/1-UTF-8.txt &&
+        gitweb_run "p=.git;a=commit"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+       'encode(commit): iso-8859-1' \
+       '. ../t3901-8859-1.txt &&
+        echo "ISO-8859-1" >> file &&
+        git add file &&
+        git config i18n.commitencoding ISO-8859-1 &&
+        git commit -F ../t3900/ISO-8859-1.txt &&
+        git config --unset i18n.commitencoding &&
+        gitweb_run "p=.git;a=commit"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+       'encode(log): utf-8 and iso-8859-1' \
+       'gitweb_run "p=.git;a=log"'
+test_debug 'cat gitweb.log'
+
 test_done
index 10816e95a07c23dda7554c102c306d7e9beca606..963bb89b08e64188ba278587f63f380653b019c6 100644 (file)
@@ -122,4 +122,12 @@ int read_mmfile(mmfile_t *ptr, const char *filename)
        return 0;
 }
 
+#define FIRST_FEW_BYTES 8000
+int buffer_is_binary(const char *ptr, unsigned long size)
+{
+       if (FIRST_FEW_BYTES < size)
+               size = FIRST_FEW_BYTES;
+       return !!memchr(ptr, 0, size);
+}
+
 
index 1918808081c00daf20a16a1592c0ed9be6d79be4..536f4e4d9784e0e5ffdc108a5be4bf758d1578ba 100644 (file)
@@ -18,5 +18,6 @@ int parse_hunk_header(char *line, int len,
                      int *ob, int *on,
                      int *nb, int *nn);
 int read_mmfile(mmfile_t *ptr, const char *filename);
+int buffer_is_binary(const char *ptr, unsigned long size);
 
 #endif