* [PATCH 0/6] Use time_t
From: Johannes Schindelin @ 2017-02-27 21:30 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
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 `time_t` exists, and at
least on 64-bit Windows it is 64-bit. Meaning: we *can* support these
absurd future dates on those platforms.
So let's do this.
One notable fallout of this patch series is that on 64-bit Linux (and
other platforms where `unsigned long` is 64-bit), we now limit the range
of dates to LONG_MAX (i.e. the *signed* maximum value). This needs to be
done as `time_t` can be signed (and indeed is at least on my Ubuntu
setup).
Obviously, I think that we can live with that, and I hope that all
interested parties agree.
Johannes Schindelin (6):
t0006 & t5000: prepare for 64-bit time_t
Specify explicitly where we parse timestamps
Introduce a new "printf format" for timestamps
Prepare for timestamps to use 64-bit signed types
ref-filter: avoid using `unsigned long` for catch-all data type
Use time_t where appropriate
Documentation/technical/api-parse-options.txt | 8 +--
Makefile | 4 ++
archive-tar.c | 5 +-
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 | 10 +--
builtin/reflog.c | 24 +++----
builtin/show-branch.c | 4 +-
builtin/worktree.c | 4 +-
bundle.c | 4 +-
cache.h | 14 ++---
commit.c | 16 ++---
commit.h | 2 +-
config.mak.uname | 2 +
credential-cache--daemon.c | 12 ++--
date.c | 90 +++++++++++++--------------
fetch-pack.c | 8 +--
fsck.c | 2 +-
git-compat-util.h | 10 +++
http-backend.c | 4 +-
parse-options-cb.c | 4 +-
pretty.c | 4 +-
reachable.c | 10 ++-
reachable.h | 4 +-
ref-filter.c | 22 +++----
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 | 11 ++--
t/helper/test-parse-options.c | 4 +-
t/t0006-date.sh | 4 +-
t/t5000-tar-tree.sh | 6 +-
t/test-lib.sh | 2 +
tag.c | 4 +-
tag.h | 2 +-
upload-pack.c | 8 +--
vcs-svn/fast_export.c | 8 +--
vcs-svn/fast_export.h | 4 +-
vcs-svn/svndump.c | 2 +-
wt-status.c | 2 +-
51 files changed, 221 insertions(+), 199 deletions(-)
base-commit: e7e07d5a4fcc2a203d9873968ad3e6bd4d7419d7
Published-As: https://github.com/dscho/git/releases/tag/time_t-may-be-int64-v1
Fetch-It-Via: git fetch https://github.com/dscho/git time_t-may-be-int64-v1
--
2.11.1.windows.1.379.g44ae0bc
^ permalink raw reply
* [PATCH 2/6] Specify explicitly where we parse timestamps
From: Johannes Schindelin @ 2017-02-27 21:30 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <cover.1488231002.git.johannes.schindelin@gmx.de>
Currently, Git's source code represents all timestamps as `unsigned
long`. In preparation for using `time_t` instead, let's introduce a
symbol `parse_timestamp` (currently being defined to `strtoul`) where
appropriate, so that we can later easily switch to use `strtoull()`
instead.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/am.c | 2 +-
bundle.c | 2 +-
commit.c | 4 ++--
date.c | 6 +++---
fsck.c | 2 +-
git-compat-util.h | 2 ++
pretty.c | 2 +-
ref-filter.c | 2 +-
t/helper/test-date.c | 2 +-
tag.c | 2 +-
upload-pack.c | 2 +-
11 files changed, 15 insertions(+), 13 deletions(-)
diff --git a/builtin/am.c b/builtin/am.c
index 31fb60578f6..75e2d939036 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, &end, 10);
+ timestamp = parse_timestamp(str, &end, 10);
if (errno)
return error(_("invalid timestamp"));
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 2cf85158b48..7f56b643704 100644
--- a/commit.c
+++ b/commit.c
@@ -90,7 +90,7 @@ static unsigned long parse_commit_date(const char *buf, const char *tail)
if (buf >= tail)
return 0;
/* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
- return strtoul(dateptr, NULL, 10);
+ return parse_timestamp(dateptr, NULL, 10);
}
static struct commit_graft **commit_graft;
@@ -608,7 +608,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, &date_end, 10);
+ date = parse_timestamp(ident.date_begin, &date_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..a8848f6e141 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, &end, 10);
+ num = parse_timestamp(date, &end, 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, &end, 10);
+ stamp = parse_timestamp(date, &end, 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, &end, 10);
+ time_t number = parse_timestamp(date, &end, 10);
switch (*end) {
case ':':
diff --git a/fsck.c b/fsck.c
index 939792752bf..33a66e68a83 100644
--- a/fsck.c
+++ b/fsck.c
@@ -690,7 +690,7 @@ static int fsck_ident(const char **ident, struct object *obj, struct fsck_option
p++;
if (*p == '0' && p[1] != ' ')
return report(options, obj, FSCK_MSG_ZERO_PADDED_DATE, "invalid author/committer line - zero-padded date");
- if (date_overflows(strtoul(p, &end, 10)))
+ if (date_overflows(parse_timestamp(p, &end, 10)))
return report(options, obj, FSCK_MSG_BAD_DATE_OVERFLOW, "invalid author/committer line - date causes integer overflow");
if ((end == p || *end != ' '))
return report(options, obj, FSCK_MSG_BAD_DATE, "invalid author/committer line - bad date");
diff --git a/git-compat-util.h b/git-compat-util.h
index ef6d560e156..5eff97bea2e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -319,6 +319,8 @@ extern char *gitdirname(char *);
#define PRIo32 "o"
#endif
+#define parse_timestamp strtoul
+
#ifndef PATH_SEP
#define PATH_SEP ':'
#endif
diff --git a/pretty.c b/pretty.c
index 5e683830d9d..6d1e1e87e7d 100644
--- a/pretty.c
+++ b/pretty.c
@@ -409,7 +409,7 @@ const char *show_ident_date(const struct ident_split *ident,
long tz = 0;
if (ident->date_begin && ident->date_end)
- date = strtoul(ident->date_begin, NULL, 10);
+ date = parse_timestamp(ident->date_begin, NULL, 10);
if (date_overflows(date))
date = 0;
else {
diff --git a/ref-filter.c b/ref-filter.c
index 3820b21cc75..6fab0db5e0d 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -637,7 +637,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
if (!eoemail)
goto bad;
- timestamp = strtoul(eoemail + 2, &zone, 10);
+ timestamp = parse_timestamp(eoemail + 2, &zone, 10);
if (timestamp == ULONG_MAX)
goto bad;
tz = strtol(zone, NULL, 10);
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index 4727bea255c..98637053760 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -33,7 +33,7 @@ static void show_dates(const char **argv, const char *format)
* Do not use our normal timestamp parsing here, as the point
* is to test the formatting code in isolation.
*/
- t = strtol(*argv, &arg, 10);
+ t = parse_timestamp(*argv, &arg, 10);
while (*arg == ' ')
arg++;
tz = atoi(arg);
diff --git a/tag.c b/tag.c
index 243d1fdbbcb..55d07725777 100644
--- a/tag.c
+++ b/tag.c
@@ -111,7 +111,7 @@ static unsigned long parse_tag_date(const char *buf, const char *tail)
if (buf >= tail)
return 0;
/* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
- return strtoul(dateptr, NULL, 10);
+ return parse_timestamp(dateptr, NULL, 10);
}
int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
diff --git a/upload-pack.c b/upload-pack.c
index 7597ba3405e..8c47dc1707a 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -775,7 +775,7 @@ static void receive_needs(void)
}
if (skip_prefix(line, "deepen-since ", &arg)) {
char *end = NULL;
- deepen_since = strtoul(arg, &end, 0);
+ deepen_since = parse_timestamp(arg, &end, 0);
if (!end || *end || !deepen_since ||
/* revisions.c's max_age -1 is special */
deepen_since == -1)
--
2.11.1.windows.1.379.g44ae0bc
^ permalink raw reply related
* Re: [PATCH] t6300: avoid creating refs/heads/HEAD
From: Junio C Hamano @ 2017-02-27 21:44 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <xmqqshmzuyam.fsf@gitster.mtv.corp.google.com>
Junio C Hamano <gitster@pobox.com> writes:
> ... I suspect that calling interpret_empty_at() from
> that function is fundamentally flawed. The "@" end user types never
> means refs/heads/HEAD, and HEAD@{either reflog or -1} would not mean
> anything that should be taken as a branch_name, either.
The latter should read "HEAD@{either reflog or -1 or 'upstream'}"
Or do we make HEAD@{upstream} to mean "deref HEAD to learn the
current branch name and then take its upstream"? If so @@{upstream}
might logically make sense, but I do not see why @{upstream} without
HEAD or @ is not sufficient to begin with, so...
^ permalink raw reply
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Thomas Gummerer @ 2017-02-27 21:53 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
Matthieu Moy
In-Reply-To: <xmqqwpcbuyrd.fsf@gitster.mtv.corp.google.com>
On 02/27, Junio C Hamano wrote:
> Thomas Gummerer <t.gummerer@gmail.com> writes:
>
> > if test -z "$patch_mode"
> > then
> > - git reset --hard ${GIT_QUIET:+-q}
> > + if test $# != 0
> > + then
> > + git reset ${GIT_QUIET:+-q} -- "$@"
> > + git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
>
> "ls-files -z" on the command line?
>
> Apparently new tests do not cover the correctness of this codepath.
>
> I wonder if this
>
> git ls-files -z --modified "$@" |
> git checkout-index -z --force --stdin
>
> is what the above "checkout" wanted to do. The "reset" in the
> previous step presumably updated the index entries that match
> specified pathspec to those of the HEAD, so checking out the paths
> that match "$@" from the index would be the same as checking them
> out from the HEAD (while updating the index with them).
Yes, you're completely right, this is exactly what it should have
done. Sorry for being slow on getting this right.
> Perhaps squash the following into an appropriate patch in the
> series?
Thanks, I'll squash this in and re-roll.
> git-stash.sh | 3 ++-
> t/t3903-stash.sh | 16 ++++++++++++++++
> 2 files changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/git-stash.sh b/git-stash.sh
> index 28d0624c75..9c70662cc8 100755
> --- a/git-stash.sh
> +++ b/git-stash.sh
> @@ -300,7 +300,8 @@ push_stash () {
> if test $# != 0
> then
> git reset ${GIT_QUIET:+-q} -- "$@"
> - git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
> + git ls-files -z --modified -- "$@" |
> + git checkout-index -z --force --stdin
> git clean --force ${GIT_QUIET:+-q} -d -- "$@"
> else
> git reset --hard ${GIT_QUIET:+-q}
> diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
> index f7733b4dd4..e868aafab2 100755
> --- a/t/t3903-stash.sh
> +++ b/t/t3903-stash.sh
> @@ -891,4 +891,20 @@ test_expect_success 'stash without verb with pathspec' '
> test_path_is_file bar
> '
>
> +test_expect_success 'stash with pathspec matching multiple paths' '
> + echo original >file &&
> + echo original >other-file &&
> + git commit -m "two" file other-file &&
> + echo modified >file &&
> + echo modified >other-file &&
> + git stash -- "*file" &&
> + echo original >expect &&
> + test_cmp expect file &&
> + test_cmp expect other-file &&
> + git stash pop &&
> + echo modified >expect &&
> + test_cmp expect file &&
> + test_cmp expect other-file
> +'
> +
> test_done
^ permalink raw reply
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Thomas Gummerer @ 2017-02-27 21:56 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
Matthieu Moy
In-Reply-To: <xmqq60jvwewc.fsf@gitster.mtv.corp.google.com>
On 02/27, Junio C Hamano wrote:
> Thomas Gummerer <t.gummerer@gmail.com> writes:
>
> > + test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
>
> This silent "exit 1" made me scratch my head, but --error-unmatch
> would have already given an error message, like
>
> error: pathspec 'no such' did not match any file(s) known to git.
> Did you forget to 'git add'?
>
> so that would be OK.
Yeah exactly, the plan was to let --error-unmatch print the error
message, as it's better at giving a good error message than we could
easily do here I think.
Maybe this deserves a comment so others won't have the same doubts
about this line?
^ permalink raw reply
* Re: [PATCH] t6300: avoid creating refs/heads/HEAD
From: Junio C Hamano @ 2017-02-27 22:18 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20170227214147.5ezxskhihi3cc77m@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> The "other" stuff could sometimes be useful, I guess. It's not _always_
> wrong to do:
>
> git branch -f @{upstream} foo
>
> It depends on what your @{upstream} resolves to. Switching to just using
> interpret_nth_prior_checkout() would break the case when it resolves to
> a local branch. I'm not sure if we're OK with that or not. If we want to
> keep all the existing cases working, I think we need something like the
> "not_in_refs_heads" patch I posted elsewhere.
I haven't seen that patch, but yes, telling the caller if the
returned value is meant to be used inside refs/heads/ is the right
approach and makes it possible for "@{upstream}" (and just "@") to
be handled sensibly in "git branch -m @{that at-mark thing}".
^ permalink raw reply
* Re: [PATCH 2/2] apply: handle assertion failure gracefully
From: René Scharfe @ 2017-02-27 22:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Vegard Nossum, git, Christian Couder, Michal Zalewski
In-Reply-To: <xmqqmvd7wgc7.fsf@gitster.mtv.corp.google.com>
Am 27.02.2017 um 21:04 schrieb Junio C Hamano:
> René Scharfe <l.s.r@web.de> writes:
>
>>> diff --git a/apply.c b/apply.c
>>> index cbf7cc7f2..9219d2737 100644
>>> --- a/apply.c
>>> +++ b/apply.c
>>> @@ -3652,7 +3652,6 @@ static int check_preimage(struct apply_state *state,
>>> if (!old_name)
>>> return 0;
>>>
>>> - assert(patch->is_new <= 0);
>>
>> 5c47f4c6 (builtin-apply: accept patch to an empty file) added that
>> line. Its intent was to handle diffs that contain an old name even for
>> a file that's created. Citing from its commit message: "When we
>> cannot be sure by parsing the patch that it is not a creation patch,
>> we shouldn't complain when if there is no such a file." Why not stop
>> complaining also in case we happen to know for sure that it's a
>> creation patch? I.e., why not replace the assert() with:
>>
>> if (patch->is_new == 1)
>> goto is_new;
>>
>>> previous = previous_patch(state, patch, &status);
>
> When the caller does know is_new is true, old_name must be made/left
> NULL. That is the invariant this assert is checking to catch an
> error in the calling code.
There are some places in apply.c that set ->is_new to 1, but none of
them set ->old_name to NULL at the same time.
Having to keep these two members in sync sounds iffy anyway. Perhaps
accessors can help, e.g. a setter which frees old_name when is_new is
set to 1, or a getter which returns NULL for old_name if is_new is 1.
René
^ permalink raw reply
* Re: [PATCH 1/2] apply: guard against renames of non-existant empty files
From: René Scharfe @ 2017-02-27 22:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Vegard Nossum, git, Christian Couder, Michal Zalewski
In-Reply-To: <xmqqinnvwg2d.fsf@gitster.mtv.corp.google.com>
Am 27.02.2017 um 21:10 schrieb Junio C Hamano:
> René Scharfe <l.s.r@web.de> writes:
>
>> Would it make sense to mirror the previously existing condition and
>> check for is_new instead? I.e.:
>>
>> if ((!patch->is_delete && !patch->new_name) ||
>> (!patch->is_new && !patch->old_name)) {
>>
>
> Yes, probably.
>
>> or
>>
>> if (!(patch->is_delete || patch->new_name) ||
>> !(patch->is_new || patch->old_name)) {
>
> This happens after calling parse_git_header() so we should know the
> actual value of is_delete and is_new by now (instead of mistaking
> -1 aka "unknown" as true), so this rewrite would also be OK.
The two variants are logically equivalent -- (!a && !b) == !(a || b). I
wonder if the second one may be harder to read, though.
René
^ permalink raw reply
* Re: [PATCH v2] convert: add "status=delayed" to filter process protocol
From: Jakub Narębski @ 2017-02-27 22:11 UTC (permalink / raw)
To: Lars Schneider, Jeff King
Cc: Git List, Junio C Hamano, Torsten Bögershausen, Eric Wong,
Taylor Blau
In-Reply-To: <E4A6D866-D046-4CF3-8050-666FD6C98F7B@gmail.com>
W dniu 27.02.2017 o 11:32, Lars Schneider pisze:
>
>> On 27 Feb 2017, at 10:58, Jeff King <peff@peff.net> wrote:
>>
>> On Sun, Feb 26, 2017 at 07:48:16PM +0100, Lars Schneider wrote:
>>
>>> +If the request cannot be fulfilled within a reasonable amount of time
>>> +then the filter can respond with a "delayed" status and a flush packet.
>>> +Git will perform the same request at a later point in time, again. The
>>> +filter can delay a response multiple times for a single request.
>>> +------------------------
>>> +packet: git< status=delayed
>>> +packet: git< 0000
>>> +------------------------
Is it something that happens instead of filter process sending the contents
of file, or is it something that happens after sending some part of the
contents (maybe empty) instead of empty list to keep "status=success"
unchanged or instead of "status=error" if there was a problem processing
file?
>>> +
>>
>> So Git just asks for the same content again? I see two issues with that:
>>
>> 1. Does git have to feed the blob content again? That can be expensive
>> to access or to keep around in memory.
>>
>> 2. What happens when the item isn't ready on the second request? I can
>> think of a few options:
>>
>> a. The filter immediately says "nope, still delayed". But then
>> Git ends up busy-looping with "is this one ready yet?"
>>
>> b. The filter blocks until the item is ready. But then if other
>> items _are_ ready, Git cannot work on processing them. We lose
>> parallelism.
>>
>> c. You could do a hybrid: block until _some_ item is ready, and
>> then issue "delayed" responses for everything that isn't
>> ready. Then if you assume that Git is looping over and over
>> through the set of objects, it will either block or pick up
>> _something_ on each loop.
>>
>> But it makes a quadratic number of requests in the worst case.
>> E.g., imagine you have N items and the last one is available
>> first, then the second-to-last, and so on. You'll ask N times,
>> then N-1, then N-2, and so on.
The current solution is a 'busy loop' one that I wrote about[1][2],
see below.
>
> I completely agree - I need to change that. However, the goal of the v2
> iteration was to get the "convert" interface in an acceptable state.
> That's what I intended to say in the patch comment section:
>
> "Please ignore all changes behind async_convert_to_working_tree() and
> async_filter_finish() for now as I plan to change the implementation
> as soon as the interface is in an acceptable state."
I think that it is more important to start with a good abstraction,
and the proposal for protocol, rather than getting bogged down in
implementation details that may change as the idea for protocol
extension changes.
>>
>> I think it would be much more efficient to do something like:
>>
>> [Git issues a request and gives it an opaque index id]
>> git> command=smudge
>> git> pathname=foo
>> git> index=0
>> git> 0000
>> git> CONTENT
>> git> 0000
>>
>> [The data isn't ready yet, so the filter tells us so...]
>> git< status=delayed
>> git< 0000
So is it only as replacement for "status=success" + contents or
"status=abort", that is upfront before sending any part of the file?
Or, as one can assume from the point of the paragraph with the
"status=delayed", it is about replacing null list for success or
"status=error" after sending some part (maybe empty) of a file,
that is:
[filter driver says that it can process contents]
git< status=success
git< 0000
git< PARTIAL_SMUDGED_CONTENT (maybe empty)
[there was some delay, for example one of shards is slow]
git< 0000
git< status=delayed
git< 0000
>>
>> [Git may make other requests, that are either served or delayed]
>> git> command=smudge
>> git> pathname=foo
>> git> index=1
>> git> 0000
>> git< status=success
>> git< 0000
>> git< CONTENT
>> git< 0000
>>
>> [Now Git has processed all of the items, and each one either has its
>> final status, or has been marked as delayed. So we ask for a delayed
>> item]
>> git> command=wait
>> git> 0000
In my proposal[2] I have called this "command=continue"... but at this
point it is bikeshedding. I think "command=wait" (or "await" ;-))
might be better.
>>
>> [Some time may pass if nothing is ready. But eventually we get...]
>> git< status=success
Or
git< status=resumed
If it would not be undue burden on the filter driver process, we might
require for it to say where to continue at (in bytes), e.g.
git< from=16426
That should, of course, go below index/pathname line.
>> git< index=0
Or a filter driver could have used pathname as an index, that is
git< pathname=path/testfile.dat
>> git< 0000
>> git< CONTENT
>> git< 0000
>>
>> From Git's side, the loop is something like:
>>
>> while (delayed_items > 0) {
>> /* issue a wait, and get back the status/index pair */
>> status = send_wait(&index);
>> delayed_items--;
This looks like my 'event loop' proposal[1][2], see below.
>>
>> /*
>> * use "index" to find the right item in our list of files;
>> * the format can be opaque to the filter, so we could index
>> * it however we like. But probably numeric indices in an array
>> * are the simplest.
>> */
>> assert(index > 0 && index < nr_items);
>> item[index].status = status;
>> if (status == SUCCESS)
>> read_content(&item[index]);
>> }
>>
>> and the filter side just attaches the "index" string to whatever its
>> internal queue structure is, and feeds it back verbatim when processing
>> that item finishes.
I have wrote about this for v1 version of this patch series:
[1]: https://public-inbox.org/git/ec8078ef-8ff2-d26f-ef73-5ef612737eee@gmail.com/
[2]: https://public-inbox.org/git/17fa31a5-8689-2766-952b-704f433a5b3a@gmail.com/
>
> That could work! I had something like that in mind:
>
> I teach Git a new command "list_completed" or similar. The filter
> blocks this call until at least one item is ready for Git.
> Then the filter responds with a list of paths that identify the
> "ready items". Then Git asks for these ready items just with the
> path and not with any content. Could that work? Wouldn't the path
> be "unique" to identify a blob per filter run?
Why in the "drain" phase it is still Git that needs to ask filter for
contents, one file after another? Wouldn't it be easier and simpler
for filter to finish sending contents, and send signal that it has
finished continue'ing?
To summarize my earlier emails, current proposal looks for me as if
it were a "busy loop" solution, that is[2]:
while there are delayed paths:
for each delayed path:
request path from filter [a]
fetch the thing (supporting "delayed") [b]
if path done
do the caller's thing to use buf
remove it from delayed paths list
Footnotes:
----------
a) We don't send the Git-side contents of blob again, isn't it?
So we need some protocol extension / new understanding anyway.
for example that we don't send contents if we request path again.
b) If path is not ready at all, filter protocol would send status=delayed
with empty contents. This means that we would immediately go to the
next path, if there is one.
There are some cases where busy loop is preferable, but I don't think
it is the case here.
The "event loop" solution, which is I think what Peff proposed, would
be something like this (from the protocol point of view, rather than
from the Git code point of view)[1]:
while there are delayed paths:
get path that is ready from filter
fetch the thing to buf (supporting "delayed")
if path done
do the caller's thing to use buf
(e.g. finish checkout path, eof convert, etc.)
We can either trust filter process to tell us when it finished sending
delayed paths, or keep list of paths that are being delayed in Git.
Also, one thing that we need to be solved, assuming that the proposed
extension allows to send partial data from filter to be delayed and
continued later, is that Git needs to keep this partial response in buf;
this is because of precedence of gitattributes applying:
Interaction between checkin/checkout attributes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the check-in codepath, the worktree file is first converted with
`filter` driver (if specified and corresponding driver defined), then
the result is processed with `ident` (if specified), and then finally
with `text` (again, if specified and applicable).
In the check-out codepath, the blob content is first converted with
`text`, and then `ident` and fed to `filter`.
Or maybe I misunderstood something; I am a bit confused by check-in
vs check-out there...
Note that with support of "command=wait" / "command=continue" Git
could interrupt sending contents, and drain unfinished files, if
it needs it... then continue sending rest of files. Well, if the
protocol extension is interpreted to allow for this.
Best regards,
--
Jakub Narębski
^ permalink raw reply
* [PATCH 1/6] t0006 & t5000: prepare for 64-bit time_t
From: Johannes Schindelin @ 2017-02-27 21:30 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <cover.1488231002.git.johannes.schindelin@gmx.de>
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 does not use `time_t`, is all.
The earlier quick fix 6b9c38e14cd (t0006: skip "far in the future" test
when unsigned long is not long enough, 2016-07-11) forced the test cases
to be skipped that require a 64-bit (or larger) data type to be used to
represent the time.
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`.
So let's just add another prerequisite to test specifically whether
timestamps are represented by a 64-bit data type or not. Later, when we
will have switched to using `time_t` where appropriate, we can flip that
prerequisite to test `time_t` instead of `long`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
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:<format> [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, &now);
else if (!strcmp(*argv, "approxidate"))
parse_approxidate(argv+1, &now);
+ 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" '1466000000'
# 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 +0000" 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 +0000" 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 86d77c16dd3..6151a3d70f8 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1163,3 +1163,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.11.1.windows.1.379.g44ae0bc
^ permalink raw reply related
* Re: [PATCH 2/2] commit: don't check for space twice when looking for header
From: Jakub Narębski @ 2017-02-27 22:27 UTC (permalink / raw)
To: René Scharfe, Git List; +Cc: Junio C Hamano
In-Reply-To: <b1d5c882-38b8-dd2d-2e5f-aafb8dfada81@web.de>
W dniu 25.02.2017 o 20:27, René Scharfe pisze:
> Both standard_header_field() and excluded_header_field() check if
> there's a space after the buffer that's handed to them. We already
> check in the caller if that space is present. Don't bother calling
> the functions if it's missing, as they are guaranteed to return 0 in
> that case, and remove the now redundant checks from them.
>
> Signed-off-by: Rene Scharfe <l.s.r@web.de>
> ---
> commit.c | 18 ++++++++----------
> 1 file changed, 8 insertions(+), 10 deletions(-)
>
> diff --git a/commit.c b/commit.c
> index 173c6d3818..fab8269731 100644
> --- a/commit.c
> +++ b/commit.c
> @@ -1308,11 +1308,11 @@ void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data)
>
> static inline int standard_header_field(const char *field, size_t len)
> {
> - return ((len == 4 && !memcmp(field, "tree ", 5)) ||
> - (len == 6 && !memcmp(field, "parent ", 7)) ||
> - (len == 6 && !memcmp(field, "author ", 7)) ||
> - (len == 9 && !memcmp(field, "committer ", 10)) ||
> - (len == 8 && !memcmp(field, "encoding ", 9)));
> + return ((len == 4 && !memcmp(field, "tree", 4)) ||
> + (len == 6 && !memcmp(field, "parent", 6)) ||
> + (len == 6 && !memcmp(field, "author", 6)) ||
> + (len == 9 && !memcmp(field, "committer", 9)) ||
> + (len == 8 && !memcmp(field, "encoding", 8)));
I agree (for what it is worth from me) with the rest of changes,
but I think current code is better self-documenting for this
function.
> }
>
> static int excluded_header_field(const char *field, size_t len, const char **exclude)
> @@ -1322,8 +1322,7 @@ static int excluded_header_field(const char *field, size_t len, const char **exc
>
> while (*exclude) {
> size_t xlen = strlen(*exclude);
> - if (len == xlen &&
> - !memcmp(field, *exclude, xlen) && field[xlen] == ' ')
> + if (len == xlen && !memcmp(field, *exclude, xlen))
> return 1;
> exclude++;
> }
> @@ -1357,9 +1356,8 @@ static struct commit_extra_header *read_commit_extra_header_lines(
> eof = memchr(line, ' ', next - line);
> if (!eof)
> eof = next;
> -
> - if (standard_header_field(line, eof - line) ||
> - excluded_header_field(line, eof - line, exclude))
> + else if (standard_header_field(line, eof - line) ||
> + excluded_header_field(line, eof - line, exclude))
> continue;
>
> it = xcalloc(1, sizeof(*it));
>
^ permalink raw reply
* Re: [BUG] branch renamed to 'HEAD'
From: Junio C Hamano @ 2017-02-27 22:28 UTC (permalink / raw)
To: Jeff King; +Cc: Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <20170227090233.uk7dfruggytgmuw2@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I guess something like the patch below works, but I wonder if there is a
> less-horrible way to accomplish the same thing.
I suspect that a less-horrible would be a lot more intrusive. It
would go like "interpret-branch-name only gives local branch name,
and when it does not show it, the callers that know they do not
necessarily need local branch name would call other at-mark things".
As you pointed out with the @{upstream} that potentially point at a
local branch, it will quickly get more involved, I would think, and
I tend to think that this patch of yours is probably the least evil
one among possible solutions.
Perhaps with s/not_in_refs_heads/not_a_branch_name/ (or swapping
polarity, "is_a_branch_name"), the resulting code may not be too
hard to read?
Thanks.
^ permalink raw reply
* Re: [PATCH 2/2] apply: handle assertion failure gracefully
From: Junio C Hamano @ 2017-02-27 22:33 UTC (permalink / raw)
To: René Scharfe; +Cc: Vegard Nossum, git, Christian Couder, Michal Zalewski
In-Reply-To: <f191e3a8-a55b-7030-ebbb-3f46c74fdc94@web.de>
René Scharfe <l.s.r@web.de> writes:
> Am 27.02.2017 um 21:04 schrieb Junio C Hamano:
>> René Scharfe <l.s.r@web.de> writes:
>>
>>>> diff --git a/apply.c b/apply.c
>>>> index cbf7cc7f2..9219d2737 100644
>>>> --- a/apply.c
>>>> +++ b/apply.c
>>>> @@ -3652,7 +3652,6 @@ static int check_preimage(struct apply_state *state,
>>>> if (!old_name)
>>>> return 0;
>>>>
>>>> - assert(patch->is_new <= 0);
>>>
>>> 5c47f4c6 (builtin-apply: accept patch to an empty file) added that
>>> line. Its intent was to handle diffs that contain an old name even for
>>> a file that's created. Citing from its commit message: "When we
>>> cannot be sure by parsing the patch that it is not a creation patch,
>>> we shouldn't complain when if there is no such a file." Why not stop
>>> complaining also in case we happen to know for sure that it's a
>>> creation patch? I.e., why not replace the assert() with:
>>>
>>> if (patch->is_new == 1)
>>> goto is_new;
>>>
>>>> previous = previous_patch(state, patch, &status);
>>
>> When the caller does know is_new is true, old_name must be made/left
>> NULL. That is the invariant this assert is checking to catch an
>> error in the calling code.
>
> There are some places in apply.c that set ->is_new to 1, but none of
> them set ->old_name to NULL at the same time.
I thought all of these are flipping ->is_new that used to be -1
(unknown) to (now we know it is new), and sets only new_name without
doing anything to old_name, because they know originally both names
are set to NULL.
> Having to keep these two members in sync sounds iffy anyway. Perhaps
> accessors can help, e.g. a setter which frees old_name when is_new is
> set to 1, or a getter which returns NULL for old_name if is_new is 1.
Definitely, the setter would make it harder to make the mistake.
^ permalink raw reply
* Re: [PATCH 05/10] submodule--helper: add is_active command
From: Brandon Williams @ 2017-02-27 18:35 UTC (permalink / raw)
To: Stefan Beller; +Cc: git@vger.kernel.org
In-Reply-To: <CAGZ79kZKH_e2NLd=A=og452f-1bfFcSoi5=SM5oetu87TT766Q@mail.gmail.com>
On 02/23, Stefan Beller wrote:
> On Thu, Feb 23, 2017 at 3:47 PM, Brandon Williams <bmwill@google.com> wrote:
> > There are a lot of places where an explicit check for
> > submodule."<name>".url is done to see if a submodule exists. In order
> > to more easily facilitate the use of the submodule.active config option
> > to indicate active submodules, add a helper which can be used to query
> > if a submodule is active or not.
> >
> > Signed-off-by: Brandon Williams <bmwill@google.com>
> > ---
> > builtin/submodule--helper.c | 11 ++++++++
> > t/t7413-submodule-is-active.sh | 63 ++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 74 insertions(+)
> > create mode 100755 t/t7413-submodule-is-active.sh
> >
> > diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
> > index df0d9c166..dac02604d 100644
> > --- a/builtin/submodule--helper.c
> > +++ b/builtin/submodule--helper.c
> > @@ -1128,6 +1128,16 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
> > return 0;
> > }
> >
> > +static int is_active(int argc, const char **argv, const char *prefix)
> > +{
> > + if (argc != 2)
> > + die("submodule--helper is-active takes exactly 1 arguments");
> > +
> > + gitmodules_config();
> > +
> > + return !is_submodule_initialized(argv[1]);
> > +}
> > +
> > #define SUPPORT_SUPER_PREFIX (1<<0)
> >
> > struct cmd_struct {
> > @@ -1147,6 +1157,7 @@ static struct cmd_struct commands[] = {
> > {"init", module_init, 0},
> > {"remote-branch", resolve_remote_submodule_branch, 0},
> > {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
> > + {"is-active", is_active, 0},
> > };
> >
> > int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
> > diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh
> > new file mode 100755
> > index 000000000..683487020
> > --- /dev/null
> > +++ b/t/t7413-submodule-is-active.sh
> > @@ -0,0 +1,63 @@
> > +#!/bin/sh
> > +
> > +test_description='Test submodule--helper is-active
> > +
> > +This test verifies that `git submodue--helper is-active` correclty identifies
> > +submodules which are "active" and interesting to the user.
> > +'
> > +
> > +. ./test-lib.sh
> > +
> > +test_expect_success 'setup' '
> > + git init sub &&
> > + test_commit -C sub initial &&
> > + git init super &&
> > + test_commit -C super initial &&
> > + git -C super submodule add ../sub sub1 &&
> > + git -C super submodule add ../sub sub2 &&
> > + git -C super commit -a -m "add 2 submodules at sub{1,2}"
> > +'
> > +
> > +test_expect_success 'is-active works with urls' '
> > + git -C super submodule--helper is-active sub1 &&
> > + git -C super submodule--helper is-active sub2 &&
> > +
> > + git -C super config --unset submodule.sub1.URL &&
> > + test_must_fail git -C super submodule--helper is-active sub1 &&
> > + git -C super config submodule.sub1.URL ../sub &&
> > + git -C super submodule--helper is-active sub1
> > +'
> > +
> > +test_expect_success 'is-active works with basic submodule.active config' '
> > + git -C super config --add submodule.active "." &&
> > + git -C super config --unset submodule.sub1.URL &&
> > + git -C super config --unset submodule.sub2.URL &&
>
> I think we'd want to unset only one of them here
>
> > +
> > + git -C super submodule--helper is-active sub1 &&
> > + git -C super submodule--helper is-active sub2 &&
>
> to test 2 different cases of one being active by config setting only and
> the other having both.
Will do.
>
> I could not spot test for having the URL set but the config setting set, not
> including the submodule, e.g.
>
> git -C super config submodule.sub1.URL ../sub &&
> git -C super submodule.active ":(exclude)sub1" &&
>
> which would be expected to not be active, as once the configuration
> is there it takes precedence over any (no)URL setting?
The last test, tests this functionality as the URL settings for both
sub1 and sub2 are in the config. You'll notice in the tests where I
unset the URL config, that they get added back at the end of the test so
that future tests have a clean state to work with.
--
Brandon Williams
^ permalink raw reply
* Re: Reference for quote "creating branch is not the issue, merging is", in context of Subversion/Git
From: Jakub Narębski @ 2017-02-27 22:42 UTC (permalink / raw)
To: Igor Djordjevic, Michael Hüttermann, git
In-Reply-To: <32232f89-a6f8-be30-278a-bdfedae0716a@gmail.com>
W dniu 26.02.2017 o 16:19, Igor Djordjevic pisze:
> Hello Michael,
>
> On 26/02/2017 12:40, Michael Hüttermann wrote:
>> Linus Torvalds made a statement regarding merging/branching and stated
>> (as far as I know) that "creating branch is not the issue, merge is", in
>> context of Subversion/Git.
>> I do not find the origin source for that. Can you please help and point
>> me to a statement or article where Linus elaborated on this?
>
> Could it be that you think of "Tech Talk: Linus Torvalds on Git"[1]
> (held on May 3, 2007)?
>
> To give you some clue, here`s an excerpt from Linus' talk/presentation
> (taken from the transcript[2] containing the whole thing):
>
> "... Subversion for example, talks very loudly about how they do CVS
> right by making branching really cheap. It's probably on their main
> webpage where they probably say branching in subversion is O(1)
> operation, you can do as many cheap branches as you want. Nevermind
> that O(1) is actually with pretty large O I think, but even if it
> takes a millionth of a second to do branching, who cares? It's the
> wrong thing you are measuring. Nobody is interested in branching,
> branches are completely useless unless you merge them, and CVS cannot
> merge anything at all. You can merge things once, but because CVS
> then forgets what you did, you can never ever merge anything again
> without getting horrible horrible conflicts. Merging in subversion is
> a complete disaster. The subversion people kind of acknowledge this
> and they have a plan, and their plan sucks too. It is incredible how
> stupid these people are. They've been looking at the wrong problem
> all the time. Branching is not the issue, merging is..."
>
> This specific branch/merge performance talk starts at 50:20[3], where
> the part quoted above comes at 51:34[4].
Note also that while "creating branch is not the issue, merge is"
remains true, modern Subversion (post 1.5) makes merging easy thanks
to svn:mergeinfo property.
Though it does it in completely different way than Git and other
"graph of commits" VCS-es, because of the "branch is directory"
philosophy, namely that it keeps information about what was merged
in, rather than finding common ancestor(s) and using this information
for resolving merge.
>
> Please note that there`s more context before and after this excerpt
> that puts it all into the meant perspective, so you may really want
> to watch/listen/read the whole thing anyway.
>
> Regards,
> Buga
>
> [1] https://www.youtube.com/watch?v=4XpnKHJAok8
> [2] https://git.wiki.kernel.org/index.php/LinusTalk200705Transcript
> [3] https://youtu.be/4XpnKHJAok8?t=3020
> [4] https://youtu.be/4XpnKHJAok8?t=3094
>
^ permalink raw reply
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Junio C Hamano @ 2017-02-27 20:32 UTC (permalink / raw)
To: Thomas Gummerer
Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
Matthieu Moy
In-Reply-To: <20170225213306.2410-5-t.gummerer@gmail.com>
Thomas Gummerer <t.gummerer@gmail.com> writes:
> if test -z "$patch_mode"
> then
> - git reset --hard ${GIT_QUIET:+-q}
> + if test $# != 0
> + then
> + git reset ${GIT_QUIET:+-q} -- "$@"
> + git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
"ls-files -z" on the command line?
Apparently new tests do not cover the correctness of this codepath.
I wonder if this
git ls-files -z --modified "$@" |
git checkout-index -z --stdin
is what the above "checkout" wanted to do. The "reset" in the
previous step presumably updated the index entries that match
specified pathspec to those of the HEAD, so checking out the paths
that match "$@" from the index would be the same as checking them
out from the HEAD (while updating the index with them).
> + git clean --force ${GIT_QUIET:+-q} -d -- "$@"
> + else
> + git reset --hard ${GIT_QUIET:+-q}
> + fi
Thanks.
^ permalink raw reply
* Re: [PATCH 2/6] Specify explicitly where we parse timestamps
From: Junio C Hamano @ 2017-02-27 22:37 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <12b60c14dad15e3252e314771b3fe369305bbfc5.1488231002.git.johannes.schindelin@gmx.de>
Johannes Schindelin <johannes.schindelin@gmx.de> writes:
> Currently, Git's source code represents all timestamps as `unsigned
> long`. In preparation for using `time_t` instead, let's introduce a
> symbol `parse_timestamp` (currently being defined to `strtoul`) where
> appropriate, so that we can later easily switch to use `strtoull()`
> instead.
This definitely is a very good thing to do as a separate step.
> diff --git a/date.c b/date.c
> index a996331f5b3..a8848f6e141 100644
> --- a/date.c
> +++ b/date.c
> ...
> @@ -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, &end, 10);
> + time_t number = parse_timestamp(date, &end, 10);
This hunk does not belong to this step. Everybody else in this step
still receives parse_timestamp()'s return value in ulong, not time_t.
I presume that that will happen in the final step 6/6 (which could
be a huge patch that exceeds 100k?)
^ permalink raw reply
* Re: [PATCH 2/6] Specify explicitly where we parse timestamps
From: Junio C Hamano @ 2017-02-27 22:51 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <xmqqwpcbmfai.fsf@gitster.mtv.corp.google.com>
Junio C Hamano <gitster@pobox.com> writes:
>> - unsigned long number = strtoul(date, &end, 10);
>> + time_t number = parse_timestamp(date, &end, 10);
>
> This hunk does not belong to this step. Everybody else in this step
obviously I meant "the left half of this hunk" ;-)
> still receives parse_timestamp()'s return value in ulong, not time_t.
> I presume that that will happen in the final step 6/6 (which could
> be a huge patch that exceeds 100k?)
^ permalink raw reply
* Re: [PATCH 1/6] t0006 & t5000: prepare for 64-bit time_t
From: Junio C Hamano @ 2017-02-27 22:55 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <3871d1d9de0315a1a98bce5d8f544a5e18917f25.1488231002.git.johannes.schindelin@gmx.de>
Johannes Schindelin <johannes.schindelin@gmx.de> writes:
> 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`.
>
> So let's just add another prerequisite to test specifically whether
> timestamps are represented by a 64-bit data type or not. Later, when we
> will have switched to using `time_t` where appropriate, we can flip that
> prerequisite to test `time_t` instead of `long`.
The changes that move from LONG_IS to TIME_IS in this patch are all
about time (iow, LONG_IS_64BIT prereq is still used in the check on
sizes). The patch looks sensible.
^ permalink raw reply
* Re: [PATCH 2/2] commit: don't check for space twice when looking for header
From: René Scharfe @ 2017-02-27 22:54 UTC (permalink / raw)
To: Jakub Narębski, Git List; +Cc: Junio C Hamano
In-Reply-To: <1dd0884c-032c-fb04-67f6-8b181fd65eea@gmail.com>
Am 27.02.2017 um 23:27 schrieb Jakub Narębski:
> W dniu 25.02.2017 o 20:27, René Scharfe pisze:
>> Both standard_header_field() and excluded_header_field() check if
>> there's a space after the buffer that's handed to them. We already
>> check in the caller if that space is present. Don't bother calling
>> the functions if it's missing, as they are guaranteed to return 0 in
>> that case, and remove the now redundant checks from them.
>>
>> Signed-off-by: Rene Scharfe <l.s.r@web.de>
>> ---
>> commit.c | 18 ++++++++----------
>> 1 file changed, 8 insertions(+), 10 deletions(-)
>>
>> diff --git a/commit.c b/commit.c
>> index 173c6d3818..fab8269731 100644
>> --- a/commit.c
>> +++ b/commit.c
>> @@ -1308,11 +1308,11 @@ void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *data)
>>
>> static inline int standard_header_field(const char *field, size_t len)
>> {
>> - return ((len == 4 && !memcmp(field, "tree ", 5)) ||
>> - (len == 6 && !memcmp(field, "parent ", 7)) ||
>> - (len == 6 && !memcmp(field, "author ", 7)) ||
>> - (len == 9 && !memcmp(field, "committer ", 10)) ||
>> - (len == 8 && !memcmp(field, "encoding ", 9)));
>> + return ((len == 4 && !memcmp(field, "tree", 4)) ||
>> + (len == 6 && !memcmp(field, "parent", 6)) ||
>> + (len == 6 && !memcmp(field, "author", 6)) ||
>> + (len == 9 && !memcmp(field, "committer", 9)) ||
>> + (len == 8 && !memcmp(field, "encoding", 8)));
>
> I agree (for what it is worth from me) with the rest of changes,
> but I think current code is better self-documenting for this
> function.
Having a function that is given a buffer/length pair and accessing the
byte after it raises questions, though. :)
Nicer than keeping the space would be to use excluded_header_field() for
standard headers as well as a next step, I think -- but that would be a
bit slower.
>
>> }
>>
>> static int excluded_header_field(const char *field, size_t len, const char **exclude)
>> @@ -1322,8 +1322,7 @@ static int excluded_header_field(const char *field, size_t len, const char **exc
>>
>> while (*exclude) {
>> size_t xlen = strlen(*exclude);
>> - if (len == xlen &&
>> - !memcmp(field, *exclude, xlen) && field[xlen] == ' ')
>> + if (len == xlen && !memcmp(field, *exclude, xlen))
>> return 1;
>> exclude++;
>> }
>> @@ -1357,9 +1356,8 @@ static struct commit_extra_header *read_commit_extra_header_lines(
>> eof = memchr(line, ' ', next - line);
>> if (!eof)
>> eof = next;
>> -
>> - if (standard_header_field(line, eof - line) ||
>> - excluded_header_field(line, eof - line, exclude))
>> + else if (standard_header_field(line, eof - line) ||
>> + excluded_header_field(line, eof - line, exclude))
>> continue;
>>
>> it = xcalloc(1, sizeof(*it));
>>
>
^ permalink raw reply
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Junio C Hamano @ 2017-02-27 22:58 UTC (permalink / raw)
To: Thomas Gummerer
Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
Matthieu Moy
In-Reply-To: <20170227215627.GB17065@hank>
Thomas Gummerer <t.gummerer@gmail.com> writes:
> On 02/27, Junio C Hamano wrote:
>> Thomas Gummerer <t.gummerer@gmail.com> writes:
>>
>> > + test -n "$untracked" || git ls-files --error-unmatch -- "$@" >/dev/null || exit 1
>>
>> This silent "exit 1" made me scratch my head, but --error-unmatch
>> would have already given an error message, like
>>
>> error: pathspec 'no such' did not match any file(s) known to git.
>> Did you forget to 'git add'?
>>
>> so that would be OK.
>
> Yeah exactly, the plan was to let --error-unmatch print the error
> message, as it's better at giving a good error message than we could
> easily do here I think.
>
> Maybe this deserves a comment so others won't have the same doubts
> about this line?
Nah, I do not think so. It probably is obvious for those who write
(and read) "--error-unmatch". I was just being slow to realize that
the sole point of that option was to complain ;-)
^ permalink raw reply
* Re: [PATCH] t6300: avoid creating refs/heads/HEAD
From: Jeff King @ 2017-02-27 21:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqqefyjnwat.fsf@gitster.mtv.corp.google.com>
On Mon, Feb 27, 2017 at 01:44:26PM -0800, Junio C Hamano wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> > ... I suspect that calling interpret_empty_at() from
> > that function is fundamentally flawed. The "@" end user types never
> > means refs/heads/HEAD, and HEAD@{either reflog or -1} would not mean
> > anything that should be taken as a branch_name, either.
>
> The latter should read "HEAD@{either reflog or -1 or 'upstream'}"
>
> Or do we make HEAD@{upstream} to mean "deref HEAD to learn the
> current branch name and then take its upstream"? If so @@{upstream}
> might logically make sense, but I do not see why @{upstream} without
> HEAD or @ is not sufficient to begin with, so...
Yes, HEAD@{upstream} and @@{upstream} are both resolved to the actual
branch name. I also was puzzled whether there was any real use over just
@{upstream}. But it does work, and if you had a script which looked for,
say, $branch@{upstream}, you'd probably want branch=HEAD to keep
working.
The "branch=@" case I am less sympathetic to, as it was mainly supposed
to be a command-line convenience. But it _does_ work now.
-Peff
^ permalink raw reply
* Re: [PATCH v7 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Junio C Hamano @ 2017-02-27 21:09 UTC (permalink / raw)
To: Thomas Gummerer
Cc: git, Jeff King, Johannes Schindelin, sunny, Jakub Narębski,
Matthieu Moy
In-Reply-To: <20170225213306.2410-5-t.gummerer@gmail.com>
Thomas Gummerer <t.gummerer@gmail.com> writes:
> if test -z "$patch_mode"
> then
> - git reset --hard ${GIT_QUIET:+-q}
> + if test $# != 0
> + then
> + git reset ${GIT_QUIET:+-q} -- "$@"
> + git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
"ls-files -z" on the command line?
Apparently new tests do not cover the correctness of this codepath.
I wonder if this
git ls-files -z --modified "$@" |
git checkout-index -z --force --stdin
is what the above "checkout" wanted to do. The "reset" in the
previous step presumably updated the index entries that match
specified pathspec to those of the HEAD, so checking out the paths
that match "$@" from the index would be the same as checking them
out from the HEAD (while updating the index with them).
Perhaps squash the following into an appropriate patch in the
series?
git-stash.sh | 3 ++-
t/t3903-stash.sh | 16 ++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/git-stash.sh b/git-stash.sh
index 28d0624c75..9c70662cc8 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -300,7 +300,8 @@ push_stash () {
if test $# != 0
then
git reset ${GIT_QUIET:+-q} -- "$@"
- git checkout ${GIT_QUIET:+-q} HEAD -- $(git ls-files -z --modified "$@")
+ git ls-files -z --modified -- "$@" |
+ git checkout-index -z --force --stdin
git clean --force ${GIT_QUIET:+-q} -d -- "$@"
else
git reset --hard ${GIT_QUIET:+-q}
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index f7733b4dd4..e868aafab2 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -891,4 +891,20 @@ test_expect_success 'stash without verb with pathspec' '
test_path_is_file bar
'
+test_expect_success 'stash with pathspec matching multiple paths' '
+ echo original >file &&
+ echo original >other-file &&
+ git commit -m "two" file other-file &&
+ echo modified >file &&
+ echo modified >other-file &&
+ git stash -- "*file" &&
+ echo original >expect &&
+ test_cmp expect file &&
+ test_cmp expect other-file &&
+ git stash pop &&
+ echo modified >expect &&
+ test_cmp expect file &&
+ test_cmp expect other-file
+'
+
test_done
^ permalink raw reply related
* [PATCH 6/6] Use time_t where appropriate
From: Johannes Schindelin @ 2017-02-27 21:31 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <cover.1488231002.git.johannes.schindelin@gmx.de>
Git's source code assumes that unsigned long is at least as precise as
time_t. That 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 time_t instead.
Note that in some systems (most notably 32-bit Linux), time_t is *still*
only 32-bit.
Therefore, it might seem desirable to simply replace unsigned long by
int64_t when working with timestamps, but that comes with its own set of
problems, as we often interact with the system's date functions that
*do* use time_t.
So let's just stick with time_t.
By necessity, this is a very, very large patch, as it has to replace all
timestamps' data type in one go.
As `time_t` can be signed, we now have to switch to using LONG_MAX as
the maximum timestamp lest expressions like `timestamp < TIME_MAX`
evaluate to false. Technically, this introduces a limitation on
platforms where we used 64-bit unsigned longs to represent timestamps
before. Practically, however, this simply unifies the behavior with
platforms where `time_t` is signed (and where sending too large
timestamps to libc functions would fail).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Documentation/technical/api-parse-options.txt | 8 ++---
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 | 2 +-
builtin/receive-pack.c | 6 ++--
builtin/reflog.c | 24 ++++++-------
builtin/show-branch.c | 4 +--
builtin/worktree.c | 2 +-
bundle.c | 2 +-
cache.h | 14 ++++----
commit.c | 12 +++----
commit.h | 2 +-
config.mak.uname | 2 ++
credential-cache--daemon.c | 12 +++----
date.c | 50 +++++++++++++--------------
fetch-pack.c | 6 ++--
git-compat-util.h | 2 +-
http-backend.c | 4 +--
parse-options-cb.c | 4 +--
pretty.c | 2 +-
reachable.c | 10 +++---
reachable.h | 4 +--
ref-filter.c | 2 +-
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 | 4 +--
t/helper/test-parse-options.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 +-
45 files changed, 140 insertions(+), 140 deletions(-)
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 27bd701c0d6..28c9a64fc11 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -178,13 +178,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, &int_var, description)`::
+`OPT_DATE(short, long, &time_t_var, description)`::
Introduce an option with date argument, see `approxidate()`.
- The timestamp is put into `int_var`.
+ The timestamp is put into `time_t_var`.
-`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
+`OPT_EXPIRY_DATE(short, long, &time_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 `time_t_var`.
`OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
Introduce an option with argument.
diff --git a/builtin/am.c b/builtin/am.c
index 75e2d939036..c3e0a4816e4 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -877,7 +877,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
if (skip_prefix(sb.buf, "# User ", &str))
fprintf(out, "From: %s\n", str);
else if (skip_prefix(sb.buf, "# Date ", &str)) {
- unsigned long timestamp;
+ time_t timestamp;
long tz, tz2;
char *end;
diff --git a/builtin/blame.c b/builtin/blame.c
index c9486dd580b..33701a1353e 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1570,13 +1570,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
struct commit_info {
struct strbuf author;
struct strbuf author_mail;
- unsigned long author_time;
+ time_t author_time;
struct strbuf author_tz;
/* filled only when asked for details */
struct strbuf committer;
struct strbuf committer_mail;
- unsigned long committer_time;
+ time_t committer_time;
struct strbuf committer_tz;
struct strbuf summary;
@@ -1587,7 +1587,7 @@ struct commit_info {
*/
static void get_ac_line(const char *inbuf, const char *what,
struct strbuf *name, struct strbuf *mail,
- unsigned long *time, struct strbuf *tz)
+ time_t *time, struct strbuf *tz)
{
struct ident_split ident;
size_t len, maillen, namelen;
@@ -1846,7 +1846,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
stop_progress(&pi.progress);
}
-static const char *format_time(unsigned long time, const char *tz_str,
+static const char *format_time(time_t time, const char *tz_str,
int show_raw_time)
{
static struct strbuf time_buf = STRBUF_INIT;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 5413c76e7a6..42452744d67 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -397,7 +397,7 @@ static int fsck_obj_buffer(const unsigned char *sha1, enum object_type type,
static int default_refs;
static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1,
- unsigned long timestamp)
+ time_t timestamp)
{
struct object *obj;
@@ -418,7 +418,7 @@ static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1,
}
static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
const char *refname = cb_data;
diff --git a/builtin/gc.c b/builtin/gc.c
index 331f2192607..7be9d106c0b 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -67,7 +67,7 @@ static void git_config_date_string(const char *key, const char **output)
if (git_config_get_string_const(key, output))
return;
if (strcmp(*output, "now")) {
- unsigned long now = approxidate("now");
+ time_t now = approxidate("now");
if (approxidate(*output) >= now)
git_die_config(key, _("Invalid %s: '%s'"), key, *output);
}
diff --git a/builtin/log.c b/builtin/log.c
index 24612c2299a..c0d3143d0e3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -904,7 +904,7 @@ static void gen_message_id(struct rev_info *info, char *base)
{
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "%s.%"PRItime".git.%s", base,
- (unsigned long) time(NULL),
+ (time_t) time(NULL),
git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
info->message_id = strbuf_detach(&buf, NULL);
}
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index b572a37c261..5a9580230c8 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -132,7 +132,7 @@ static void add_one_commit(unsigned char *sha1, struct rev_collect *revs)
}
static int collect_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *ident, unsigned long timestamp,
+ const char *ident, time_t timestamp,
int tz, const char *message, void *cbdata)
{
struct rev_collect *revs = cbdata;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index a0f16407b93..5faafeda96f 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -10,7 +10,7 @@
typedef struct rev_name {
const char *tip_name;
- unsigned long taggerdate;
+ time_t taggerdate;
int generation;
int distance;
} rev_name;
@@ -21,7 +21,7 @@ static long cutoff = LONG_MAX;
#define MERGE_TRAVERSAL_WEIGHT 65535
static void name_rev(struct commit *commit,
- const char *tip_name, unsigned long taggerdate,
+ const char *tip_name, time_t taggerdate,
int generation, int distance,
int deref)
{
@@ -145,7 +145,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo
struct name_ref_data *data = cb_data;
int can_abbreviate_output = data->tags_only && data->name_only;
int deref = 0;
- unsigned long taggerdate = TIME_MAX;
+ time_t taggerdate = TIME_MAX;
if (data->tags_only && !starts_with(path, "refs/tags/"))
return 0;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 8841f8b366b..e46ed73f51b 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -44,7 +44,7 @@ static uint32_t nr_result, nr_written;
static int non_empty;
static int reuse_delta = 1, reuse_object = 1;
static int keep_unreachable, unpack_unreachable, include_tag;
-static unsigned long unpack_unreachable_expiration;
+static time_t unpack_unreachable_expiration;
static int pack_loose_unreachable;
static int local;
static int have_non_local_packs;
@@ -2593,7 +2593,7 @@ static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
static struct sha1_array recent_objects;
static int loosened_object_can_be_discarded(const unsigned char *sha1,
- unsigned long mtime)
+ time_t mtime)
{
if (!unpack_unreachable_expiration)
return 0;
diff --git a/builtin/prune.c b/builtin/prune.c
index 1e5eb0292b1..a8babb1f201 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -13,7 +13,7 @@ static const char * const prune_usage[] = {
};
static int show_only;
static int verbose;
-static unsigned long expire;
+static time_t expire;
static int show_progress = -1;
static int prune_tmp_file(const char *fullpath)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 4a878645847..1b21617c601 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -77,7 +77,7 @@ static const char *NONCE_OK = "OK";
static const char *NONCE_SLOP = "SLOP";
static const char *nonce_status;
static long nonce_stamp_slop;
-static unsigned long nonce_stamp_slop_limit;
+static time_t nonce_stamp_slop_limit;
static struct ref_transaction *transaction;
static enum {
@@ -451,7 +451,7 @@ static void hmac_sha1(unsigned char *out,
git_SHA1_Final(out, &ctx);
}
-static char *prepare_push_cert_nonce(const char *path, unsigned long stamp)
+static char *prepare_push_cert_nonce(const char *path, time_t stamp)
{
struct strbuf buf = STRBUF_INIT;
unsigned char sha1[20];
@@ -493,7 +493,7 @@ static char *find_header(const char *msg, size_t len, const char *key)
static const char *check_nonce(const char *buf, size_t len)
{
char *nonce = find_header(buf, len, "nonce");
- unsigned long stamp, ostamp;
+ time_t stamp, ostamp;
char *bohmac, *expect = NULL;
const char *retval = NONCE_BAD;
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 7a7136e53e2..331c874174e 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -16,14 +16,14 @@ static const char reflog_delete_usage[] =
static const char reflog_exists_usage[] =
"git reflog exists <ref>";
-static unsigned long default_reflog_expire;
-static unsigned long default_reflog_expire_unreachable;
+static time_t default_reflog_expire;
+static time_t default_reflog_expire_unreachable;
struct cmd_reflog_expire_cb {
struct rev_info revs;
int stalefix;
- unsigned long expire_total;
- unsigned long expire_unreachable;
+ time_t expire_total;
+ time_t expire_unreachable;
int recno;
};
@@ -219,7 +219,7 @@ static int keep_entry(struct commit **it, unsigned char *sha1)
static void mark_reachable(struct expire_reflog_policy_cb *cb)
{
struct commit_list *pending;
- unsigned long expire_limit = cb->mark_limit;
+ time_t expire_limit = cb->mark_limit;
struct commit_list *leftover = NULL;
for (pending = cb->mark_list; pending; pending = pending->next)
@@ -284,7 +284,7 @@ static int unreachable(struct expire_reflog_policy_cb *cb, struct commit *commit
* Return true iff the specified reflog entry should be expired.
*/
static int should_expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
@@ -392,8 +392,8 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus
static struct reflog_expire_cfg {
struct reflog_expire_cfg *next;
- unsigned long expire_total;
- unsigned long expire_unreachable;
+ time_t expire_total;
+ time_t expire_unreachable;
char pattern[FLEX_ARRAY];
} *reflog_expire_cfg, **reflog_expire_cfg_tail;
@@ -415,7 +415,7 @@ static struct reflog_expire_cfg *find_cfg_ent(const char *pattern, size_t len)
return ent;
}
-static int parse_expire_cfg_value(const char *var, const char *value, unsigned long *expire)
+static int parse_expire_cfg_value(const char *var, const char *value, time_t *expire)
{
if (!value)
return config_error_nonbool(var);
@@ -433,7 +433,7 @@ static int reflog_expire_config(const char *var, const char *value, void *cb)
{
const char *pattern, *key;
int pattern_len;
- unsigned long expire;
+ time_t expire;
int slot;
struct reflog_expire_cfg *ent;
@@ -515,7 +515,7 @@ static void set_reflog_expiry_param(struct cmd_reflog_expire_cb *cb, int slot, c
static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
{
struct expire_reflog_policy_cb cb;
- unsigned long now = time(NULL);
+ time_t now = time(NULL);
int i, status, do_all;
int explicit_expiry = 0;
unsigned int flags = 0;
@@ -616,7 +616,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
}
static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 974f3403abe..512b5e3db34 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -742,7 +742,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
base = strtoul(reflog_base, &ep, 10);
if (*ep) {
/* Ah, that is a date spec... */
- unsigned long at;
+ time_t at;
at = approxidate(reflog_base);
read_ref_at(ref, flags, at, -1, oid.hash, NULL,
NULL, NULL, &base);
@@ -753,7 +753,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
char *logmsg;
char *nth_desc;
const char *msg;
- unsigned long timestamp;
+ time_t timestamp;
int tz;
if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg,
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 3df95e112e5..f12a0e4689c 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -30,7 +30,7 @@ struct add_opts {
static int show_only;
static int verbose;
-static unsigned long expire;
+static time_t expire;
static int prune_worktree(const char *id, struct strbuf *reason)
{
diff --git a/bundle.c b/bundle.c
index f43bfcf5ff3..75b82e6b653 100644
--- a/bundle.c
+++ b/bundle.c
@@ -211,7 +211,7 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
unsigned long size;
enum object_type type;
char *buf = NULL, *line, *lineend;
- unsigned long date;
+ time_t date;
int result = 1;
if (revs->max_age == -1 && revs->min_age == -1)
diff --git a/cache.h b/cache.h
index 61fc86e6d71..a276d1ea1b0 100644
--- a/cache.h
+++ b/cache.h
@@ -1361,18 +1361,18 @@ struct date_mode {
#define DATE_MODE(t) date_mode_from_type(DATE_##t)
struct date_mode *date_mode_from_type(enum date_mode_type type);
-const char *show_date(unsigned long time, int timezone, const struct date_mode *mode);
-void show_date_relative(unsigned long time, int tz, const struct timeval *now,
+const char *show_date(time_t time, int timezone, const struct date_mode *mode);
+void show_date_relative(time_t time, int tz, const struct timeval *now,
struct strbuf *timebuf);
int parse_date(const char *date, struct strbuf *out);
-int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
-int parse_expiry_date(const char *date, unsigned long *timestamp);
+int parse_date_basic(const char *date, time_t *timestamp, int *offset);
+int parse_expiry_date(const char *date, time_t *timestamp);
void datestamp(struct strbuf *out);
#define approxidate(s) approxidate_careful((s), NULL)
-unsigned long approxidate_careful(const char *, int *);
-unsigned long approxidate_relative(const char *date, const struct timeval *now);
+time_t approxidate_careful(const char *, int *);
+time_t approxidate_relative(const char *date, const struct timeval *now);
void parse_date_format(const char *format, struct date_mode *mode);
-int date_overflows(unsigned long date);
+int date_overflows(time_t date);
#define IDENT_STRICT 1
#define IDENT_NO_DATE 2
diff --git a/commit.c b/commit.c
index 7f56b643704..ab379e9d6f4 100644
--- a/commit.c
+++ b/commit.c
@@ -66,7 +66,7 @@ struct commit *lookup_commit_reference_by_name(const char *name)
return commit;
}
-static unsigned long parse_commit_date(const char *buf, const char *tail)
+static time_t parse_commit_date(const char *buf, const char *tail)
{
const char *dateptr;
@@ -474,8 +474,8 @@ struct commit_list * commit_list_insert_by_date(struct commit *item, struct comm
static int commit_list_compare_by_date(const void *a, const void *b)
{
- unsigned long a_date = ((const struct commit_list *)a)->item->date;
- unsigned long b_date = ((const struct commit_list *)b)->item->date;
+ time_t a_date = ((const struct commit_list *)a)->item->date;
+ time_t b_date = ((const struct commit_list *)b)->item->date;
if (a_date < b_date)
return 1;
if (a_date > b_date)
@@ -599,7 +599,7 @@ static void record_author_date(struct author_date_slab *author_date,
const char *ident_line;
size_t ident_len;
char *date_end;
- unsigned long date;
+ time_t date;
ident_line = find_commit_header(buffer, "author", &ident_len);
if (!ident_line)
@@ -622,8 +622,8 @@ static int compare_commits_by_author_date(const void *a_, const void *b_,
{
const struct commit *a = a_, *b = b_;
struct author_date_slab *author_date = cb_data;
- unsigned long a_date = *(author_date_slab_at(author_date, a));
- unsigned long b_date = *(author_date_slab_at(author_date, b));
+ time_t a_date = *(author_date_slab_at(author_date, a));
+ time_t b_date = *(author_date_slab_at(author_date, b));
/* newer commits with larger date first */
if (a_date < b_date)
diff --git a/commit.h b/commit.h
index 9c12abb9111..7b2d3d0b8a8 100644
--- a/commit.h
+++ b/commit.h
@@ -17,7 +17,7 @@ struct commit {
struct object object;
void *util;
unsigned int index;
- unsigned long date;
+ time_t date;
struct commit_list *parents;
struct tree *tree;
};
diff --git a/config.mak.uname b/config.mak.uname
index 447f36ac2e3..ea1a71a936b 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -370,6 +370,7 @@ ifeq ($(uname_S),Windows)
NO_INET_PTON = YesPlease
NO_INET_NTOP = YesPlease
NO_POSIX_GOODIES = UnfortunatelyYes
+ TIME_T_IS_INT64 = YesItIs
NATIVE_CRLF = YesPlease
DEFAULT_HELP_FORMAT = html
@@ -520,6 +521,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_INET_PTON = YesPlease
NO_INET_NTOP = YesPlease
NO_POSIX_GOODIES = UnfortunatelyYes
+ TIME_T_IS_INT64 = YesItIs
DEFAULT_HELP_FORMAT = html
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c
index b298ac01e4f..364e5e0c5be 100644
--- a/credential-cache--daemon.c
+++ b/credential-cache--daemon.c
@@ -8,7 +8,7 @@ static struct tempfile socket_file;
struct credential_cache_entry {
struct credential item;
- unsigned long expiration;
+ time_t expiration;
};
static struct credential_cache_entry *entries;
static int entries_nr;
@@ -47,12 +47,12 @@ static void remove_credential(const struct credential *c)
e->expiration = 0;
}
-static int check_expirations(void)
+static time_t check_expirations(void)
{
- static unsigned long wait_for_entry_until;
+ static time_t wait_for_entry_until;
int i = 0;
- unsigned long now = time(NULL);
- unsigned long next = TIME_MAX;
+ time_t now = time(NULL);
+ time_t next = TIME_MAX;
/*
* Initially give the client 30 seconds to actually contact us
@@ -159,7 +159,7 @@ static void serve_one_client(FILE *in, FILE *out)
static int serve_cache_loop(int fd)
{
struct pollfd pfd;
- unsigned long wakeup;
+ time_t wakeup;
wakeup = check_expirations();
if (!wakeup)
diff --git a/date.c b/date.c
index 23dee2964c1..dad2d0c807e 100644
--- a/date.c
+++ b/date.c
@@ -39,7 +39,7 @@ static const char *weekday_names[] = {
"Sundays", "Mondays", "Tuesdays", "Wednesdays", "Thursdays", "Fridays", "Saturdays"
};
-static time_t gm_time_t(unsigned long time, int tz)
+static time_t gm_time_t(time_t time, int tz)
{
int minutes;
@@ -54,7 +54,7 @@ static time_t gm_time_t(unsigned long time, int tz)
* thing, which means that tz -0100 is passed in as the integer -100,
* even though it means "sixty minutes off"
*/
-static struct tm *time_to_tm(unsigned long time, int tz)
+static struct tm *time_to_tm(time_t time, int tz)
{
time_t t = gm_time_t(time, tz);
return gmtime(&t);
@@ -64,7 +64,7 @@ static struct tm *time_to_tm(unsigned long time, int tz)
* What value of "tz" was in effect back then at "time" in the
* local timezone?
*/
-static int local_tzoffset(unsigned long time)
+static int local_tzoffset(time_t time)
{
time_t t, t_local;
struct tm tm;
@@ -88,11 +88,11 @@ static int local_tzoffset(unsigned long time)
return offset * eastwest;
}
-void show_date_relative(unsigned long time, int tz,
+void show_date_relative(time_t time, int tz,
const struct timeval *now,
struct strbuf *timebuf)
{
- unsigned long diff;
+ time_t diff;
if (now->tv_sec < time) {
strbuf_addstr(timebuf, _("in the future"));
return;
@@ -140,9 +140,9 @@ void show_date_relative(unsigned long time, int tz,
}
/* Give years and months for 5 years or so */
if (diff < 1825) {
- unsigned long totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
- unsigned long years = totalmonths / 12;
- unsigned long months = totalmonths % 12;
+ time_t totalmonths = (diff * 12 * 2 + 365) / (365 * 2);
+ time_t years = totalmonths / 12;
+ time_t months = totalmonths % 12;
if (months) {
struct strbuf sb = STRBUF_INIT;
strbuf_addf(&sb, Q_("%"PRItime" year", "%"PRItime" years", years), years);
@@ -172,7 +172,7 @@ struct date_mode *date_mode_from_type(enum date_mode_type type)
return &mode;
}
-const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
+const char *show_date(time_t time, int tz, const struct date_mode *mode)
{
struct tm *tm;
static struct strbuf timebuf = STRBUF_INIT;
@@ -425,7 +425,7 @@ static int is_date(int year, int month, int day, struct tm *now_tm, time_t now,
return 0;
}
-static int match_multi_number(unsigned long num, char c, const char *date,
+static int match_multi_number(time_t num, char c, const char *date,
char *end, struct tm *tm, time_t now)
{
struct tm now_tm;
@@ -508,7 +508,7 @@ static int match_digit(const char *date, struct tm *tm, int *offset, int *tm_gmt
{
int n;
char *end;
- unsigned long num;
+ time_t num;
num = parse_timestamp(date, &end, 10);
@@ -635,7 +635,7 @@ static int match_tz(const char *date, int *offp)
return end - date;
}
-static void date_string(unsigned long date, int offset, struct strbuf *buf)
+static void date_string(time_t date, int offset, struct strbuf *buf)
{
int sign = '+';
@@ -650,10 +650,10 @@ static void date_string(unsigned long date, int offset, struct strbuf *buf)
* Parse a string like "0 +0000" as ancient timestamp near epoch, but
* only when it appears not as part of any other string.
*/
-static int match_object_header_date(const char *date, unsigned long *timestamp, int *offset)
+static int match_object_header_date(const char *date, time_t *timestamp, int *offset)
{
char *end;
- unsigned long stamp;
+ time_t stamp;
int ofs;
if (*date < '0' || '9' < *date)
@@ -675,11 +675,11 @@ static int match_object_header_date(const char *date, unsigned long *timestamp,
/* Gr. strptime is crap for this; it doesn't have a way to require RFC2822
(i.e. English) day/month names, and it doesn't work correctly with %z. */
-int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
+int parse_date_basic(const char *date, time_t *timestamp, int *offset)
{
struct tm tm;
int tm_gmt;
- unsigned long dummy_timestamp;
+ time_t dummy_timestamp;
int dummy_offset;
if (!timestamp)
@@ -747,7 +747,7 @@ int parse_date_basic(const char *date, unsigned long *timestamp, int *offset)
return 0; /* success */
}
-int parse_expiry_date(const char *date, unsigned long *timestamp)
+int parse_expiry_date(const char *date, time_t *timestamp)
{
int errors = 0;
@@ -771,7 +771,7 @@ int parse_expiry_date(const char *date, unsigned long *timestamp)
int parse_date(const char *date, struct strbuf *result)
{
- unsigned long timestamp;
+ time_t timestamp;
int offset;
if (parse_date_basic(date, ×tamp, &offset))
return -1;
@@ -845,7 +845,7 @@ void datestamp(struct strbuf *out)
* Relative time update (eg "2 days ago"). If we haven't set the time
* yet, we need to set it from current time.
*/
-static unsigned long update_tm(struct tm *tm, struct tm *now, unsigned long sec)
+static time_t update_tm(struct tm *tm, struct tm *now, time_t sec)
{
time_t n;
@@ -1114,7 +1114,7 @@ static void pending_number(struct tm *tm, int *num)
}
}
-static unsigned long approxidate_str(const char *date,
+static time_t approxidate_str(const char *date,
const struct timeval *tv,
int *error_ret)
{
@@ -1151,9 +1151,9 @@ static unsigned long approxidate_str(const char *date,
return update_tm(&tm, &now, 0);
}
-unsigned long approxidate_relative(const char *date, const struct timeval *tv)
+time_t approxidate_relative(const char *date, const struct timeval *tv)
{
- unsigned long timestamp;
+ time_t timestamp;
int offset;
int errors = 0;
@@ -1162,10 +1162,10 @@ unsigned long approxidate_relative(const char *date, const struct timeval *tv)
return approxidate_str(date, tv, &errors);
}
-unsigned long approxidate_careful(const char *date, int *error_ret)
+time_t approxidate_careful(const char *date, int *error_ret)
{
struct timeval tv;
- unsigned long timestamp;
+ time_t timestamp;
int offset;
int dummy = 0;
if (!error_ret)
@@ -1180,7 +1180,7 @@ unsigned long approxidate_careful(const char *date, int *error_ret)
return approxidate_str(date, &tv, error_ret);
}
-int date_overflows(unsigned long t)
+int date_overflows(time_t t)
{
time_t sys;
diff --git a/fetch-pack.c b/fetch-pack.c
index 54fb35e39c5..d3401733b05 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -356,7 +356,7 @@ static int find_common(struct fetch_pack_args *args,
if (args->depth > 0)
packet_buf_write(&req_buf, "deepen %d", args->depth);
if (args->deepen_since) {
- unsigned long max_age = approxidate(args->deepen_since);
+ time_t max_age = approxidate(args->deepen_since);
packet_buf_write(&req_buf, "deepen-since %"PRItime, max_age);
}
if (args->deepen_not) {
@@ -545,7 +545,7 @@ static int mark_complete_oid(const char *refname, const struct object_id *oid,
}
static void mark_recent_complete_commits(struct fetch_pack_args *args,
- unsigned long cutoff)
+ time_t cutoff)
{
while (complete && cutoff <= complete->item->date) {
print_verbose(args, _("Marking %s as complete"),
@@ -630,7 +630,7 @@ static int everything_local(struct fetch_pack_args *args,
{
struct ref *ref;
int retval;
- unsigned long cutoff = 0;
+ time_t cutoff = 0;
save_commit_buffer = 0;
diff --git a/git-compat-util.h b/git-compat-util.h
index 5cf1133532d..027f3b2f8eb 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -326,7 +326,7 @@ extern char *gitdirname(char *);
#else
#define PRItime "lu"
#define parse_timestamp strtoul
-#define TIME_MAX ULONG_MAX
+#define TIME_MAX LONG_MAX
#endif
#ifndef PATH_SEP
diff --git a/http-backend.c b/http-backend.c
index eef0a361f4f..4e88735a9e3 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -90,7 +90,7 @@ static void hdr_int(struct strbuf *hdr, const char *name, uintmax_t value)
strbuf_addf(hdr, "%s: %" PRIuMAX "\r\n", name, value);
}
-static void hdr_date(struct strbuf *hdr, const char *name, unsigned long when)
+static void hdr_date(struct strbuf *hdr, const char *name, time_t when)
{
const char *value = show_date(when, 0, DATE_MODE(RFC2822));
hdr_str(hdr, name, value);
@@ -105,7 +105,7 @@ static void hdr_nocache(struct strbuf *hdr)
static void hdr_cache_forever(struct strbuf *hdr)
{
- unsigned long now = time(NULL);
+ time_t now = time(NULL);
hdr_date(hdr, "Date", now);
hdr_date(hdr, "Expires", now + 31536000);
hdr_str(hdr, "Cache-Control", "public, max-age=31536000");
diff --git a/parse-options-cb.c b/parse-options-cb.c
index b7d8f7dcb2c..a560d8d0b8c 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -31,14 +31,14 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
int unset)
{
- *(unsigned long *)(opt->value) = approxidate(arg);
+ *(time_t *)(opt->value) = approxidate(arg);
return 0;
}
int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
int unset)
{
- return parse_expiry_date(arg, (unsigned long *)opt->value);
+ return parse_expiry_date(arg, (time_t *)opt->value);
}
int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
diff --git a/pretty.c b/pretty.c
index 6d1e1e87e7d..ab689009536 100644
--- a/pretty.c
+++ b/pretty.c
@@ -405,7 +405,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, size_t len,
const char *show_ident_date(const struct ident_split *ident,
const struct date_mode *mode)
{
- unsigned long date = 0;
+ time_t date = 0;
long tz = 0;
if (ident->date_begin && ident->date_end)
diff --git a/reachable.c b/reachable.c
index d0199cace4a..f4d2be6beb7 100644
--- a/reachable.c
+++ b/reachable.c
@@ -55,12 +55,11 @@ static void mark_commit(struct commit *c, void *data)
struct recent_data {
struct rev_info *revs;
- unsigned long timestamp;
+ time_t timestamp;
};
static void add_recent_object(const unsigned char *sha1,
- unsigned long mtime,
- struct recent_data *data)
+ time_t mtime, struct recent_data *data)
{
struct object *obj;
enum object_type type;
@@ -139,7 +138,7 @@ static int add_recent_packed(const unsigned char *sha1,
}
int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
- unsigned long timestamp)
+ time_t timestamp)
{
struct recent_data data;
int r;
@@ -156,8 +155,7 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
}
void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
- unsigned long mark_recent,
- struct progress *progress)
+ time_t mark_recent, struct progress *progress)
{
struct connectivity_progress cp;
diff --git a/reachable.h b/reachable.h
index d23efc36ec5..2a7f6588941 100644
--- a/reachable.h
+++ b/reachable.h
@@ -3,8 +3,8 @@
struct progress;
extern int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
- unsigned long timestamp);
+ time_t timestamp);
extern void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
- unsigned long mark_recent, struct progress *);
+ time_t mark_recent, struct progress *);
#endif
diff --git a/ref-filter.c b/ref-filter.c
index b8b34d4dd9e..265b7c03845 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -618,7 +618,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
{
const char *eoemail = strstr(buf, "> ");
char *zone;
- unsigned long timestamp;
+ time_t timestamp;
long tz;
struct date_mode date_mode = { DATE_NORMAL };
const char *formatp;
diff --git a/reflog-walk.c b/reflog-walk.c
index a246af27678..d1a8673c348 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -12,7 +12,7 @@ struct complete_reflogs {
struct reflog_info {
unsigned char osha1[20], nsha1[20];
char *email;
- unsigned long timestamp;
+ time_t timestamp;
int tz;
char *message;
} *items;
@@ -20,7 +20,7 @@ struct complete_reflogs {
};
static int read_one_reflog(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct complete_reflogs *array = cb_data;
@@ -69,7 +69,7 @@ static struct complete_reflogs *read_complete_reflog(const char *ref)
}
static int get_reflog_recno_by_time(struct complete_reflogs *array,
- unsigned long timestamp)
+ time_t timestamp)
{
int i;
for (i = array->nr - 1; i >= 0; i--)
@@ -141,7 +141,7 @@ void init_reflog_walk(struct reflog_walk_info **info)
int add_reflog_for_walk(struct reflog_walk_info *info,
struct commit *commit, const char *name)
{
- unsigned long timestamp = 0;
+ time_t timestamp = 0;
int recno = -1;
struct string_list_item *item;
struct complete_reflogs *reflogs;
diff --git a/refs.c b/refs.c
index cd36b64ed93..546e9080555 100644
--- a/refs.c
+++ b/refs.c
@@ -658,7 +658,7 @@ int is_branch(const char *refname)
struct read_ref_at_cb {
const char *refname;
- unsigned long at_time;
+ time_t at_time;
int cnt;
int reccnt;
unsigned char *sha1;
@@ -667,15 +667,15 @@ struct read_ref_at_cb {
unsigned char osha1[20];
unsigned char nsha1[20];
int tz;
- unsigned long date;
+ time_t date;
char **msg;
- unsigned long *cutoff_time;
+ time_t *cutoff_time;
int *cutoff_tz;
int *cutoff_cnt;
};
static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct read_ref_at_cb *cb = cb_data;
@@ -722,7 +722,7 @@ static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
}
static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp,
+ const char *email, time_t timestamp,
int tz, const char *message, void *cb_data)
{
struct read_ref_at_cb *cb = cb_data;
@@ -742,9 +742,9 @@ static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
return 1;
}
-int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
+int read_ref_at(const char *refname, unsigned int flags, time_t at_time, int cnt,
unsigned char *sha1, char **msg,
- unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
+ time_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
{
struct read_ref_at_cb cb;
diff --git a/refs.h b/refs.h
index 9fbff90e79b..1748827a7ba 100644
--- a/refs.h
+++ b/refs.h
@@ -262,9 +262,9 @@ int safe_create_reflog(const char *refname, int force_create, struct strbuf *err
/** Reads log for the value of ref during at_time. **/
int read_ref_at(const char *refname, unsigned int flags,
- unsigned long at_time, int cnt,
+ time_t at_time, int cnt,
unsigned char *sha1, char **msg,
- unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
+ time_t *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
/** Check if a particular reflog exists */
int reflog_exists(const char *refname);
@@ -293,7 +293,7 @@ int delete_reflog(const char *refname);
/* iterate over reflog entries */
typedef int each_reflog_ent_fn(
unsigned char *old_sha1, unsigned char *new_sha1,
- const char *committer, unsigned long timestamp,
+ const char *committer, time_t timestamp,
int tz, const char *msg, void *cb_data);
int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
@@ -536,7 +536,7 @@ typedef void reflog_expiry_prepare_fn(const char *refname,
typedef int reflog_expiry_should_prune_fn(unsigned char *osha1,
unsigned char *nsha1,
const char *email,
- unsigned long timestamp, int tz,
+ time_t timestamp, int tz,
const char *message, void *cb_data);
typedef void reflog_expiry_cleanup_fn(void *cb_data);
diff --git a/refs/files-backend.c b/refs/files-backend.c
index c041d4ba21a..4316de3a692 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -3115,7 +3115,7 @@ static int show_one_reflog_ent(struct strbuf *sb, each_reflog_ent_fn fn, void *c
{
unsigned char osha1[20], nsha1[20];
char *email_end, *message;
- unsigned long timestamp;
+ time_t timestamp;
int tz;
/* old SP new SP name <email> SP time TAB msg LF */
@@ -3940,7 +3940,7 @@ struct expire_reflog_cb {
};
static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_cb *cb = cb_data;
diff --git a/revision.c b/revision.c
index b37dbec378f..419d5fa954e 100644
--- a/revision.c
+++ b/revision.c
@@ -884,7 +884,7 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
/* How many extra uninteresting commits we want to see.. */
#define SLOP 5
-static int still_interesting(struct commit_list *src, unsigned long date, int slop,
+static int still_interesting(struct commit_list *src, time_t date, int slop,
struct commit **interesting_cache)
{
/*
@@ -1018,7 +1018,7 @@ static void limit_left_right(struct commit_list *list, struct rev_info *revs)
static int limit_list(struct rev_info *revs)
{
int slop = SLOP;
- unsigned long date = ~0ul;
+ time_t date = ~0ul;
struct commit_list *list = revs->commits;
struct commit_list *newlist = NULL;
struct commit_list **p = &newlist;
@@ -1215,7 +1215,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
}
static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
handle_one_reflog_commit(osha1, cb_data);
diff --git a/revision.h b/revision.h
index 9fac1a607de..e39e5b524bb 100644
--- a/revision.h
+++ b/revision.h
@@ -181,8 +181,8 @@ struct rev_info {
/* special limits */
int skip_count;
int max_count;
- unsigned long max_age;
- unsigned long min_age;
+ time_t max_age;
+ time_t min_age;
int min_parents;
int max_parents;
int (*include_check)(struct commit *, void *);
diff --git a/sha1_name.c b/sha1_name.c
index 73a915ff1b3..9520586139e 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -658,8 +658,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
if (reflog_len) {
int nth, i;
- unsigned long at_time;
- unsigned long co_time;
+ time_t at_time;
+ time_t co_time;
int co_tz, co_cnt;
/* Is it asking for N-th entry, or approxidate? */
@@ -1052,7 +1052,7 @@ struct grab_nth_branch_switch_cbdata {
};
static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct grab_nth_branch_switch_cbdata *cb = cb_data;
diff --git a/t/helper/test-date.c b/t/helper/test-date.c
index ba309ec1760..371f9d259c6 100644
--- a/t/helper/test-date.c
+++ b/t/helper/test-date.c
@@ -47,7 +47,7 @@ static void parse_dates(const char **argv, struct timeval *now)
struct strbuf result = STRBUF_INIT;
for (; *argv; argv++) {
- unsigned long t;
+ time_t t;
int tz;
strbuf_reset(&result);
@@ -95,7 +95,7 @@ int cmd_main(int argc, const char **argv)
else if (!strcmp(*argv, "approxidate"))
parse_approxidate(argv+1, &now);
else if (!strcmp(*argv, "is64bit"))
- return sizeof(unsigned long) == 8 ? 0 : 1;
+ return sizeof(time_t) == 8 ? 0 : 1;
else
usage(usage_msg);
return 0;
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index 7d93627e454..8af62dd7501 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -5,7 +5,7 @@
static int boolean = 0;
static int integer = 0;
static unsigned long magnitude = 0;
-static unsigned long timestamp;
+static time_t timestamp;
static int abbrev = 7;
static int verbose = -1; /* unspecified */
static int dry_run = 0, quiet = 0;
diff --git a/tag.c b/tag.c
index 55d07725777..a0b22c788b6 100644
--- a/tag.c
+++ b/tag.c
@@ -97,7 +97,7 @@ struct tag *lookup_tag(const unsigned char *sha1)
return object_as_type(obj, OBJ_TAG, 0);
}
-static unsigned long parse_tag_date(const char *buf, const char *tail)
+static time_t parse_tag_date(const char *buf, const char *tail)
{
const char *dateptr;
diff --git a/tag.h b/tag.h
index a5721b6731e..aaf56849de8 100644
--- a/tag.h
+++ b/tag.h
@@ -9,7 +9,7 @@ struct tag {
struct object object;
struct object *tagged;
char *tag;
- unsigned long date;
+ time_t date;
};
extern struct tag *lookup_tag(const unsigned char *sha1);
diff --git a/upload-pack.c b/upload-pack.c
index c2be661f6d4..4dcc6aa8d95 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -35,7 +35,7 @@ static const char * const upload_pack_usage[] = {
#define CLIENT_SHALLOW (1u << 18)
#define HIDDEN_REF (1u << 19)
-static unsigned long oldest_have;
+static time_t oldest_have;
static int deepen_relative;
static int multi_ack;
@@ -735,7 +735,7 @@ static void receive_needs(void)
struct string_list deepen_not = STRING_LIST_INIT_DUP;
int depth = 0;
int has_non_tip = 0;
- unsigned long deepen_since = 0;
+ time_t deepen_since = 0;
int deepen_rev_list = 0;
shallow_nr = 0;
diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 6c9f2866d8b..5df87ce6bb4 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -68,7 +68,7 @@ void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
}
void fast_export_begin_note(uint32_t revision, const char *author,
- const char *log, unsigned long timestamp, const char *note_ref)
+ const char *log, time_t timestamp, const char *note_ref)
{
static int firstnote = 1;
size_t loglen = strlen(log);
@@ -93,7 +93,7 @@ static char gitsvnline[MAX_GITSVN_LINE_LEN];
void fast_export_begin_commit(uint32_t revision, const char *author,
const struct strbuf *log,
const char *uuid, const char *url,
- unsigned long timestamp, const char *local_ref)
+ time_t timestamp, const char *local_ref)
{
static const struct strbuf empty = STRBUF_INIT;
if (!log)
diff --git a/vcs-svn/fast_export.h b/vcs-svn/fast_export.h
index c8b5adb811c..864dada2b31 100644
--- a/vcs-svn/fast_export.h
+++ b/vcs-svn/fast_export.h
@@ -11,10 +11,10 @@ void fast_export_delete(const char *path);
void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
void fast_export_note(const char *committish, const char *dataref);
void fast_export_begin_note(uint32_t revision, const char *author,
- const char *log, unsigned long timestamp, const char *note_ref);
+ const char *log, time_t timestamp, const char *note_ref);
void fast_export_begin_commit(uint32_t revision, const char *author,
const struct strbuf *log, const char *uuid,const char *url,
- unsigned long timestamp, const char *local_ref);
+ time_t timestamp, const char *local_ref);
void fast_export_end_commit(uint32_t revision);
void fast_export_data(uint32_t mode, off_t len, struct line_buffer *input);
void fast_export_buf_to_data(const struct strbuf *data);
diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c
index e4b395963b9..9e1eb8d4176 100644
--- a/vcs-svn/svndump.c
+++ b/vcs-svn/svndump.c
@@ -47,7 +47,7 @@ static struct {
static struct {
uint32_t revision;
- unsigned long timestamp;
+ time_t timestamp;
struct strbuf log, author, note;
} rev_ctx;
diff --git a/wt-status.c b/wt-status.c
index d47012048f8..da261363551 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1374,7 +1374,7 @@ struct grab_1st_switch_cbdata {
};
static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp, int tz,
+ const char *email, time_t timestamp, int tz,
const char *message, void *cb_data)
{
struct grab_1st_switch_cbdata *cb = cb_data;
--
2.11.1.windows.1.379.g44ae0bc
^ permalink raw reply related
* Re: [BUG] branch renamed to 'HEAD'
From: Junio C Hamano @ 2017-02-28 0:33 UTC (permalink / raw)
To: Jacob Keller; +Cc: Jeff King, Karthik Nayak, Luc Van Oostenryck, Git List
In-Reply-To: <CA+P7+xpVt6NtSajqMX8OQ_SKdC9tfHH40JgK=9DgBxo9nMaWLA@mail.gmail.com>
Jacob Keller <jacob.keller@gmail.com> writes:
> What about changing interpret-branch-name gains a flag to return a
> fully qualified ref rather than returning just the name? That seems
> like it would be more reasonable behavior.
There are two kinds of callers to i-b-n. The ones that want a local
branch name because they are parsing special places on the command
line that using a local branch name makes difference (as opposed to
using any extended SHA-1 expression), like "git checkout master"
(which means different thing from "git checkout master^0"). And the
ones that can use any object name.
It depends on how your flag works, but if it means "add refs/heads/
when you got a local branch name", then that would not work well for
the former callers, as end-user inputs @{-1} and refs/heads/master
would become indistinguishable. The former is expanded to 'master'
(if you were on that branch) and ends up being refs/heads/master.
"git checkout refs/heads/master" would be (unless you have a branch
with that name, i.e. refs/heads/refs/heads/master) a request to
detach HEAD at the commit, but the user wanted to be on the previous
branch. And the latter iclass of callers are probably already happy
with or without the flag, so they won't be helped, either.
A flag to affect the behaviour (as opposed to &flag as a secondary
return value, like Peff's patch does) can be made to work. Perhaps
a flag that says "keep the input as is if the result is not a local
branch name" would pass an input "@" intact and that may be
sufficient to allow "git branch -m @" to rename the current branch
to "@" (I do not think it is a sensible rename, though ;-). But
probably some callers need to keep the original input and compare
with the result to see if we expanded anything if we go that route.
At that point, I am not sure if there are much differences in the
ease of use between the two approaches.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox