diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Documentation/RelNotes-1.5.2.1.txt | 53 | ||||
-rw-r--r-- | Documentation/RelNotes-1.5.3.txt | 109 | ||||
-rw-r--r-- | Documentation/SubmittingPatches | 8 | ||||
-rwxr-xr-x | Documentation/cmd-list.perl | 3 | ||||
-rw-r--r-- | Documentation/git-am.txt | 5 | ||||
-rw-r--r-- | Documentation/git-applymbox.txt | 98 | ||||
-rw-r--r-- | Documentation/git-applypatch.txt | 53 | ||||
-rw-r--r-- | Documentation/git-fsck.txt | 5 | ||||
-rw-r--r-- | Documentation/git-mailinfo.txt | 2 | ||||
-rw-r--r-- | Documentation/git-submodule.txt | 65 | ||||
-rw-r--r-- | Documentation/hooks.txt | 13 | ||||
-rw-r--r-- | Makefile | 4 | ||||
l--------- | RelNotes | 2 | ||||
-rw-r--r-- | builtin-apply.c | 17 | ||||
-rw-r--r-- | builtin-fsck.c | 42 | ||||
-rw-r--r-- | diff.c | 7 | ||||
-rwxr-xr-x | git-applymbox.sh | 121 | ||||
-rwxr-xr-x | git-applypatch.sh | 212 | ||||
-rwxr-xr-x | git-submodule.sh | 194 | ||||
-rwxr-xr-x | gitweb/gitweb.perl | 41 | ||||
-rw-r--r-- | grep.c | 12 | ||||
-rw-r--r-- | merge-recursive.c | 6 | ||||
-rwxr-xr-x | t/t6024-recursive-merge.sh | 14 | ||||
-rwxr-xr-x | t/t7400-submodule-basic.sh | 143 | ||||
-rwxr-xr-x | t/t9500-gitweb-standalone-no-errors.sh | 28 | ||||
-rw-r--r-- | xdiff-interface.c | 8 | ||||
-rw-r--r-- | xdiff-interface.h | 1 |
28 files changed, 727 insertions, 543 deletions
diff --git a/.gitignore b/.gitignore index 4dc0c395f..8e75c99d6 100644 --- a/.gitignore +++ b/.gitignore @@ -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 index 000000000..ebf20e22a --- /dev/null +++ b/Documentation/RelNotes-1.5.2.1.txt @@ -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 index 000000000..d111661a7 --- /dev/null +++ b/Documentation/RelNotes-1.5.3.txt @@ -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 diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index b94d9a816..b9baa1d3b 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -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. diff --git a/Documentation/cmd-list.perl b/Documentation/cmd-list.perl index 443802a9a..a181f753e 100755 --- a/Documentation/cmd-list.perl +++ b/Documentation/cmd-list.perl @@ -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 diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index f78e5dc28..f3387f5d0 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -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 index ea919ba5d..000000000 --- a/Documentation/git-applymbox.txt +++ /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 index 451434a75..000000000 --- a/Documentation/git-applypatch.txt +++ /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 - diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index 8c68cf037..ed6413a3c 100644 --- a/Documentation/git-fsck.txt +++ b/Documentation/git-fsck.txt @@ -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 diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt index 8eadcebfc..16956951d 100644 --- a/Documentation/git-mailinfo.txt +++ b/Documentation/git-mailinfo.txt @@ -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 index 000000000..cb0424f77 --- /dev/null +++ b/Documentation/git-submodule.txt @@ -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 diff --git a/Documentation/hooks.txt b/Documentation/hooks.txt index aabb9750f..6836477ca 100644 --- a/Documentation/hooks.txt +++ b/Documentation/hooks.txt @@ -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 ---------- @@ -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 \ @@ -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 diff --git a/builtin-apply.c b/builtin-apply.c index e71789803..c6f736c14 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -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" : ""); diff --git a/builtin-fsck.c b/builtin-fsck.c index 9959818ce..bacae5dfa 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -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); } @@ -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 index c18e80ff8..000000000 --- a/git-applymbox.sh +++ /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 index 8df2aee4c..000000000 --- a/git-applypatch.sh +++ /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 index 000000000..6ed5a6ced --- /dev/null +++ b/git-submodule.sh @@ -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 diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index c3921cb0b..e92596c29 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -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/ / /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/ / /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"; @@ -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); diff --git a/merge-recursive.c b/merge-recursive.c index 8f72b2c07..4a82b741a 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -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, diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index a39855613..058db9cc5 100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -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 index 000000000..627472972 --- /dev/null +++ b/t/t7400-submodule-basic.sh @@ -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 diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index b92ab6331..44ae503b9 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -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 diff --git a/xdiff-interface.c b/xdiff-interface.c index 10816e95a..963bb89b0 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -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); +} + diff --git a/xdiff-interface.h b/xdiff-interface.h index 191880808..536f4e4d9 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -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 |