Skip to content

Commit 0016024

Browse files
peffgitster
authored andcommitted
git-config: always treat --int as 64-bit internally
When you run "git config --int", the maximum size of integer you get depends on how git was compiled, and what it considers to be an "int". This is almost useful, because your scripts calling "git config" will behave similarly to git internally. But relying on this is dubious; you have to actually know how git treats each value internally (e.g., int versus unsigned long), which is not documented and is subject to change. And even if you know it is "unsigned long", we do not have a git-config option to match that behavior. Furthermore, you may simply be asking git to store a value on your behalf (e.g., configuration for a hook). In that case, the relevant range check has nothing at all to do with git, but rather with whatever scripting tools you are using (and git has no way of knowing what the appropriate range is there). Not only is the range check useless, but it is actively harmful, as there is no way at all for scripts to look at config variables with large values. For instance, one cannot reliably get the value of pack.packSizeLimit via git-config. On an LP64 system, git happily uses a 64-bit "unsigned long" internally to represent the value, but the script cannot read any value over 2G. Ideally, the "--int" option would simply represent an arbitrarily large integer. For practical purposes, however, a 64-bit integer is large enough, and is much easier to implement (and if somebody overflows it, we will still notice the problem, and not simply return garbage). Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2f66658 commit 0016024

File tree

4 files changed

+29
-3
lines changed

4 files changed

+29
-3
lines changed

builtin/config.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ static int collect_config(const char *key_, const char *value_, void *cb)
128128
must_print_delim = 1;
129129
}
130130
if (types == TYPE_INT)
131-
sprintf(value, "%d", git_config_int(key_, value_?value_:""));
131+
sprintf(value, "%"PRId64,
132+
git_config_int64(key_, value_ ? value_ : ""));
132133
else if (types == TYPE_BOOL)
133134
vptr = git_config_bool(key_, value_) ? "true" : "false";
134135
else if (types == TYPE_BOOL_OR_INT) {
@@ -265,8 +266,8 @@ static char *normalize_value(const char *key, const char *value)
265266
else {
266267
normalized = xmalloc(64);
267268
if (types == TYPE_INT) {
268-
int v = git_config_int(key, value);
269-
sprintf(normalized, "%d", v);
269+
int64_t v = git_config_int64(key, value);
270+
sprintf(normalized, "%"PRId64, v);
270271
}
271272
else if (types == TYPE_BOOL)
272273
sprintf(normalized, "%s",

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,7 @@ extern int git_config_with_options(config_fn_t fn, void *,
11901190
extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
11911191
extern int git_parse_ulong(const char *, unsigned long *);
11921192
extern int git_config_int(const char *, const char *);
1193+
extern int64_t git_config_int64(const char *, const char *);
11931194
extern unsigned long git_config_ulong(const char *, const char *);
11941195
extern int git_config_bool_or_int(const char *, const char *, int *);
11951196
extern int git_config_bool(const char *, const char *);

config.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,15 @@ static int git_parse_int(const char *value, int *ret)
534534
return 1;
535535
}
536536

537+
static int git_parse_int64(const char *value, int64_t *ret)
538+
{
539+
intmax_t tmp;
540+
if (!git_parse_signed(value, &tmp, maximum_signed_value_of_type(int64_t)))
541+
return 0;
542+
*ret = tmp;
543+
return 1;
544+
}
545+
537546
int git_parse_ulong(const char *value, unsigned long *ret)
538547
{
539548
uintmax_t tmp;
@@ -565,6 +574,14 @@ int git_config_int(const char *name, const char *value)
565574
return ret;
566575
}
567576

577+
int64_t git_config_int64(const char *name, const char *value)
578+
{
579+
int64_t ret;
580+
if (!git_parse_int64(value, &ret))
581+
die_bad_number(name, value);
582+
return ret;
583+
}
584+
568585
unsigned long git_config_ulong(const char *name, const char *value)
569586
{
570587
unsigned long ret;

t/t1300-repo-config.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,13 @@ test_expect_success numbers '
652652
test_cmp expect actual
653653
'
654654

655+
test_expect_success '--int is at least 64 bits' '
656+
git config giga.watts 121g &&
657+
echo 129922760704 >expect &&
658+
git config --int --get giga.watts >actual &&
659+
test_cmp expect actual
660+
'
661+
655662
test_expect_success 'invalid unit' '
656663
git config aninvalid.unit "1auto" &&
657664
echo 1auto >expect &&

0 commit comments

Comments
 (0)