Skip to content
Snippets Groups Projects
Commit dddbad72 authored by Johannes Schindelin's avatar Johannes Schindelin Committed by Junio C Hamano
Browse files

timestamp_t: a new data type for timestamps


Git's source code assumes that unsigned long is at least as precise as
time_t. Which is incorrect, and causes a lot of problems, in particular
where unsigned long is only 32-bit (notably on Windows, even in 64-bit
versions).

So let's just use a more appropriate data type instead. In preparation
for this, we introduce the new `timestamp_t` data type.

By necessity, this is a very, very large patch, as it has to replace all
timestamps' data type in one go.

As we will use a data type that is not necessarily identical to `time_t`,
we need to be very careful to use `time_t` whenever we interact with the
system functions, and `timestamp_t` everywhere else.

Signed-off-by: default avatarJohannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
parent cb71f8bd
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -183,13 +183,13 @@ There are some macros to easily define options:
scale the provided value by 1024, 1024^2 or 1024^3 respectively.
The scaled value is put into `unsigned_long_var`.
 
`OPT_DATE(short, long, &int_var, description)`::
`OPT_DATE(short, long, &timestamp_t_var, description)`::
Introduce an option with date argument, see `approxidate()`.
The timestamp is put into `int_var`.
The timestamp is put into `timestamp_t_var`.
 
`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
`OPT_EXPIRY_DATE(short, long, &timestamp_t_var, description)`::
Introduce an option with expiry date argument, see `parse_expiry_date()`.
The timestamp is put into `int_var`.
The timestamp is put into `timestamp_t_var`.
 
`OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
Introduce an option with argument.
Loading
Loading
Loading
Loading
@@ -27,9 +27,12 @@ static int write_tar_filter_archive(const struct archiver *ar,
*/
#if ULONG_MAX == 0xFFFFFFFF
#define USTAR_MAX_SIZE ULONG_MAX
#define USTAR_MAX_MTIME ULONG_MAX
#else
#define USTAR_MAX_SIZE 077777777777UL
#define USTAR_MAX_SIZE 077777777777ULL
#endif
#if TIME_MAX == 0xFFFFFFFF
#define USTAR_MAX_MTIME TIME_MAX
#else
#define USTAR_MAX_MTIME 077777777777UL
#endif
 
Loading
Loading
Loading
Loading
@@ -545,9 +545,17 @@ static void write_zip_trailer(const unsigned char *sha1)
write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
}
 
static void dos_time(time_t *time, int *dos_date, int *dos_time)
static void dos_time(timestamp_t *timestamp, int *dos_date, int *dos_time)
{
struct tm *t = localtime(time);
time_t time;
struct tm *t;
if (date_overflows(*timestamp))
die("timestamp too large for this system: %"PRItime,
*timestamp);
time = (time_t)*timestamp;
t = localtime(&time);
*timestamp = time;
 
*dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
(t->tm_year + 1900 - 1980) * 512;
Loading
Loading
Loading
Loading
@@ -9,7 +9,7 @@ struct archiver_args {
struct tree *tree;
const unsigned char *commit_sha1;
const struct commit *commit;
time_t time;
timestamp_t time;
struct pathspec pathspec;
unsigned int verbose : 1;
unsigned int worktree_attributes : 1;
Loading
Loading
Loading
Loading
@@ -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;
timestamp_t timestamp;
long tz, tz2;
char *end;
 
Loading
Loading
Loading
Loading
@@ -1561,13 +1561,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;
timestamp_t author_time;
struct strbuf author_tz;
 
/* filled only when asked for details */
struct strbuf committer;
struct strbuf committer_mail;
unsigned long committer_time;
timestamp_t committer_time;
struct strbuf committer_tz;
 
struct strbuf summary;
Loading
Loading
@@ -1578,7 +1578,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)
timestamp_t *time, struct strbuf *tz)
{
struct ident_split ident;
size_t len, maillen, namelen;
Loading
Loading
@@ -1837,7 +1837,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(timestamp_t time, const char *tz_str,
int show_raw_time)
{
static struct strbuf time_buf = STRBUF_INIT;
Loading
Loading
Loading
Loading
@@ -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_oid(const char *refname, struct object_id *oid,
unsigned long timestamp)
timestamp_t timestamp)
{
struct object *obj;
 
Loading
Loading
@@ -418,7 +418,7 @@ static void fsck_handle_reflog_oid(const char *refname, struct object_id *oid,
}
 
static int fsck_handle_reflog_ent(struct object_id *ooid, struct object_id *noid,
const char *email, unsigned long timestamp, int tz,
const char *email, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
const char *refname = cb_data;
Loading
Loading
Loading
Loading
@@ -33,7 +33,7 @@ static int aggressive_window = 250;
static int gc_auto_threshold = 6700;
static int gc_auto_pack_limit = 50;
static int detach_auto = 1;
static unsigned long gc_log_expire_time;
static timestamp_t gc_log_expire_time;
static const char *gc_log_expire = "1.day.ago";
static const char *prune_expire = "2.weeks.ago";
static const char *prune_worktrees_expire = "3.months.ago";
Loading
Loading
Loading
Loading
@@ -911,7 +911,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),
(timestamp_t) time(NULL),
git_committer_info(IDENT_NO_NAME|IDENT_NO_DATE|IDENT_STRICT));
info->message_id = strbuf_detach(&buf, NULL);
}
Loading
Loading
Loading
Loading
@@ -132,7 +132,7 @@ static void add_one_commit(struct object_id *oid, struct rev_collect *revs)
}
 
static int collect_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
const char *ident, unsigned long timestamp,
const char *ident, timestamp_t timestamp,
int tz, const char *message, void *cbdata)
{
struct rev_collect *revs = cbdata;
Loading
Loading
Loading
Loading
@@ -10,7 +10,7 @@
 
typedef struct rev_name {
const char *tip_name;
unsigned long taggerdate;
timestamp_t taggerdate;
int generation;
int distance;
} rev_name;
Loading
Loading
@@ -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, timestamp_t taggerdate,
int generation, int distance,
int deref)
{
Loading
Loading
@@ -146,7 +146,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 = ULONG_MAX;
timestamp_t taggerdate = TIME_MAX;
 
if (data->tags_only && !starts_with(path, "refs/tags/"))
return 0;
Loading
Loading
Loading
Loading
@@ -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 timestamp_t unpack_unreachable_expiration;
static int pack_loose_unreachable;
static int local;
static int have_non_local_packs;
Loading
Loading
@@ -2675,7 +2675,7 @@ static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
static struct oid_array recent_objects;
 
static int loosened_object_can_be_discarded(const struct object_id *oid,
unsigned long mtime)
timestamp_t mtime)
{
if (!unpack_unreachable_expiration)
return 0;
Loading
Loading
Loading
Loading
@@ -13,7 +13,7 @@ static const char * const prune_usage[] = {
};
static int show_only;
static int verbose;
static unsigned long expire;
static timestamp_t expire;
static int show_progress = -1;
 
static int prune_tmp_file(const char *fullpath)
Loading
Loading
@@ -111,7 +111,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
};
char *s;
 
expire = ULONG_MAX;
expire = TIME_MAX;
save_commit_buffer = 0;
check_replace_refs = 0;
ref_paranoia = 1;
Loading
Loading
Loading
Loading
@@ -78,7 +78,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 timestamp_t nonce_stamp_slop_limit;
static struct ref_transaction *transaction;
 
static enum {
Loading
Loading
@@ -454,7 +454,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, timestamp_t stamp)
{
struct strbuf buf = STRBUF_INIT;
unsigned char sha1[20];
Loading
Loading
@@ -496,7 +496,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;
timestamp_t stamp, ostamp;
char *bohmac, *expect = NULL;
const char *retval = NONCE_BAD;
 
Loading
Loading
Loading
Loading
@@ -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 timestamp_t default_reflog_expire;
static timestamp_t default_reflog_expire_unreachable;
 
struct cmd_reflog_expire_cb {
struct rev_info revs;
int stalefix;
unsigned long expire_total;
unsigned long expire_unreachable;
timestamp_t expire_total;
timestamp_t expire_unreachable;
int recno;
};
 
Loading
Loading
@@ -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;
timestamp_t expire_limit = cb->mark_limit;
struct commit_list *leftover = NULL;
 
for (pending = cb->mark_list; pending; pending = pending->next)
Loading
Loading
@@ -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, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
Loading
Loading
@@ -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;
timestamp_t expire_total;
timestamp_t expire_unreachable;
char pattern[FLEX_ARRAY];
} *reflog_expire_cfg, **reflog_expire_cfg_tail;
 
Loading
Loading
@@ -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, timestamp_t *expire)
{
if (!value)
return config_error_nonbool(var);
Loading
Loading
@@ -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;
timestamp_t expire;
int slot;
struct reflog_expire_cfg *ent;
 
Loading
Loading
@@ -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);
timestamp_t now = time(NULL);
int i, status, do_all;
int explicit_expiry = 0;
unsigned int flags = 0;
Loading
Loading
@@ -616,7 +616,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
}
 
static int count_reflog_ent(struct object_id *ooid, struct object_id *noid,
const char *email, unsigned long timestamp, int tz,
const char *email, timestamp_t timestamp, int tz,
const char *message, void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
Loading
Loading
Loading
Loading
@@ -735,7 +735,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;
timestamp_t at;
at = approxidate(reflog_base);
read_ref_at(ref, flags, at, -1, oid.hash, NULL,
NULL, NULL, &base);
Loading
Loading
@@ -746,7 +746,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
char *logmsg;
char *nth_desc;
const char *msg;
unsigned long timestamp;
timestamp_t timestamp;
int tz;
 
if (read_ref_at(ref, flags, 0, base+i, oid.hash, &logmsg,
Loading
Loading
Loading
Loading
@@ -30,7 +30,7 @@ struct add_opts {
 
static int show_only;
static int verbose;
static unsigned long expire;
static timestamp_t expire;
 
static int prune_worktree(const char *id, struct strbuf *reason)
{
Loading
Loading
@@ -131,7 +131,7 @@ static int prune(int ac, const char **av, const char *prefix)
OPT_END()
};
 
expire = ULONG_MAX;
expire = TIME_MAX;
ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
if (ac)
usage_with_options(worktree_usage, options);
Loading
Loading
Loading
Loading
@@ -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;
timestamp_t date;
int result = 1;
 
if (revs->max_age == -1 && revs->min_age == -1)
Loading
Loading
Loading
Loading
@@ -1476,18 +1476,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(timestamp_t time, int timezone, const struct date_mode *mode);
void show_date_relative(timestamp_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, timestamp_t *timestamp, int *offset);
int parse_expiry_date(const char *date, timestamp_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);
timestamp_t approxidate_careful(const char *, int *);
timestamp_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(timestamp_t date);
 
#define IDENT_STRICT 1
#define IDENT_NO_DATE 2
Loading
Loading
Loading
Loading
@@ -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 timestamp_t parse_commit_date(const char *buf, const char *tail)
{
const char *dateptr;
 
Loading
Loading
@@ -473,8 +473,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;
timestamp_t a_date = ((const struct commit_list *)a)->item->date;
timestamp_t b_date = ((const struct commit_list *)b)->item->date;
if (a_date < b_date)
return 1;
if (a_date > b_date)
Loading
Loading
@@ -598,7 +598,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;
timestamp_t date;
 
ident_line = find_commit_header(buffer, "author", &ident_len);
if (!ident_line)
Loading
Loading
@@ -621,8 +621,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));
timestamp_t a_date = *(author_date_slab_at(author_date, a));
timestamp_t b_date = *(author_date_slab_at(author_date, b));
 
/* newer commits with larger date first */
if (a_date < b_date)
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment