Re: [PATCH v3 09/12] revision.c: --all adds HEAD from all worktrees
On 04/19/2017 01:01 PM, Nguyễn Thái Ngọc Duy wrote: > Unless single_worktree is set, --all now adds HEAD from all worktrees. > > Since reachable.c code does not use setup_revisions(), we need to call > other_head_refs_submodule() explicitly there to have the same effect on > "git prune", so that we won't accidentally delete objects needed by some > other HEADs. > > A new FIXME is added because we would need something like > > int refs_other_head_refs(struct ref_store *, each_ref_fn, cb_data); > > in addition to other_head_refs() to handle it, which might require > > int get_submodule_worktrees(const char *submodule, int flags); > > It could be a separate topic to reduce the scope of this one. > > Signed-off-by: Nguyễn Thái Ngọc Duy> --- > reachable.c | 1 + > refs.c | 22 ++ > refs.h | 1 + > revision.c | 13 + > submodule.c | 2 ++ > t/t5304-prune.sh | 12 > 6 files changed, 51 insertions(+) > > diff --git a/reachable.c b/reachable.c > index a8a979bd4f..a3b938b46c 100644 > --- a/reachable.c > +++ b/reachable.c > @@ -177,6 +177,7 @@ void mark_reachable_objects(struct rev_info *revs, int > mark_reflog, > > /* detached HEAD is not included in the list above */ > head_ref(add_one_ref, revs); > + other_head_refs(add_one_ref, revs); > > /* Add all reflog info */ > if (mark_reflog) > diff --git a/refs.c b/refs.c > index 537052f7ba..23e3607674 100644 > --- a/refs.c > +++ b/refs.c > @@ -1780,3 +1780,25 @@ int rename_ref(const char *oldref, const char *newref, > const char *logmsg) > { > return refs_rename_ref(get_main_ref_store(), oldref, newref, logmsg); > } > + > +int other_head_refs(each_ref_fn fn, void *cb_data) > +{ > + struct worktree **worktrees, **p; > + int ret = 0; > + > + worktrees = get_worktrees(0); > + for (p = worktrees; *p; p++) { > + struct worktree *wt = *p; > + struct ref_store *refs; > + > + if (wt->is_current) > + continue; > + > + refs = get_worktree_ref_store(wt); > + ret = refs_head_ref(refs, fn, cb_data); > + if (ret) > + break; > + } > + free_worktrees(worktrees); > + return ret; > +} This function is mainly about iterating through all worktrees. Therefore it feels out of place in the refs module. But I don't have a strong feeling about it. > diff --git a/refs.h b/refs.h > index e06db37118..cc71b6c7a0 100644 > --- a/refs.h > +++ b/refs.h > @@ -247,6 +247,7 @@ int refs_for_each_remote_ref(struct ref_store *refs, >each_ref_fn fn, void *cb_data); > > int head_ref(each_ref_fn fn, void *cb_data); > +int other_head_refs(each_ref_fn fn, void *cb_data); > int for_each_ref(each_ref_fn fn, void *cb_data); > int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data); > int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, > diff --git a/revision.c b/revision.c > index c329070c89..040a0064f6 100644 > --- a/revision.c > +++ b/revision.c > @@ -2105,6 +2105,13 @@ static int handle_revision_pseudo_opt(const char > *submodule, > int argcount; > > if (submodule) { > + /* > + * We need some something like get_submodule_worktrees() > + * before we can go through all worktrees of a submodule, > + * .e.g with adding all HEADs from --all, which is not > + * supported right now, so stick to single worktree. > + */ > + assert(revs->single_worktree != 0); You don't need `!= 0` above. We usually don't use `assert(foo)` but rather `if (!foo) die("BUG:...")`, which gives a better error message and isn't switched off if a distribution compiles with NDEBUG. But here I'm confused about whether this check failing really indicates a bug within git, or whether it could indicate a situation that the user has set up that git just can't handle right now. For example, maybe the user will set up a submodule that itself uses worktrees (even if that's not possible now, maybe they will have done it with some future version of git or with another tool). If the problem is only that this version of git is too stupid to handle pruning safely in that situation, it would be more appropriate to use something more like if (!refs->single_worktree) die("error: git is currently unable to handle submodules that use linked worktrees"); > refs = get_submodule_ref_store(submodule); > } else > refs = get_main_ref_store(); > [...] Michael
[PATCH v2] status: add color config slots for branch info in "--short --branch"
Add color config slots to be used in the status short-format when displaying local and remote tracking branch information. Signed-off-by: Stephen Kent--- Documentation/config.txt | 5 - builtin/commit.c | 4 contrib/completion/git-completion.bash | 2 ++ t/t7508-status.sh | 5 +++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 475e874..96e9cf8 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1137,7 +1137,10 @@ color.status.:: `untracked` (files which are not tracked by Git), `branch` (the current branch), `nobranch` (the color the 'no branch' warning is shown in, defaulting - to red), or + to red), + `localBranch` or `remoteBranch` (the local and remote branch names, + respectively, when branch and tracking information is displayed in the + status short-format), or `unmerged` (files which have unmerged changes). color.ui:: diff --git a/builtin/commit.c b/builtin/commit.c index 4e288bc..43846d5 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1263,6 +1263,10 @@ static int parse_status_slot(const char *slot) return WT_STATUS_NOBRANCH; if (!strcasecmp(slot, "unmerged")) return WT_STATUS_UNMERGED; + if (!strcasecmp(slot, "localBranch")) + return WT_STATUS_LOCAL_BRANCH; + if (!strcasecmp(slot, "remoteBranch")) + return WT_STATUS_REMOTE_BRANCH; return -1; } diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 1150164..f0542b6 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2377,7 +2377,9 @@ _git_config () color.status.added color.status.changed color.status.header + color.status.localBranch color.status.nobranch + color.status.remoteBranch color.status.unmerged color.status.untracked color.status.updated diff --git a/t/t7508-status.sh b/t/t7508-status.sh index fb00e6d..7d42085 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -610,7 +610,8 @@ test_expect_success 'status --porcelain ignores relative paths setting' ' test_expect_success 'setup unique colors' ' git config status.color.untracked blue && - git config status.color.branch green + git config status.color.branch green && + git config status.color.localBranch yellow ' @@ -675,7 +676,7 @@ test_expect_success 'status -s with color.status' ' ' cat >expect <<\EOF -## master +## master M dir1/modified A dir2/added ?? dir1/untracked -- 2.10.2
Re: [PATCH] Add color slots for branch names in "git status --short --branch"
Hi Peff and Junio, I've updated the commit message and updated one of the existing unit tests for this feature. Patch version 2 will follow shortly after this email. Responses to both of your comments: I wondered if this "short-format" was accurate. But indeed, we do not seem to color the local/remote branch specially in long-format mode, so it really is only the short format that is affected. Right, the hardcoded red and green colors only seem to be used for the branch and remote tracking branch names (and commit counts) in the status short-format. There is an existing color slot "color.status.branch" for the branch name in the default (long) status format which is different than the new color config slots this patch adds. I'm wondering if it makes sense to also use color.status.branch for the local branch color in short-format. On the other hand, I have configured different colors in the short and long status format for the local branch name and I find it useful for them to be separate color slots. Normally we match config names in the code as all lowercase, since the key names we get from the config parser will be normalized. Here it works with your mixed-case because you're using strcasecmp(). Obviously that was picked up from the surrounding code, but I think those existing strcasecmp() calls could (and perhaps should) just be strcmp(). I don't know if it's worth converting them or not. If we leave them all as strcasecmp(), I don't mind your camelCase names, for readability. I chose the localBranch and remoteBranch camel case names for consistency with the existing "color.decorate.remoteBranch" color config slot in log-tree.c. The documentation for color.decorate.remoteBranch uses that camel case name, but the config option is case-insensitive. I'm happy to use whatever names are best for the short status branch name color slots. Let me know if I should change them and what I should replace them with. I know we do not test color.status. at all (other than t4026 that makes sure a configuration from future version of Git that specifies a slot that is not yet known to our version of Git is safely ignored without triggering an error), but perhaps we would want a new test or two at the end of t7508? I see the existing tests for git status in t7508. The unit tests set up some mock repository modifications to test git status output, so I've modified one of the tests to include a custom color for the local branch in git status -sb. t7508 doesn't seem to contain any tests that include an ahead or behind commit count, so I didn't make any test changes for the remote tracking branch color. What's the best course of action here? Thanks! Stephen On Wed, Apr 19, 2017 at 23:30, Junio C Hamano wrote: Stephen Kentwrites: Subject: Re: [PATCH] Add color slots for branch names in "git status --short --branch" We spell one-liner title of our commits as ": " typically. In this case, this is about the output from the status command, so status: make the color used "--shrot --branch" output configurable or something, perhaps? Signed-off-by: Stephen Kent --- Documentation/config.txt | 5 - builtin/commit.c | 4 contrib/completion/git-completion.bash | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 475e874..96e9cf8 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1137,7 +1137,10 @@ color.status.:: `untracked` (files which are not tracked by Git), `branch` (the current branch), `nobranch` (the color the 'no branch' warning is shown in, defaulting - to red), or + to red), + `localBranch` or `remoteBranch` (the local and remote branch names, + respectively, when branch and tracking information is displayed in the + status short-format), or `unmerged` (files which have unmerged changes). OK. color.ui:: diff --git a/builtin/commit.c b/builtin/commit.c index 4e288bc..43846d5 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -1263,6 +1263,10 @@ static int parse_status_slot(const char *slot) return WT_STATUS_NOBRANCH; if (!strcasecmp(slot, "unmerged")) return WT_STATUS_UNMERGED; + if (!strcasecmp(slot, "localBranch")) + return WT_STATUS_LOCAL_BRANCH; + if (!strcasecmp(slot, "remoteBranch")) + return WT_STATUS_REMOTE_BRANCH; return -1; } OK. I know we do not test color.status. at all (other than t4026 that makes sure a configuration from future version of Git that specifies a slot that is not yet known to our version of Git is safely ignored without triggering an error), but perhaps we would want a new test or two at the end of t7508? Thanks.
Re: [PATCH v3 08/12] refs: remove dead for_each_*_submodule()
On 04/19/2017 01:01 PM, Nguyễn Thái Ngọc Duy wrote: > These are used in revision.c. After the last patch they are replaced > with the refs_ version. Delete them (except for_each_remote_ref_submodule > which is still used by submodule.c) ❤❤ I love the way this is going. Michael
Re: [PATCH v3 05/12] refs: move submodule slash stripping code to get_submodule_ref_store
On 04/19/2017 01:01 PM, Nguyễn Thái Ngọc Duy wrote: > This is a better place that will benefit all submodule callers instead > of just resolve_gitlink_ref() > > Signed-off-by: Nguyễn Thái Ngọc Duy> --- > refs.c | 33 + > 1 file changed, 17 insertions(+), 16 deletions(-) > > diff --git a/refs.c b/refs.c > index 5902a3d9e5..26474cb62a 100644 > --- a/refs.c > +++ b/refs.c > @@ -1422,25 +1422,10 @@ const char *resolve_ref_unsafe(const char *refname, > int resolve_flags, > int resolve_gitlink_ref(const char *submodule, const char *refname, > unsigned char *sha1) > { > - size_t len = strlen(submodule); > struct ref_store *refs; > int flags; > > - while (len && submodule[len - 1] == '/') > - len--; > - > - if (!len) > - return -1; > - > - if (submodule[len]) { > - /* We need to strip off one or more trailing slashes */ > - char *stripped = xmemdupz(submodule, len); > - > - refs = get_submodule_ref_store(stripped); > - free(stripped); > - } else { > - refs = get_submodule_ref_store(submodule); > - } > + refs = get_submodule_ref_store(submodule); > > if (!refs) > return -1; > @@ -1558,7 +1543,17 @@ struct ref_store *get_submodule_ref_store(const char > *submodule) > { > struct strbuf submodule_sb = STRBUF_INIT; > struct ref_store *refs; > + char *to_free = NULL; > int ret; > + size_t len; > + > + if (submodule) { > + len = strlen(submodule); > + while (len && submodule[len - 1] == '/') > + len--; > + if (!len) > + submodule = NULL; > + } Ugh. Should a submodule named "///" *really* be considered to refer to the main ref_store? I understand that's what the code did before this patch, but it seems to me more like an accident of the old design rather than something worth supporting. In other words, if a caller would really pass us such a string, it seems like we could declare the caller buggy, no? > [...] Otherwise, looks good and makes a lot of sense. Michael
Re: [PATCH v3 04/12] refs.c: refactor get_submodule_ref_store(), share common free block
On 04/19/2017 01:01 PM, Nguyễn Thái Ngọc Duy wrote: > Signed-off-by: Nguyễn Thái Ngọc Duy> --- > refs.c | 12 +--- > 1 file changed, 5 insertions(+), 7 deletions(-) > > diff --git a/refs.c b/refs.c > index 5d31fb6bcf..5902a3d9e5 100644 > --- a/refs.c > +++ b/refs.c > @@ -1570,19 +1570,16 @@ struct ref_store *get_submodule_ref_store(const char > *submodule) > > refs = lookup_ref_store_map(_ref_stores, submodule); > if (refs) > - return refs; > + goto done; > > strbuf_addstr(_sb, submodule); > ret = is_nonbare_repository_dir(_sb); > - strbuf_release(_sb); > if (!ret) > - return NULL; > + goto done; > > ret = submodule_to_gitdir(_sb, submodule); > - if (ret) { > - strbuf_release(_sb); > - return NULL; > - } > + if (ret) > + goto done; After this change, the temporary variable `ret` could be eliminated. > [...] Michael
Re: [PATCH v4 0/5] Kill manual ref parsing code in worktree.c
On 04/14/2017 03:40 AM, Junio C Hamano wrote: > Nguyễn Thái Ngọc Duywrites: > >> v4 adds a new patch, 2/5, which makes the hashmap related functions in >> refs.c generic, so I could add a new map for worktree ref stores and >> not abuse submodule hashmap. >> >> I mentioned about moving these hashmap back to submodule.c and >> worktree.c where it can map more than just ref stores (in worktree >> case, we can cache 'struct worktree', for example). But I'm not doing >> it now to keep things small. >> >> The commit message in 1/5 is rephrased a bit, hopefully clearer. > > Michael, does this look good to replace what has been queued? I finally reviewed this patch series. The refs-related changes look fine, and the submodule-related changes (which I'm not so familiar with) looks plausible. It's a nice cleanup :-) Michael
Re: [PATCH v4 3/5] refs: introduce get_worktree_ref_store()
On 04/04/2017 12:21 PM, Nguyễn Thái Ngọc Duy wrote: > files-backend at this point is still aware of the per-repo/worktree > separation in refs, so it can handle a linked worktree. > > Some refs operations are known not working when current files-backend is > used in a linked worktree (e.g. reflog). Tests will be written when > refs_* functions start to be called with worktree backend to verify that > they work as expected. > > Note: accessing a worktree of a submodule remains unaddressed. Perhaps > after get_worktrees() can access submodule (or rather a new function > get_submodule_worktrees(), that lists worktrees of a submodule), we can > update this function to work with submodules as well. > > Signed-off-by: Nguyễn Thái Ngọc Duy> --- > refs.c | 31 +++ > refs.h | 2 ++ > 2 files changed, 33 insertions(+) > > diff --git a/refs.c b/refs.c > index 875e30a0b8..a4083caf6a 100644 > --- a/refs.c > +++ b/refs.c > @@ -10,6 +10,7 @@ > #include "object.h" > #include "tag.h" > #include "submodule.h" > +#include "worktree.h" > > /* > * List of all available backends > @@ -1486,6 +1487,9 @@ static struct ref_store *main_ref_store; > /* A hashmap of ref_stores, stored by submodule name: */ > static struct hashmap submodule_ref_stores; > > +/* A hashmap of ref_stores, stored by worktree id: */ > +static struct hashmap worktree_ref_stores; > + > /* > * Look up a ref store by name. If that ref_store hasn't been > * registered yet, return NULL. > @@ -1590,6 +1594,33 @@ struct ref_store *get_submodule_ref_store(const char > *submodule) > return refs; > } > > +struct ref_store *get_worktree_ref_store(const struct worktree *wt) > +{ > + struct ref_store *refs; > + unsigned int refs_all_capabilities = > + REF_STORE_READ | REF_STORE_WRITE | > + REF_STORE_ODB | REF_STORE_MAIN; This constant appears another place, too. It might make sense to define a constant `REF_STORE_ALL_CAPABILITIES` in `refs-internal.h` alongside the individual bit values. If you prefer not to, please at least declare this variable `const` to spare the reader the trouble of looking to see whether it is modified before it is used. Otherwise, looks fine to me. > [...] Michael
[PATCH] git_fopen: fix a sparse 'not declared' warning
Commit 8f4f6e53d2 ("config.mak.uname: set FREAD_READS_DIRECTORIES for Linux and FreeBSD", 20-04-2017) caused sparse to issue a 'not declared, should it be static?' warning on Linux. This is a result of the method employed by 'compat/fopen.c' to suppress the (possible) redefinition of the (system) fopen macro, which also removes the extern declaration of the git_fopen function. In order to suppress the warning, introduce a new macro to suppress the definition (or possibly the re-definition) of the fopen symbol as a macro override. This new macro (SUPPRESS_FOPEN_REDEFINITION) is only defined in 'compat/fopen.c', just prior to the inclusion of the 'git-compat-util.h' header file. Signed-off-by: Ramsay Jones--- Hi Duy, Could you (or Junio) please add this to your 'nd/fopen-errors' branch, either as a separate patch or squash it into commit 8f4f6e53d2 ("config.mak.uname: set FREAD_READS_DIRECTORIES for Linux and FreeBSD", 20-04-2017). I think it would be better as a separate commit, but I will leave you to decide on that. ;-) Thanks! ATB, Ramsay Jones compat/fopen.c| 4 ++-- git-compat-util.h | 10 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/compat/fopen.c b/compat/fopen.c index b5ca142fe..107b3e818 100644 --- a/compat/fopen.c +++ b/compat/fopen.c @@ -1,14 +1,14 @@ /* * The order of the following two lines is important. * - * FREAD_READS_DIRECTORIES is undefined before including git-compat-util.h + * SUPPRESS_FOPEN_REDEFINITION is defined before including git-compat-util.h * to avoid the redefinition of fopen within git-compat-util.h. This is * necessary since fopen is a macro on some platforms which may be set * based on compiler options. For example, on AIX fopen is set to fopen64 * when _LARGE_FILES is defined. The previous technique of merely undefining * fopen after including git-compat-util.h is inadequate in this case. */ -#undef FREAD_READS_DIRECTORIES +#define SUPPRESS_FOPEN_REDEFINITION #include "../git-compat-util.h" FILE *git_fopen(const char *path, const char *mode) diff --git a/git-compat-util.h b/git-compat-util.h index b1e48e5e9..691ebf370 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -698,10 +698,12 @@ char *gitstrdup(const char *s); #endif #ifdef FREAD_READS_DIRECTORIES -#ifdef fopen -#undef fopen -#endif -#define fopen(a,b) git_fopen(a,b) +# if !defined(SUPPRESS_FOPEN_REDEFINITION) +# ifdef fopen +# undef fopen +# endif +# define fopen(a,b) git_fopen(a,b) +# endif extern FILE *git_fopen(const char*, const char*); #endif -- 2.12.0
[PATCH] worktree: fix an 'Using integer as a NULL pointer' warning
Signed-off-by: Ramsay Jones--- Hi Duy, If you need to re-roll your 'nd/worktree-move' branch could you please squash this into the relevant patch (commit 8a1dc92e91 ("worktree move: refuse to move worktrees with submodules", 20-04-2017)). Thanks! ATB, Ramsay Jones builtin/worktree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index ff9ccb57f..c54abd5b8 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -534,7 +534,7 @@ static int unlock_worktree(int ac, const char **av, const char *prefix) static void validate_no_submodules(const struct worktree *wt) { - struct index_state istate = {0}; + struct index_state istate = { NULL }; int i, found_submodules = 0; if (read_index_from(, worktree_git_path(wt, "index")) > 0) { -- 2.12.0
Re: [GIT 2.12.2 REGRESSION] git cherry-pick -x
On Fri, Apr 21, 2017 at 03:10:03PM -0700, Stefan Beller wrote: > +Jonathan, who worked on trailers > [...] > > I haven't tried bisecting precisely, but somewhere along the way git > > cherry-pick -x regressed between 2.9.3 and 2.12.2. Yeah, it bisects to 967dfd4d5 (sequencer: use trailer's trailer layout, 2016-11-02). -Peff
Re: [GIT 2.12.2 REGRESSION] git cherry-pick -x
+Jonathan, who worked on trailers On Fri, Apr 21, 2017 at 3:01 PM, Brian Norriswrote: > Hi all, > > I haven't tried bisecting precisely, but somewhere along the way git > cherry-pick -x regressed between 2.9.3 and 2.12.2. > > Looking at upstream linux.git, I can do: > > git fetch git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next > git cherry-pick -x 7b309aef0463340d3ad5449d1f605d14e10a4225 > > And see the following ending to the new commit: > > Acked-by: Arnd Bergmann (cherry picked from commit > 7b309aef0463340d3ad5449d1f605d14e10a4225) > > On 2.9.3, this worked fine: > > Acked-by: Arnd Bergmann > (cherry picked from commit 7b309aef0463340d3ad5449d1f605d14e10a4225) > > This issue doesn't happen on all commits; maybe it's bad parsing looking > at 'Signed-off' and the like? > > Regards, > Brian
Re: [PATCH] t/perf: correctly align non-ASCII descriptions in output
On Sat, Apr 22, 2017 at 12:02:02AM +0200, Ævar Arnfjörð Bjarmason wrote: > > Yeah, I know "use utf8" doesn't work for that, but I was thinking there > > was some other trick. Digging...ah, here it is: > > > > use open ':encoding(utf8)' > > > > No clue how portable that is. For such a small script it may be better > > to just stick with vanilla binmode(). > > Yeah that would work, but doesn't work on 5.8.0, which is the lowest > version we support. Thanks for looking that up. For the benefit of the maintainer, I'll summarize: Ævar's original patch is fine as-is. -Peff
Re: [PATCH] t/perf: correctly align non-ASCII descriptions in output
On Fri, Apr 21, 2017 at 11:35 PM, Jeff Kingwrote: > On Fri, Apr 21, 2017 at 11:28:42PM +0200, Ævar Arnfjörð Bjarmason wrote: > >> > I thought there was some "use" flag we could set to just make all of our >> > handles utf8. But all I could come up with was stuff like PERLIO and >> > "perl -C". Using binmode isn't too bad, though (I think you could >> > just do it as part of the open, too, but I'm not sure if antique >> > versions of perl support that). >> >> [Debugging perl encoding issues is one of the many perks of my dayjob] >> >> Using binmode like this is about as straightforward as you can get, >> the former occurrence could be equivalently replaced by: >> >> utf8::decode(my $line = <$fh>); >> >> But better just to mark the handle as utf8. There's a fancier way to >> do it as part of the three-arg-open syntax, but I couldn't remember >> whether all the perl versions we support have it. > > Yeah, I agree marking the handle is better. binmode is pretty > straightforward, but we'd have to remember to manually set it if we add > any other handles. That's probably not a big deal in this particular > script, though, which is pretty short. > >> About the "use" flag, you're probably thinking of the confusingly >> named "use utf8", but that's to set your source code to utf8, not your >> handles, e.g.: >> >> $ perl -CA -MDevel::Peek -wE 'use utf8; my $日本語 = shift; Dump $日本語' æ >> SV = PV(0x12cc090) at 0x12cded8 >> REFCNT = 1 >> FLAGS = (PADMY,POK,pPOK,UTF8) >> PV = 0x12de460 "\303\246"\0 [UTF8 "\x{e6}"] >> CUR = 2 >> LEN = 16 >> >> As you can see people got a bit overexcited about Unicode in the 90s. > > Yeah, I know "use utf8" doesn't work for that, but I was thinking there > was some other trick. Digging...ah, here it is: > > use open ':encoding(utf8)' > > No clue how portable that is. For such a small script it may be better > to just stick with vanilla binmode(). Yeah that would work, but doesn't work on 5.8.0, which is the lowest version we support.
[GIT 2.12.2 REGRESSION] git cherry-pick -x
Hi all, I haven't tried bisecting precisely, but somewhere along the way git cherry-pick -x regressed between 2.9.3 and 2.12.2. Looking at upstream linux.git, I can do: git fetch git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next git cherry-pick -x 7b309aef0463340d3ad5449d1f605d14e10a4225 And see the following ending to the new commit: Acked-by: Arnd Bergmann(cherry picked from commit 7b309aef0463340d3ad5449d1f605d14e10a4225) On 2.9.3, this worked fine: Acked-by: Arnd Bergmann (cherry picked from commit 7b309aef0463340d3ad5449d1f605d14e10a4225) This issue doesn't happen on all commits; maybe it's bad parsing looking at 'Signed-off' and the like? Regards, Brian
Re: [PATCH] t/perf: correctly align non-ASCII descriptions in output
On Fri, Apr 21, 2017 at 11:28:42PM +0200, Ævar Arnfjörð Bjarmason wrote: > > I thought there was some "use" flag we could set to just make all of our > > handles utf8. But all I could come up with was stuff like PERLIO and > > "perl -C". Using binmode isn't too bad, though (I think you could > > just do it as part of the open, too, but I'm not sure if antique > > versions of perl support that). > > [Debugging perl encoding issues is one of the many perks of my dayjob] > > Using binmode like this is about as straightforward as you can get, > the former occurrence could be equivalently replaced by: > > utf8::decode(my $line = <$fh>); > > But better just to mark the handle as utf8. There's a fancier way to > do it as part of the three-arg-open syntax, but I couldn't remember > whether all the perl versions we support have it. Yeah, I agree marking the handle is better. binmode is pretty straightforward, but we'd have to remember to manually set it if we add any other handles. That's probably not a big deal in this particular script, though, which is pretty short. > About the "use" flag, you're probably thinking of the confusingly > named "use utf8", but that's to set your source code to utf8, not your > handles, e.g.: > > $ perl -CA -MDevel::Peek -wE 'use utf8; my $日本語 = shift; Dump $日本語' æ > SV = PV(0x12cc090) at 0x12cded8 > REFCNT = 1 > FLAGS = (PADMY,POK,pPOK,UTF8) > PV = 0x12de460 "\303\246"\0 [UTF8 "\x{e6}"] > CUR = 2 > LEN = 16 > > As you can see people got a bit overexcited about Unicode in the 90s. Yeah, I know "use utf8" doesn't work for that, but I was thinking there was some other trick. Digging...ah, here it is: use open ':encoding(utf8)' No clue how portable that is. For such a small script it may be better to just stick with vanilla binmode(). -Peff
Re: [PATCH] t/perf: correctly align non-ASCII descriptions in output
On Fri, Apr 21, 2017 at 10:41 PM, Jeff Kingwrote: > On Fri, Apr 21, 2017 at 07:44:28PM +, Ævar Arnfjörð Bjarmason wrote: > >> Change the test descriptions from being treated as binary blobs by >> perl to being treated as UTF-8. This ensures that e.g. a test >> description like "æ" is counted as 1 character, not 2. >> >> I have WIP performance tests for non-ASCII grep patterns on another >> topic that are affected by this. > > Makes sense. As this is purely about test titles in our project, > choosing utf8 as the only encoding is quite sensible. *Nod* >> diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl >> index 924b19dab4..1dbc85b214 100755 >> --- a/t/perf/aggregate.perl >> +++ b/t/perf/aggregate.perl >> @@ -88,6 +88,7 @@ for my $t (@tests) { >> sub read_descr { >> my $name = shift; >> open my $fh, "<", $name or return ""; >> + binmode $fh, ":utf8" or die "PANIC on binmode: $!"; > > I thought there was some "use" flag we could set to just make all of our > handles utf8. But all I could come up with was stuff like PERLIO and > "perl -C". Using binmode isn't too bad, though (I think you could > just do it as part of the open, too, but I'm not sure if antique > versions of perl support that). [Debugging perl encoding issues is one of the many perks of my dayjob] Using binmode like this is about as straightforward as you can get, the former occurrence could be equivalently replaced by: utf8::decode(my $line = <$fh>); But better just to mark the handle as utf8. There's a fancier way to do it as part of the three-arg-open syntax, but I couldn't remember whether all the perl versions we support have it. About the "use" flag, you're probably thinking of the confusingly named "use utf8", but that's to set your source code to utf8, not your handles, e.g.: $ perl -CA -MDevel::Peek -wE 'use utf8; my $日本語 = shift; Dump $日本語' æ SV = PV(0x12cc090) at 0x12cded8 REFCNT = 1 FLAGS = (PADMY,POK,pPOK,UTF8) PV = 0x12de460 "\303\246"\0 [UTF8 "\x{e6}"] CUR = 2 LEN = 16 As you can see people got a bit overexcited about Unicode in the 90s.
Git archive doesn't fully support zip64
Dear git, git archive, when writing a zip file, has a silent 4GB file size limit (on the inputs as well as the output), as it doesn’t fully support zip64. Although a zip archive written by git which is larger than 4GB can be often still be unzipped, it won’t be fully useable and some tools (e.g. zipdetails) can’t read it at all. I suggest either git should be changed to fully support zip64 or it should give a proper error when either an input or the output is too large. Thanks, K.
Re: [PATCH] t/perf: correctly align non-ASCII descriptions in output
On Fri, Apr 21, 2017 at 07:44:28PM +, Ævar Arnfjörð Bjarmason wrote: > Change the test descriptions from being treated as binary blobs by > perl to being treated as UTF-8. This ensures that e.g. a test > description like "æ" is counted as 1 character, not 2. > > I have WIP performance tests for non-ASCII grep patterns on another > topic that are affected by this. Makes sense. As this is purely about test titles in our project, choosing utf8 as the only encoding is quite sensible. > diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl > index 924b19dab4..1dbc85b214 100755 > --- a/t/perf/aggregate.perl > +++ b/t/perf/aggregate.perl > @@ -88,6 +88,7 @@ for my $t (@tests) { > sub read_descr { > my $name = shift; > open my $fh, "<", $name or return ""; > + binmode $fh, ":utf8" or die "PANIC on binmode: $!"; I thought there was some "use" flag we could set to just make all of our handles utf8. But all I could come up with was stuff like PERLIO and "perl -C". Using binmode isn't too bad, though (I think you could just do it as part of the open, too, but I'm not sure if antique versions of perl support that). -Peff
[PATCH v2] completion: optionally disable checkout DWIM
When we complete branch names for "git checkout", we also complete remote branch names that could trigger the DWIM behavior. Depending on your workflow and project, this can be either convenient or annoying. For instance, my clone of gitster.git contains 74 local "jk/*" branches, but origin contains another 147. When I want to checkout a local branch but can't quite remember the name, tab completion shows me 251 entries. And worse, for a topic that has been picked up for pu, the upstream branch name is likely to be similar to mine, leading to a high probability that I pick the wrong one and accidentally create a new branch. This patch adds a way for the user to tell the completion code not to include DWIM suggestions for checkout. This can already be done by typing: git checkout --no-guess jk/ but that's rather cumbersome. The downside, of course, is that you no longer get completion support when you _do_ want to invoke the DWIM behavior. But depending on your workflow, that may not be a big loss (for instance, in git.git I am much more likely to want to detach, so I'd type "git checkout origin/jk/" anyway). Signed-off-by: Jeff King--- Compared to v1, this version requires the new variable be set to "1" (to leave more room for later extension), and uses short-circuiting || for the logic. contrib/completion/git-completion.bash | 11 ++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 1150164d5..f977b54d8 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -28,6 +28,14 @@ # completion style. For example '!f() { : git commit ; ... }; f' will # tell the completion to use commit completion. This also works with aliases # of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". +# +# You can set the following environment variables to influence the behavior of +# the completion routines: +# +# GIT_COMPLETION_CHECKOUT_NO_GUESS +# +# When set to "1", do not include "DWIM" suggestions in git-checkout +# completion (e.g., completing "foo" when "origin/foo" exists). case "$COMP_WORDBREAKS" in *:*) : great ;; @@ -1248,7 +1256,8 @@ _git_checkout () # check if --track, --no-track, or --no-guess was specified # if so, disable DWIM mode local flags="--track --no-track --no-guess" track_opt="--track" - if [ -n "$(__git_find_on_cmdline "$flags")" ]; then + if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] || + [ -n "$(__git_find_on_cmdline "$flags")" ]; then track_opt='' fi __git_complete_refs $track_opt -- 2.13.0.rc0.364.g36b4d8031
Re: [PATCH] completion: optionally disable checkout DWIM
On Fri, Apr 21, 2017 at 10:14:48PM +0200, SZEDER Gábor wrote: > >> This is flexible enough for me, but it's possible somebody would want > >> this on a per-repo basis. I don't know that we want to read from `git > >> config`, though, because it's relatively expensive to do so. People who > >> want per-repo settings are probably better off with a hook that triggers > >> when they "cd" around, and sets up their preferences. > > We could discern between more than just empty vs. non-empty state of > the environment variable, e.g.: > > - if empty/unset, then include "DWIM" suggestions. > - if set to 'config', then query the 'completion.checkoutNoGuess' > configuration variable, and omit "DWIM" suggestions if its true. > - if set to something else, then omit "DWIM" suggestions. > > Then users can themselves decide, whether the per-repo configurability > is worth the overhead of running 'git config'. Yep, that would work. I wasn't going to bother with that complexity unless somebody really wanted it. The important thing is not to paint ourselves into a corner. By the rules you gave above, it would probably be fine to extend my patch later to match. But we could also be more specific (e.g., look for some positive value like "1"). > >> +# You can set the following environment variables to influence the > >> behavior of > >> +# the completion routines: > >> +# > >> +# GIT_COMPLETION_CHECKOUT_NO_GUESS > > That's one long variable name :) > Of course it has to start with the 'GIT_COMPLETION_' prefix, and you > can't win from there... Yeah, I had the same thought. I also considered using "DWIM", which is the name by which I know the feature. But since "--no-guess" is the matching option, I went with that. > >> @@ -1248,7 +1256,8 @@ _git_checkout () > >> # check if --track, --no-track, or --no-guess was specified > >> # if so, disable DWIM mode > >> local flags="--track --no-track --no-guess" > >> track_opt="--track" > >> - if [ -n "$(__git_find_on_cmdline "$flags")" ]; then > >> + if [ -n "$GIT_COMPLETION_CHECKOUT_NO_GUESS" -o \ > >> + -n "$(__git_find_on_cmdline "$flags")" ]; then > > || would be better than '-o', because the former short-circuits when > the first condition is true, but the latter doesn't. Ah, I didn't know that. Usually I use "||", but I thought "-o" was generally preferred in bash-specific scripts. We definitely want to short circuit here. -Peff
Re: [PATCH] test-lib: abort when can't remove trash directory
On Thu, Apr 20, 2017 at 06:52:30PM +0200, SZEDER Gábor wrote: > diff --git a/t/test-lib.sh b/t/test-lib.sh > index 13b569682..e9e6f677d 100644 > --- a/t/test-lib.sh > +++ b/t/test-lib.sh > @@ -761,9 +761,12 @@ test_done () { > say "1..$test_count$skip_all" > fi > > - test -d "$remove_trash" && > + test -d "$remove_trash" || > + error "Tests passed but trash directory already removed before > test cleanup; aborting" I think I found out why this "test -d" was here in the first place: $ ./t-basic.sh --debug [...] # passed all 77 test(s) 1..77 error: Tests passed but trash directory already removed before test cleanup; aborting When --debug is in use, we do not set $remove_trash. The original was relying on 'test -d ""' to return false. I think this whole removal block should probably be moved inside a conditional like: if test -n "$remove_trash" then ... fi I also wonder if we should come up with a better name than $remove_trash. A script which unknowingly overwrites that variable would be disastrous. Perhaps we should drop it entirely and just do: if test -z "$debug" then test -d "$TRASH_DIRECTORY" || error "Tests passed but..." [and so forth...] fi -Peff
Re: [PATCH] completion: optionally disable checkout DWIM
On Fri, Apr 21, 2017 at 7:01 AM, Junio C Hamanowrote: > Jeff King writes: > >> When we complete branch names for "git checkout", we also >> complete remote branch names that could trigger the DWIM >> behavior. Depending on your workflow and project, this can >> be either convenient or annoying. >> ... >> This is flexible enough for me, but it's possible somebody would want >> this on a per-repo basis. I don't know that we want to read from `git >> config`, though, because it's relatively expensive to do so. People who >> want per-repo settings are probably better off with a hook that triggers >> when they "cd" around, and sets up their preferences. We could discern between more than just empty vs. non-empty state of the environment variable, e.g.: - if empty/unset, then include "DWIM" suggestions. - if set to 'config', then query the 'completion.checkoutNoGuess' configuration variable, and omit "DWIM" suggestions if its true. - if set to something else, then omit "DWIM" suggestions. Then users can themselves decide, whether the per-repo configurability is worth the overhead of running 'git config'. > Sounds OK. I am kind of surprised that --no-guess is the only way > to turn off this dwimming (not in the completion side, but there > does not seem to be a way to tell "git checkout" that you do not > need that create-missing-branch-out-of-remote-tracking). > >> contrib/completion/git-completion.bash | 11 ++- >> 1 file changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/contrib/completion/git-completion.bash >> b/contrib/completion/git-completion.bash >> index 1150164d5..f53b18fae 100644 >> --- a/contrib/completion/git-completion.bash >> +++ b/contrib/completion/git-completion.bash >> @@ -28,6 +28,14 @@ >> # completion style. For example '!f() { : git commit ; ... }; f' will >> # tell the completion to use commit completion. This also works with >> aliases >> # of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". >> +# >> +# You can set the following environment variables to influence the behavior >> of >> +# the completion routines: >> +# >> +# GIT_COMPLETION_CHECKOUT_NO_GUESS That's one long variable name :) Of course it has to start with the 'GIT_COMPLETION_' prefix, and you can't win from there... >> +# When non-empty, do not include "DWIM" suggestions in git-checkout >> +# completion (e.g., completing "foo" when "origin/foo" exists). >> >> case "$COMP_WORDBREAKS" in >> *:*) : great ;; >> @@ -1248,7 +1256,8 @@ _git_checkout () >> # check if --track, --no-track, or --no-guess was specified >> # if so, disable DWIM mode >> local flags="--track --no-track --no-guess" track_opt="--track" >> - if [ -n "$(__git_find_on_cmdline "$flags")" ]; then >> + if [ -n "$GIT_COMPLETION_CHECKOUT_NO_GUESS" -o \ >> + -n "$(__git_find_on_cmdline "$flags")" ]; then || would be better than '-o', because the former short-circuits when the first condition is true, but the latter doesn't. >> track_opt='' >> fi >> __git_complete_refs $track_opt On Fri, Apr 21, 2017 at 7:01 AM, Junio C Hamano wrote: > Jeff King writes: > >> When we complete branch names for "git checkout", we also >> complete remote branch names that could trigger the DWIM >> behavior. Depending on your workflow and project, this can >> be either convenient or annoying. >> ... >> This is flexible enough for me, but it's possible somebody would want >> this on a per-repo basis. I don't know that we want to read from `git >> config`, though, because it's relatively expensive to do so. People who >> want per-repo settings are probably better off with a hook that triggers >> when they "cd" around, and sets up their preferences. > > Sounds OK. I am kind of surprised that --no-guess is the only way > to turn off this dwimming (not in the completion side, but there > does not seem to be a way to tell "git checkout" that you do not > need that create-missing-branch-out-of-remote-tracking). > >> contrib/completion/git-completion.bash | 11 ++- >> 1 file changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/contrib/completion/git-completion.bash >> b/contrib/completion/git-completion.bash >> index 1150164d5..f53b18fae 100644 >> --- a/contrib/completion/git-completion.bash >> +++ b/contrib/completion/git-completion.bash >> @@ -28,6 +28,14 @@ >> # completion style. For example '!f() { : git commit ; ... }; f' will >> # tell the completion to use commit completion. This also works with >> aliases >> # of form "!sh -c '...'". For example, "!sh -c ': git commit ; ... '". >> +# >> +# You can set the following environment variables to influence the behavior >> of >> +# the completion routines: >> +# >> +# GIT_COMPLETION_CHECKOUT_NO_GUESS >> +# >> +# When non-empty, do not
Re: [PATCH] test-lib: abort when can't remove trash directory
On Fri, Apr 21, 2017 at 2:48 AM, Junio C Hamanowrote: > SZEDER Gábor writes: > >> We had two similar bugs in the tests sporadically triggering error >> messages during the removal of the trash directory, see commits >> bb05510e5 (t5510: run auto-gc in the foreground, 2016-05-01) and >> ef09036cf (t6500: wait for detached auto gc at the end of the test >> script, 2017-04-13). The test script succeeded nonetheless, because >> these errors are ignored during housekeeping in 'test_done'. >> >> However, such an error is a sign that something is fishy in the test >> script. Print an error message and abort the test script when the >> trash directory can't be removed successfully or is already removed, >> because that's unexpected and we woud prefer somebody notice and s/woud/would/ >> figure out why. > Note, that the commit message references ef09036cf (t6500: wait for >> detached auto gc at the end of the test script, 2017-04-13), which >> is still only in 'pu'. > > I think that one is already part of 2.13-rc0 ;-) Yeah, I should have fetched before submitting.
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 05:23:51PM +0200, Christian Couder wrote: > > I just tried on "pu" and only the first test > > (t7009-filter-branch-null-sha1.sh) fails there. > > I bisected this test's failure (when using > GIT_TEST_SPLIT_INDEX=YesPlease) to e6a1dd77e1 (read-cache: regenerate > shared index if necessary, 2017-02-27). > > The failing test is the following: > > test_expect_success 'filter commands are still checked' ' > test_must_fail git filter-branch \ > --force --prune-empty \ > --index-filter "git rm --cached --ignore-unmatch three.t" > ' > > And if I add the following at the beginning of the test: > > git config splitIndex.maxPercentChange 100 && > > the test then passes. > > So It looks like in split index mode the test doesn't expect the > shared index to be regenerated. > Maybe Peff, as he is the author of this test, or Duy have an idea about this? Right. The test has a broken tree with a null sha1, and filter-branch will do: GIT_ALLOW_NULL_SHA1=1 git read-tree $broken to allow it to enter the index. We expect that further commands that write out the index will not allow it (so you can run commands that remove the broken entry, but not ones that leave it). So without split index, this command: git rm --cached three.t will fail. But in split-index mode, the broken entry is in another index, and is left untouched. I'm not sure there's a way to reconcile the split-index behavior with what the test is expecting; it's inherently optimizing out the thing that the test wants to check. Probably we should catch the broken index entry when we write out the tree, too. We usually do catch missing objects, but this one is a gitlink, so it's OK for it to be missing. I think we should catch the null sha1 specifically, though, as that was the intent of the commit that added t7009. So the patch below _almost_ works. It fixes the failing test. But note the new test I added, with a noop index-filter. That checks that we don't retain the cache-tree extension from the bogus tree when reading. But for some reason it fails on split-index mode. Does cache-tree stuff somehow work differently there? diff --git a/cache-tree.c b/cache-tree.c index 345ea3596..34baa6d85 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -354,7 +354,9 @@ static int update_one(struct cache_tree *it, entlen = pathlen - baselen; i++; } - if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) { + + if (is_null_sha1(sha1) || + (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))) { strbuf_release(); if (expected_missing) return -1; diff --git a/read-cache.c b/read-cache.c index b3d0f3c30..15a4779f2 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2197,6 +2197,7 @@ static int do_write_index(struct index_state *istate, int newfd, int entries = istate->cache_nr; struct stat st; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; + int drop_cache_tree = 0; for (i = removed = extended = 0; i < entries; i++) { if (cache[i]->ce_flags & CE_REMOVE) @@ -2247,6 +2248,8 @@ static int do_write_index(struct index_state *istate, int newfd, warning(msg, ce->name); else return error(msg, ce->name); + + drop_cache_tree = 1; } if (ce_write_entry(, newfd, ce, previous_name) < 0) return -1; @@ -2265,7 +2268,7 @@ static int do_write_index(struct index_state *istate, int newfd, if (err) return -1; } - if (!strip_extensions && istate->cache_tree) { + if (!strip_extensions && !drop_cache_tree && istate->cache_tree) { struct strbuf sb = STRBUF_INIT; cache_tree_write(, istate->cache_tree); diff --git a/t/t7009-filter-branch-null-sha1.sh b/t/t7009-filter-branch-null-sha1.sh index c27f90f28..a8d9ec498 100755 --- a/t/t7009-filter-branch-null-sha1.sh +++ b/t/t7009-filter-branch-null-sha1.sh @@ -31,6 +31,12 @@ test_expect_success 'setup: bring HEAD and index in sync' ' git commit -a -m "back to normal" ' +test_expect_success 'noop filter-branch complains' ' + test_must_fail git filter-branch \ + --force --prune-empty \ + --index-filter "true" +' + test_expect_success 'filter commands are still checked' ' test_must_fail git filter-branch \ --force --prune-empty \
[PATCH] t/perf: correctly align non-ASCII descriptions in output
Change the test descriptions from being treated as binary blobs by perl to being treated as UTF-8. This ensures that e.g. a test description like "æ" is counted as 1 character, not 2. I have WIP performance tests for non-ASCII grep patterns on another topic that are affected by this. Now instead of: $ ./run p-perf-lib-sanity.sh [...] .4: export a weird var 0.00(0.00+0.00) .5: éḿíẗ ńöń-ÁŚĆÍÍ ćḧáŕáćẗéŕś 0.00(0.00+0.00) .7: important variables available in subshells 0.00(0.00+0.00) [...] We emit: [...] .4: export a weird var 0.00(0.00+0.00) .5: éḿíẗ ńöń-ÁŚĆÍÍ ćḧáŕáćẗéŕś 0.00(0.00+0.00) .7: important variables available in subshells 0.00(0.00+0.00) [...] Fixes code originally added in 342e9ef2d9 ("Introduce a performance testing framework", 2012-02-17). Signed-off-by: Ævar Arnfjörð Bjarmason--- t/perf/aggregate.perl | 3 +++ t/perf/p-perf-lib-sanity.sh | 2 ++ 2 files changed, 5 insertions(+) diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl index 924b19dab4..1dbc85b214 100755 --- a/t/perf/aggregate.perl +++ b/t/perf/aggregate.perl @@ -88,6 +88,7 @@ for my $t (@tests) { sub read_descr { my $name = shift; open my $fh, "<", $name or return ""; + binmode $fh, ":utf8" or die "PANIC on binmode: $!"; my $line = <$fh>; close $fh or die "cannot close $name"; chomp $line; @@ -147,6 +148,8 @@ for my $t (@subtests) { my $totalwidth = 3*@dirs+$descrlen; $totalwidth += $_ for (@colwidth); +binmode STDOUT, ":utf8" or die "PANIC on binmode: $!"; + printf "%-${descrlen}s", "Test"; for my $i (0..$#dirs) { my $d = $dirs[$i]; diff --git a/t/perf/p-perf-lib-sanity.sh b/t/perf/p-perf-lib-sanity.sh index cf8e1efce7..002c21e52a 100755 --- a/t/perf/p-perf-lib-sanity.sh +++ b/t/perf/p-perf-lib-sanity.sh @@ -33,6 +33,8 @@ test_perf 'export a weird var' ' test_export bar ' +test_perf 'éḿíẗ ńöń-ÁŚĆÍÍ ćḧáŕáćẗéŕś' 'true' + test_expect_success 'test_export works with weird vars' ' echo "$bar" && test "$bar" = "weird # variable" -- 2.11.0
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 07:25:21PM +0700, Duy Nguyen wrote: > >> Yeah, you are right. > >> It looks like we have GIT_TEST_OPTS to pass options like --debug, > >> --valgrind, --verbose, but we don't have an environment variable to > >> set config options. > > > > Or maybe GIT_CONFIG_PARAMETERS works for this purpose? > > It has to be set inside test-lib.sh, not from outside because > environment variables from outside are filtered if I remember > correctly and only a few specials plus those GIT_TEST_ can survive. > Some tests override GIT_CONFIG_PARAMETERS themselves to pass config > vars to certain command (I know because I just did a couple days ago > ;).which loses core.splitIndex. It does seem reasonable to have a GIT_TEST_REPO_CONFIG that sets some variables by default in the trash repository created by test_create_repo. That doesn't quite catch everything, because a few tests make their own sub-repos. But those cases are usually testing something very specific anyway. -Peff
[PATCH] cache-tree: reject entries with null sha1
We generally disallow null sha1s from entering the index, due to 4337b5856 (do not write null sha1s to on-disk index, 2012-07-28). However, we loosened that in 83bd7437c (write_index: optionally allow broken null sha1s, 2013-08-27) so that tools like filter-branch could be used to repair broken history. However, we should make sure that these broken entries do not get propagated into new trees. For most entries, we'd catch them with the missing-object check (since presumably the null sha1 does not exist in our object database). But gitlink entries do not need reachability, so we may blindly copy the entry into a bogus tree. This patch rejects all null sha1s (with the same "invalid entry" message that missing objects get) when building trees from the index. It does so even for non-gitlinks, and even when "write-tree" is given the --missing-ok flag. The null sha1 is a special sentinel value that is already rejected in trees by fsck; whether the object exists or not, it is an error to put it in a tree. Note that for this to work, we must also avoid reusing an existing cache-tree that contains the null sha1. This patch does so by just refusing to write out any cache tree when the index contains a null sha1. This is blunter than we need to be; we could just reject the subtree that contains the offending entry. But it's not worth the complexity. The behavior is unchanged unless you have a broken index entry, and even then we'd refuse the whole index write unless the emergency GIT_ALLOW_NULL_SHA1 is in use. And even then the end result is only a performance drop (any write-tree will have to generate the whole cache-tree from scratch). The tests bear some explanation. The existing test in t7009 doesn't catch this problem, because our index-filter runs "git rm --cached", which will try to rewrite the updated index and barf on the bogus entry. So we never even make it to write-tree. The new test there adds a noop index-filter, which does show the problem. The new tests in t1601 are slightly redundant with what filter-branch is doing under the hood in t7009. But as they're much more direct, they're easier to reason about. And should filter-branch ever change or go away, we'd want to make sure that these plumbing commands behave sanely. Signed-off-by: Jeff King--- When merged to pu, this fixes the existing test breakage in t7009 when GIT_TEST_SPLIT_INDEX is used (because the split index didn't rewrite the whole index, "git rm --cached" didn't always barf). But I think it's worth doing on its own merits, as demonstrated by the new tests. The one thing I haven't figured out it is why the new test in t7009 fails with the split-index. And even more curiously, the new tests in t1601 _don't_ fail with it, even if I instrument the fake index to have more entries (making it more likely to split). cache-tree.c | 4 +++- read-cache.c | 5 - t/t1601-index-bogus.sh | 22 ++ t/t7009-filter-branch-null-sha1.sh | 6 ++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100755 t/t1601-index-bogus.sh diff --git a/cache-tree.c b/cache-tree.c index 345ea3596..34baa6d85 100644 --- a/cache-tree.c +++ b/cache-tree.c @@ -354,7 +354,9 @@ static int update_one(struct cache_tree *it, entlen = pathlen - baselen; i++; } - if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) { + + if (is_null_sha1(sha1) || + (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1))) { strbuf_release(); if (expected_missing) return -1; diff --git a/read-cache.c b/read-cache.c index e44775182..6851de892 100644 --- a/read-cache.c +++ b/read-cache.c @@ -2054,6 +2054,7 @@ static int do_write_index(struct index_state *istate, int newfd, int entries = istate->cache_nr; struct stat st; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; + int drop_cache_tree = 0; for (i = removed = extended = 0; i < entries; i++) { if (cache[i]->ce_flags & CE_REMOVE) @@ -2104,6 +2105,8 @@ static int do_write_index(struct index_state *istate, int newfd, warning(msg, ce->name); else return error(msg, ce->name); + + drop_cache_tree = 1; } if (ce_write_entry(, newfd, ce, previous_name) < 0) return -1; @@ -2122,7 +2125,7 @@ static int do_write_index(struct index_state *istate, int newfd, if (err) return -1; } - if (!strip_extensions && istate->cache_tree) { + if (!strip_extensions && !drop_cache_tree && istate->cache_tree) { struct strbuf sb = STRBUF_INIT;
[PATCH v6 2/8] convert: move packet_write_list() into pkt-line as packet_writel()
Add packet_writel() which writes multiple lines in a single call and then calls packet_flush_gently(). Update convert.c to use the new packet_writel() function from pkt-line. Signed-off-by: Ben Peart--- convert.c | 23 ++- pkt-line.c | 19 +++ pkt-line.h | 1 + 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/convert.c b/convert.c index 8d652bf27c..793c29ebfd 100644 --- a/convert.c +++ b/convert.c @@ -521,25 +521,6 @@ static struct cmd2process *find_multi_file_filter_entry(struct hashmap *hashmap, return hashmap_get(hashmap, , NULL); } -static int packet_write_list(int fd, const char *line, ...) -{ - va_list args; - int err; - va_start(args, line); - for (;;) { - if (!line) - break; - if (strlen(line) > LARGE_PACKET_DATA_MAX) - return -1; - err = packet_write_fmt_gently(fd, "%s\n", line); - if (err) - return err; - line = va_arg(args, const char*); - } - va_end(args); - return packet_flush_gently(fd); -} - static void read_multi_file_filter_status(int fd, struct strbuf *status) { struct strbuf **pair; @@ -616,7 +597,7 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons sigchain_push(SIGPIPE, SIG_IGN); - err = packet_write_list(process->in, "git-filter-client", "version=2", NULL); + err = packet_writel(process->in, "git-filter-client", "version=2", NULL); if (err) goto done; @@ -632,7 +613,7 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons if (err) goto done; - err = packet_write_list(process->in, "capability=clean", "capability=smudge", NULL); + err = packet_writel(process->in, "capability=clean", "capability=smudge", NULL); for (;;) { cap_buf = packet_read_line(process->out, NULL); diff --git a/pkt-line.c b/pkt-line.c index bfdb177b34..756410d2f6 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -171,6 +171,25 @@ int packet_write_fmt_gently(int fd, const char *fmt, ...) return status; } +int packet_writel(int fd, const char *line, ...) +{ + va_list args; + int err; + va_start(args, line); + for (;;) { + if (!line) + break; + if (strlen(line) > LARGE_PACKET_DATA_MAX) + return -1; + err = packet_write_fmt_gently(fd, "%s\n", line); + if (err) + return err; + line = va_arg(args, const char*); + } + va_end(args); + return packet_flush_gently(fd); +} + static int packet_write_gently(const int fd_out, const char *buf, size_t size) { static char packet_write_buffer[LARGE_PACKET_MAX]; diff --git a/pkt-line.h b/pkt-line.h index ad30db101a..957b9a5fa3 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -25,6 +25,7 @@ void packet_buf_flush(struct strbuf *buf); void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3))); int packet_flush_gently(int fd); int packet_write_fmt_gently(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3))); +int packet_writel(int fd, const char *line, ...); int write_packetized_from_fd(int fd_in, int fd_out); int write_packetized_from_buf(const char *src_in, size_t len, int fd_out); -- 2.12.0.windows.1.33.g243d9b384c
[PATCH] tests: fix tests broken under GETTEXT_POISON=YesPlease
The GETTEXT_POISON=YesPlease compile-time testing option added in my bb946bba76 ("i18n: add GETTEXT_POISON to simulate unfriendly translator", 2011-02-22) has been slowly bitrotting as strings have been marked for translation, and new tests have been added without running it. I brought this up on the list ("[BUG] test suite broken with GETTEXT_POISON=YesPlease", [1]) asking whether this mode was useful at all anymore. At least one person occasionally uses it, and Lars Schneider offered to change one of the the Travis builds to run in this mode, so fix up the failing ones. My test setup runs most of the tests, with the notable exception of skipping all the p4 tests, so it's possible that there's still some lurking regressions I haven't fixed. 1.Signed-off-by: Ævar Arnfjörð Bjarmason --- t/t1309-early-config.sh | 2 +- t/t1430-bad-ref-name.sh | 2 +- t/t3203-branch-output.sh | 2 +- t/t3404-rebase-interactive.sh| 14 +++--- t/t3415-rebase-autosquash.sh | 10 +- t/t3903-stash.sh | 4 ++-- t/t4205-log-pretty-formats.sh| 4 ++-- t/t5316-pack-delta-depth.sh | 8 ++-- t/t6134-pathspec-in-submodule.sh | 4 ++-- t/t7004-tag.sh | 4 ++-- t/t7406-submodule-update.sh | 2 +- t/t7509-commit.sh| 4 ++-- t/t7800-difftool.sh | 4 ++-- 13 files changed, 34 insertions(+), 30 deletions(-) diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh index b97357b8ab..016e43b8d5 100755 --- a/t/t1309-early-config.sh +++ b/t/t1309-early-config.sh @@ -59,7 +59,7 @@ test_with_config () { test_expect_success 'ignore .git/ with incompatible repository version' ' test_with_config "[core]repositoryformatversion = 99" 2>err && - grep "warning:.* Expected git repo version <= [1-9]" err + test_i18ngrep "warning:.* Expected git repo version <= [1-9]" err ' test_expect_failure 'ignore .git/ with invalid repository version' ' diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 8937e25e49..2003ec7907 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -122,7 +122,7 @@ test_expect_success 'push cannot create a badly named ref' ' ! grep -e "broken\.\.\.ref" output ' -test_expect_failure 'push --mirror can delete badly named ref' ' +test_expect_failure !GETTEXT_POISON 'push --mirror can delete badly named ref' ' top=$(pwd) && git init src && git init dest && diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index 5778c0afe1..a428ae6703 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -236,7 +236,7 @@ test_expect_success 'git branch --format option' ' Refname is refs/heads/ref-to-remote EOF git branch --format="Refname is %(refname)" >actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 33d392ba11..e07d6d8cd2 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -366,7 +366,7 @@ test_expect_success 'verbose flag is heeded, even after --continue' ' grep "^ file1 | 2 +-$" output ' -test_expect_success 'multi-squash only fires up editor once' ' +test_expect_success !GETTEXT_POISON 'multi-squash only fires up editor once' ' base=$(git rev-parse HEAD~4) && set_fake_editor && FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \ @@ -376,7 +376,7 @@ test_expect_success 'multi-squash only fires up editor once' ' test 1 = $(git show | grep ONCE | wc -l) ' -test_expect_success 'multi-fixup does not fire up editor' ' +test_expect_success !GETTEXT_POISON 'multi-fixup does not fire up editor' ' git checkout -b multi-fixup E && base=$(git rev-parse HEAD~4) && set_fake_editor && @@ -426,7 +426,7 @@ D ONCE EOF -test_expect_success 'squash and fixup generate correct log messages' ' +test_expect_success !GETTEXT_POISON 'squash and fixup generate correct log messages' ' git checkout -b squash-fixup E && base=$(git rev-parse HEAD~4) && set_fake_editor && @@ -439,7 +439,7 @@ test_expect_success 'squash and fixup generate correct log messages' ' git branch -D squash-fixup ' -test_expect_success 'squash ignores comments' ' +test_expect_success !GETTEXT_POISON 'squash ignores comments' ' git checkout -b skip-comments E && base=$(git rev-parse HEAD~4) && set_fake_editor && @@ -452,7 +452,7 @@ test_expect_success 'squash ignores comments' ' git branch -D skip-comments ' -test_expect_success 'squash ignores blank lines' ' +test_expect_success !GETTEXT_POISON 'squash ignores blank lines' ' git checkout -b skip-blank-lines E && base=$(git rev-parse HEAD~4)
[PATCH v6 8/8] convert: Update subprocess_read_status to not die on EOF
Enable sub-processes to gracefully handle when the process dies by updating subprocess_read_status to return an error on EOF instead of dying. Update apply_multi_file_filter to take advantage of the revised subprocess_read_status. Signed-off-by: Ben Peart--- convert.c | 10 -- sub-process.c | 10 +++--- sub-process.h | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/convert.c b/convert.c index 79d04907a5..f1e168bc30 100644 --- a/convert.c +++ b/convert.c @@ -635,7 +635,10 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len if (err) goto done; - subprocess_read_status(process->out, _status); + err = subprocess_read_status(process->out, _status); + if (err) + goto done; + err = strcmp(filter_status.buf, "success"); if (err) goto done; @@ -644,7 +647,10 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len if (err) goto done; - subprocess_read_status(process->out, _status); + err = subprocess_read_status(process->out, _status); + if (err) + goto done; + err = strcmp(filter_status.buf, "success"); done: diff --git a/sub-process.c b/sub-process.c index 536b60cced..92f8aea70a 100644 --- a/sub-process.c +++ b/sub-process.c @@ -21,13 +21,15 @@ struct subprocess_entry *subprocess_find_entry(struct hashmap *hashmap, const ch return hashmap_get(hashmap, , NULL); } -void subprocess_read_status(int fd, struct strbuf *status) +int subprocess_read_status(int fd, struct strbuf *status) { struct strbuf **pair; char *line; + int len; + for (;;) { - line = packet_read_line(fd, NULL); - if (!line) + len = packet_read_line_gently(fd, NULL, ); + if ((len < 0) || !line) break; pair = strbuf_split_str(line, '=', 2); if (pair[0] && pair[0]->len && pair[1]) { @@ -39,6 +41,8 @@ void subprocess_read_status(int fd, struct strbuf *status) } strbuf_list_free(pair); } + + return (len < 0) ? len : 0; } void subprocess_stop(struct hashmap *hashmap, struct subprocess_entry *entry) diff --git a/sub-process.h b/sub-process.h index a88e782bfc..7d451e1cde 100644 --- a/sub-process.h +++ b/sub-process.h @@ -44,6 +44,6 @@ static inline struct child_process *subprocess_get_child_process( * key/value pairs and return the value from the last "status" packet */ -void subprocess_read_status(int fd, struct strbuf *status); +int subprocess_read_status(int fd, struct strbuf *status); #endif -- 2.12.0.windows.1.33.g243d9b384c
Re: [PATCH 00/15] Handle fopen() errors
On Fri, Apr 21, 2017 at 07:27:20PM +0700, Duy Nguyen wrote: > On Fri, Apr 21, 2017 at 6:52 PM, Junio C Hamanowrote: > > Yes, but (1) we'd need to be careful about --quiet > > Yeah. It's a real pain point for making changes like this. At some > point we should just have a global (maybe multi-level) quiet flag. I don't think it's too bad here. Isn't it just: FILE *fh = quiet ? fopen(x, y) : fopen_or_warn(x, y); It is a little annoying to have to repeat "x", though (which is sometimes a git_path() invocation). -Peff
[PATCH v6 5/8] convert: Update generic functions to only use generic data structures
Update all functions that are going to be moved into a reusable module so that they only work with the reusable data structures. Move code that is specific to the filter out into the filter specific functions. Signed-off-by: Ben Peart--- convert.c | 41 +++-- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/convert.c b/convert.c index bfb19beed5..d15b10a3c5 100644 --- a/convert.c +++ b/convert.c @@ -556,7 +556,6 @@ static void kill_multi_file_filter(struct hashmap *hashmap, struct subprocess_en finish_command(>process); hashmap_remove(hashmap, entry, NULL); - free(entry); } static void stop_multi_file_filter(struct child_process *process) @@ -570,14 +569,15 @@ static void stop_multi_file_filter(struct child_process *process) finish_command(process); } -static int start_multi_file_filter_fn(struct cmd2process *entry) +static int start_multi_file_filter_fn(struct subprocess_entry *subprocess) { int err; + struct cmd2process *entry = (struct cmd2process *)subprocess; struct string_list cap_list = STRING_LIST_INIT_NODUP; char *cap_buf; const char *cap_name; - struct child_process *process = >subprocess.process; - const char *cmd = entry->subprocess.cmd; + struct child_process *process = >process; + const char *cmd = subprocess->cmd; sigchain_push(SIGPIPE, SIG_IGN); @@ -629,17 +629,16 @@ static int start_multi_file_filter_fn(struct cmd2process *entry) return err; } -static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, const char *cmd) +typedef int(*subprocess_start_fn)(struct subprocess_entry *entry); +int start_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *entry, const char *cmd, + subprocess_start_fn startfn) { int err; - struct cmd2process *entry; struct child_process *process; const char *argv[] = { cmd, NULL }; - entry = xmalloc(sizeof(*entry)); - entry->subprocess.cmd = cmd; - entry->supported_capabilities = 0; - process = >subprocess.process; + entry->cmd = cmd; + process = >process; child_process_init(process); process->argv = argv; @@ -649,22 +648,23 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons process->clean_on_exit = 1; process->clean_on_exit_handler = stop_multi_file_filter; - if (start_command(process)) { + err = start_command(process); + if (err) { error("cannot fork to run external filter '%s'", cmd); - return NULL; + return err; } hashmap_entry_init(entry, strhash(cmd)); - err = start_multi_file_filter_fn(entry); + err = startfn(entry); if (err) { error("initialization for external filter '%s' failed", cmd); - kill_multi_file_filter(hashmap, >subprocess); - return NULL; + kill_multi_file_filter(hashmap, entry); + return err; } hashmap_add(hashmap, entry); - return entry; + return 0; } static int apply_multi_file_filter(const char *path, const char *src, size_t len, @@ -689,9 +689,13 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len fflush(NULL); if (!entry) { - entry = start_multi_file_filter(_process_map, cmd); - if (!entry) + entry = xmalloc(sizeof(*entry)); + entry->supported_capabilities = 0; + + if (start_multi_file_filter(_process_map, >subprocess, cmd, start_multi_file_filter_fn)) { + free(entry); return 0; + } } process = >subprocess.process; @@ -765,6 +769,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len */ error("external filter '%s' failed", cmd); kill_multi_file_filter(_process_map, >subprocess); + free(entry); } } else { strbuf_swap(dst, ); -- 2.12.0.windows.1.33.g243d9b384c
[PATCH v6 6/8] convert: rename reusable sub-process functions
Do a mechanical rename of the functions that will become the reusable sub-process module. Signed-off-by: Ben Peart--- convert.c | 40 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/convert.c b/convert.c index d15b10a3c5..cfae45aeee 100644 --- a/convert.c +++ b/convert.c @@ -507,8 +507,8 @@ struct cmd2process { unsigned int supported_capabilities; }; -static int cmd_process_map_initialized; -static struct hashmap cmd_process_map; +static int subprocess_map_initialized; +static struct hashmap subprocess_map; static int cmd2process_cmp(const struct subprocess_entry *e1, const struct subprocess_entry *e2, @@ -517,7 +517,7 @@ static int cmd2process_cmp(const struct subprocess_entry *e1, return strcmp(e1->cmd, e2->cmd); } -static struct subprocess_entry *find_multi_file_filter_entry(struct hashmap *hashmap, const char *cmd) +static struct subprocess_entry *subprocess_find_entry(struct hashmap *hashmap, const char *cmd) { struct subprocess_entry key; @@ -526,7 +526,7 @@ static struct subprocess_entry *find_multi_file_filter_entry(struct hashmap *has return hashmap_get(hashmap, , NULL); } -static void read_multi_file_filter_status(int fd, struct strbuf *status) +static void subprocess_read_status(int fd, struct strbuf *status) { struct strbuf **pair; char *line; @@ -546,7 +546,7 @@ static void read_multi_file_filter_status(int fd, struct strbuf *status) } } -static void kill_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *entry) +static void subprocess_stop(struct hashmap *hashmap, struct subprocess_entry *entry) { if (!entry) return; @@ -558,10 +558,10 @@ static void kill_multi_file_filter(struct hashmap *hashmap, struct subprocess_en hashmap_remove(hashmap, entry, NULL); } -static void stop_multi_file_filter(struct child_process *process) +static void subprocess_exit_handler(struct child_process *process) { sigchain_push(SIGPIPE, SIG_IGN); - /* Closing the pipe signals the filter to initiate a shutdown. */ + /* Closing the pipe signals the subprocess to initiate a shutdown. */ close(process->in); close(process->out); sigchain_pop(SIGPIPE); @@ -630,7 +630,7 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess) } typedef int(*subprocess_start_fn)(struct subprocess_entry *entry); -int start_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *entry, const char *cmd, +int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, const char *cmd, subprocess_start_fn startfn) { int err; @@ -646,11 +646,11 @@ int start_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *en process->in = -1; process->out = -1; process->clean_on_exit = 1; - process->clean_on_exit_handler = stop_multi_file_filter; + process->clean_on_exit_handler = subprocess_exit_handler; err = start_command(process); if (err) { - error("cannot fork to run external filter '%s'", cmd); + error("cannot fork to run subprocess '%s'", cmd); return err; } @@ -658,8 +658,8 @@ int start_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *en err = startfn(entry); if (err) { - error("initialization for external filter '%s' failed", cmd); - kill_multi_file_filter(hashmap, entry); + error("initialization for subprocess '%s' failed", cmd); + subprocess_stop(hashmap, entry); return err; } @@ -678,12 +678,12 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len struct strbuf filter_status = STRBUF_INIT; const char *filter_type; - if (!cmd_process_map_initialized) { - cmd_process_map_initialized = 1; - hashmap_init(_process_map, (hashmap_cmp_fn) cmd2process_cmp, 0); + if (!subprocess_map_initialized) { + subprocess_map_initialized = 1; + hashmap_init(_map, (hashmap_cmp_fn) cmd2process_cmp, 0); entry = NULL; } else { - entry = (struct cmd2process *)find_multi_file_filter_entry(_process_map, cmd); + entry = (struct cmd2process *)subprocess_find_entry(_map, cmd); } fflush(NULL); @@ -692,7 +692,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len entry = xmalloc(sizeof(*entry)); entry->supported_capabilities = 0; - if (start_multi_file_filter(_process_map, >subprocess, cmd, start_multi_file_filter_fn)) { + if (subprocess_start(_map, >subprocess, cmd, start_multi_file_filter_fn)) {
[PATCH v6 7/8] sub-process: move sub-process functions into separate files
Move the sub-proces functions into sub-process.h/c. Add documentation for the new module in Documentation/technical/api-sub-process.txt Signed-off-by: Ben Peart--- Documentation/technical/api-sub-process.txt | 59 Makefile| 1 + convert.c | 104 +--- sub-process.c | 102 +++ sub-process.h | 49 + 5 files changed, 212 insertions(+), 103 deletions(-) create mode 100644 Documentation/technical/api-sub-process.txt create mode 100644 sub-process.c create mode 100644 sub-process.h diff --git a/Documentation/technical/api-sub-process.txt b/Documentation/technical/api-sub-process.txt new file mode 100644 index 00..793508cf3e --- /dev/null +++ b/Documentation/technical/api-sub-process.txt @@ -0,0 +1,59 @@ +sub-process API +=== + +The sub-process API makes it possible to run background sub-processes +for the entire lifetime of a Git invocation. If Git needs to communicate +with an external process multiple times, then this can reduces the process +invocation overhead. Git and the sub-process communicate through stdin and +stdout. + +The sub-processes are kept in a hashmap by command name and looked up +via the subprocess_find_entry function. If an existing instance can not +be found then a new process should be created and started. When the +parent git command terminates, all sub-processes are also terminated. + +This API is based on the run-command API. + +Data structures +--- + +* `struct subprocess_entry` + +The sub-process structure. Members should not be accessed directly. + +Types +- + +'int(*subprocess_start_fn)(struct subprocess_entry *entry)':: + + User-supplied function to initialize the sub-process. This is + typically used to negotiate the interface version and capabilities. + + +Functions +- + +`cmd2process_cmp`:: + + Function to test two subprocess hashmap entries for equality. + +`subprocess_start`:: + + Start a subprocess and add it to the subprocess hashmap. + +`subprocess_stop`:: + + Kill a subprocess and remove it from the subprocess hashmap. + +`subprocess_find_entry`:: + + Find a subprocess in the subprocess hashmap. + +`subprocess_get_child_process`:: + + Get the underlying `struct child_process` from a subprocess. + +`subprocess_read_status`:: + + Helper function to read packets looking for the last "status=" + key/value pair. diff --git a/Makefile b/Makefile index eb1a1a7cff..97c87fb647 100644 --- a/Makefile +++ b/Makefile @@ -840,6 +840,7 @@ LIB_OBJS += streaming.o LIB_OBJS += string-list.o LIB_OBJS += submodule.o LIB_OBJS += submodule-config.o +LIB_OBJS += sub-process.o LIB_OBJS += symlinks.o LIB_OBJS += tag.o LIB_OBJS += tempfile.o diff --git a/convert.c b/convert.c index cfae45aeee..79d04907a5 100644 --- a/convert.c +++ b/convert.c @@ -4,6 +4,7 @@ #include "quote.h" #include "sigchain.h" #include "pkt-line.h" +#include "sub-process.h" /* * convert.c - convert a file when checking it out and checking it in. @@ -496,12 +497,6 @@ static int apply_single_file_filter(const char *path, const char *src, size_t le #define CAP_CLEAN(1u<<0) #define CAP_SMUDGE (1u<<1) -struct subprocess_entry { - struct hashmap_entry ent; /* must be the first member! */ - const char *cmd; - struct child_process process; -}; - struct cmd2process { struct subprocess_entry subprocess; /* must be the first member! */ unsigned int supported_capabilities; @@ -510,65 +505,6 @@ struct cmd2process { static int subprocess_map_initialized; static struct hashmap subprocess_map; -static int cmd2process_cmp(const struct subprocess_entry *e1, - const struct subprocess_entry *e2, - const void *unused) -{ - return strcmp(e1->cmd, e2->cmd); -} - -static struct subprocess_entry *subprocess_find_entry(struct hashmap *hashmap, const char *cmd) -{ - struct subprocess_entry key; - - hashmap_entry_init(, strhash(cmd)); - key.cmd = cmd; - return hashmap_get(hashmap, , NULL); -} - -static void subprocess_read_status(int fd, struct strbuf *status) -{ - struct strbuf **pair; - char *line; - for (;;) { - line = packet_read_line(fd, NULL); - if (!line) - break; - pair = strbuf_split_str(line, '=', 2); - if (pair[0] && pair[0]->len && pair[1]) { - /* the last "status=" line wins */ - if (!strcmp(pair[0]->buf, "status=")) { - strbuf_reset(status); - strbuf_addbuf(status, pair[1]); - } - } - strbuf_list_free(pair); -
[PATCH v6 0/8] refactor the filter process code into a reusable module
Refactor the filter..process code into a separate sub-process module that can be used to reduce the cost of starting up a sub-process for multiple commands. It does this by keeping the external process running and processing all commands by communicating over standard input and standard output using the packet format (pkt-line) based protocol. Full documentation is in Documentation/technical/api-sub-process.txt. This code is refactored from: Commit edcc85814c ("convert: add filter..process option", 2016-10-16) keeps the external process running and processes all commands Ben Peart (8): pkt-line: add packet_read_line_gently() convert: move packet_write_list() into pkt-line as packet_writel() convert: Split start_multi_file_filter into two separate functions convert: Separate generic structures and variables from the filter specific ones convert: Update generic functions to only use generic data structures convert: rename reusable sub-process functions sub-process: move sub-process functions into separate files convert: Update subprocess_read_status to not die on EOF Documentation/technical/api-sub-process.txt | 59 ++ Makefile| 1 + convert.c | 161 ++-- pkt-line.c | 33 +- pkt-line.h | 11 ++ sub-process.c | 106 ++ sub-process.h | 49 + 7 files changed, 291 insertions(+), 129 deletions(-) create mode 100644 Documentation/technical/api-sub-process.txt create mode 100644 sub-process.c create mode 100644 sub-process.h -- 2.12.0.windows.1.33.g243d9b384c
Re: [BUG] test suite broken with GETTEXT_POISON=YesPlease
On Fri, Apr 21, 2017 at 4:47 PM, Michael J Gruberwrote: > Ævar Arnfjörð Bjarmason venit, vidit, dixit 20.04.2017 23:58: >> As a refresh of everyone's memory (because mine needed it). This is a >> feature I added back in 2011 when the i18n support was initially >> added. >> >> There was concern at the time that we would inadvertently mark >> plumbing messages for translation, particularly something in a shared >> code path, and this was a way to hopefully smoke out those issues with >> the test suite. >> >> However compiling with it breaks a couple of dozen tests, I stopped >> digging when I saw some broke back in 2014. >> >> What should be done about this? I think if we're going to keep them >> they need to be run regularly by something like Travis (Lars CC'd), >> however empirical evidence suggests that not running them is just fine >> too, so should we just remove support for this test mode? >> >> I don't care, but I can come up with the patch either way, but would >> only be motivated to write the one-time fix for it if some CI system >> is actually running them regularly, otherwise they'll just be subject >> to bitrotting again. >> > > I use that switch when I change something that involves l10n, but > usually I run specific tests only. To be honest: I have to make sure not > to get confused by (nor forget one of) the build flag GETTEXT_POISON and > the environment variable GIT_GETTEXT_POISON. I'm not sure I always > tested what I meant to test... For any of the built-in tests, you just need to compile git with GETTEXT_POISON=YesPlease, the env var is set by test-lib.sh for you, you only need to set GIT_GETTEXT_POISON=1 if you're ad-hoc running some git command yourself, e.g.: $ ./git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean $ GIT_GETTEXT_POISON=1 ./git status # GETTEXT POISON #master # GETTEXT POISON #
[PATCH v6 4/8] convert: Separate generic structures and variables from the filter specific ones
To enable future reuse of the filter..process infrastructure, split the cmd2process structure into two separate parts. subprocess_entry will now contain the generic data required to manage the creation and tracking of the child process in a hashmap. Also move all knowledge of the hashmap into the generic functions. cmd2process is a filter protocol specific structure that is used to track the negotiated capabilities of the filter. Signed-off-by: Ben Peart--- convert.c | 35 --- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/convert.c b/convert.c index 36401fe087..bfb19beed5 100644 --- a/convert.c +++ b/convert.c @@ -496,26 +496,31 @@ static int apply_single_file_filter(const char *path, const char *src, size_t le #define CAP_CLEAN(1u<<0) #define CAP_SMUDGE (1u<<1) -struct cmd2process { +struct subprocess_entry { struct hashmap_entry ent; /* must be the first member! */ - unsigned int supported_capabilities; const char *cmd; struct child_process process; }; +struct cmd2process { + struct subprocess_entry subprocess; /* must be the first member! */ + unsigned int supported_capabilities; +}; + static int cmd_process_map_initialized; static struct hashmap cmd_process_map; -static int cmd2process_cmp(const struct cmd2process *e1, - const struct cmd2process *e2, +static int cmd2process_cmp(const struct subprocess_entry *e1, + const struct subprocess_entry *e2, const void *unused) { return strcmp(e1->cmd, e2->cmd); } -static struct cmd2process *find_multi_file_filter_entry(struct hashmap *hashmap, const char *cmd) +static struct subprocess_entry *find_multi_file_filter_entry(struct hashmap *hashmap, const char *cmd) { - struct cmd2process key; + struct subprocess_entry key; + hashmap_entry_init(, strhash(cmd)); key.cmd = cmd; return hashmap_get(hashmap, , NULL); @@ -541,7 +546,7 @@ static void read_multi_file_filter_status(int fd, struct strbuf *status) } } -static void kill_multi_file_filter(struct hashmap *hashmap, struct cmd2process *entry) +static void kill_multi_file_filter(struct hashmap *hashmap, struct subprocess_entry *entry) { if (!entry) return; @@ -571,8 +576,8 @@ static int start_multi_file_filter_fn(struct cmd2process *entry) struct string_list cap_list = STRING_LIST_INIT_NODUP; char *cap_buf; const char *cap_name; - struct child_process *process = >process; - const char *cmd = entry->cmd; + struct child_process *process = >subprocess.process; + const char *cmd = entry->subprocess.cmd; sigchain_push(SIGPIPE, SIG_IGN); @@ -632,9 +637,9 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons const char *argv[] = { cmd, NULL }; entry = xmalloc(sizeof(*entry)); - entry->cmd = cmd; + entry->subprocess.cmd = cmd; entry->supported_capabilities = 0; - process = >process; + process = >subprocess.process; child_process_init(process); process->argv = argv; @@ -654,7 +659,7 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons err = start_multi_file_filter_fn(entry); if (err) { error("initialization for external filter '%s' failed", cmd); - kill_multi_file_filter(hashmap, entry); + kill_multi_file_filter(hashmap, >subprocess); return NULL; } @@ -678,7 +683,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len hashmap_init(_process_map, (hashmap_cmp_fn) cmd2process_cmp, 0); entry = NULL; } else { - entry = find_multi_file_filter_entry(_process_map, cmd); + entry = (struct cmd2process *)find_multi_file_filter_entry(_process_map, cmd); } fflush(NULL); @@ -688,7 +693,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len if (!entry) return 0; } - process = >process; + process = >subprocess.process; if (!(wanted_capability & entry->supported_capabilities)) return 0; @@ -759,7 +764,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len * Force shutdown and restart if another blob requires filtering. */ error("external filter '%s' failed", cmd); - kill_multi_file_filter(_process_map, entry); + kill_multi_file_filter(_process_map, >subprocess); } } else { strbuf_swap(dst, ); -- 2.12.0.windows.1.33.g243d9b384c
[PATCH v6 3/8] convert: Split start_multi_file_filter into two separate functions
To enable future reuse of the filter..process infrastructure, split start_multi_file_filter into two separate parts. start_multi_file_filter will now only contain the generic logic to manage the creation and tracking of the child process in a hashmap. start_multi_file_filter_fn is a protocol specific initialization function that will negotiate the multi-file-filter interface version and capabilities. Signed-off-by: Ben Peart--- convert.c | 62 -- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/convert.c b/convert.c index 793c29ebfd..36401fe087 100644 --- a/convert.c +++ b/convert.c @@ -565,35 +565,14 @@ static void stop_multi_file_filter(struct child_process *process) finish_command(process); } -static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, const char *cmd) +static int start_multi_file_filter_fn(struct cmd2process *entry) { int err; - struct cmd2process *entry; - struct child_process *process; - const char *argv[] = { cmd, NULL }; struct string_list cap_list = STRING_LIST_INIT_NODUP; char *cap_buf; const char *cap_name; - - entry = xmalloc(sizeof(*entry)); - entry->cmd = cmd; - entry->supported_capabilities = 0; - process = >process; - - child_process_init(process); - process->argv = argv; - process->use_shell = 1; - process->in = -1; - process->out = -1; - process->clean_on_exit = 1; - process->clean_on_exit_handler = stop_multi_file_filter; - - if (start_command(process)) { - error("cannot fork to run external filter '%s'", cmd); - return NULL; - } - - hashmap_entry_init(entry, strhash(cmd)); + struct child_process *process = >process; + const char *cmd = entry->cmd; sigchain_push(SIGPIPE, SIG_IGN); @@ -642,7 +621,38 @@ static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, cons done: sigchain_pop(SIGPIPE); - if (err || errno == EPIPE) { + return err; +} + +static struct cmd2process *start_multi_file_filter(struct hashmap *hashmap, const char *cmd) +{ + int err; + struct cmd2process *entry; + struct child_process *process; + const char *argv[] = { cmd, NULL }; + + entry = xmalloc(sizeof(*entry)); + entry->cmd = cmd; + entry->supported_capabilities = 0; + process = >process; + + child_process_init(process); + process->argv = argv; + process->use_shell = 1; + process->in = -1; + process->out = -1; + process->clean_on_exit = 1; + process->clean_on_exit_handler = stop_multi_file_filter; + + if (start_command(process)) { + error("cannot fork to run external filter '%s'", cmd); + return NULL; + } + + hashmap_entry_init(entry, strhash(cmd)); + + err = start_multi_file_filter_fn(entry); + if (err) { error("initialization for external filter '%s' failed", cmd); kill_multi_file_filter(hashmap, entry); return NULL; @@ -733,7 +743,7 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len done: sigchain_pop(SIGPIPE); - if (err || errno == EPIPE) { + if (err) { if (!strcmp(filter_status.buf, "error")) { /* The filter signaled a problem with the file. */ } else if (!strcmp(filter_status.buf, "abort")) { -- 2.12.0.windows.1.33.g243d9b384c
[PATCH v6 1/8] pkt-line: add packet_read_line_gently()
Add packet_read_line_gently() to enable reading a line without dying on EOF. Signed-off-by: Ben Peart--- pkt-line.c | 14 +- pkt-line.h | 10 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pkt-line.c b/pkt-line.c index d4b6bfe076..bfdb177b34 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -315,7 +315,7 @@ static char *packet_read_line_generic(int fd, PACKET_READ_CHOMP_NEWLINE); if (dst_len) *dst_len = len; - return len ? packet_buffer : NULL; + return (len > 0) ? packet_buffer : NULL; } char *packet_read_line(int fd, int *len_p) @@ -323,6 +323,18 @@ char *packet_read_line(int fd, int *len_p) return packet_read_line_generic(fd, NULL, NULL, len_p); } +int packet_read_line_gently(int fd, int *dst_len, char** dst_line) +{ + int len = packet_read(fd, NULL, NULL, + packet_buffer, sizeof(packet_buffer), + PACKET_READ_CHOMP_NEWLINE|PACKET_READ_GENTLE_ON_EOF); + if (dst_len) + *dst_len = len; + if (dst_line) + *dst_line = (len > 0) ? packet_buffer : NULL; + return len; +} + char *packet_read_line_buf(char **src, size_t *src_len, int *dst_len) { return packet_read_line_generic(-1, src, src_len, dst_len); diff --git a/pkt-line.h b/pkt-line.h index 18eac64830..ad30db101a 100644 --- a/pkt-line.h +++ b/pkt-line.h @@ -74,6 +74,16 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, char char *packet_read_line(int fd, int *size); /* + * Convenience wrapper for packet_read that sets the PACKET_READ_GENTLE_ON_EOF + * and CHOMP_NEWLINE options. The return value specifies the number of bytes + * read into the buffer or -1 on truncated input. If the *dst_line parameter + * is not NULL it will return NULL for a flush packet and otherwise points to + * a static buffer (that may be overwritten by subsequent calls). If the size + * parameter is not NULL, the length of the packet is written to it. + */ +int packet_read_line_gently(int fd, int *size, char** dst_line); + +/* * Same as packet_read_line, but read from a buf rather than a descriptor; * see packet_read for details on how src_* is used. */ -- 2.12.0.windows.1.33.g243d9b384c
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 4:25 PM, Christian Couderwrote: > On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummerer > wrote: >> On 04/20, Christian Couder wrote: >>> >>> Could you try with the following patch: >>> >>> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ >> >> Yeah, I tried with and without that patch with the same result. >> Unless I'm screwing something up when testing I don't think this fixes >> the issue unfortunately. > > I just tried on "pu" and only the first test > (t7009-filter-branch-null-sha1.sh) fails there. I bisected this test's failure (when using GIT_TEST_SPLIT_INDEX=YesPlease) to e6a1dd77e1 (read-cache: regenerate shared index if necessary, 2017-02-27). The failing test is the following: test_expect_success 'filter commands are still checked' ' test_must_fail git filter-branch \ --force --prune-empty \ --index-filter "git rm --cached --ignore-unmatch three.t" ' And if I add the following at the beginning of the test: git config splitIndex.maxPercentChange 100 && the test then passes. So It looks like in split index mode the test doesn't expect the shared index to be regenerated. Maybe Peff, as he is the author of this test, or Duy have an idea about this?
Re: [BUG] test suite broken with GETTEXT_POISON=YesPlease
On Fri, Apr 21, 2017 at 4:54 PM, Lars Schneiderwrote: > >> Am 20.04.2017 um 23:58 schrieb Ævar Arnfjörð Bjarmason : >> >> As a refresh of everyone's memory (because mine needed it). This is a >> feature I added back in 2011 when the i18n support was initially >> added. >> >> There was concern at the time that we would inadvertently mark >> plumbing messages for translation, particularly something in a shared >> code path, and this was a way to hopefully smoke out those issues with >> the test suite. >> >> However compiling with it breaks a couple of dozen tests, I stopped >> digging when I saw some broke back in 2014. >> >> What should be done about this? I think if we're going to keep them >> they need to be run regularly by something like Travis (Lars CC'd), >> however empirical evidence suggests that not running them is just fine >> too, so should we just remove support for this test mode? > > Right now we are building and testing Git in the following configurations: > > 1. Linux, gcc, stable Perforce an GitLFS version (used by git-p4 tests) > 2. Linux, gcc, stable Perforce an GitLFS version (used by git-p4 tests) * > 3. OSX, clang, latest Perforce an GitLFS version (used by git-p4 tests) > 4. OSX, clang, latest Perforce an GitLFS version (used by git-p4 tests) * > 5. Linux32, gcc, no git-p4 tests > 6. Windows, gcc, no git-p4 tests > > 1-4 run the same tests right now. This was especially useful in the beginning > to identify flaky tests (t0025 is still flaky!). > > We could easily run the tests in 1-4 with different configurations. E.g. > enable GETTEXT_POISON in 2. > > Cheers, > Lars > > *) 2 and 4 use the wrong compiler right now. 2 should use clang on Linux and > 4 should use gcc. A patch is on my todo list. Great, thanks. I'll fixup the poison tests then.
[PATCHv3 4/4] builtin/reset: add --recurse-submodules switch
git-reset is yet another working tree manipulator, which should be taught about submodules. When a user uses git-reset and requests to recurse into submodules, this will reset the submodules to the object name as recorded in the superproject, detaching the HEADs. Signed-off-by: Stefan Beller--- This replaces the topmost patch in sb/reset-recurse-submodules. The only difference is the rewording of the commit message. Thanks, Stefan builtin/reset.c| 30 ++ t/t7112-reset-submodule.sh | 8 2 files changed, 38 insertions(+) diff --git a/builtin/reset.c b/builtin/reset.c index fc3b906c47..5ce27fcaed 100644 --- a/builtin/reset.c +++ b/builtin/reset.c @@ -21,6 +21,27 @@ #include "parse-options.h" #include "unpack-trees.h" #include "cache-tree.h" +#include "submodule.h" +#include "submodule-config.h" + +static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT; + +static int option_parse_recurse_submodules(const struct option *opt, + const char *arg, int unset) +{ + if (unset) { + recurse_submodules = RECURSE_SUBMODULES_OFF; + return 0; + } + if (arg) + recurse_submodules = + parse_update_recurse_submodules_arg(opt->long_name, + arg); + else + recurse_submodules = RECURSE_SUBMODULES_ON; + + return 0; +} static const char * const git_reset_usage[] = { N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] []"), @@ -283,6 +304,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix) N_("reset HEAD, index and working tree"), MERGE), OPT_SET_INT(0, "keep", _type, N_("reset HEAD but keep local changes"), KEEP), + { OPTION_CALLBACK, 0, "recurse-submodules", _submodules, + "reset", "control recursive updating of submodules", + PARSE_OPT_OPTARG, option_parse_recurse_submodules }, OPT_BOOL('p', "patch", _mode, N_("select hunks interactively")), OPT_BOOL('N', "intent-to-add", _to_add, N_("record only the fact that removed paths will be added later")), @@ -295,6 +319,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix) PARSE_OPT_KEEP_DASHDASH); parse_args(, argv, prefix, patch_mode, ); + if (recurse_submodules != RECURSE_SUBMODULES_DEFAULT) { + gitmodules_config(); + git_config(submodule_config, NULL); + set_config_update_recurse_submodules(RECURSE_SUBMODULES_ON); + } + unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash); if (unborn) { /* reset on unborn branch: treat as reset to empty tree */ diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh index 2eda6adeb1..f86ccdf215 100755 --- a/t/t7112-reset-submodule.sh +++ b/t/t7112-reset-submodule.sh @@ -5,6 +5,14 @@ test_description='reset can handle submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh +KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1 +KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1 +KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1 + +test_submodule_switch_recursing "git reset --recurse-submodules --keep" + +test_submodule_forced_switch_recursing "git reset --hard --recurse-submodules" + test_submodule_switch "git reset --keep" test_submodule_switch "git reset --merge" -- 2.13.0.rc0.2.g0d1ae48b0e
Re: [BUG] test suite broken with GETTEXT_POISON=YesPlease
Ævar Arnfjörð Bjarmason venit, vidit, dixit 20.04.2017 23:58: > As a refresh of everyone's memory (because mine needed it). This is a > feature I added back in 2011 when the i18n support was initially > added. > > There was concern at the time that we would inadvertently mark > plumbing messages for translation, particularly something in a shared > code path, and this was a way to hopefully smoke out those issues with > the test suite. > > However compiling with it breaks a couple of dozen tests, I stopped > digging when I saw some broke back in 2014. > > What should be done about this? I think if we're going to keep them > they need to be run regularly by something like Travis (Lars CC'd), > however empirical evidence suggests that not running them is just fine > too, so should we just remove support for this test mode? > > I don't care, but I can come up with the patch either way, but would > only be motivated to write the one-time fix for it if some CI system > is actually running them regularly, otherwise they'll just be subject > to bitrotting again. > I use that switch when I change something that involves l10n, but usually I run specific tests only. To be honest: I have to make sure not to get confused by (nor forget one of) the build flag GETTEXT_POISON and the environment variable GIT_GETTEXT_POISON. I'm not sure I always tested what I meant to test... Michael
RE: Proposal for "fetch-any-blob Git protocol" and server design
Hi Jonathan, Sorry for the delayed response - other work got in the way, unfortunately! Kevin -Original Message- From: Jonathan Tan [mailto:jonathanta...@google.com] Sent: Thursday, April 13, 2017 4:13 PM >> I know we're considering server behavior here, but how large do you generally >> expect these blob-want requests to be? I ask because we took an initial >> approach >> very similar to this, however, we had a hard time being clever about >> figuring out >> what set of blobs to request for those clients that didn't want the entire >> set, and >> ended up falling back to single-blob requests. >> >> Obviously, this could be due to thenature of our >> filesystem-virtualization-based client, >> but I also suspect that the teams attacking this problem are more often than >> not dealing >> with very large blob objects, so the cost of a round-trip becomes lower >> relative to sending >> the object content itself. > > I am envisioning (1a) as described in Jeff Hostetler's e-mail [1] ("a > pre-command or hook to identify needed blobs and pre-fetch them before > allowing the actual command to start"), so a Git command would typically > make a single request that contains all the blobs required, but my > proposal can also handle (1c) ('"fault" them in as necessary in > read_object() while the command is running and without any pre-fetch > (either synchronously or asynchronously and with/without a helper > process)'). > > Even if we decided to go with single-blob requests and responses, it is > still important to send them as packfiles, so that the server can serve > them directly from its compressed storage without first having to > uncompress them. > > [1] > https://public-inbox.org/git/1488999039-37631-1-git-send-email-...@jeffhostetler.com/ Ah, I missed this. If we think we can build meaningfully-sized requests via (1a) and (1b), then I agree - packs are optimal. However, if single-blob requests/responses dominate, I have a few concerns, mostly from experience playing with something similar: * Regardless of the size of the object or number returned, the client will need to `index-pack` the result and create a corresponding `.idx` file, which requires decompression to construct (right?) * Unless the client's repository is repacked aggressively, we'll pollute the `.git\objects\pack` directory with little indexes (somewhere around 4KiB minimum) and packfiles rapidly, which would degrade performance. One rudimentary workaround would be to loosen these packs on the client if they were under a certain size/object count. I think fetch does this already? In either case, shifting the pack decompression/loose object recompression problem to the client instead of the server is probably a good principle, but in our case it simply wasn't fast enough to serve single blobs interactively (e.g. opening a source file you don't have locally). I'm hopeful that the proposed partial clone solutions you referenced would reduce the frequency of this being required. >> Being a bit more clever about packing objects (e.g. splitting blobs out from >> commits >> and trees) improved this a bit, but we still hit a bottlenecks from what >> appeared to >> be a large number of memory-mapping operations on a ~140GiB packfile of >> blobs. >> >> Each `pack-objects` process would consume approximately one CPU core for the >> duration of the request. It's possible that further splitting of these large >> blob packs >> would have improved performance in some scenarios, but that would increase >> the >> amount of pack-index lookups necessary to find a single object. > > I'm not very experienced with mmap, but I thought that memory-mapping a > large file in itself does not incur much of a performance penalty (if > any) - it is the accesses that count. I experimented with 15,000 and > 150,000 MiB files and mmap and they seem to be handled quite well. Also, > how many objects are "pack-objects" packing here? Back when we took this approach, it was ~4000 blob objects at a time. Perhaps we were being bitten by the Windows implementation of git_mmap[3]?. When I profiled the 4k blob scenario, the majority of CPU and wall time was spent in MapViewOfFileEx, which looks like it could mean accesses as well. [3] https://github.com/git/git/blob/master/compat/win32mmap.c >> This seems like a clever way to avoid the canonical >> `/info/refs?service=git-upload-pack` >> capability negotiation on every call. However, using error handling to >> fallback seems >> slightly wonky to me. Hopefully users are incentivized to upgrade their >> clients. > > By "error handling to fallback", do you mean in my proposal or in a > possible future one (assuming my proposal is implemented)? I don't think > my proposal requires any error handling to fallback (since only new > clients can clone partially - old clients will just clone totally and > obliviously), but I acknowledge that this
Re: [BUG] test suite broken with GETTEXT_POISON=YesPlease
> Am 20.04.2017 um 23:58 schrieb Ævar Arnfjörð Bjarmason: > > As a refresh of everyone's memory (because mine needed it). This is a > feature I added back in 2011 when the i18n support was initially > added. > > There was concern at the time that we would inadvertently mark > plumbing messages for translation, particularly something in a shared > code path, and this was a way to hopefully smoke out those issues with > the test suite. > > However compiling with it breaks a couple of dozen tests, I stopped > digging when I saw some broke back in 2014. > > What should be done about this? I think if we're going to keep them > they need to be run regularly by something like Travis (Lars CC'd), > however empirical evidence suggests that not running them is just fine > too, so should we just remove support for this test mode? Right now we are building and testing Git in the following configurations: 1. Linux, gcc, stable Perforce an GitLFS version (used by git-p4 tests) 2. Linux, gcc, stable Perforce an GitLFS version (used by git-p4 tests) * 3. OSX, clang, latest Perforce an GitLFS version (used by git-p4 tests) 4. OSX, clang, latest Perforce an GitLFS version (used by git-p4 tests) * 5. Linux32, gcc, no git-p4 tests 6. Windows, gcc, no git-p4 tests 1-4 run the same tests right now. This was especially useful in the beginning to identify flaky tests (t0025 is still flaky!). We could easily run the tests in 1-4 with different configurations. E.g. enable GETTEXT_POISON in 2. Cheers, Lars *) 2 and 4 use the wrong compiler right now. 2 should use clang on Linux and 4 should use gcc. A patch is on my todo list.
Re: [PATCH 0/6] nd/worktree-move update
On Thu, Apr 20, 2017 at 05:10:18PM +0700, Nguyễn Thái Ngọc Duy wrote: > - fixes the compile problem on latest master (because prefix_filename >takes one argument less) It also now returns an allocated buffer. So: > --- a/builtin/worktree.c > +++ b/builtin/worktree.c > @@ -561,9 +561,7 @@ static int move_worktree(int ac, const char **av, const > char *prefix) > if (ac != 2) > usage_with_options(worktree_usage, options); > > - strbuf_addstr(, prefix_filename(prefix, > - strlen(prefix), > - av[1])); > + strbuf_addstr(, prefix_filename(prefix, av[1])); ...this is now a leak. Probably: const char *filename = prefix_filename(prefix, av[1]); strbuf_attach(, filename, strlen(filename), strlen(filename)); is what you want. That would be less awkward if we had a strbuf_attach_str(). Or if we had a strbuf variant of prefix_filename(), you could do: prefix_filename_buf(, prefix, av[1]); I almost added that when I did the prefix_filename() work, since it uses a strbuf internally. But there were no callers that would have used it. Maybe it's worth doing now. -- >8 -- >From d0b933fc023023a017df9268360aa327c28b90f0 Mon Sep 17 00:00:00 2001 From: Jeff KingDate: Fri, 21 Apr 2017 10:53:07 -0400 Subject: [PATCH] prefix_filename: add strbuf variant Now that prefix_filename() always allocates, it's awkward to put its value directly into a strbuf. You have to either free: const char *filename = prefix_filename(prefix, arg); strbuf_addstr(, filename); free(filename); or you have to attach: const char *filename = prefix_filename(prefix, arg); strbuf_attach(, filename, strlen(filename), strlen(filename)); Since we're already using a strbuf internally, it's easy to provide a variant that lets you write directly into one: prefix_filename_buf(, prefix, arg); For consistency with git_path_buf(), the function overwrites the strbuf rather than appending. Signed-off-by: Jeff King --- abspath.c | 17 - cache.h | 6 ++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/abspath.c b/abspath.c index 7f1cfe979..7594f62a5 100644 --- a/abspath.c +++ b/abspath.c @@ -246,21 +246,28 @@ char *absolute_pathdup(const char *path) return strbuf_detach(, NULL); } -char *prefix_filename(const char *pfx, const char *arg) +void prefix_filename_buf(struct strbuf *path, const char *pfx, const char *arg) { - struct strbuf path = STRBUF_INIT; size_t pfx_len = pfx ? strlen(pfx) : 0; + strbuf_reset(path); + if (!pfx_len) ; /* nothing to prefix */ else if (is_absolute_path(arg)) pfx_len = 0; else - strbuf_add(, pfx, pfx_len); + strbuf_add(path, pfx, pfx_len); - strbuf_addstr(, arg); + strbuf_addstr(path, arg); #ifdef GIT_WINDOWS_NATIVE - convert_slashes(path.buf + pfx_len); + convert_slashes(path->buf + pfx_len); #endif +} + +char *prefix_filename(const char *pfx, const char *arg) +{ + struct strbuf path = STRBUF_INIT; + prefix_filename_buf(, pfx, arg); return strbuf_detach(, NULL); } diff --git a/cache.h b/cache.h index ba27595d5..209039a98 100644 --- a/cache.h +++ b/cache.h @@ -548,6 +548,12 @@ extern char *prefix_path_gently(const char *prefix, int len, int *remaining, con */ extern char *prefix_filename(const char *prefix, const char *path); +/* + * Like prefix_filename, but write into "buf", overwriting any + * previous contents of the strbuf. + */ +extern void prefix_filename_buf(struct strbuf *out, const char *prefix, const char *path); + extern int check_filename(const char *prefix, const char *name); extern void verify_filename(const char *prefix, const char *name, -- 2.13.0.rc0.364.g36b4d8031
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummererwrote: > On 04/20, Christian Couder wrote: >> >> Could you try with the following patch: >> >> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ > > Yeah, I tried with and without that patch with the same result. > Unless I'm screwing something up when testing I don't think this fixes > the issue unfortunately. I just tried on "pu" and only the first test (t7009-filter-branch-null-sha1.sh) fails there.
Re: What's cooking in git.git (Apr 2017, #04; Wed, 19)
On Fri, Apr 21, 2017 at 11:50 AM, Johannes Schindelinwrote: > > Since that "let's aggregate everything and only push out the final result > at the end of the day" approach does not really allow the Continuous > Testing to identify problems associated with individual topic branches, I > have another job that bisects the breakages Great! > (with all associated problems > I reported earlier, as you apply some patches on top of really ancient > commits and bisect wants to test all merge bases first) First bisect should ask you to test merge bases only if there are "good" commits that are not ancestors of the "bad" commit. So I don't know how you want to bisect, but it seems to me that you could just go back to a previous know "good" commit when the one you have is not an ancestor of the "bad" commit. This would get rid of the whole merge base problem. Second yeah there is probably an old bug in bisect there. In theory in most cases bisect should ask you to test only one merge base, as: - if the merge base is "bad", it means that the bug has been fixed between the merge base and your "good" commit, and bisecting will stop, - if the merge base is "good", it means that all the merge bases that are ancestor of this merge base are also good, so there is no need to test them But that theory can work only if bisect is asking you to test a merge base that is a descendant of many (if not all the other merge bases), but unfortunately I don't think bisect is smart enough for that yet. > because the > required time *definitely* would let Travis time out all the time. Those > bisect results are even less visible than the Travis results, see e.g. > https://github.com/git/git/commit/2e3a8b9035a#commitcomment-21836854. Nice that they exists though!
Re: [PATCH] completion: expand "push --delete " for refs on that
On Tue, Apr 18, 2017 at 3:31 PM, Ævar Arnfjörð Bjarmasonwrote: > Change the completion of "push --delete " to complete > refs on that , not all refs. Good. > Before this e.g. cloning git.git > and doing "git push --delete origin p" will complete nothing, Well, it will complete all local branches starting with 'p', but perhaps you don't happen to have any. > whereas origin/p will uselessly complete origin/pu. > > Now p will complete as "pu". The completion of giving --delete > later, e.g. "git push origin --delete p" remains unchanged, this > is a bug, but is a general existing limitation of the bash completion, > and not how git-push is documented, so I'm not fixing that case. > > I looked over t9902-completion.sh but couldn't quickly find out how to > add a test for this, Yeah, this helper function has to look at the whole command line to do its thing, and we don't have other unit test-like tests doing something like that. One option would be something like this: @@ -1162,6 +1162,19 @@ test_expect_success '__git_complete_fetch_refspecs - fully qualified & prefix' ' test_cmp expected out ' +test_expect_success '__git_complete_remote_or_refspec - push -d' ' + sed -e "s/Z$//" >expected <<-EOF && + master-in-other Z + EOF + ( + words=(git push -d other ma) && + cword=${#words[@]} cur=${words[cword-1]} && + __git_complete_remote_or_refspec && + print_comp + ) && + test_cmp expected out +' + test_expect_success 'teardown after ref completion' ' git branch -d matching-branch && git tag -d matching-tag && This is chatty, no question about that, but it only excercises __git_complete_remote_or_refspec() (and __git_refs() behind its back), and thus fits right in there with other refs completion tests. The other option would be something like this: @@ -1348,6 +1361,10 @@ test_expect_success 'complete tree filename with metacharacters' ' EOF ' +test_expect_success 'complete remote refs for git push -d' ' + test_completion "git push -d other ma" "master-in-other " +' + test_expect_success 'send-email' ' test_completion "git send-email --cov" "--cover-letter " && test_completion "git send-email ma" "master " While this is much more compact, it does excercise the whole shebang, therefore it has to go to the integration tests. However, at that point in the test script there aren't any remote refs in the repository (and, consequently this test will fail as it is), so you would need to add a few, which in turn would most likely require adjustments in other tests. I'm partial to the former, even if it's more lines of code, because if it were to fail, then it already narrowed down the scope where we'd need to look for the cause of the failure. Take your pick :) > but all the existing tests pass, and all my > manual testing of "git push --delete ..." does the right > thing now. > > Signed-off-by: Ævar Arnfjörð Bjarmason > --- > contrib/completion/git-completion.bash | 7 +-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/contrib/completion/git-completion.bash > b/contrib/completion/git-completion.bash > index 1150164d5c..2e5b3ed776 100644 > --- a/contrib/completion/git-completion.bash > +++ b/contrib/completion/git-completion.bash > @@ -701,7 +701,7 @@ __git_complete_revlist () > __git_complete_remote_or_refspec () > { > local cur_="$cur" cmd="${words[1]}" > - local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 > + local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0 delete=0 > if [ "$cmd" = "remote" ]; then > ((c++)) > fi > @@ -709,6 +709,7 @@ __git_complete_remote_or_refspec () > i="${words[c]}" > case "$i" in > --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;; > + --delete) delete=1 ;; I noticed the two identical __git_complete_refs() calls in the hunk below. How about: -d|--delete) [ "$cmd" = "push" ] && lhs=0 ;; First, it recognizes the short option, too. Second, with 'push -d' any ref is interpreted as the right hand side of a refspec whose left hand side is empty (i.e. '-d pu' means ':pu'). That 'lhs=0' tells the rest of the function to complete the right hand side of a refspec, i.e. in case of 'push' to list remote refs, which is exactly what you want. And you won't need the extra if branch in the hunk below, or the new local variable. In this case, however, we should check that the command is 'push' as well, just in case the other commands whose completion is driven by this helper function get these options in the future. > --all) > case "$cmd" in > push) no_complete_refspec=1 ;; > @@ -761,7 +762,9 @@ __git_complete_remote_or_refspec () > fi > ;; > push) > -
Re: [PATCH 00/15] Handle fopen() errors
On Fri, Apr 21, 2017 at 6:52 PM, Junio C Hamanowrote: > Yes, but (1) we'd need to be careful about --quiet Yeah. It's a real pain point for making changes like this. At some point we should just have a global (maybe multi-level) quiet flag. -- Duy
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 6:57 PM, Christian Couderwrote: > On Fri, Apr 21, 2017 at 1:46 PM, Christian Couder > wrote: >> On Fri, Apr 21, 2017 at 11:53 AM, Duy Nguyen wrote: >>> On Fri, Apr 21, 2017 at 2:10 PM, Christian Couder >>> wrote: On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummerer wrote: > On 04/20, Christian Couder wrote: >> >> Could you try with the following patch: >> >> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ > > Yeah, I tried with and without that patch with the same result. > Unless I'm screwing something up when testing I don't think this fixes > the issue unfortunately. Ok, I will take a look soon. By the way I think that GIT_TEST_SPLIT_INDEX has become redundant now that there is core.splitIndex. So perhaps in the long run it will be best to deprecate GIT_TEST_SPLIT_INDEX and eventually remove it. >>> >>> I think you can't, at least the way I understand this variable. It's a >>> _test_ variable to force exercise split index code path a whole lot >>> more, by running the entire test suite with split index always >>> enabled, instead of just a couple in t-split-index.sh. We can't >>> achieve the same with core.splitIndex because that's more about user >>> control and you can't just set core.splitIndex for the entire test >>> suite (can we?). >> >> Yeah, you are right. >> It looks like we have GIT_TEST_OPTS to pass options like --debug, >> --valgrind, --verbose, but we don't have an environment variable to >> set config options. > > Or maybe GIT_CONFIG_PARAMETERS works for this purpose? It has to be set inside test-lib.sh, not from outside because environment variables from outside are filtered if I remember correctly and only a few specials plus those GIT_TEST_ can survive. Some tests override GIT_CONFIG_PARAMETERS themselves to pass config vars to certain command (I know because I just did a couple days ago ;).which loses core.splitIndex. -- Duy
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 1:46 PM, Christian Couderwrote: > On Fri, Apr 21, 2017 at 11:53 AM, Duy Nguyen wrote: >> On Fri, Apr 21, 2017 at 2:10 PM, Christian Couder >> wrote: >>> On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummerer >>> wrote: On 04/20, Christian Couder wrote: > > Could you try with the following patch: > > http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ Yeah, I tried with and without that patch with the same result. Unless I'm screwing something up when testing I don't think this fixes the issue unfortunately. >>> >>> Ok, I will take a look soon. >>> >>> By the way I think that GIT_TEST_SPLIT_INDEX has become redundant now >>> that there is core.splitIndex. >>> So perhaps in the long run it will be best to deprecate >>> GIT_TEST_SPLIT_INDEX and eventually remove it. >> >> I think you can't, at least the way I understand this variable. It's a >> _test_ variable to force exercise split index code path a whole lot >> more, by running the entire test suite with split index always >> enabled, instead of just a couple in t-split-index.sh. We can't >> achieve the same with core.splitIndex because that's more about user >> control and you can't just set core.splitIndex for the entire test >> suite (can we?). > > Yeah, you are right. > It looks like we have GIT_TEST_OPTS to pass options like --debug, > --valgrind, --verbose, but we don't have an environment variable to > set config options. Or maybe GIT_CONFIG_PARAMETERS works for this purpose?
Re: [PATCH 00/15] Handle fopen() errors
On Fri, Apr 21, 2017 at 8:04 PM, Duy Nguyenwrote: > On Fri, Apr 21, 2017 at 1:29 PM, Jeff King wrote: >> >> I had a similar thought while reading through it. I think it would be >> shorter still with: >> >> FILE *fopen_or_warn(const char *path, const char *mode) >> { >> FILE *fh = fopen(path, mode); >> if (!fh) >> warn_failure_to_read_open_optional_path(path); >> return fh; >> } >> >> And then quite a few of the patches could just be >> s/fopen/fopen_or_warn/. > > Jeff.. oh Jeff.. you have made it _way_ too convenient that after a > quick grep at fopen( again, I found a couple more places that I would > have just ignored last time (too much work), but now all I need to do > is Alt-f to the end of fopen and Alt-/ a few times. Too tempting.. :) Yes, but (1) we'd need to be careful about --quiet, and (2) we would also need a wrapper for open(2).
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 11:53 AM, Duy Nguyenwrote: > On Fri, Apr 21, 2017 at 2:10 PM, Christian Couder > wrote: >> On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummerer >> wrote: >>> On 04/20, Christian Couder wrote: Could you try with the following patch: http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ >>> >>> Yeah, I tried with and without that patch with the same result. >>> Unless I'm screwing something up when testing I don't think this fixes >>> the issue unfortunately. >> >> Ok, I will take a look soon. >> >> By the way I think that GIT_TEST_SPLIT_INDEX has become redundant now >> that there is core.splitIndex. >> So perhaps in the long run it will be best to deprecate >> GIT_TEST_SPLIT_INDEX and eventually remove it. > > I think you can't, at least the way I understand this variable. It's a > _test_ variable to force exercise split index code path a whole lot > more, by running the entire test suite with split index always > enabled, instead of just a couple in t-split-index.sh. We can't > achieve the same with core.splitIndex because that's more about user > control and you can't just set core.splitIndex for the entire test > suite (can we?). Yeah, you are right. It looks like we have GIT_TEST_OPTS to pass options like --debug, --valgrind, --verbose, but we don't have an environment variable to set config options.
Re: [PATCH 00/15] Handle fopen() errors
On Fri, Apr 21, 2017 at 1:29 PM, Jeff Kingwrote: > On Thu, Apr 20, 2017 at 08:41:32PM -0700, Junio C Hamano wrote: > >> Junio C Hamano writes: >> >> > I wonder if it is OK to only special case ENOENT for !fp cases, >> > where existing code silently returns. Perhaps it is trying to read >> > an optional file, and it returns silently because lack of it is >> > perfectly OK for the purpose of the code. Are there cases where >> > this optional file is inside an optional directory, leading to >> > ENOTDIR, instead of ENOENT, observed and reported by your check? >> >> "git grep -B1 warn_on_inaccessible" is enlightening. I wonder if we >> want to wrap the two lines into a hard to misuse helper function, >> something along this line. Would having this patch as a preparatory >> step shrink your series? The patch count would be the same, but you >> wouldn't be writing "if (errno != ENOENT)" lines yourself. > > I had a similar thought while reading through it. I think it would be > shorter still with: > > FILE *fopen_or_warn(const char *path, const char *mode) > { > FILE *fh = fopen(path, mode); > if (!fh) > warn_failure_to_read_open_optional_path(path); > return fh; > } > > And then quite a few of the patches could just be > s/fopen/fopen_or_warn/. Jeff.. oh Jeff.. you have made it _way_ too convenient that after a quick grep at fopen( again, I found a couple more places that I would have just ignored last time (too much work), but now all I need to do is Alt-f to the end of fopen and Alt-/ a few times. Too tempting.. :) -- Duy
[PATCH v4 3/9] t0006 & t5000: skip "far in the future" test when time_t is too limited
Git's source code refers to timestamps as unsigned long, which is ill-defined, as there is no guarantee about the number of bits that data type has. In preparation of switching to another data type that is large enough to hold "far in the future" dates, we need to prepare the t0006-date.sh script for the case where we *still* cannot format those dates if the system library uses 32-bit time_t. Signed-off-by: Johannes Schindelin--- t/helper/test-date.c | 5 - t/t0006-date.sh | 4 ++-- t/t5000-tar-tree.sh | 2 +- t/test-lib.sh| 1 + 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 4727bea255c..ac7c66c733b 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -5,7 +5,8 @@ static const char *usage_msg = "\n" " test-date show: [time_t]...\n" " test-date parse [date]...\n" " test-date approxidate [date]...\n" -" test-date is64bit\n"; +" test-date is64bit\n" +" test-date time_t-is64bit\n"; static void show_relative_dates(const char **argv, struct timeval *now) { @@ -96,6 +97,8 @@ int cmd_main(int argc, const char **argv) parse_approxidate(argv+1, ); else if (!strcmp(*argv, "is64bit")) return sizeof(unsigned long) == 8 ? 0 : 1; + else if (!strcmp(*argv, "time_t-is64bit")) + return sizeof(time_t) == 8 ? 0 : 1; else usage(usage_msg); return 0; diff --git a/t/t0006-date.sh b/t/t0006-date.sh index 9539b425ffb..42d4ea61ef5 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -53,8 +53,8 @@ check_show unix-local "$TIME" '146600' # arbitrary time absurdly far in the future FUTURE="5758122296 -0400" -check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT -check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +" TIME_IS_64BIT +check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT +check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +" TIME_IS_64BIT,TIME_T_IS_64BIT check_parse() { echo "$1 -> $2" >expect diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 997aa9dea28..fe2d4f15a73 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -402,7 +402,7 @@ test_expect_success TIME_IS_64BIT 'generate tar with future mtime' ' git archive HEAD >future.tar ' -test_expect_success TAR_HUGE,TIME_IS_64BIT 'system tar can read our future mtime' ' +test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' ' echo 4147 >expect && tar_info future.tar | cut -d" " -f2 >actual && test_cmp expect actual diff --git a/t/test-lib.sh b/t/test-lib.sh index beee1d847ff..8d25cb7c183 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1166,3 +1166,4 @@ test_lazy_prereq LONG_IS_64BIT ' ' test_lazy_prereq TIME_IS_64BIT 'test-date is64bit' +test_lazy_prereq TIME_T_IS_64BIT 'test-date time_t-is64bit' -- 2.12.2.windows.2.406.gd14a8f8640f
[PATCH v4 2/9] t0006 & t5000: prepare for 64-bit timestamps
Git's source code refers to timestamps as unsigned longs. On 32-bit platforms, as well as on Windows, unsigned long is not large enough to capture dates that are "absurdly far in the future". It is perfectly valid by the C standard, of course, for the `long` data type to refer to 32-bit integers. That is why the `time_t` data type exists: so that it can be 64-bit even if `long` is 32-bit. Git's source code simply uses an incorrect data type for timestamps, is all. The earlier quick fix 6b9c38e14cd (t0006: skip "far in the future" test when unsigned long is not long enough, 2016-07-11) papered over this issue simply by skipping the respective test cases on platforms where they would fail due to the data type in use. This quick fix, however, tests for *long* to be 64-bit or not. What we need, though, is a test that says whether *whatever data type we use for timestamps* is 64-bit or not. The same quick fix was used to handle the similar problem where Git's source code uses `unsigned long` to represent size, instead of `size_t`, conflating the two issues. So let's just add another prerequisite to test specifically whether timestamps are represented by a 64-bit data type or not. Later, after we switch to a larger data type, we can flip that prerequisite to test `time_t` instead of `long`. Signed-off-by: Johannes Schindelin--- t/helper/test-date.c | 5 - t/t0006-date.sh | 4 ++-- t/t5000-tar-tree.sh | 6 +++--- t/test-lib.sh| 2 ++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 506054bcd5d..4727bea255c 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -4,7 +4,8 @@ static const char *usage_msg = "\n" " test-date relative [time_t]...\n" " test-date show: [time_t]...\n" " test-date parse [date]...\n" -" test-date approxidate [date]...\n"; +" test-date approxidate [date]...\n" +" test-date is64bit\n"; static void show_relative_dates(const char **argv, struct timeval *now) { @@ -93,6 +94,8 @@ int cmd_main(int argc, const char **argv) parse_dates(argv+1, ); else if (!strcmp(*argv, "approxidate")) parse_approxidate(argv+1, ); + else if (!strcmp(*argv, "is64bit")) + return sizeof(unsigned long) == 8 ? 0 : 1; else usage(usage_msg); return 0; diff --git a/t/t0006-date.sh b/t/t0006-date.sh index c0c910867d7..9539b425ffb 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -53,8 +53,8 @@ check_show unix-local "$TIME" '146600' # arbitrary time absurdly far in the future FUTURE="5758122296 -0400" -check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" LONG_IS_64BIT -check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +" LONG_IS_64BIT +check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT +check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +" TIME_IS_64BIT check_parse() { echo "$1 -> $2" >expect diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 886b6953e40..997aa9dea28 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -390,7 +390,7 @@ test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' ' test_cmp expect actual ' -test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' +test_expect_success TIME_IS_64BIT 'set up repository with far-future commit' ' rm -f .git/index && echo content >file && git add file && @@ -398,11 +398,11 @@ test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' git commit -m "tempori parendum" ' -test_expect_success LONG_IS_64BIT 'generate tar with future mtime' ' +test_expect_success TIME_IS_64BIT 'generate tar with future mtime' ' git archive HEAD >future.tar ' -test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our future mtime' ' +test_expect_success TAR_HUGE,TIME_IS_64BIT 'system tar can read our future mtime' ' echo 4147 >expect && tar_info future.tar | cut -d" " -f2 >actual && test_cmp expect actual diff --git a/t/test-lib.sh b/t/test-lib.sh index 13b5696822d..beee1d847ff 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1164,3 +1164,5 @@ build_option () { test_lazy_prereq LONG_IS_64BIT ' test 8 -le "$(build_option sizeof-long)" ' + +test_lazy_prereq TIME_IS_64BIT 'test-date is64bit' -- 2.12.2.windows.2.406.gd14a8f8640f
[PATCH v4 4/9] Specify explicitly where we parse timestamps
Currently, Git's source code represents all timestamps as `unsigned long`. In preparation for using a more appropriate data type, let's introduce a symbol `parse_timestamp` (currently being defined to `strtoul`) where appropriate, so that we can later easily switch to, say, use `strtoull()` instead. Signed-off-by: Johannes Schindelin--- builtin/am.c | 2 +- builtin/receive-pack.c | 4 ++-- bundle.c | 2 +- commit.c | 6 +++--- date.c | 6 +++--- fsck.c | 2 +- git-compat-util.h | 2 ++ pretty.c | 2 +- ref-filter.c | 2 +- refs/files-backend.c | 2 +- t/helper/test-date.c | 2 +- tag.c | 4 ++-- upload-pack.c | 2 +- 13 files changed, 20 insertions(+), 18 deletions(-) diff --git a/builtin/am.c b/builtin/am.c index f7a7a971fbe..2c93adc69c3 100644 --- a/builtin/am.c +++ b/builtin/am.c @@ -882,7 +882,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr) char *end; errno = 0; - timestamp = strtoul(str, , 10); + timestamp = parse_timestamp(str, , 10); if (errno) return error(_("invalid timestamp")); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 3cba3fd278f..9a4c2a7ade4 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -534,7 +534,7 @@ static const char *check_nonce(const char *buf, size_t len) retval = NONCE_BAD; goto leave; } - stamp = strtoul(nonce, , 10); + stamp = parse_timestamp(nonce, , 10); if (bohmac == nonce || bohmac[0] != '-') { retval = NONCE_BAD; goto leave; @@ -552,7 +552,7 @@ static const char *check_nonce(const char *buf, size_t len) * would mean it was issued by another server with its clock * skewed in the future. */ - ostamp = strtoul(push_cert_nonce, NULL, 10); + ostamp = parse_timestamp(push_cert_nonce, NULL, 10); nonce_stamp_slop = (long)ostamp - (long)stamp; if (nonce_stamp_slop_limit && diff --git a/bundle.c b/bundle.c index bbf4efa0a0a..f43bfcf5ff3 100644 --- a/bundle.c +++ b/bundle.c @@ -227,7 +227,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs) line = memchr(line, '>', lineend ? lineend - line : buf + size - line); if (!line++) goto out; - date = strtoul(line, NULL, 10); + date = parse_timestamp(line, NULL, 10); result = (revs->max_age == -1 || revs->max_age < date) && (revs->min_age == -1 || revs->min_age > date); out: diff --git a/commit.c b/commit.c index 73c78c2b80c..0d2d0fa1984 100644 --- a/commit.c +++ b/commit.c @@ -89,8 +89,8 @@ static unsigned long parse_commit_date(const char *buf, const char *tail) /* nada */; if (buf >= tail) return 0; - /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */ - return strtoul(dateptr, NULL, 10); + /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */ + return parse_timestamp(dateptr, NULL, 10); } static struct commit_graft **commit_graft; @@ -607,7 +607,7 @@ static void record_author_date(struct author_date_slab *author_date, !ident.date_begin || !ident.date_end) goto fail_exit; /* malformed "author" line */ - date = strtoul(ident.date_begin, _end, 10); + date = parse_timestamp(ident.date_begin, _end, 10); if (date_end != ident.date_end) goto fail_exit; /* malformed date */ *(author_date_slab_at(author_date, commit)) = date; diff --git a/date.c b/date.c index a996331f5b3..495c207c64f 100644 --- a/date.c +++ b/date.c @@ -510,7 +510,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt char *end; unsigned long num; - num = strtoul(date, , 10); + num = parse_timestamp(date, , 10); /* * Seconds since 1970? We trigger on that for any numbers with @@ -658,7 +658,7 @@ static int match_object_header_date(const char *date, unsigned long *timestamp, if (*date < '0' || '9' < *date) return -1; - stamp = strtoul(date, , 10); + stamp = parse_timestamp(date, , 10); if (*end != ' ' || stamp == ULONG_MAX || (end[1] != '+' && end[1] != '-')) return -1; date = end + 2; @@ -1066,7 +1066,7 @@ static const char *approxidate_digit(const char *date, struct tm *tm, int *num, time_t now) { char *end; - unsigned long number = strtoul(date, , 10); + unsigned long number = parse_timestamp(date, , 10); switch (*end) { case ':': diff --git a/fsck.c b/fsck.c index
[PATCH v4 6/9] Introduce a new data type for timestamps
Git's source code assumes that unsigned long is at least as precise as time_t. Which is incorrect, and causes a lot of problems, in particular where unsigned long is only 32-bit (notably on Windows, even in 64-bit versions). So let's just use a more appropriate data type instead. In preparation for this, we introduce the new `timestamp_t` data type. By necessity, this is a very, very large patch, as it has to replace all timestamps' data type in one go. As we will use a data type that is not necessarily identical to `time_t`, we need to be very careful to use `time_t` whenever we interact with the system functions, and `timestamp_t` everywhere else. Signed-off-by: Johannes Schindelin--- Documentation/technical/api-parse-options.txt | 8 ++-- archive-tar.c | 5 +- archive-zip.c | 12 - archive.h | 2 +- builtin/am.c | 2 +- builtin/blame.c | 8 ++-- builtin/fsck.c| 4 +- builtin/gc.c | 2 +- builtin/log.c | 2 +- builtin/merge-base.c | 2 +- builtin/name-rev.c| 6 +-- builtin/pack-objects.c| 4 +- builtin/prune.c | 4 +- builtin/receive-pack.c| 6 +-- builtin/reflog.c | 24 +- builtin/show-branch.c | 4 +- builtin/worktree.c| 4 +- bundle.c | 2 +- cache.h | 14 +++--- commit.c | 12 ++--- commit.h | 2 +- config.c | 2 +- credential-cache--daemon.c| 12 ++--- date.c| 66 +-- fetch-pack.c | 6 +-- git-compat-util.h | 2 + http-backend.c| 4 +- parse-options-cb.c| 4 +- pretty.c | 2 +- reachable.c | 9 ++-- reachable.h | 4 +- ref-filter.c | 4 +- reflog-walk.c | 8 ++-- refs.c| 14 +++--- refs.h| 8 ++-- refs/files-backend.c | 4 +- revision.c| 6 +-- revision.h| 4 +- sha1_name.c | 6 +-- t/helper/test-date.c | 8 ++-- t/helper/test-parse-options.c | 2 +- t/helper/test-ref-store.c | 2 +- tag.c | 2 +- tag.h | 2 +- upload-pack.c | 4 +- vcs-svn/fast_export.c | 4 +- vcs-svn/fast_export.h | 4 +- vcs-svn/svndump.c | 2 +- wt-status.c | 2 +- 49 files changed, 169 insertions(+), 157 deletions(-) diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt index 36768b479e1..829b5581105 100644 --- a/Documentation/technical/api-parse-options.txt +++ b/Documentation/technical/api-parse-options.txt @@ -183,13 +183,13 @@ There are some macros to easily define options: scale the provided value by 1024, 1024^2 or 1024^3 respectively. The scaled value is put into `unsigned_long_var`. -`OPT_DATE(short, long, _var, description)`:: +`OPT_DATE(short, long, _t_var, description)`:: Introduce an option with date argument, see `approxidate()`. - The timestamp is put into `int_var`. + The timestamp is put into `timestamp_t_var`. -`OPT_EXPIRY_DATE(short, long, _var, description)`:: +`OPT_EXPIRY_DATE(short, long, _t_var, description)`:: Introduce an option with expiry date argument, see `parse_expiry_date()`. - The timestamp is put into `int_var`. + The timestamp is put into `timestamp_t_var`. `OPT_CALLBACK(short, long, , arg_str, description, func_ptr)`:: Introduce an option with argument. diff --git a/archive-tar.c b/archive-tar.c index 380e3aedd23..695339a2369 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -27,9 +27,12 @@ static int write_tar_filter_archive(const struct archiver *ar, */ #if ULONG_MAX == 0x #define USTAR_MAX_SIZE ULONG_MAX -#define USTAR_MAX_MTIME ULONG_MAX #else #define
[PATCH v4 9/9] show_date_ident(): defer date overflow check
Now that we use uintmax_t for timestamps, we can represent timestamps that would not fit inside the time_t data type. As long as we do not have to use the system functions, we can even display them, e.g. as Unix epoch. Signed-off-by: Johannes Schindelin--- pretty.c | 12 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pretty.c b/pretty.c index 587d48371b0..35fd290096a 100644 --- a/pretty.c +++ b/pretty.c @@ -410,14 +410,10 @@ const char *show_ident_date(const struct ident_split *ident, if (ident->date_begin && ident->date_end) date = parse_timestamp(ident->date_begin, NULL, 10); - if (date_overflows(date)) - date = 0; - else { - if (ident->tz_begin && ident->tz_end) - tz = strtol(ident->tz_begin, NULL, 10); - if (tz >= INT_MAX || tz <= INT_MIN) - tz = 0; - } + if (ident->tz_begin && ident->tz_end) + tz = strtol(ident->tz_begin, NULL, 10); + if (tz >= INT_MAX || tz <= INT_MIN) + tz = 0; return show_date(date, tz, mode); } -- 2.12.2.windows.2.406.gd14a8f8640f
[PATCH v4 5/9] Introduce a new "printf format" for timestamps
Currently, Git's source code treats all timestamps as if they were unsigned longs. Therefore, it is okay to write "%lu" when printing them. There is a substantial problem with that, though: at least on Windows, time_t is *larger* than unsigned long, and hence we will want to switch away from the ill-specified `unsigned long` data type. So let's introduce the pseudo format "PRItime" (currently simply being defined to "lu") to make it easier to change the data type used for timestamps. Signed-off-by: Johannes Schindelin--- builtin/blame.c | 6 +++--- builtin/fsck.c| 2 +- builtin/log.c | 2 +- builtin/receive-pack.c| 4 ++-- builtin/rev-list.c| 2 +- builtin/rev-parse.c | 2 +- date.c| 26 +- fetch-pack.c | 2 +- git-compat-util.h | 1 + refs/files-backend.c | 2 +- t/helper/test-date.c | 2 +- t/helper/test-parse-options.c | 2 +- t/helper/test-ref-store.c | 2 +- upload-pack.c | 2 +- vcs-svn/fast_export.c | 4 ++-- 15 files changed, 31 insertions(+), 30 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index 07506a3e457..e4b3c7b0ebf 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -1727,11 +1727,11 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat) get_commit_info(suspect->commit, , 1); printf("author %s\n", ci.author.buf); printf("author-mail %s\n", ci.author_mail.buf); - printf("author-time %lu\n", ci.author_time); + printf("author-time %"PRItime"\n", ci.author_time); printf("author-tz %s\n", ci.author_tz.buf); printf("committer %s\n", ci.committer.buf); printf("committer-mail %s\n", ci.committer_mail.buf); - printf("committer-time %lu\n", ci.committer_time); + printf("committer-time %"PRItime"\n", ci.committer_time); printf("committer-tz %s\n", ci.committer_tz.buf); printf("summary %s\n", ci.summary.buf); if (suspect->commit->object.flags & UNINTERESTING) @@ -1844,7 +1844,7 @@ static const char *format_time(unsigned long time, const char *tz_str, strbuf_reset(_buf); if (show_raw_time) { - strbuf_addf(_buf, "%lu %s", time, tz_str); + strbuf_addf(_buf, "%"PRItime" %s", time, tz_str); } else { const char *time_str; diff --git a/builtin/fsck.c b/builtin/fsck.c index f76e4163abb..af7b985c6eb 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -407,7 +407,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid, if (timestamp && name_objects) add_decoration(fsck_walk_options.object_names, obj, - xstrfmt("%s@{%ld}", refname, timestamp)); + xstrfmt("%s@{%"PRItime"}", refname, timestamp)); obj->used = 1; mark_object_reachable(obj); } else { diff --git a/builtin/log.c b/builtin/log.c index b3b10cc1edb..f93ef6c7100 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -910,7 +910,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids) static void gen_message_id(struct rev_info *info, char *base) { struct strbuf buf = STRBUF_INIT; - strbuf_addf(, "%s.%lu.git.%s", base, + strbuf_addf(, "%s.%"PRItime".git.%s", base, (unsigned long) time(NULL), git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT)); info->message_id = strbuf_detach(, NULL); diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 9a4c2a7ade4..c49333c9b66 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -459,12 +459,12 @@ static char *prepare_push_cert_nonce(const char *path, unsigned long stamp) struct strbuf buf = STRBUF_INIT; unsigned char sha1[20]; - strbuf_addf(, "%s:%lu", path, stamp); + strbuf_addf(, "%s:%"PRItime, path, stamp); hmac_sha1(sha1, buf.buf, buf.len, cert_nonce_seed, strlen(cert_nonce_seed));; strbuf_release(); /* RFC 2104 5. HMAC-SHA1-80 */ - strbuf_addf(, "%lu-%.*s", stamp, 20, sha1_to_hex(sha1)); + strbuf_addf(, "%"PRItime"-%.*s", stamp, 20, sha1_to_hex(sha1)); return strbuf_detach(, NULL); } diff --git a/builtin/rev-list.c b/builtin/rev-list.c index bcf77f0b8a2..3b292c99bda 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -80,7 +80,7 @@ static void show_commit(struct commit *commit, void *data) } if (info->show_timestamp) - printf("%lu ", commit->date); + printf("%"PRItime" ", commit->date); if (info->header_prefix)
[PATCH v4 7/9] Abort if the system time cannot handle one of our timestamps
We are about to switch to a new data type for time stamps that is definitely not smaller or equal, but larger or equal to time_t. So before using the system functions to process or format timestamps, let's make extra certain that they can handle what we feed them. Signed-off-by: Johannes Schindelin--- date.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/date.c b/date.c index 92ab31aa441..75f6335cd09 100644 --- a/date.c +++ b/date.c @@ -46,7 +46,10 @@ static time_t gm_time_t(timestamp_t time, int tz) minutes = tz < 0 ? -tz : tz; minutes = (minutes / 100)*60 + (minutes % 100); minutes = tz < 0 ? -minutes : minutes; - return time + minutes * 60; + + if (date_overflows(time + minutes * 60)) + die("Timestamp too large for this system: %"PRItime, time); + return (time_t)time + minutes * 60; } /* @@ -70,7 +73,10 @@ static int local_tzoffset(timestamp_t time) struct tm tm; int offset, eastwest; - t = time; + if (date_overflows(time)) + die("Timestamp too large for this system: %"PRItime, time); + + t = (time_t)time; localtime_r(, ); t_local = tm_to_time_t(); -- 2.12.2.windows.2.406.gd14a8f8640f
[PATCH v4 8/9] Use uintmax_t for timestamps
Previously, we used `unsigned long` for timestamps. This was only a good choice on Linux, where we know implicitly that `unsigned long` is what is used for `time_t`. However, we want to use a different data type for timestamps for two reasons: - there is nothing that says that `unsigned long` should be the same data type as `time_t`, and indeed, on 64-bit Windows for example, it is not: `unsigned long` is 32-bit but `time_t` is 64-bit. - even on 32-bit Linux, where `unsigned long` (and thereby `time_t`) is 32-bit, we *want* to be able to encode timestamps in Git that are currently absurdly far in the future, *even if* the system library is not able to format those timestamps into date strings. So let's just switch to the maximal integer type available, which should be at least 64-bit for all practical purposes these days. It certainly cannot be worse than `unsigned long`, so... Signed-off-by: Johannes Schindelin--- git-compat-util.h | 10 +++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/git-compat-util.h b/git-compat-util.h index 72c12173a14..c678ca94b8f 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -319,10 +319,14 @@ extern char *gitdirname(char *); #define PRIo32 "o" #endif -typedef unsigned long timestamp_t; -#define PRItime "lu" -#define parse_timestamp strtoul +typedef uintmax_t timestamp_t; +#define PRItime PRIuMAX +#define parse_timestamp strtoumax +#ifdef ULLONG_MAX +#define TIME_MAX ULLONG_MAX +#else #define TIME_MAX ULONG_MAX +#endif #ifndef PATH_SEP #define PATH_SEP ':' -- 2.12.2.windows.2.406.gd14a8f8640f
[PATCH v4 0/9] Introduce timestamp_t for timestamps
Git v2.9.2 was released in a hurry to accomodate for platforms like Windows, where the `unsigned long` data type is 32-bit even for 64-bit setups. The quick fix was to simply disable all the testing with "absurd" future dates. However, we can do much better than that, as we already make use of 64-bit data types internally. There is no good reason why we should not use the same for timestamps. Hence, let's use uintmax_t for timestamps. Note: while the `time_t` data type exists and is meant to be used for timestamps, on 32-bit Linux it is *still* 32-bit. An earlier iteration used `time_t` for that reason, but it came with a few serious downsides: as `time_t` can be signed (and indeed, on Windows it is an int64_t), Git's expectation that 0 is the minimal value does no longer hold true, introducing its own set of interesting challenges. Besides, if we *can* handle far in the future timestamps (except for formatting them using the system libraries), it is more consistent to do so. The upside of using `uintmax_t` for timestamps is that we do a much better job to support far in the future timestamps across all platforms, including 32-bit ones. The downside is that those platforms that use a 32-bit `time_t` will barf when parsing or formatting those timestamps. This iteration has two fixes for issues reported by Travis CI (thank deity for Continuous Testing, eh?), one by the MacOSX nodes (but not by the Linux nor the Windows nodes), the other by the windows node (which reminds me to run tests after rebasing to `master` not only in a Linux VM but also on Windows, even if it takes ages there due to the heavy shell scripting). After reading Junio's comments on the cover letter of v2, I had another look at the usage of date_overflows() and was able to relax two of them. Changes since v3: - fixed the fix in archive-zip.c that tried to report a too large timestamp (and would have reported the uninitialized time_t instead) - adjusted the so-far forgotten each_reflog() function (that was introduced after v1, in 80f2a6097c4 (t/helper: add test-ref-store to test ref-store functions, 2017-03-26)) to use timestamp_t and PRItime, too - removed the date_overflows() check from time_to_tm(), as it calls gm_time_t() which already performs that check - the date_overflows() check in show_ident_date() was removed, as we do not know at that point yet whether we use the system functions to render the date or not (and there would not be a problem in the latter case) Johannes Schindelin (9): ref-filter: avoid using `unsigned long` for catch-all data type t0006 & t5000: prepare for 64-bit timestamps t0006 & t5000: skip "far in the future" test when time_t is too limited Specify explicitly where we parse timestamps Introduce a new "printf format" for timestamps Introduce a new data type for timestamps Abort if the system time cannot handle one of our timestamps Use uintmax_t for timestamps show_date_ident(): defer date overflow check Documentation/technical/api-parse-options.txt | 8 +- archive-tar.c | 5 +- archive-zip.c | 12 ++- archive.h | 2 +- builtin/am.c | 4 +- builtin/blame.c | 14 ++-- builtin/fsck.c| 6 +- builtin/gc.c | 2 +- builtin/log.c | 4 +- builtin/merge-base.c | 2 +- builtin/name-rev.c| 6 +- builtin/pack-objects.c| 4 +- builtin/prune.c | 4 +- builtin/receive-pack.c| 14 ++-- builtin/reflog.c | 24 +++--- builtin/rev-list.c| 2 +- builtin/rev-parse.c | 2 +- builtin/show-branch.c | 4 +- builtin/worktree.c| 4 +- bundle.c | 4 +- cache.h | 14 ++-- commit.c | 18 ++--- commit.h | 2 +- config.c | 2 +- credential-cache--daemon.c| 12 +-- date.c| 106 ++ fetch-pack.c | 8 +- fsck.c| 2 +- git-compat-util.h | 9 +++ http-backend.c| 4 +- parse-options-cb.c| 4 +- pretty.c | 16 ++-- reachable.c | 9 +-- reachable.h | 4 +- ref-filter.c
[PATCH v4 1/9] ref-filter: avoid using `unsigned long` for catch-all data type
In its `atom_value` struct, the ref-filter source code wants to store different values in a field called `ul` (for `unsigned long`), e.g. timestamps. However, as we are about to switch the data type of timestamps away from `unsigned long` (because it may be 32-bit even when `time_t` is 64-bit), that data type is not large enough. Simply change that field to use `uintmax_t` instead. This patch is a bit larger than the mere change of the data type because the field's name was tied to its data type, which has been fixed at the same time. Signed-off-by: Johannes Schindelin--- ref-filter.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ref-filter.c b/ref-filter.c index 3a640448fd8..92871266001 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -351,7 +351,7 @@ struct ref_formatting_state { struct atom_value { const char *s; void (*handler)(struct atom_value *atomv, struct ref_formatting_state *state); - unsigned long ul; /* used for sorting when not FIELD_STR */ + uintmax_t value; /* used for sorting when not FIELD_STR */ struct used_atom *atom; }; @@ -723,7 +723,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct object if (!strcmp(name, "objecttype")) v->s = typename(obj->type); else if (!strcmp(name, "objectsize")) { - v->ul = sz; + v->value = sz; v->s = xstrfmt("%lu", sz); } else if (deref) @@ -770,8 +770,8 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object v->s = xstrdup(oid_to_hex(>tree->object.oid)); } else if (!strcmp(name, "numparent")) { - v->ul = commit_list_count(commit->parents); - v->s = xstrfmt("%lu", v->ul); + v->value = commit_list_count(commit->parents); + v->s = xstrfmt("%lu", (unsigned long)v->value); } else if (!strcmp(name, "parent")) { struct commit_list *parents; @@ -875,11 +875,11 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam if ((tz == LONG_MIN || tz == LONG_MAX) && errno == ERANGE) goto bad; v->s = xstrdup(show_date(timestamp, tz, _mode)); - v->ul = timestamp; + v->value = timestamp; return; bad: v->s = ""; - v->ul = 0; + v->value = 0; } /* See grab_values */ @@ -1941,9 +1941,9 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru else if (cmp_type == FIELD_STR) cmp = cmp_fn(va->s, vb->s); else { - if (va->ul < vb->ul) + if (va->value < vb->value) cmp = -1; - else if (va->ul == vb->ul) + else if (va->value == vb->value) cmp = cmp_fn(a->refname, b->refname); else cmp = 1; -- 2.12.2.windows.2.406.gd14a8f8640f
Re: [PATCH v3 0/8] Introduce timestamp_t for timestamps
Hi Junio, On Thu, 20 Apr 2017, Junio C Hamano wrote: > Johannes Schindelinwrites: > > > Note: while the `time_t` data type exists and is meant to be used for > > timestamps, on 32-bit Linux it is *still* 32-bit. An earlier iteration > > used `time_t` for that reason, but it came with a few serious > > downsides: as `time_t` can be signed (and indeed, on Windows it is an > > int64_t), Git's expectation that 0 is the minimal value does no longer > > hold true, introducing its own set of interesting challenges. Besides, > > if we *can* handle far in the future timestamps (except for formatting > > them using the system libraries), it is more consistent to do so. > > I somehow had an impression that the list consensus during the > discussion on an earlier round of this series was that time_t is > more appropriate, as platforms with time_t with inadequent range > will be updated before it gets too late at around 2038 (or they will > die off). There was this sentiment, but that would require a change in Git's source code where it can handle unsigned *and* signed data types for timestamps, and that was too much of a change to bring in that late in the patch series. Besides, supporting a signed timestamp data type is a separate issue from trying to support dates that are insanely far in the future. > After all, at some point we need to interact with the > platform functions that expect time_t as their interface and they do > not take our own timestamp_t without casting. No, not necessarily. When we generate a .zip archive, for example, we may never need to parse or format the timestamps. When we log with a format that does not require the system routines to format the date (e.g. Unix epoch). And when we do not parse nor format the timestamps to begin with, e.g. fetching and pushing or committing. It is *only* when we try to parse or format timestamps, *and* the system's time_t is not large enough, that we run into trouble. This is an improvement from before, where we would run into trouble whenever time_t was larger than unsigned long, *or* whenever time_t is too small for those timestamps. Your comment, and my reaction, reminded me that I had planned to look into all calls to date_overflow() and remove those that are now unnecessary, or at least move them to the place where they are absolutely necessary. > But that is provided if not introducing timestamp_t and using time_t > results in a simpler code. I do not know if that is the case. As I had pointed out in my reply to Peff: removing the assumption that 0 is the minimal timestamp is something I am unwilling to tackle, it looks way too fragile/dangerous to me to do this in the time I could allocate for that. > For timestamps in the distant past, even though time_t could be > unsigned, I do not think anybody came up with a concrete example of a > platform with such a problem during the previous discussions, while I do > recall people wanting to use Git to store historical documents with > timestamps before 1970. We do expect 0 can be used as a sentinel, which > needs to be updated once we seriously start supporting such use cases. > I think that (i.e. should the timestamp be signed?) is more or less > unrelated to the focus of the discussion that stemed from this topic, > which was "ulong that is often 32-bit does not necessarily fit the > notion of time on a platform, which is time_t, and we need to widen it", > which all involved in the discussion agreed. If anybody feels strongly enough about representing timestamps earlier than the Jan 1 1970, they should feel very welcome to work on this. My patch series would make that task slightly easier, even. > In any case, when merged to 'pu', this had a slight conflict with > topics in flight in builtin/name-rev.c and I think I resolved it > correctly, but please double check. I double-checked, there were just two conversions from `unsigned long taggerdate` to `timestamp_t taggerdate`. I repeated the merge with my latest iteration and resolved them the same way as you did. Apart from the date_overflows() changes I mentioned above, I also fixed the problems identified by Travis CI and VSTS Build. v4 is coming, Dscho
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 2:10 PM, Christian Couderwrote: > On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummerer > wrote: >> On 04/20, Christian Couder wrote: >>> >>> Could you try with the following patch: >>> >>> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ >> >> Yeah, I tried with and without that patch with the same result. >> Unless I'm screwing something up when testing I don't think this fixes >> the issue unfortunately. > > Ok, I will take a look soon. > > By the way I think that GIT_TEST_SPLIT_INDEX has become redundant now > that there is core.splitIndex. > So perhaps in the long run it will be best to deprecate > GIT_TEST_SPLIT_INDEX and eventually remove it. I think you can't, at least the way I understand this variable. It's a _test_ variable to force exercise split index code path a whole lot more, by running the entire test suite with split index always enabled, instead of just a couple in t-split-index.sh. We can't achieve the same with core.splitIndex because that's more about user control and you can't just set core.splitIndex for the entire test suite (can we?). I would understand if the failed tests are about core.splitIndex (they both try to control how split index is created), but failed tests look totally unrelated. We may have discovered some bug (or that git_path one Jeff mentioned). -- Duy
Re: What's cooking in git.git (Apr 2017, #04; Wed, 19)
Hi Junio, On Thu, 20 Apr 2017, Junio C Hamano wrote: > Lars Schneiderwrites: > > >> * bw/forking-and-threading (2017-04-19) 11 commits > >> - run-command: block signals between fork and execve > >> - run-command: add note about forking and threading > >> - run-command: handle dup2 and close errors in child > >> - run-command: eliminate calls to error handling functions in child > >> - run-command: don't die in child when duping /dev/null > >> - run-command: prepare child environment before forking > >> - string-list: add string_list_remove function > >> - run-command: use the async-signal-safe execv instead of execvp > >> - run-command: prepare command before forking > >> - t0061: run_command executes scripts without a #! line > >> - t5550: use write_script to generate post-update hook > >> > >> The "run-command" APIimplementation has been made more robust > >> against dead-locking in a threaded environment. > >> > >> Will merge to 'next'. > > > > There might be a problem on Windows with this (that's just a hunch, i can't > > test this right now): > > https://travis-ci.org/git/git/jobs/223830474 > > Thanks for keeping an eye on Travis output. My eyes learned to > ignore the Windows section as its failures often seem to be due to > timing out. Part of the reason is that you push out all of the branches in one go, typically at the very end of your work day. The idea of Continuous Integration is a little orthogonal to that style, suggesting to build & test whenever new changes come into the integration branch. As a consequence, my original setup was a little overloaded: the VM sat idle most of the time, and when you pushed, it was overloaded. To accommodate even that use case, I managed to pry away some resources that should be mostly idle at the time you push, and that should be able to run up to 4 builds in parallel (the number "4" is not really magic, it is the number of integration branches of git.git). Since that "let's aggregate everything and only push out the final result at the end of the day" approach does not really allow the Continuous Testing to identify problems associated with individual topic branches, I have another job that bisects the breakages (with all associated problems I reported earlier, as you apply some patches on top of really ancient commits and bisect wants to test all merge bases first) because the required time *definitely* would let Travis time out all the time. Those bisect results are even less visible than the Travis results, see e.g. https://github.com/git/git/commit/2e3a8b9035a#commitcomment-21836854. Having said that, I do not think that it makes sense for you to change your habits, as proper Continuous Integration (as opposed to a variation of Continuous Testing that we use, really) would take a lot more of a change than you are comfortable with: it would look a lot more Pull Request centric than the current mailing list centered process. Ciao, Dscho
Re: [PATCH] refs.h: rename submodule arguments to submodule_path
On Fri, Apr 21, 2017 at 1:42 PM, Michael Haggertywrote: > On 04/21/2017 08:32 AM, Michael Haggerty wrote: >> [...] >> I've CCed Duy because I don't know whether he has more plans regarding >> submodule references [...] get rid of the >> `for_each_ref_submodule()` family of functions entirely. >> >> So perhaps the code that this patch touches won't be around long anyway. > > Oh yeah, he has done exactly that in his nd/prune-in-worktree patch > series. (I knew I'd seen that somewhere...) > > So it seems that the argument renaming has mostly been overtaken by > events, though even after Duy's patch series there are a few `const char > *submodule` arguments that could be renamed. Yeah. After that series, the only place that takes a submodule (path) is get_submodule_ref_store() (other functions are just helpers). Renaming it to submodule_path makes perfect sense. Johannes Sixt when reviewing that series also noticed the "path" nature of this "submodule" argument and suggested converting submodule[x] == '/' to is_dir_sep(submodule[i]) for that reason. At this point, I think Stefan even has the opportunity to reference/look up a submodule ref store by something other than a path (like "struct submodule *", or by name) if he wants to. But if you do that, maybe rename the current function to get_submodule_ref_store_by_path() before you add a new get_submodule_ref_store_by_whatever(). About ".. because I don't know whether he (Duy) has more plans regarding submodule references", I plan to convert "submodule[x] == '/'" to is_dir_sep(submodule[x]), but I think that's about it. I'm not involved much in submodule to see the direction it's heading. As far as refs code is concerned, a "struct ref_store *" is all it needs, regardless of how you obtain it. -- Duy
RE: [PATCH] Increase core.packedGitLimit
Hi Dave, On Thu, 20 Apr 2017, David Turner wrote: > > We might want to think about replacing git_config_ulong with > git_config_size_t in nearly all cases. "long" has ceased to be > useful. More modern versions of C prefer uint64_t, but I > think that we'll usually want size_t because these values will > be used as memory limits of various sorts. Indeed, `unsigned long` has ceased to be useful ever since the introduction of inttypes.h. It is just too undefined. We probably also need git_config_off_t(), though, and maybe even git_config_ssize_t(). I would definitely welcome a change in direction where we use datatypes also as a documentation of the variables' purpose. Ciao, Dscho
Re: [PATCH] completion: optionally disable checkout DWIM
On Thu, Apr 20, 2017 at 1:12 PM, Jeff Kingwrote: > When we complete branch names for "git checkout", we also > complete remote branch names that could trigger the DWIM > behavior. Depending on your workflow and project, this can > be either convenient or annoying. > > For instance, my clone of gitster.git contains 74 local > "jk/*" branches, but origin contains another 147. When I > want to checkout a local branch but can't quite remember the > name, tab completion shows me 251 entries. And worse, for a > topic that has been picked up for pu, the upstream branch > name is likely to be similar to mine, leading to a high > probability that I pick the wrong one and accidentally > create a new branch. > > This patch adds a way for the user to tell the completion > code not to include DWIM suggestions for checkout. This can > already be done by typing: > > git checkout --no-guess jk/ > > but that's rather cumbersome. The downside, of course, is > that you no longer get completion support when you _do_ want > to invoke the DWIM behavior. But depending on your workflow, > that may not be a big loss (for instance, in git.git I am > much more likely to want to detach, so I'd type "git > checkout origin/jk/" anyway). > > Signed-off-by: Jeff King > --- > This is flexible enough for me, but it's possible somebody would want > this on a per-repo basis. I don't know that we want to read from `git > config`, though, because it's relatively expensive to do so. People who > want per-repo settings are probably better off with a hook that triggers > when they "cd" around, and sets up their preferences. > I would use this. Completing these can get quite cumbersome to use when I have only a few local branches but many remote ones like in git.git Thanks, Jake
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Thu, Apr 20, 2017 at 11:24 PM, Thomas Gummererwrote: > On 04/20, Christian Couder wrote: >> >> Could you try with the following patch: >> >> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ > > Yeah, I tried with and without that patch with the same result. > Unless I'm screwing something up when testing I don't think this fixes > the issue unfortunately. Ok, I will take a look soon. By the way I think that GIT_TEST_SPLIT_INDEX has become redundant now that there is core.splitIndex. So perhaps in the long run it will be best to deprecate GIT_TEST_SPLIT_INDEX and eventually remove it.
Re: [BUG] test suite broken with GIT_TEST_SPLIT_INDEX
On Fri, Apr 21, 2017 at 6:01 AM, Junio C Hamanowrote: > Christian Couder writes: > >> Could you try with the following patch: >> >> http://public-inbox.org/git/20170330210354.20018-1-chrisc...@tuxfamily.org/ > > Ah, this reminds me. The patch has been in the stalled state for > quite some time due to confusing description. How about explaining > it like so and merge it to 'next'? Yeah, I am ok with this description. Thanks!
Re: [PATCH] refs.h: rename submodule arguments to submodule_path
On 04/21/2017 08:32 AM, Michael Haggerty wrote: > [...] > I've CCed Duy because I don't know whether he has more plans regarding > submodule references [...] get rid of the > `for_each_ref_submodule()` family of functions entirely. > > So perhaps the code that this patch touches won't be around long anyway. Oh yeah, he has done exactly that in his nd/prune-in-worktree patch series. (I knew I'd seen that somewhere...) So it seems that the argument renaming has mostly been overtaken by events, though even after Duy's patch series there are a few `const char *submodule` arguments that could be renamed. Michael
Re: [PATCH] refs.h: rename submodule arguments to submodule_path
On 04/21/2017 03:12 AM, Junio C Hamano wrote: > Stefan Bellerwrites: > >> + Junio > > Just like Michael, I do not have strong enough opinion for or > against this patch to comment on it. > > I do agree with you that it would be a good longer-term direction to > use "submodule" for a "struct submodule" (i.e. submodule object), > and call a string that names a submodule either "submodule_name" or > "submodule_path" depending on how it names one, for maintainability > of the code. > > However I am not convinced that this patch is an improvement. Even > though parameter names in decls only serve documentation purpose and > it is even OK to only have type without name there, if we are going > to _have_ names, it would make sense to match them to the parameter > names actually used in the implementation. > > Updating these names used in refs.c would make a very noisy patch, > of course. But I am not sure if it is a good middle ground to avoid > that and to update only refs.h. One should never infer too much from my silence. As often as not it's because I'm simply busy with other things. But in this case Junio's right. I think it is a good idea to use argument names in declarations as documentation, and I also agree that it is a minus for the names in the declarations not to agree with the names in the definition. But the code that would have to be touched already has a lot of work going on in it, so conflicts would be likely. I've CCed Duy because I don't know whether he has more plans regarding submodule references. A natural followup to his recent work would be to add a feature to the `submodule` module that allows a caller to look up the `ref_store` object for the submodule. Then client code could use the `refs_for_each_ref(struct ref_store *, ...)` family of functions to access such references, and we could get rid of the `for_each_ref_submodule()` family of functions entirely. So perhaps the code that this patch touches won't be around long anyway. Michael
Re: [PATCH 05/15] log: report errno on failure to fopen() a file
On Thu, Apr 20, 2017 at 06:25:59PM +0700, Nguyễn Thái Ngọc Duy wrote: > Signed-off-by: Nguyễn Thái Ngọc Duy> --- > builtin/log.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/builtin/log.c b/builtin/log.c > index b3b10cc1ed..26d6a3cf14 100644 > --- a/builtin/log.c > +++ b/builtin/log.c > @@ -858,7 +858,8 @@ static int open_next_file(struct commit *commit, const > char *subject, > printf("%s\n", filename.buf + outdir_offset); > > if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) > - return error(_("Cannot open patch file %s"), filename.buf); > + return error_errno(_("Cannot open patch file %s"), > +filename.buf); > > strbuf_release(); > return 0; Not a new problem with your patch, but just looking at the context it seems clear that "filename" is leaked in the error case. -Peff
Re: [PATCH 00/15] Handle fopen() errors
On Thu, Apr 20, 2017 at 08:41:32PM -0700, Junio C Hamano wrote: > Junio C Hamanowrites: > > > I wonder if it is OK to only special case ENOENT for !fp cases, > > where existing code silently returns. Perhaps it is trying to read > > an optional file, and it returns silently because lack of it is > > perfectly OK for the purpose of the code. Are there cases where > > this optional file is inside an optional directory, leading to > > ENOTDIR, instead of ENOENT, observed and reported by your check? > > "git grep -B1 warn_on_inaccessible" is enlightening. I wonder if we > want to wrap the two lines into a hard to misuse helper function, > something along this line. Would having this patch as a preparatory > step shrink your series? The patch count would be the same, but you > wouldn't be writing "if (errno != ENOENT)" lines yourself. I had a similar thought while reading through it. I think it would be shorter still with: FILE *fopen_or_warn(const char *path, const char *mode) { FILE *fh = fopen(path, mode); if (!fh) warn_failure_to_read_open_optional_path(path); return fh; } And then quite a few of the patches could just be s/fopen/fopen_or_warn/. -Peff
Re: [PATCH v3 0/8] Introduce timestamp_t for timestamps
Johannes Schindelinwrites: > Note: while the `time_t` data type exists and is meant to be used for > timestamps, on 32-bit Linux it is *still* 32-bit. An earlier iteration > used `time_t` for that reason, but it came with a few serious downsides: > as `time_t` can be signed (and indeed, on Windows it is an int64_t), > Git's expectation that 0 is the minimal value does no longer hold true, > introducing its own set of interesting challenges. Besides, if we *can* > handle far in the future timestamps (except for formatting them using > the system libraries), it is more consistent to do so. I somehow had an impression that the list consensus during the discussion on an earlier round of this series was that time_t is more appropriate, as platforms with time_t with inadequent range will be updated before it gets too late at around 2038 (or they will die off). After all, at some point we need to interact with the platform functions that expect time_t as their interface and they do not take our own timestamp_t without casting. But that is provided if not introducing timestamp_t and using time_t results in a simpler code. I do not know if that is the case. For timestamps in the distant past, even though time_t could be unsigned, I do not think anybody came up with a concrete example of a platform with such a problem during the previous discussions, while I do recall people wanting to use Git to store historical documents with timestamps before 1970. We do expect 0 can be used as a sentinel, which needs to be updated once we seriously start supporting such use cases. I think that (i.e. should the timestamp be signed?) is more or less unrelated to the focus of the discussion that stemed from this topic, which was "ulong that is often 32-bit does not necessarily fit the notion of time on a platform, which is time_t, and we need to widen it", which all involved in the discussion agreed. In any case, when merged to 'pu', this had a slight conflict with topics in flight in builtin/name-rev.c and I think I resolved it correctly, but please double check. I will have to revamp the resolution rerere remembered when the next version of this series starts using time_t instead of timestamp_t anyway, but it is better to always get conflict resolution right. That is what maintainers do and what they are for ;-) Thanks.