Re: Pretty format specifier for commit count?
On Mon, Jan 19, 2015 at 02:54:13PM +0100, Michael J Gruber wrote: Josh Triplett schrieb am 19.01.2015 um 02:29: I'd like to use git-log to generate a Debian changelog file (with one entry per commit), which has entries like this: package-name (version-number) unstable; urgency=low * ... -- Example Person per...@example.org RFC822-date Since I'm intentionally generating one entry per commit, I can generate *almost* all of this with git log: git log --pretty='format:packagename (FIXME) unstable; urgency=low%n%n * %s%n%w(0,4,4)%+b%w(0,0,0)%n -- %an %ae %aD%n' This produces entries like this: packagename (FIXME) unstable; urgency=low * Example change Long description of example change. -- Josh Triplett j...@joshtriplett.org Thu, 8 Jan 2015 16:36:52 -0800 packagename (FIXME) unstable; urgency=low * Initial version -- Josh Triplett j...@joshtriplett.org Thu, 8 Jan 2015 16:36:51 -0800 Would it be possible to add a format specifier producing a commit count, similar to that provided by git-describe? Such a specifier would allow filling in the version number in the format above (replacing the FIXME). (Note that the version numbers need to monotonically increase; otherwise I would just use the commit hash as the version numer.) - Josh Triplett Can you be a bit more specific about the type count that you are after? git describe counts commits since the most recent tag (possibly within a specific subset of all tags). Is that your desired format? That might work, since the repository in question has no tags; I'd actually like commits since root commit. I could imagine scenarios in which both most recent tag and commits since most recent tag would be useful format specifiers; however, for this use case, I'm looking for commits since root commit. (I won't suggest scripting around rev-list, describe and log -1 because you know that already...) Right. Though as far as I can tell, git describe doesn't actually do what I'm looking for. rev-list --count $commit does (though that'd be N**2), as would something like rev-list --reverse HEAD | nl | while read count hash ; do ..., but I'd like to do better than that. - Josh Triplett -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 15/18] fsck: Document the new receive.fsck.* options.
On Mon, Jan 19, 2015 at 10:51 AM, Johannes Schindelin johannes.schinde...@gmx.de wrote: Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- diff --git a/Documentation/config.txt b/Documentation/config.txt index ae6791d..7371a5f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2130,6 +2130,31 @@ receive.fsckObjects:: Defaults to false. If not set, the value of `transfer.fsckObjects` is used instead. +receive.fsck.*:: + When `receive.fsckObjects` is set to true, errors can be switched + to warnings and vice versa by configuring the `receive.fsck.*` + settings. These settings contain comma-separated lists of fsck + message IDs. For convenience, fsck prefixes the error/warning with + the message ID, e.g. missing-email: invalid author/committer line + - missing email means that setting `receive.fsck.ignore = + missing-email` will hide that issue. ++ +-- + error:: + a comma-separated list of fsck message IDs that should be + trigger fsck to error out. + warn:: + a comma-separated list of fsck message IDs that should be + displayed, but fsck should continue to error out. + ignore:: + a comma-separated list of fsck message IDs that should be + ignored completely. ++ +This feature is intended to support working with legacy repositories +which would not pass pushing when `receive.fsckObjects = true`, allowing +the host to accept repositories certain known issues but still catch s/certain/with / +other issues. + receive.unpackLimit:: If the number of objects received in a push is below this limit then the objects will be unpacked into loose object -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] rebase -i: respect core.abbrev for real
On Mon, Jan 19, 2015 at 9:20 AM, Kirill A. Shutemov kirill.shute...@linux.intel.com wrote: I have tried to fix this before: see 568950388be2, but it doesn't really work. I don't know how it happend, but that commit makes interactive rebase to respect core.abbrev only during --edit-todo, but not the initial todo list edit. For this time I've included a test-case to avoid this frustration again. Signed-off-by: Kirill A. Shutemov kirill.shute...@linux.intel.com --- diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 8197ed29a9ec..a8ffc24ce46b 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1039,4 +1039,11 @@ test_expect_success 'short SHA-1 collide' ' ) ' +test_expect_success 'respect core.abbrev' ' + git config core.abbrev 12 + set_cat_todo_editor + test_must_fail git rebase -i HEAD~4 todo-list 21 Broken -chain. + test 4 = $(grep -c pick [0-9a-f]\{12,\} todo-list) +' + test_done -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Unused #include statements
Robert, Peff and Junio. Thank you all for your feedback. It's clear now what sort of analysis I should aim towards. Thanks, Zoltan -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 15/18] fsck: Document the new receive.fsck.* options.
Hi Eric, On 2015-01-19 23:44, Eric Sunshine wrote: On Mon, Jan 19, 2015 at 10:51 AM, Johannes Schindelin johannes.schinde...@gmx.de wrote: Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- diff --git a/Documentation/config.txt b/Documentation/config.txt index ae6791d..7371a5f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2130,6 +2130,31 @@ receive.fsckObjects:: Defaults to false. If not set, the value of `transfer.fsckObjects` is used instead. +receive.fsck.*:: + When `receive.fsckObjects` is set to true, errors can be switched + to warnings and vice versa by configuring the `receive.fsck.*` + settings. These settings contain comma-separated lists of fsck + message IDs. For convenience, fsck prefixes the error/warning with + the message ID, e.g. missing-email: invalid author/committer line + - missing email means that setting `receive.fsck.ignore = + missing-email` will hide that issue. ++ +-- + error:: + a comma-separated list of fsck message IDs that should be + trigger fsck to error out. + warn:: + a comma-separated list of fsck message IDs that should be + displayed, but fsck should continue to error out. + ignore:: + a comma-separated list of fsck message IDs that should be + ignored completely. ++ +This feature is intended to support working with legacy repositories +which would not pass pushing when `receive.fsckObjects = true`, allowing +the host to accept repositories certain known issues but still catch s/certain/with / Good catch. Fixed here (to be included in the next re-roll): https://github.com/dscho/git/commit/2517476646835e61c33581935fc68062a8ff3f56#diff-ba92ef40c548c691816362bbdc35a613R2155 Thanks! Dscho -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: donation
From: Collins, Margaret Sent: Monday, January 19, 2015 5:28 PM To: margaret.coll...@iammorrison.com Subject: donation Liliane bettencourt donation to you, reply my email for more details ( bettencourtlia...@hotmail.com This email is subject to certain disclaimers, which may be reviewed via the following link. http://compass-usa.com/Pages/Disclaimer.aspx. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Proper plumbing for porcelain gpg formats on git show?
Jason Pyeron schrieb am 16.01.2015 um 21:05: -Original Message- From: Junio C Hamano Sent: Friday, January 16, 2015 14:53 Jonathan Nieder jrnie...@gmail.com writes: would there be interest in accepting a patch for %Gs - the raw GPG text from the commit %Gf - the key fingerprint There may be bikeshedding on the exact format specifier, but aside from that I don't see why not. ;-) I was about to say As long as the execution is good, why not? Spawning an extra process 'gpg --list-packets' is not quite acceptable without properly being lazy is not acceptable. But verify_signed_buffer() reads gpg --status-fd=1 --verify output, it is already done lazily in format_commit_one() only when the %G? placeholder is used, and the output we parse that are prefixed by [GNUPG:] should have enough information to grab the fingerprint from on the VALIDSIG line. So I do not see a lot of room to screw-up the execution ;-). This kind of begs the question of extracting signatures, not in one's keyring. I was surprised to see %GK fail because it was not yet in the keyring. I would also expect a B, not a N for %G?, maybe there should be a X for can't verify. $ gpg --delete-keys DA0848AD gpg (GnuPG) 2.0.14; Copyright (C) 2009 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. pub 2048R/DA0848AD 2014-06-24 Jason Pyeron jpye...@pdinc.us Delete this key from the keyring? (y/N) y $ git diff-tree -s --format=%G? HEAD N $ git diff-tree -s --format=%GG HEAD gpg: Signature made Fri 16 Jan 2015 01:33:12 PM EST using RSA key ID DA0848AD gpg: Can't check signature: No public key $ git diff-tree -s --format=%GK HEAD $ gpg --keyserver hkp://pgp.mit.edu --recv-keys 8D6B5984DA0848AD gpg: requesting key DA0848AD from hkp server pgp.mit.edu gpg: key DA0848AD: public key Jason Pyeron jpye...@pdinc.us imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) $ git diff-tree -s --format=%G? HEAD U $ git diff-tree -s --format=%GG HEAD gpg: Signature made Fri 16 Jan 2015 01:33:12 PM EST using RSA key ID DA0848AD gpg: Good signature from Jason Pyeron jpye...@pdinc.us gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 8C88 9ECF 7A2F 7977 7CE9 13B4 8D6B 5984 DA08 48AD $ git diff-tree -s --format=%GK HEAD 8D6B5984DA0848AD I'm not exactly sure what you are trying to extract, but git verify-commit -v gives you the actual signature, which you can then feed into gpg/gpgsplit for surgery according to taste. As far as git goes, I think it should give you all gpg information that it has available but not morph into a gpg frontend or trust manager. Ultimately, signature verification in its true meaning requires human inspection of the full gpg output. Michael -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] branch: add support for --dry-run option
Alexander Kuleshov schrieb am 17.01.2015 um 08:35: This patch adds support -d/--dry-run option for branch(es) deletion. If -d/--dry-run option passed to git branch -d branch..., branch(es) will not be removed, instead just print list of branches that are to be removed. For example: $ git branch a b c * master $ git branch -d -n a b c delete branch 'a' (261c0d1) delete branch 'b' (261c0d1) delete branch 'c' (261c0d1) Is there a case where deleting a b c would not delete a b c? In other words: What new information does a dry-run give the user, other than what branch --list -v would give already? (We could need a shortcut on the latter, but that is a different topic.) Michael -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] rebase -i: respect core.abbrev for real
I have tried to fix this before: see 568950388be2, but it doesn't really work. I don't know how it happend, but that commit makes interactive rebase to respect core.abbrev only during --edit-todo, but not the initial todo list edit. For this time I've included a test-case to avoid this frustration again. Signed-off-by: Kirill A. Shutemov kirill.shute...@linux.intel.com --- git-rebase--interactive.sh| 4 ++-- t/t3404-rebase-interactive.sh | 7 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index c6a4629cbc2b..1855e12f1ada 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -962,7 +962,7 @@ else shortrevisions=$shorthead fi git rev-list $merges_option --pretty=oneline --abbrev-commit \ - --abbrev=7 --reverse --left-right --topo-order \ + --reverse --left-right --topo-order \ $revisions ${restrict_revision+^$restrict_revision} | \ sed -n s/^//p | while read -r shortsha1 rest @@ -1020,7 +1020,7 @@ then # just the history of its first-parent for others that will # be rebasing on top of it git rev-list --parents -1 $rev | cut -d' ' -s -f2 $dropped/$rev - short=$(git rev-list -1 --abbrev-commit --abbrev=7 $rev) + short=$(git rev-list -1 --abbrev-commit $rev) sane_grep -v ^[a-z][a-z]* $short $todo ${todo}2 ; mv ${todo}2 $todo rm $rewritten/$rev fi diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 8197ed29a9ec..a8ffc24ce46b 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1039,4 +1039,11 @@ test_expect_success 'short SHA-1 collide' ' ) ' +test_expect_success 'respect core.abbrev' ' + git config core.abbrev 12 + set_cat_todo_editor + test_must_fail git rebase -i HEAD~4 todo-list 21 + test 4 = $(grep -c pick [0-9a-f]\{12,\} todo-list) +' + test_done -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Pretty format specifier for commit count?
Josh Triplett schrieb am 19.01.2015 um 02:29: I'd like to use git-log to generate a Debian changelog file (with one entry per commit), which has entries like this: package-name (version-number) unstable; urgency=low * ... -- Example Person per...@example.org RFC822-date Since I'm intentionally generating one entry per commit, I can generate *almost* all of this with git log: git log --pretty='format:packagename (FIXME) unstable; urgency=low%n%n * %s%n%w(0,4,4)%+b%w(0,0,0)%n -- %an %ae %aD%n' This produces entries like this: packagename (FIXME) unstable; urgency=low * Example change Long description of example change. -- Josh Triplett j...@joshtriplett.org Thu, 8 Jan 2015 16:36:52 -0800 packagename (FIXME) unstable; urgency=low * Initial version -- Josh Triplett j...@joshtriplett.org Thu, 8 Jan 2015 16:36:51 -0800 Would it be possible to add a format specifier producing a commit count, similar to that provided by git-describe? Such a specifier would allow filling in the version number in the format above (replacing the FIXME). (Note that the version numbers need to monotonically increase; otherwise I would just use the commit hash as the version numer.) - Josh Triplett Can you be a bit more specific about the type count that you are after? git describe counts commits since the most recent tag (possibly within a specific subset of all tags). Is that your desired format? (I won't suggest scripting around rev-list, describe and log -1 because you know that already...) Michael -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 17/18] fsck: Introduce `git fsck --quick`
This option avoids unpacking each and all objects, and just verifies the connectivity. In particular with large repositories, this speeds up the operation, at the expense of missing corrupt blobs and ignoring unreachable objects, if any. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- Documentation/git-fsck.txt | 7 ++- builtin/fsck.c | 7 ++- t/t1450-fsck.sh| 22 ++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt index 25c431d..b98fb43 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] -[--[no-]full] [--strict] [--verbose] [--lost-found] +[--[no-]full] [--quick] [--strict] [--verbose] [--lost-found] [--[no-]dangling] [--[no-]progress] [object*] DESCRIPTION @@ -60,6 +60,11 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs object pools. This is now default; you can turn it off with --no-full. +--quick:: + Check only the connectivity of tags, commits and tree objects. By + avoiding to unpack blobs, this speeds up the operation, at the + expense of missing corrupt objects. + --strict:: Enable more strict checking, namely to catch a file mode recorded with g+w bit set, which was created by older diff --git a/builtin/fsck.c b/builtin/fsck.c index d5403c4..c767909 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -23,6 +23,7 @@ static int show_tags; static int show_unreachable; static int include_reflogs = 1; static int check_full = 1; +static int quick; static int check_strict; static int keep_cache_objects; static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT; @@ -184,6 +185,8 @@ static void check_reachable_object(struct object *obj) if (!(obj-flags HAS_OBJ)) { if (has_sha1_pack(obj-sha1)) return; /* it is in pack - forget about it */ + if (quick has_sha1_file(obj-sha1)) + return; printf(missing %s %s\n, typename(obj-type), sha1_to_hex(obj-sha1)); errors_found |= ERROR_REACHABLE; return; @@ -618,6 +621,7 @@ static struct option fsck_opts[] = { OPT_BOOL(0, cache, keep_cache_objects, N_(make index objects head nodes)), OPT_BOOL(0, reflogs, include_reflogs, N_(make reflogs head nodes (default))), OPT_BOOL(0, full, check_full, N_(also consider packs and alternate objects)), + OPT_BOOL(0, quick, quick, N_(check only connectivity)), OPT_BOOL(0, strict, check_strict, N_(enable more strict checking)), OPT_BOOL(0, lost-found, write_lost_and_found, N_(write dangling objects in .git/lost-found)), @@ -654,7 +658,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) git_config(fsck_config, NULL); fsck_head_link(); - fsck_object_dir(get_object_directory()); + if (!quick) + fsck_object_dir(get_object_directory()); prepare_alt_odb(); for (alt = alt_odb_list; alt; alt = alt-next) { diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index a79ff9f..1c624a3 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -431,4 +431,26 @@ test_expect_success 'fsck notices ref pointing to missing tag' ' test_must_fail git -C missing fsck ' +test_expect_success 'fsck --quick' ' + rm -rf quick + git init quick + ( + cd quick + touch empty + git add empty + test_commit empty + empty=.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 + rm -f $empty + echo invalid $empty + test_must_fail git fsck --strict + git fsck --strict --quick + tree=$(git rev-parse HEAD:) + suffix=${tree#??} + tree=.git/objects/${tree%$suffix}/$suffix + rm -f $tree + echo invalid $tree + test_must_fail git fsck --strict --quick + ) +' + test_done -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/18] Introduce an internal API to interact with the fsck machinery
At the moment, the git-fsck's integrity checks are targeted toward the end user, i.e. the error messages are really just messages, intended for human consumption. Under certain circumstances, some of those errors should be allowed to be turned into mere warnings, though, because the cost of fixing the issues might well be larger than the cost of carrying those flawed objects. For example, when an already-public repository contains a commit object with two authors for years, it does not make sense to force the maintainer to rewrite the history, affecting all contributors negatively by forcing them to update. This branch introduces an internal fsck API to be able to turn some of the errors into warnings, and to make it easier to call the fsck machinery from elsewhere in general. I am proud to report that this work has been sponsored by GitHub. Interdiff vs v1 below the diffstat. Sorry for the size; the comments I received for v1 made it necessary to change the patch series rather extensively (I rebased the branch twenty-five times since sending off the first version of the patch series, which might also serve as an apology for not getting v2 out sooner). Johannes Schindelin (19): fsck: Introduce fsck options fsck: Introduce identifiers for fsck messages fsck: Provide a function to parse fsck message IDs fsck: Offer a function to demote fsck errors to warnings fsck: Allow demoting errors to warnings via receive.fsck.warn = key fsck: Report the ID of the error/warning fsck: Make fsck_ident() warn-friendly fsck: Make fsck_commit() warn-friendly fsck: Handle multiple authors in commits specially fsck: Make fsck_tag() warn-friendly fsck: Add a simple test for receive.fsck.* fsck: Disallow demoting grave fsck errors to warnings fsck: Optionally ignore specific fsck issues completely fsck: Allow upgrading fsck warnings to errors fsck: Document the new receive.fsck.* options. fsck: Support demoting errors to warnings fsck: Introduce `git fsck --quick` fsck: git receive-pack: support excluding objects from fsck'ing Documentation/config.txt| 38 +++ Documentation/git-fsck.txt | 7 +- builtin/fsck.c | 66 +++-- builtin/index-pack.c| 13 +- builtin/receive-pack.c | 35 ++- builtin/unpack-objects.c| 16 +- fsck.c | 525 +++- fsck.h | 27 ++- t/t1450-fsck.sh | 37 ++- t/t5302-pack-index.sh | 2 +- t/t5504-fetch-receive-strict.sh | 46 11 files changed, 648 insertions(+), 164 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 4f86d3f..0daba8a 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1209,14 +1209,14 @@ filter.driver.smudge:: linkgit:gitattributes[5] for details. fsck.*:: - With these options, fsck errors can be switched to warnings and - vice versa by setting e.g. `fsck.bad-name` to `warn` or `error` - (or `ignore` to hide those errors completely). For convenience, - fsck prefixes the error/warning with the name of the option, e.g. - missing-email: invalid author/committer line - missing email - means that setting `fsck.missing-email` to `ignore` will hide that - issue. For convenience, camelCased options are accepted, too (e.g. - `fsck.missingEmail`). + The `fsck.error`, `fsck.warn` and `fsck.ignore` settings specify + comma-separated lists of fsck message IDs which should trigger + fsck to error out, to print the message and continue, or to ignore + said messages, respectively. ++ +For convenience, fsck prefixes the error/warning with the name of the option, +e.g. missing-email: invalid author/committer line - missing email means +that setting `fsck.ignore = missing-email` will hide that issue. + This feature is intended to support working with legacy repositories which cannot be repaired without disruptive changes. @@ -2144,18 +2144,29 @@ receive.fsckObjects:: is used instead. receive.fsck.*:: - When `receive.fsckObjects is set to true, errors can be switched - to warnings and vice versa by setting e.g. `receive.fsck.bad-name` - to `warn` or `error` (or `ignore` to hide those errors - completely). For convenience, fsck prefixes the error/warning - with the name of the option, e.g. missing-email: invalid - author/committer line - missing email means that setting - `receive.fsck.missing-email` to `ignore` will hide that issue. - For convenience, camelCased options are accepted, too (e.g. - `receive.fsck.missingEmail`). + When `receive.fsckObjects` is set to true, errors can be switched + to warnings and vice versa by configuring the `receive.fsck.*` + settings. These settings contain comma-separated lists of fsck + message IDs. For convenience, fsck
[PATCH v2 04/18] fsck: Offer a function to demote fsck errors to warnings
There are legacy repositories out there whose older commits and tags have issues that prevent pushing them when 'receive.fsckObjects' is set. One real-life example is a commit object that has been hand-crafted to list two authors. Often, it is not possible to fix those issues without disrupting the work with said repositories, yet it is still desirable to perform checks by setting `receive.fsckObjects = true`. This commit is the first step to allow demoting specific fsck issues to mere warnings. The function added by this commit parses a list of settings in the form: missing-email=warn,bad-name=warn,... Unfortunately, the FSCK_WARN/FSCK_ERROR flag is only really heeded by git fsck so far, but other call paths (e.g. git index-pack --strict) error out *always* no matter what type was specified. Therefore, we need to take extra care to default to all FSCK_ERROR in those cases. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 64 +--- fsck.h | 7 +-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/fsck.c b/fsck.c index 2d91e28..7d4c22c 100644 --- a/fsck.c +++ b/fsck.c @@ -100,13 +100,67 @@ static int fsck_msg_severity(enum fsck_msg_id msg_id, { int severity; - severity = msg_id_info[msg_id].severity; - if (options-strict severity == FSCK_WARN) - severity = FSCK_ERROR; + if (options-msg_severity msg_id = 0 msg_id FSCK_MSG_MAX) + severity = options-msg_severity[msg_id]; + else { + severity = msg_id_info[msg_id].severity; + if (options-strict severity == FSCK_WARN) + severity = FSCK_ERROR; + } return severity; } +static inline int substrcmp(const char *string, int len, const char *match) +{ + int match_len = strlen(match); + if (match_len != len) + return -1; + return memcmp(string, match, len); +} + +void fsck_set_severity(struct fsck_options *options, const char *mode) +{ + int severity = FSCK_ERROR; + + if (!options-msg_severity) { + int i; + int *msg_severity = malloc(sizeof(int) * FSCK_MSG_MAX); + for (i = 0; i FSCK_MSG_MAX; i++) + msg_severity[i] = fsck_msg_severity(i, options); + options-msg_severity = msg_severity; + } + + while (*mode) { + int len = strcspn(mode, ,|), equal, msg_id; + + if (!len) { + mode++; + continue; + } + + for (equal = 0; equal len; equal++) + if (mode[equal] == '=') + break; + + if (equal len) { + if (!substrcmp(mode, equal, error)) + severity = FSCK_ERROR; + else if (!substrcmp(mode, equal, warn)) + severity = FSCK_WARN; + else + die(Unknown fsck message severity: '%.*s', + equal, mode); + mode += equal + 1; + len -= equal + 1; + } + + msg_id = parse_msg_id(mode, len); + options-msg_severity[msg_id] = severity; + mode += len; + } +} + __attribute__((format (printf, 4, 5))) static int report(struct fsck_options *options, struct object *object, enum fsck_msg_id id, const char *fmt, ...) @@ -596,6 +650,10 @@ int fsck_object(struct object *obj, void *data, unsigned long size, int fsck_error_function(struct object *obj, int severity, const char *message) { + if (severity == FSCK_WARN) { + warning(object %s: %s, sha1_to_hex(obj-sha1), message); + return 0; + } error(object %s: %s, sha1_to_hex(obj-sha1), message); return 1; } diff --git a/fsck.h b/fsck.h index f6f268a..4349860 100644 --- a/fsck.h +++ b/fsck.h @@ -6,6 +6,8 @@ struct fsck_options; +void fsck_set_severity(struct fsck_options *options, const char *mode); + /* * callback function for fsck_walk * type is the expected type of the object or OBJ_ANY @@ -25,10 +27,11 @@ struct fsck_options { fsck_walk_func walk; fsck_error error_func; unsigned strict:1; + int *msg_severity; }; -#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0 } -#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1 } +#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL } +#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL } /* descend in all linked child objects * the return value is: -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at
[PATCH v2 14/18] fsck: Allow upgrading fsck warnings to errors
The 'invalid tag name' and 'missing tagger entry' warnings can now be upgraded to errors by specifying `invalid-tag-name` and `missing-tagger-entry` to the receive.fsck.error config setting. Incidentally, the missing tagger warning is now really shown as a warning (as opposed to being reported with the error: prefix, as it used to be the case before this commit). Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c| 24 +--- t/t5302-pack-index.sh | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/fsck.c b/fsck.c index 649c8fe..480cd87 100644 --- a/fsck.c +++ b/fsck.c @@ -10,6 +10,7 @@ #include utf8.h #define FSCK_FATAL -1 +#define FSCK_INFO -2 #define FOREACH_MSG_ID(FUNC) \ /* fatal errors */ \ @@ -55,10 +56,11 @@ FUNC(HAS_DOT, WARN) \ FUNC(HAS_DOTDOT, WARN) \ FUNC(HAS_DOTGIT, WARN) \ - FUNC(INVALID_TAG_NAME, WARN) \ - FUNC(MISSING_TAGGER_ENTRY, WARN) \ FUNC(NULL_SHA1, WARN) \ - FUNC(ZERO_PADDED_FILEMODE, WARN) + FUNC(ZERO_PADDED_FILEMODE, WARN) \ + /* infos (reported as warnings, but ignored by default) */ \ + FUNC(INVALID_TAG_NAME, INFO) \ + FUNC(MISSING_TAGGER_ENTRY, INFO) #define MSG_ID(id, severity) FSCK_MSG_##id, enum fsck_msg_id { @@ -200,6 +202,8 @@ static int report(struct fsck_options *options, struct object *object, if (msg_severity == FSCK_FATAL) msg_severity = FSCK_ERROR; + else if (msg_severity == FSCK_INFO) + msg_severity = FSCK_WARN; append_msg_id(sb, msg_id_info[id].id_string); @@ -658,15 +662,21 @@ static int fsck_tag_buffer(struct tag *tag, const char *data, goto done; } strbuf_addf(sb, refs/tags/%.*s, (int)(eol - buffer), buffer); - if (check_refname_format(sb.buf, 0)) - report(options, tag-object, FSCK_MSG_INVALID_TAG_NAME, + if (check_refname_format(sb.buf, 0)) { + ret = report(options, tag-object, FSCK_MSG_INVALID_TAG_NAME, invalid 'tag' name: %.*s, (int)(eol - buffer), buffer); + if (ret) + goto done; + } buffer = eol + 1; - if (!skip_prefix(buffer, tagger , buffer)) + if (!skip_prefix(buffer, tagger , buffer)) { /* early tags do not contain 'tagger' lines; warn only */ - report(options, tag-object, FSCK_MSG_MISSING_TAGGER_ENTRY, invalid format - expected 'tagger' line); + ret = report(options, tag-object, FSCK_MSG_MISSING_TAGGER_ENTRY, invalid format - expected 'tagger' line); + if (ret) + goto done; + } else ret = fsck_ident(buffer, tag-object, options); diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 61bc8da..3dc5ec4 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -259,7 +259,7 @@ EOF thirtyeight=${tag#??} rm -f .git/objects/${tag%$thirtyeight}/$thirtyeight git index-pack --strict tag-test-${pack1}.pack 2err -grep ^error:.* expected .tagger. line err +grep ^warning:.* expected .tagger. line err ' test_done -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 18/18] fsck: git receive-pack: support excluding objects from fsck'ing
The optional new config option `receive.fsck.skiplist` specifies the path to a file listing the names, i.e. SHA-1s, one per line, of objects that are to be ignored by `git receive-pack` when `receive.fsckObjects = true`. This is extremely handy in case of legacy repositories where it would cause more pain to change incorrect objects than to live with them (e.g. a duplicate 'author' line in an early commit object). The intended use case is for server administrators to inspect objects that are reported by `git push` as being too problematic to enter the repository, and to add the objects' SHA-1 to a (preferably sorted) file when the objects are legitimate, i.e. when it is determined that those problematic objects should be allowed to enter the server. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- builtin/receive-pack.c | 9 +++ fsck.c | 53 + fsck.h | 1 + t/t5504-fetch-receive-strict.sh | 12 ++ 4 files changed, 75 insertions(+) diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index da2e019..40514c2 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -116,6 +116,15 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } + if (starts_with(var, receive.fsck.skiplist)) { + const char *path = is_absolute_path(value) ? + value : git_path(%s, value); + if (fsck_severity.len) + strbuf_addch(fsck_severity, ','); + strbuf_addf(fsck_severity, skiplist=%s, path); + return 0; + } + if (starts_with(var, receive.fsck.)) { if (fsck_severity.len) strbuf_addch(fsck_severity, ','); diff --git a/fsck.c b/fsck.c index 480cd87..dbf9fa1 100644 --- a/fsck.c +++ b/fsck.c @@ -8,6 +8,7 @@ #include fsck.h #include refs.h #include utf8.h +#include sha1-array.h #define FSCK_FATAL -1 #define FSCK_INFO -2 @@ -117,6 +118,43 @@ static int fsck_msg_severity(enum fsck_msg_id msg_id, return severity; } +static void init_skiplist(struct fsck_options *options, const char *path) +{ + static struct sha1_array skiplist = SHA1_ARRAY_INIT; + int sorted, fd; + char buffer[41]; + unsigned char sha1[20]; + + if (options-skiplist) + sorted = options-skiplist-sorted; + else { + sorted = 1; + options-skiplist = skiplist; + } + + fd = open(path, O_RDONLY); + if (fd 0) + die(Could not open skip list: %s, path); + for (;;) { + int result = read_in_full(fd, buffer, sizeof(buffer)); + if (result 0) + die_errno(Could not read '%s', path); + if (!result) + break; + if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') + die(Invalid SHA-1: %s, buffer); + sha1_array_append(skiplist, sha1); + if (sorted skiplist.nr 1 + hashcmp(skiplist.sha1[skiplist.nr - 2], + sha1) 0) + sorted = 0; + } + close(fd); + + if (sorted) + skiplist.sorted = 1; +} + static inline int substrcmp(const char *string, int len, const char *match) { int match_len = strlen(match); @@ -156,6 +194,17 @@ void fsck_set_severity(struct fsck_options *options, const char *mode) severity = FSCK_WARN; else if (!substrcmp(mode, equal, ignore)) severity = FSCK_IGNORE; + else if (!substrcmp(mode, equal, skiplist)) { + char *path = xstrndup(mode + equal + 1, + len - equal - 1); + + if (equal == len) + die(skiplist requires a path); + init_skiplist(options, path); + free(path); + mode += len; + continue; + } else die(Unknown fsck message severity: '%.*s', equal, mode); @@ -700,6 +749,10 @@ static int fsck_tag(struct tag *tag, const char *data, int fsck_object(struct object *obj, void *data, unsigned long size, struct fsck_options *options) { + if (options-skiplist + sha1_array_lookup(options-skiplist, obj-sha1) = 0) + return 0; + if (!obj) return report(options, obj, FSCK_MSG_INVALID_OBJECT_SHA1, no valid object to fsck); diff --git a/fsck.h b/fsck.h index
[PATCH v2 01/18] fsck: Introduce fsck options
Just like the diff machinery, we are about to introduce more settings, therefore it makes sense to carry them around as a (pointer to a) struct containing all of them. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- builtin/fsck.c | 20 +-- builtin/index-pack.c | 9 +-- builtin/unpack-objects.c | 11 ++-- fsck.c | 150 +++ fsck.h | 17 +- 5 files changed, 114 insertions(+), 93 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index a27515a..2241e29 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -25,6 +25,8 @@ static int include_reflogs = 1; static int check_full = 1; static int check_strict; static int keep_cache_objects; +static struct fsck_options fsck_walk_options = FSCK_OPTIONS_DEFAULT; +static struct fsck_options fsck_obj_options = FSCK_OPTIONS_DEFAULT; static unsigned char head_sha1[20]; static const char *head_points_at; static int errors_found; @@ -76,7 +78,7 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...) static struct object_array pending; -static int mark_object(struct object *obj, int type, void *data) +static int mark_object(struct object *obj, int type, void *data, struct fsck_options *options) { struct object *parent = data; @@ -119,7 +121,7 @@ static int mark_object(struct object *obj, int type, void *data) static void mark_object_reachable(struct object *obj) { - mark_object(obj, OBJ_ANY, NULL); + mark_object(obj, OBJ_ANY, NULL, NULL); } static int traverse_one_object(struct object *obj) @@ -132,7 +134,7 @@ static int traverse_one_object(struct object *obj) if (parse_tree(tree) 0) return 1; /* error already displayed */ } - result = fsck_walk(obj, mark_object, obj); + result = fsck_walk(obj, obj, fsck_walk_options); if (tree) free_tree_buffer(tree); return result; @@ -158,7 +160,7 @@ static int traverse_reachable(void) return !!result; } -static int mark_used(struct object *obj, int type, void *data) +static int mark_used(struct object *obj, int type, void *data, struct fsck_options *options) { if (!obj) return 1; @@ -296,9 +298,9 @@ static int fsck_obj(struct object *obj) fprintf(stderr, Checking %s %s\n, typename(obj-type), sha1_to_hex(obj-sha1)); - if (fsck_walk(obj, mark_used, NULL)) + if (fsck_walk(obj, NULL, fsck_obj_options)) objerror(obj, broken links); - if (fsck_object(obj, NULL, 0, check_strict, fsck_error_func)) + if (fsck_object(obj, NULL, 0, fsck_obj_options)) return -1; if (obj-type == OBJ_TREE) { @@ -630,6 +632,12 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0); + fsck_walk_options.walk = mark_object; + fsck_obj_options.walk = mark_used; + fsck_obj_options.error_func = fsck_error_func; + if (check_strict) + fsck_obj_options.strict = 1; + if (show_progress == -1) show_progress = isatty(2); if (verbose) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 4632117..925f7b5 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -74,6 +74,7 @@ static int nr_threads; static int from_stdin; static int strict; static int do_fsck_object; +static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT; static int verbose; static int show_stat; static int check_self_contained_and_connected; @@ -191,7 +192,7 @@ static void cleanup_thread(void) #endif -static int mark_link(struct object *obj, int type, void *data) +static int mark_link(struct object *obj, int type, void *data, struct fsck_options *options) { if (!obj) return -1; @@ -782,10 +783,10 @@ static void sha1_object(const void *data, struct object_entry *obj_entry, if (!obj) die(_(invalid %s), typename(type)); if (do_fsck_object - fsck_object(obj, buf, size, 1, - fsck_error_function)) + fsck_object(obj, buf, size, fsck_options)) die(_(Error in object)); - if (fsck_walk(obj, mark_link, NULL)) + fsck_options.walk = mark_link; + if (fsck_walk(obj, NULL, fsck_options)) die(_(Not all child objects of %s are reachable), sha1_to_hex(obj-sha1)); if (obj-type == OBJ_TREE) { diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index ac66672..6d17040 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -20,6 +20,7 @@
[PATCH v2 02/18] fsck: Introduce identifiers for fsck messages
Instead of specifying whether a message by the fsck machinery constitutes an error or a warning, let's specify an identifier relating to the concrete problem that was encountered. This is necessary for upcoming support to be able to demote certain errors to warnings. In the process, simplify the requirements on the calling code: instead of having to handle full-blown varargs in every callback, we now send a string buffer ready to be used by the callback. We could use a simple enum for the message IDs here, but we want to guarantee that the enum values are associated with the appropriate severity levels. Besides, we want to introduce a parser in the next commit that maps the string representation to the enum value, hence we use the slightly ugly preprocessor construct that is extensible for use with said parser. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- builtin/fsck.c | 24 ++- fsck.c | 201 + fsck.h | 5 +- 3 files changed, 153 insertions(+), 77 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index 2241e29..99d4538 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -47,32 +47,22 @@ static int show_dangling = 1; #endif static void objreport(struct object *obj, const char *severity, - const char *err, va_list params) + const char *err) { - fprintf(stderr, %s in %s %s: , - severity, typename(obj-type), sha1_to_hex(obj-sha1)); - vfprintf(stderr, err, params); - fputs(\n, stderr); + fprintf(stderr, %s in %s %s: %s\n, + severity, typename(obj-type), sha1_to_hex(obj-sha1), err); } -__attribute__((format (printf, 2, 3))) -static int objerror(struct object *obj, const char *err, ...) +static int objerror(struct object *obj, const char *err) { - va_list params; - va_start(params, err); errors_found |= ERROR_OBJECT; - objreport(obj, error, err, params); - va_end(params); + objreport(obj, error, err); return -1; } -__attribute__((format (printf, 3, 4))) -static int fsck_error_func(struct object *obj, int type, const char *err, ...) +static int fsck_error_func(struct object *obj, int type, const char *message) { - va_list params; - va_start(params, err); - objreport(obj, (type == FSCK_WARN) ? warning : error, err, params); - va_end(params); + objreport(obj, (type == FSCK_WARN) ? warning : error, message); return (type == FSCK_WARN) ? 0 : 1; } diff --git a/fsck.c b/fsck.c index d83b811..30f7a48 100644 --- a/fsck.c +++ b/fsck.c @@ -9,6 +9,98 @@ #include refs.h #include utf8.h +#define FOREACH_MSG_ID(FUNC) \ + /* errors */ \ + FUNC(BAD_DATE, ERROR) \ + FUNC(BAD_EMAIL, ERROR) \ + FUNC(BAD_NAME, ERROR) \ + FUNC(BAD_PARENT_SHA1, ERROR) \ + FUNC(BAD_TIMEZONE, ERROR) \ + FUNC(BAD_TREE_SHA1, ERROR) \ + FUNC(DATE_OVERFLOW, ERROR) \ + FUNC(DUPLICATE_ENTRIES, ERROR) \ + FUNC(INVALID_OBJECT_SHA1, ERROR) \ + FUNC(INVALID_TAG_OBJECT, ERROR) \ + FUNC(INVALID_TREE, ERROR) \ + FUNC(INVALID_TYPE, ERROR) \ + FUNC(MISSING_AUTHOR, ERROR) \ + FUNC(MISSING_COMMITTER, ERROR) \ + FUNC(MISSING_EMAIL, ERROR) \ + FUNC(MISSING_GRAFT, ERROR) \ + FUNC(MISSING_NAME_BEFORE_EMAIL, ERROR) \ + FUNC(MISSING_OBJECT, ERROR) \ + FUNC(MISSING_PARENT, ERROR) \ + FUNC(MISSING_SPACE_BEFORE_DATE, ERROR) \ + FUNC(MISSING_SPACE_BEFORE_EMAIL, ERROR) \ + FUNC(MISSING_TAG, ERROR) \ + FUNC(MISSING_TAG_ENTRY, ERROR) \ + FUNC(MISSING_TAG_OBJECT, ERROR) \ + FUNC(MISSING_TREE, ERROR) \ + FUNC(MISSING_TYPE, ERROR) \ + FUNC(MISSING_TYPE_ENTRY, ERROR) \ + FUNC(NOT_SORTED, ERROR) \ + FUNC(NUL_IN_HEADER, ERROR) \ + FUNC(TAG_OBJECT_NOT_TAG, ERROR) \ + FUNC(UNKNOWN_TYPE, ERROR) \ + FUNC(UNTERMINATED_HEADER, ERROR) \ + FUNC(ZERO_PADDED_DATE, ERROR) \ + /* warnings */ \ + FUNC(BAD_FILEMODE, WARN) \ + FUNC(EMPTY_NAME, WARN) \ + FUNC(FULL_PATHNAME, WARN) \ + FUNC(HAS_DOT, WARN) \ + FUNC(HAS_DOTDOT, WARN) \ + FUNC(HAS_DOTGIT, WARN) \ + FUNC(INVALID_TAG_NAME, WARN) \ + FUNC(MISSING_TAGGER_ENTRY, WARN) \ + FUNC(NULL_SHA1, WARN) \ + FUNC(ZERO_PADDED_FILEMODE, WARN) + +#define MSG_ID(id, severity) FSCK_MSG_##id, +enum fsck_msg_id { + FOREACH_MSG_ID(MSG_ID) + FSCK_MSG_MAX +}; +#undef MSG_ID + +#define MSG_ID(id, severity) { FSCK_##severity }, +static struct { + int severity; +} msg_id_info[FSCK_MSG_MAX + 1] = { + FOREACH_MSG_ID(MSG_ID) + { -1 } +}; +#undef MSG_ID + +static int fsck_msg_severity(enum fsck_msg_id msg_id, + struct fsck_options *options) +{ + int severity; + + severity = msg_id_info[msg_id].severity; + if (options-strict severity == FSCK_WARN) +
[PATCH v2 06/18] fsck: Report the ID of the error/warning
Some legacy code has objects with non-fatal fsck issues; To enable the user to ignore those issues, let's print out the ID (e.g. when encountering missing-email, the user might want to call `git config receive.fsck.warn missing-email`). Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 19 +++ t/t1450-fsck.sh | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index 7d4c22c..78944f0 100644 --- a/fsck.c +++ b/fsck.c @@ -161,6 +161,23 @@ void fsck_set_severity(struct fsck_options *options, const char *mode) } } +static void append_msg_id(struct strbuf *sb, const char *msg_id) +{ + for (;;) { + char c = *(msg_id)++; + + if (!c) + break; + if (c == '_') + c = '-'; + else + c = tolower(c); + strbuf_addch(sb, c); + } + + strbuf_addstr(sb, : ); +} + __attribute__((format (printf, 4, 5))) static int report(struct fsck_options *options, struct object *object, enum fsck_msg_id id, const char *fmt, ...) @@ -169,6 +186,8 @@ static int report(struct fsck_options *options, struct object *object, struct strbuf sb = STRBUF_INIT; int msg_severity = fsck_msg_severity(id, options), result; + append_msg_id(sb, msg_id_info[id].id_string); + va_start(ap, fmt); strbuf_vaddf(sb, fmt, ap); result = options-error_func(object, msg_severity, sb.buf); diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index cfb32b6..ea0f216 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -231,8 +231,8 @@ test_expect_success 'tag with incorrect tag name missing tagger' ' git fsck --tags 2out cat expect -EOF - warning in tag $tag: invalid '\''tag'\'' name: wrong name format - warning in tag $tag: invalid format - expected '\''tagger'\'' line + warning in tag $tag: invalid-tag-name: invalid '\''tag'\'' name: wrong name format + warning in tag $tag: missing-tagger-entry: invalid format - expected '\''tagger'\'' line EOF test_cmp expect out ' -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 08/18] fsck: Make fsck_commit() warn-friendly
When fsck_commit() identifies a problem with the commit, it should try to make it possible to continue checking the commit object, in case the user wants to demote the detected errors to mere warnings. Note that some problems are too problematic to simply ignore. For example, when the header lines are mixed up, we punt after encountering an incorrect line. Therefore, demoting certain warnings to errors can hide other problems. Example: demoting the missing-author error to a warning would hide a problematic committer line. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 28 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/fsck.c b/fsck.c index 233385b..a3b1429 100644 --- a/fsck.c +++ b/fsck.c @@ -508,12 +508,18 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer, if (!skip_prefix(buffer, tree , buffer)) return report(options, commit-object, FSCK_MSG_MISSING_TREE, invalid format - expected 'tree' line); - if (get_sha1_hex(buffer, tree_sha1) || buffer[40] != '\n') - return report(options, commit-object, FSCK_MSG_BAD_TREE_SHA1, invalid 'tree' line format - bad sha1); + if (get_sha1_hex(buffer, tree_sha1) || buffer[40] != '\n') { + err = report(options, commit-object, FSCK_MSG_BAD_TREE_SHA1, invalid 'tree' line format - bad sha1); + if (err) + return err; + } buffer += 41; while (skip_prefix(buffer, parent , buffer)) { - if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') - return report(options, commit-object, FSCK_MSG_BAD_PARENT_SHA1, invalid 'parent' line format - bad sha1); + if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') { + err = report(options, commit-object, FSCK_MSG_BAD_PARENT_SHA1, invalid 'parent' line format - bad sha1); + if (err) + return err; + } buffer += 41; parent_line_count++; } @@ -522,11 +528,17 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer, if (graft) { if (graft-nr_parent == -1 !parent_count) ; /* shallow commit */ - else if (graft-nr_parent != parent_count) - return report(options, commit-object, FSCK_MSG_MISSING_GRAFT, graft objects missing); + else if (graft-nr_parent != parent_count) { + err = report(options, commit-object, FSCK_MSG_MISSING_GRAFT, graft objects missing); + if (err) + return err; + } } else { - if (parent_count != parent_line_count) - return report(options, commit-object, FSCK_MSG_MISSING_PARENT, parent objects missing); + if (parent_count != parent_line_count) { + err = report(options, commit-object, FSCK_MSG_MISSING_PARENT, parent objects missing); + if (err) + return err; + } } if (!skip_prefix(buffer, author , buffer)) return report(options, commit-object, FSCK_MSG_MISSING_AUTHOR, invalid format - expected 'author' line); -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 07/18] fsck: Make fsck_ident() warn-friendly
When fsck_ident() identifies a problem with the ident, it should still advance the pointer to the next line so that fsck can continue in the case of a mere warning. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 49 +++-- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/fsck.c b/fsck.c index 78944f0..233385b 100644 --- a/fsck.c +++ b/fsck.c @@ -453,40 +453,45 @@ static int require_end_of_header(const void *data, unsigned long size, static int fsck_ident(const char **ident, struct object *obj, struct fsck_options *options) { + const char *p = *ident; char *end; - if (**ident == '') + *ident = strchrnul(*ident, '\n'); + if (**ident == '\n') + (*ident)++; + + if (*p == '') return report(options, obj, FSCK_MSG_MISSING_NAME_BEFORE_EMAIL, invalid author/committer line - missing space before email); - *ident += strcspn(*ident, \n); - if (**ident == '') + p += strcspn(p, \n); + if (*p == '') return report(options, obj, FSCK_MSG_BAD_NAME, invalid author/committer line - bad name); - if (**ident != '') + if (*p != '') return report(options, obj, FSCK_MSG_MISSING_EMAIL, invalid author/committer line - missing email); - if ((*ident)[-1] != ' ') + if (p[-1] != ' ') return report(options, obj, FSCK_MSG_MISSING_SPACE_BEFORE_EMAIL, invalid author/committer line - missing space before email); - (*ident)++; - *ident += strcspn(*ident, \n); - if (**ident != '') + p++; + p += strcspn(p, \n); + if (*p != '') return report(options, obj, FSCK_MSG_BAD_EMAIL, invalid author/committer line - bad email); - (*ident)++; - if (**ident != ' ') + p++; + if (*p != ' ') return report(options, obj, FSCK_MSG_MISSING_SPACE_BEFORE_DATE, invalid author/committer line - missing space before date); - (*ident)++; - if (**ident == '0' (*ident)[1] != ' ') + p++; + if (*p == '0' p[1] != ' ') return report(options, obj, FSCK_MSG_ZERO_PADDED_DATE, invalid author/committer line - zero-padded date); - if (date_overflows(strtoul(*ident, end, 10))) + if (date_overflows(strtoul(p, end, 10))) return report(options, obj, FSCK_MSG_DATE_OVERFLOW, invalid author/committer line - date causes integer overflow); - if (end == *ident || *end != ' ') + if ((end == p || *end != ' ')) return report(options, obj, FSCK_MSG_BAD_DATE, invalid author/committer line - bad date); - *ident = end + 1; - if ((**ident != '+' **ident != '-') || - !isdigit((*ident)[1]) || - !isdigit((*ident)[2]) || - !isdigit((*ident)[3]) || - !isdigit((*ident)[4]) || - ((*ident)[5] != '\n')) + p = end + 1; + if ((*p != '+' *p != '-') || + !isdigit(p[1]) || + !isdigit(p[2]) || + !isdigit(p[3]) || + !isdigit(p[4]) || + (p[5] != '\n')) return report(options, obj, FSCK_MSG_BAD_TIMEZONE, invalid author/committer line - bad time zone); - (*ident) += 6; + p += 6; return 0; } -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 13/18] fsck: Optionally ignore specific fsck issues completely
An fsck issue in a legacy repository might be so common that one would like not to bother the user with mentioning it at all. With this change, that is possible by setting the respective error to ignore. This change abuses the warn=missing-email test to verify that ignore is also accepted and works correctly. And while at it, it makes sure that multiple options work, too (they are passed to unpack-objects or index-pack as a comma-separated list via the --strict=... command-line option). Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 5 + fsck.h | 1 + t/t5504-fetch-receive-strict.sh | 7 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/fsck.c b/fsck.c index f2c8044..649c8fe 100644 --- a/fsck.c +++ b/fsck.c @@ -152,6 +152,8 @@ void fsck_set_severity(struct fsck_options *options, const char *mode) severity = FSCK_ERROR; else if (!substrcmp(mode, equal, warn)) severity = FSCK_WARN; + else if (!substrcmp(mode, equal, ignore)) + severity = FSCK_IGNORE; else die(Unknown fsck message severity: '%.*s', equal, mode); @@ -193,6 +195,9 @@ static int report(struct fsck_options *options, struct object *object, struct strbuf sb = STRBUF_INIT; int msg_severity = fsck_msg_severity(id, options), result; + if (msg_severity == FSCK_IGNORE) + return 0; + if (msg_severity == FSCK_FATAL) msg_severity = FSCK_ERROR; diff --git a/fsck.h b/fsck.h index 4349860..7be6c50 100644 --- a/fsck.h +++ b/fsck.h @@ -3,6 +3,7 @@ #define FSCK_ERROR 1 #define FSCK_WARN 2 +#define FSCK_IGNORE 3 struct fsck_options; diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 2757c3a..e81cedb 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -132,7 +132,12 @@ test_expect_success 'push with receive.fsck.warn = missing-email' ' test_must_fail git push --porcelain dst bogus git --git-dir=dst/.git config receive.fsck.warn missing-email git push --porcelain dst bogus act 21 - grep missing-email act + grep missing-email act + git --git-dir=dst/.git branch -D bogus + git --git-dir=dst/.git config receive.fsck.ignore missing-email + git --git-dir=dst/.git config receive.fsck.warn bad-date + git push --porcelain dst bogus act 21 + test_must_fail grep missing-email act ' test_expect_success 'receive.fsck.warn = unterminated-header triggers error' ' -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 09/18] fsck: Handle multiple authors in commits specially
This problem has been detected in the wild, and is the primary reason to introduce an option to demote certain fsck errors to warnings. Let's offer to ignore this particular problem specifically. Technically, we could handle such repositories by setting receive.fsck.warn = missing-committer, but that could hide missing tree objects in the same commit because we cannot continue verifying any commit object after encountering a missing committer line, while we can continue in the case of multiple author lines. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 9 + 1 file changed, 9 insertions(+) diff --git a/fsck.c b/fsck.c index a3b1429..ed0a669 100644 --- a/fsck.c +++ b/fsck.c @@ -38,6 +38,7 @@ FUNC(MISSING_TREE, ERROR) \ FUNC(MISSING_TYPE, ERROR) \ FUNC(MISSING_TYPE_ENTRY, ERROR) \ + FUNC(MULTIPLE_AUTHORS, ERROR) \ FUNC(NOT_SORTED, ERROR) \ FUNC(NUL_IN_HEADER, ERROR) \ FUNC(TAG_OBJECT_NOT_TAG, ERROR) \ @@ -545,6 +546,14 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer, err = fsck_ident(buffer, commit-object, options); if (err) return err; + while (skip_prefix(buffer, author , buffer)) { + err = report(options, commit-object, FSCK_MSG_MULTIPLE_AUTHORS, invalid format - multiple 'author' lines); + if (err) + return err; + err = fsck_ident(buffer, commit-object, options); + if (err) + return err; + } if (!skip_prefix(buffer, committer , buffer)) return report(options, commit-object, FSCK_MSG_MISSING_COMMITTER, invalid format - expected 'committer' line); err = fsck_ident(buffer, commit-object, options); -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 12/18] fsck: Disallow demoting grave fsck errors to warnings
Some kinds of errors are intrinsically unrecoverable (e.g. errors while uncompressing objects). It does not make sense to allow demoting them to mere warnings. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 13 +++-- t/t5504-fetch-receive-strict.sh | 9 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index b8cbbfb..f2c8044 100644 --- a/fsck.c +++ b/fsck.c @@ -9,7 +9,12 @@ #include refs.h #include utf8.h +#define FSCK_FATAL -1 + #define FOREACH_MSG_ID(FUNC) \ + /* fatal errors */ \ + FUNC(NUL_IN_HEADER, FATAL) \ + FUNC(UNTERMINATED_HEADER, FATAL) \ /* errors */ \ FUNC(BAD_DATE, ERROR) \ FUNC(BAD_EMAIL, ERROR) \ @@ -40,10 +45,8 @@ FUNC(MISSING_TYPE_ENTRY, ERROR) \ FUNC(MULTIPLE_AUTHORS, ERROR) \ FUNC(NOT_SORTED, ERROR) \ - FUNC(NUL_IN_HEADER, ERROR) \ FUNC(TAG_OBJECT_NOT_TAG, ERROR) \ FUNC(UNKNOWN_TYPE, ERROR) \ - FUNC(UNTERMINATED_HEADER, ERROR) \ FUNC(ZERO_PADDED_DATE, ERROR) \ /* warnings */ \ FUNC(BAD_FILEMODE, WARN) \ @@ -157,6 +160,9 @@ void fsck_set_severity(struct fsck_options *options, const char *mode) } msg_id = parse_msg_id(mode, len); + if (severity != FSCK_ERROR + msg_id_info[msg_id].severity == FSCK_FATAL) + die(Cannot demote %.*s, len, mode); options-msg_severity[msg_id] = severity; mode += len; } @@ -187,6 +193,9 @@ static int report(struct fsck_options *options, struct object *object, struct strbuf sb = STRBUF_INIT; int msg_severity = fsck_msg_severity(id, options), result; + if (msg_severity == FSCK_FATAL) + msg_severity = FSCK_ERROR; + append_msg_id(sb, msg_id_info[id].id_string); va_start(ap, fmt); diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index d491172..2757c3a 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -135,4 +135,13 @@ test_expect_success 'push with receive.fsck.warn = missing-email' ' grep missing-email act ' +test_expect_success 'receive.fsck.warn = unterminated-header triggers error' ' + rm -rf dst + git init dst + git --git-dir=dst/.git config receive.fsckobjects true + git --git-dir=dst/.git config receive.fsck.warn unterminated-header + test_must_fail git push --porcelain dst HEAD act 21 + grep Cannot demote unterminated-header act +' + test_done -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 03/18] fsck: Provide a function to parse fsck message IDs
This function will be used in the next commits to allow the user to ask fsck to handle specific problems differently, e.g. demoting certain errors to warnings. It has to handle partial strings because we would like to be able to parse, say, 'missing-email,missing-tagger-entry' command lines. To make the parsing robust, we generate strings from the enum keys, and using these keys, we will map lower-case, dash-separated strings values to the corresponding enum values. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 27 +-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/fsck.c b/fsck.c index 30f7a48..2d91e28 100644 --- a/fsck.c +++ b/fsck.c @@ -63,15 +63,38 @@ enum fsck_msg_id { }; #undef MSG_ID -#define MSG_ID(id, severity) { FSCK_##severity }, +#define STR(x) #x +#define MSG_ID(id, severity) { STR(id), FSCK_##severity }, static struct { + const char *id_string; int severity; } msg_id_info[FSCK_MSG_MAX + 1] = { FOREACH_MSG_ID(MSG_ID) - { -1 } + { NULL, -1 } }; #undef MSG_ID +static int parse_msg_id(const char *text, int len) +{ + int i, j; + + for (i = 0; i FSCK_MSG_MAX; i++) { + const char *key = msg_id_info[i].id_string; + /* id_string is upper-case, with underscores */ + for (j = 0; j len; j++) { + char c = *(key++); + if (c == '_') + c = '-'; + if (text[j] != tolower(c)) + break; + } + if (j == len !*key) + return i; + } + + die(Unhandled message id: %.*s, len, text); +} + static int fsck_msg_severity(enum fsck_msg_id msg_id, struct fsck_options *options) { -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 05/18] fsck: Allow demoting errors to warnings via receive.fsck.warn = key
For example, missing emails in commit and tag objects can be demoted to mere warnings with git config receive.fsck.warn = missing-email The value is actually a comma-separated list, and there is a corresponding receive.fsck.error setting. In case that the same key is listed in multiple receive.fsck.* lines in the config, the latter configuration wins. As git receive-pack does not actually perform the checks, it hands off the setting to index-pack or unpack-objects in the form of an optional argument to the --strict option. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- builtin/index-pack.c | 4 builtin/receive-pack.c | 26 ++ builtin/unpack-objects.c | 5 + 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 925f7b5..f464ca0 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1565,6 +1565,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) } else if (!strcmp(arg, --strict)) { strict = 1; do_fsck_object = 1; + } else if (starts_with(arg, --strict=)) { + strict = 1; + do_fsck_object = 1; + fsck_set_severity(fsck_options, arg + 9); } else if (!strcmp(arg, --check-self-contained-and-connected)) { strict = 1; check_self_contained_and_connected = 1; diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index e0ce78e..da2e019 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -36,6 +36,7 @@ static enum deny_action deny_current_branch = DENY_UNCONFIGURED; static enum deny_action deny_delete_current = DENY_UNCONFIGURED; static int receive_fsck_objects = -1; static int transfer_fsck_objects = -1; +static struct strbuf fsck_severity = STRBUF_INIT; static int receive_unpack_limit = -1; static int transfer_unpack_limit = -1; static int advertise_atomic_push = 1; @@ -115,6 +116,13 @@ static int receive_pack_config(const char *var, const char *value, void *cb) return 0; } + if (starts_with(var, receive.fsck.)) { + if (fsck_severity.len) + strbuf_addch(fsck_severity, ','); + strbuf_addf(fsck_severity, %s=%s, var + 13, value); + return 0; + } + if (strcmp(var, receive.fsckobjects) == 0) { receive_fsck_objects = git_config_bool(var, value); return 0; @@ -1470,8 +1478,13 @@ static const char *unpack(int err_fd, struct shallow_info *si) argv_array_pushl(child.args, unpack-objects, hdr_arg, NULL); if (quiet) argv_array_push(child.args, -q); - if (fsck_objects) - argv_array_push(child.args, --strict); + if (fsck_objects) { + if (fsck_severity.len) + argv_array_pushf(child.args, --strict=%s, + fsck_severity.buf); + else + argv_array_push(child.args, --strict); + } child.no_stdout = 1; child.err = err_fd; child.git_cmd = 1; @@ -1488,8 +1501,13 @@ static const char *unpack(int err_fd, struct shallow_info *si) argv_array_pushl(child.args, index-pack, --stdin, hdr_arg, keep_arg, NULL); - if (fsck_objects) - argv_array_push(child.args, --strict); + if (fsck_objects) { + if (fsck_severity.len) + argv_array_pushf(child.args, --strict=%s, + fsck_severity.buf); + else + argv_array_push(child.args, --strict); + } if (fix_thin) argv_array_push(child.args, --fix-thin); child.out = -1; diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c index 6d17040..82f2d62 100644 --- a/builtin/unpack-objects.c +++ b/builtin/unpack-objects.c @@ -530,6 +530,11 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix) strict = 1; continue; } + if (starts_with(arg, --strict=)) { + strict = 1; + fsck_set_severity(fsck_options, arg + 9); + continue; + } if (starts_with(arg, --pack_header=)) { struct pack_header *hdr;
[PATCH v2 15/18] fsck: Document the new receive.fsck.* options.
Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- Documentation/config.txt | 25 + 1 file changed, 25 insertions(+) diff --git a/Documentation/config.txt b/Documentation/config.txt index ae6791d..7371a5f 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -2130,6 +2130,31 @@ receive.fsckObjects:: Defaults to false. If not set, the value of `transfer.fsckObjects` is used instead. +receive.fsck.*:: + When `receive.fsckObjects` is set to true, errors can be switched + to warnings and vice versa by configuring the `receive.fsck.*` + settings. These settings contain comma-separated lists of fsck + message IDs. For convenience, fsck prefixes the error/warning with + the message ID, e.g. missing-email: invalid author/committer line + - missing email means that setting `receive.fsck.ignore = + missing-email` will hide that issue. ++ +-- + error:: + a comma-separated list of fsck message IDs that should be + trigger fsck to error out. + warn:: + a comma-separated list of fsck message IDs that should be + displayed, but fsck should continue to error out. + ignore:: + a comma-separated list of fsck message IDs that should be + ignored completely. ++ +This feature is intended to support working with legacy repositories +which would not pass pushing when `receive.fsckObjects = true`, allowing +the host to accept repositories certain known issues but still catch +other issues. + receive.unpackLimit:: If the number of objects received in a push is below this limit then the objects will be unpacked into loose object -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 16/18] fsck: Support demoting errors to warnings
We already have support in `git receive-pack` to deal with some legacy repositories which have non-fatal issues. Let's make `git fsck` itself useful with such repositories, too, by allowing users to ignore known issues, or at least demote those issues to mere warnings. Example: `git -c fsck.ignore=missing-email fsck` would hide problems with missing emails in author, committer and tagger lines. In the same spirit that `git receive-pack`'s usage of the fsck machinery differs from `git fsck`'s – some of the non-fatal warnings in `git fsck` are fatal with `git receive-pack` when receive.fsckObjects = true, for example – we strictly separate the fsck.* from the receive.fsck.* settings. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- Documentation/config.txt | 13 + builtin/fsck.c | 15 +++ t/t1450-fsck.sh | 11 +++ 3 files changed, 39 insertions(+) diff --git a/Documentation/config.txt b/Documentation/config.txt index 7371a5f..0daba8a 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1208,6 +1208,19 @@ filter.driver.smudge:: object to a worktree file upon checkout. See linkgit:gitattributes[5] for details. +fsck.*:: + The `fsck.error`, `fsck.warn` and `fsck.ignore` settings specify + comma-separated lists of fsck message IDs which should trigger + fsck to error out, to print the message and continue, or to ignore + said messages, respectively. ++ +For convenience, fsck prefixes the error/warning with the name of the option, +e.g. missing-email: invalid author/committer line - missing email means +that setting `fsck.ignore = missing-email` will hide that issue. ++ +This feature is intended to support working with legacy repositories +which cannot be repaired without disruptive changes. + gc.aggressiveDepth:: The depth parameter used in the delta compression algorithm used by 'git gc --aggressive'. This defaults diff --git a/builtin/fsck.c b/builtin/fsck.c index 99d4538..d5403c4 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -46,6 +46,19 @@ static int show_dangling = 1; #define DIRENT_SORT_HINT(de) ((de)-d_ino) #endif +static int fsck_config(const char *var, const char *value, void *cb) +{ + if (starts_with(var, fsck.)) { + struct strbuf sb = STRBUF_INIT; + strbuf_addf(sb, %s=%s, var + 5, value); + fsck_set_severity(fsck_obj_options, sb.buf); + strbuf_release(sb); + return 0; + } + + return git_default_config(var, value, cb); +} + static void objreport(struct object *obj, const char *severity, const char *err) { @@ -638,6 +651,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) include_reflogs = 0; } + git_config(fsck_config, NULL); + fsck_head_link(); fsck_object_dir(get_object_directory()); diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index ea0f216..a79ff9f 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -287,6 +287,17 @@ test_expect_success 'rev-list --verify-objects with bad sha1' ' grep -q error: sha1 mismatch 63ff out ' +test_expect_success 'force fsck to ignore double author' ' + git cat-file commit HEAD basis + sed s/^author .*/,/ basis | tr , \\n multiple-authors + new=$(git hash-object -t commit -w --stdin multiple-authors) + test_when_finished remove_object $new + git update-ref refs/heads/bogus $new + test_when_finished git update-ref -d refs/heads/bogus + test_must_fail git fsck + git -c fsck.ignore=multiple-authors fsck +' + _bz='\0' _bz5=$_bz$_bz$_bz$_bz$_bz _bz20=$_bz5$_bz5$_bz5$_bz5 -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 11/18] fsck: Add a simple test for receive.fsck.*
Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- t/t5504-fetch-receive-strict.sh | 20 1 file changed, 20 insertions(+) diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 69ee13c..d491172 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -115,4 +115,24 @@ test_expect_success 'push with transfer.fsckobjects' ' test_cmp exp act ' +cat bogus-commit EOF +tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +author Bugs Bunny 1234567890 + +committer Bugs Bunny b...@bun.ni 1234567890 + + +This commit object intentionally broken +EOF + +test_expect_success 'push with receive.fsck.warn = missing-email' ' + commit=$(git hash-object -t commit -w --stdin bogus-commit) + git push . $commit:refs/heads/bogus + rm -rf dst + git init dst + git --git-dir=dst/.git config receive.fsckobjects true + test_must_fail git push --porcelain dst bogus + git --git-dir=dst/.git config receive.fsck.warn missing-email + git push --porcelain dst bogus act 21 + grep missing-email act +' + test_done -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 10/18] fsck: Make fsck_tag() warn-friendly
When fsck_tag() identifies a problem with the commit, it should try to make it possible to continue checking the commit object, in case the user wants to demote the detected errors to mere warnings. Just like fsck_commit(), there are certain problems that could hide other issues with the same tag object. For example, if the 'type' line is not encountered in the correct position, the 'tag' line – if there is any – would not be handled at all. Signed-off-by: Johannes Schindelin johannes.schinde...@gmx.de --- fsck.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fsck.c b/fsck.c index ed0a669..b8cbbfb 100644 --- a/fsck.c +++ b/fsck.c @@ -614,7 +614,8 @@ static int fsck_tag_buffer(struct tag *tag, const char *data, } if (get_sha1_hex(buffer, sha1) || buffer[40] != '\n') { ret = report(options, tag-object, FSCK_MSG_INVALID_OBJECT_SHA1, invalid 'object' line format - bad sha1); - goto done; + if (ret) + goto done; } buffer += 41; -- 2.0.0.rc3.9669.g840d1f9 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Regarding the determinacy of 'git describe'
On Fri, 16 Jan 2015 14:29:17 +, Andreas Krey wrote: ... === /tmp/tmp-ws-20150116-11355-v7zfcc searching to describe HEAD lightweight4 r2.4/bl-0 lightweight4 r2.4/bl-1 traversed 5 commits r2.4/bl-0-4-g689e350 Apparently, this comes because two of the commit have the same timestamp, affecting the log ordering (and presumably the order in which they are used by 'git describe' as well). Also explains why it happens with different probability on different machines. But should 'git describe' behave this way? Andreas -- Totally trivial. Famous last words. From: Linus Torvalds torvalds@*.org Date: Fri, 22 Jan 2010 07:29:21 -0800 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
dog harness, dog leash, dog clothes and dog carrier
Hi, this is Jeff Wu from China. We are a wholesaler of pet products. Main products are pet clothes, leash, harness, collar, bag and accessory. Please let me know if you are interested to buy from us, thanks! I will send the price lists and website to you then. Best regards, Jeff Wu -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] connect.c: Improve parsing of literal IPV6 addresses
When parsing an URL, older Git versions did handle URLs like ssh://2001:db8::1/repo.git the same way as ssh://[2001:db8::1]/repo.git Commit 83b058 broke the parsing of IPV6 adresses without []: It was written in mind that the fist ':' in a URL was the beginning of a port number, while the old code was more clever: Literal IPV6 addresses have always at least two ':'. When the hostandport had a ':' and the rest of the hostandport string could be parsed into an integer between 0 and 65536, then it was used as a port number, like host:22. Otherwise the first ':' was assumed to be part of a literal IPV6 address, like ssh://[2001:db8::1]/repo.git or ssh://[::1]/repo.git. Re-introduce the old parsing in get_host_and_port(). Improve the parsing to handle URLs which have a user name and a literal IPV6 like ssh://user@[2001:db8::1]/repo.git. (Thanks to Christian Taube li...@hcf.yourweb.de for reporting this long standing issue) Another regression was introduced in 83b058: A non-RFC conform URL like [localhost:222] could be used in older versions of Git to connect to run ssh -p 222 localhost. The new stricter parsing did not allow this any more. See even 8d3d28f5dba why [localhost:222] should be declared a feature. Signed-off-by: Torsten Bögershausen tbo...@web.de --- Unfortunatly my attemps to improve connect.c introduced some regressions: - git clone ssh://::1/repo did not work anymore (for some reason I assumed that literall IPV6 addresses always should have brackets, but that was wrong) - ssh://host:/repo written in the unofficial short form [host:]:repo did not work anymore. I think that should be an unoffical feature, because it worked in older Git versions On top of that, the combination of ssh://username@[host] had never be handled correctly, so fix that as well. Thanks to Christian Taube for reporting it. Comments and an extra pair of critical eyes are welcome. connect.c| 63 ++-- t/t5601-clone.sh | 2 +- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/connect.c b/connect.c index d47d0ec..b608976 100644 --- a/connect.c +++ b/connect.c @@ -274,28 +274,44 @@ static enum protocol get_protocol(const char *name) die(I don't handle protocol '%s', name); } +static char *host_end(char **hoststart, int removebrackets) +{ + char *host = *hoststart; + char *end; + char *start = strstr(host, @[); + if (start) + start++; /* Jump over '@' */ + else + start = host; + if (start[0] == '[') { + end = strchr(start + 1, ']'); + if (end) { + if (removebrackets) { + *end = 0; + memmove(start, start + 1, end - start); + end++; + } + } else + end = host; + } else + end = host; + return end; +} + #define STR_(s)# s #define STR(s) STR_(s) static void get_host_and_port(char **host, const char **port) { char *colon, *end; - - if (*host[0] == '[') { - end = strchr(*host + 1, ']'); - if (end) { - *end = 0; - end++; - (*host)++; - } else - end = *host; - } else - end = *host; + end = host_end(host, 1); colon = strchr(end, ':'); - if (colon) { - *colon = 0; - *port = colon + 1; + long portnr = strtol(colon + 1, end, 10); + if (end != colon + 1 *end == '\0' 0 = portnr portnr 65536) { + *colon = 0; + *port = colon + 1; + } } } @@ -547,13 +563,16 @@ static struct child_process *git_proxy_connect(int fd[2], char *host) return proxy; } -static const char *get_port_numeric(const char *p) +static char *get_port(char *host) { char *end; + char *p = strchr(host, ':'); + if (p) { long port = strtol(p + 1, end, 10); if (end != p + 1 *end == '\0' 0 = port port 65536) { - return p; + *p = '\0'; + return p+1; } } @@ -595,14 +614,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host, * Don't do destructive transforms as protocol code does * '[]' unwrapping in get_host_and_port() */ - if (host[0] == '[') { - end = strchr(host + 1, ']'); - if (end) { - end++; - } else - end = host; - } else - end = host; + end = host_end(host, 0); if (protocol == PROTO_LOCAL) path = end; @@ -705,7
[PATCH 3/3] t5500: Show user name and host in diag-url
The URL for ssh may have include a username before the hostname, like ssh://user@host/repo. When literal IPV6 addresses are used together with a username, the substring user@[::1] must be converted into user@::1. Make that conversion visible for the user, and write userandhost in the diagnostics Signed-off-by: Torsten Bögershausen tbo...@web.de --- connect.c | 35 +++ t/t5500-fetch-pack.sh | 51 +-- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/connect.c b/connect.c index b608976..84f8156 100644 --- a/connect.c +++ b/connect.c @@ -675,7 +675,7 @@ struct child_process *git_connect(int fd[2], const char *url, signal(SIGCHLD, SIG_DFL); protocol = parse_connect_url(url, hostandport, path); - if (flags CONNECT_DIAG_URL) { + if ((flags CONNECT_DIAG_URL) (protocol != PROTO_SSH)) { printf(Diag: url=%s\n, url ? url : NULL); printf(Diag: protocol=%s\n, prot_name(protocol)); printf(Diag: hostandport=%s\n, hostandport ? hostandport : NULL); @@ -719,18 +719,29 @@ struct child_process *git_connect(int fd[2], const char *url, get_host_and_port(ssh_host, port); if (!port) port = get_port(ssh_host); - - if (!ssh) ssh = ssh; - - argv_array_push(conn-args, ssh); - if (putty !strcasestr(ssh, tortoiseplink)) - argv_array_push(conn-args, -batch); - if (port) { - /* P is for PuTTY, p is for OpenSSH */ - argv_array_push(conn-args, putty ? -P : -p); - argv_array_push(conn-args, port); + if (flags CONNECT_DIAG_URL) { + printf(Diag: url=%s\n, url ? url : NULL); + printf(Diag: protocol=%s\n, prot_name(protocol)); + printf(Diag: userandhost=%s\n, ssh_host ? ssh_host : NULL); + printf(Diag: port=%s\n, port ? port : NONE); + printf(Diag: path=%s\n, path ? path : NULL); + + free(hostandport); + free(path); + return NULL; + } else { + if (!ssh) ssh = ssh; + + argv_array_push(conn-args, ssh); + if (putty !strcasestr(ssh, tortoiseplink)) + argv_array_push(conn-args, -batch); + if (port) { + /* P is for PuTTY, p is for OpenSSH */ + argv_array_push(conn-args, putty ? -P : -p); + argv_array_push(conn-args, port); + } + argv_array_push(conn-args, ssh_host); } - argv_array_push(conn-args, ssh_host); } else { /* remove repo-local variables from the environment */ conn-env = local_repo_env; diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 5b2b1c2..bd37f04 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -541,13 +541,30 @@ check_prot_path () { test_cmp expected actual } -check_prot_host_path () { - cat expected -EOF +check_prot_host_port_path () { + local diagport + case $2 in + *ssh*) + pp=ssh + uah=userandhost + ehost=$(echo $3 | tr -d []) + diagport=Diag: port=$4 + ;; + *) + pp=$p + uah=hostandport + ehost=$(echo $3$4 | sed -e s/22$/:22/ -e s/NONE//) + diagport= + ;; + esac + cat exp -EOF Diag: url=$1 - Diag: protocol=$2 - Diag: hostandport=$3 - Diag: path=$4 + Diag: protocol=$pp + Diag: $uah=$ehost + $diagport + Diag: path=$5 EOF + grep -v ^$ exp expected git fetch-pack --diag-url $1 actual test_cmp expected actual } @@ -557,22 +574,20 @@ do # git or ssh with scheme for p in ssh+git git+ssh git ssh do - for h in host host:12 [::1] [::1]:23 + for h in host user@host user@[::1] user@::1 do - case $p in - *ssh*) - pp=ssh - ;; - *) - pp=$p - ;; - esac
[PATCH 2/3] t5601: Add more test cases for IPV6
Test the parsing of literall IPV6 addresses more systematically: - with and without brackets (e.g. ::1 [::1]) - with brackets and port number: (e.g. [::1]:22) - with username (e.g. user@::1) - with username and brackets: Because user@[::1] was not supported on older Git version, [user@::1] had to be used as a workaround. Test that user@::1 user@[::1] and [user@::1] all do the same. Signed-off-by: Torsten Bögershausen tbo...@web.de --- t/t5601-clone.sh | 57 +++- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index f901b8a..02b40b1 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -301,11 +301,17 @@ expect_ssh () { (cd $TRASH_DIRECTORY rm -f ssh-expect ssh-output) ' { - case $1 in - none) + case $# in + 1) ;; - *) + 2) echo ssh: $1 git-upload-pack '$2' + ;; + 3) + echo ssh: $1 $2 git-upload-pack '$3' + ;; + *) + echo ssh: $1 $2 git-upload-pack '$3' $4 esac } $TRASH_DIRECTORY/ssh-expect (cd $TRASH_DIRECTORY test_cmp ssh-expect ssh-output) @@ -336,7 +342,8 @@ counter=0 test_clone_url () { counter=$(($counter + 1)) test_might_fail git clone $1 tmp$counter - expect_ssh $2 $3 + shift + expect_ssh $@ } test_expect_success !MINGW 'clone c:temp is ssl' ' @@ -359,7 +366,7 @@ done for repo in rep rep/home/project 123 do test_expect_success clone [::1]:$repo ' - test_clone_url [::1]:$repo ::1 $repo + test_clone_url [::1]:$repo ::1 $repo ' done #home directory @@ -400,24 +407,40 @@ test_expect_success 'clone ssh://host.xz:22/~repo' ' ' #IPv6 -test_expect_success 'clone ssh://[::1]/home/user/repo' ' - test_clone_url ssh://[::1]/home/user/repo ::1 /home/user/repo -' +for tuah in ::1 [::1] user@::1 user@[::1] [user@::1] +do + ehost=$(echo $tuah | tr -d []) + test_expect_success clone ssh://$tuah/home/user/repo + test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo + +done #IPv6 from home directory -test_expect_success 'clone ssh://[::1]/~repo' ' - test_clone_url ssh://[::1]/~repo ::1 ~repo -' +for tuah in ::1 [::1] user@::1 user@[::1] [user@::1] +do + euah=$(echo $tuah | tr -d []) + test_expect_success clone ssh://$tuah/~repo + test_clone_url ssh://$tuah/~repo $euah '~repo' + +done #IPv6 with port number -test_expect_success 'clone ssh://[::1]:22/home/user/repo' ' - test_clone_url ssh://[::1]:22/home/user/repo -p 22 ::1 /home/user/repo -' +for tuah in [::1] user@[::1] [user@::1] +do + euah=$(echo $tuah | tr -d []) + test_expect_success clone ssh://$tuah:22/home/user/repo + test_clone_url ssh://$tuah:22/home/user/repo '-p 22' $euah /home/user/repo + +done #IPv6 from home directory with port number -test_expect_success 'clone ssh://[::1]:22/~repo' ' - test_clone_url ssh://[::1]:22/~repo -p 22 ::1 ~repo -' +for tuah in [::1] user@[::1] [user@::1] +do + euah=$(echo $tuah | tr -d []) + test_expect_success clone ssh://$tuah:22/~repo + test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo' + +done test_expect_success 'clone from a repository with two identical branches' ' -- 2.2.0.rc1.26.g3e3a70d -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
git config --global not picking up includes
I have found that `git config --global` does not pick up any include directives in the git config file. For instance, my ~/.gitconfig contains the following: [include] path = /home/garrison/gitconfig-include And ~/gitconfig-include in turn contains [user] name = Jim Garrison However, when I pass the --global flag to git config, my name is not picked up: $ git config --global user.name $ git config user.name Jim Garrison If I instead replace .gitconfig with the contents of gitconfig-include (and in turn remove the include step), everything works as expected. $ git config --global user.name Jim Garrison $ git config user.name Jim Garrison I am using the latest git master, built on Debian jessie. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] git-config: better document default behavior for `--include`
On Mon, Jan 19, 2015 at 11:37:10AM -0800, Jim Garrison wrote: I have found that `git config --global` does not pick up any include directives in the git config file. That's by design. You asked for the entries in a specific file, and we do not follow any includes by default in that case. You can use `--include` if you want to follow includes. The documentation is quite misleading here, though. Here's a patch. -- 8 -- Subject: git-config: better document default behavior for `--include` As described in the commit message of 9b25a0b (config: add include directive, 2012-02-06), the `--include` option is only on by default in some cases. But our documentation described it as just defaults to on, which doesn't tell the whole story. Signed-off-by: Jeff King p...@peff.net --- Documentation/git-config.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt index 9dfa1a5..d42c062 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -215,7 +215,9 @@ See also FILES. --[no-]includes:: Respect `include.*` directives in config files when looking up - values. Defaults to on. + values. Defaults to `off` when a specific file is given (e.g., + using `--file`, `--global`, etc) and `on` when searching all + config files. [[FILES]] FILES -- 2.2.1.425.g441bb3c -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
git --recurse-submodule does not recurse to sub-submodules (etc.)
I have a directory with nested submodules, such as: supermodule/submodule/sub-submodule/sub-sub-submodule When I cd to supermodule and do: git push --recurse-submodule=check (or on-demand), git only pushes the submodule, but not the sub-submodule etc. Maybe this is expected behavior and not a bug, but I thought it was pretty unintuitive. I expected that git would push, well, recursively. Best Max http://www.maxheld.de -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 0/1] http: Add Accept-Language header if possible
On Sunday, January 18, 2015, Yi EungJun semtlen...@gmail.com wrote: Add an Accept-Language header which indicates the user's preferred languages defined by $LANGUAGE, $LC_ALL, $LC_MESSAGES and $LANG. Examples: LANGUAGE= - LANGUAGE=ko:en - Accept-Language: ko, en;q=0.9, *;q=0.1 LANGUAGE=ko LANG=en_US.UTF-8 - Accept-Language: ko, *;q=0.1 LANGUAGE= LANG=en_US.UTF-8 - Accept-Language: en-US, *;q=0.1 This gives git servers a chance to display remote error messages in the user's preferred language. Limit the number of languages to 1,000 because q-value must not be smaller than 0.001, and limit the length of Accept-Language header to 4,000 bytes for some HTTP servers which cannot accept such long header. Signed-off-by: Yi EungJun eungjun...@navercorp.com --- diff --git a/http.c b/http.c index 040f362..349b033 100644 --- a/http.c +++ b/http.c @@ -986,6 +993,145 @@ static void extract_content_type(struct strbuf *raw, struct strbuf *type, strbuf_addstr(charset, ISO-8859-1); } +static void write_accept_language(struct strbuf *buf) +{ + [...] + const int MAX_DECIMAL_PLACES = 3; + const int MAX_LANGUAGE_TAGS = 1000; + const int MAX_ACCEPT_LANGUAGE_HEADER_SIZE = 4000; + struct strbuf *language_tags = NULL; + int num_langs; Mental note: 'num_langs' is not initialized. + const char *s = get_preferred_languages(); + + /* Don't add Accept-Language header if no language is preferred. */ + if (!s) + return; + + /* +* Split the colon-separated string of preferred languages into +* language_tags array. +*/ + do { + /* increase language_tags array to add new language tag */ + REALLOC_ARRAY(language_tags, num_langs + 1); 'num_langs' is used here uninitialized. + strbuf_init(language_tags[num_langs], 0); + + /* collect language tag */ + for (; *s (isalnum(*s) || *s == '_'); s++) + strbuf_addch(language_tags[num_langs], *s == '_' ? '-' : *s); + + /* skip .codeset, @modifier and any other unnecessary parts */ + while (*s *s != ':') + s++; + + if (language_tags[num_langs].len 0) { Mental note: An empty () language tag is never allowed in language_tags[]. + num_langs++; This is a little bit ugly. At the top of the loop, you allocate space in the array for a strbuf and initialize it. However, if the language tag is empty (), then 'num_langs' is never incremented, so the next time through the loop, strbuf_init() is invoked on the same block of memory (assuming the realloc was a no-op since the allocation size did not change), overwriting whatever was there and possibly leaking memory. In this particular case, by examining the parser code closely, we can see that nothing was added to the strbuf, so nothing is being leaked the next time around, given the current implementation of strbuf. However, this is potentially fragile. A change to the implementation of strbuf in the future (for instance, if strbuf_init() allocates memory immediately) could result in a leak here. Moreover, this no-leak situation only holds true if no text at all has been added to the strbuf after strbuf_init(). If someone changes the parser in the future to operate a bit differently so that some text is added and then removed from the strbuf, even though the end result still has length is 0, then it will start leaking. One way to make this more robust would be to have a separate strbuf for collecting the language tag. When you encounter a non-empty tag, only then grow the array and initialize the new strbuf in the array. Finally, use strbuf_swap() to swap the collected language tag into the new array position. Something like this: struct strbuf tag = STRBUF_INIT; do { for (; *s (isalnum(*s) || *s == '_'); s++) strbuf_addch(tag, *s == '_' ? '-' : *s); [...] if (tag.len) { num_langs++; REALLOC_ARRAY(language_tags, num_langs); strbuf_init(language_tags[num_langs], 0); strbuf_swap(tag, language_tags[num_langs]); if (num_langs = ...) break; } while (...); strbuf_release(tag); + if (num_langs = MAX_LANGUAGE_TAGS - 1) /* -1 for '*' */ + break; + } + } while (*s++); + + /* write Accept-Language header into buf */ + if (num_langs = 1) { + int i; + int last_buf_len; Mental note: 'last_buf_len' is not initialized. + int max_q; + int decimal_places; + char q_format[32]; + + /* add '*' */ + REALLOC_ARRAY(language_tags, num_langs + 1); +