Skip to content

Commit

Permalink
commit-graph: consolidate fill_commit_graph_info
Browse files Browse the repository at this point in the history
Both fill_commit_graph_info() and fill_commit_in_graph() parse
information present in commit data chunk. Let's simplify the
implementation by calling fill_commit_graph_info() within
fill_commit_in_graph().

fill_commit_graph_info() used to not load committer data from commit data
chunk. However, with the upcoming switch to using corrected committer
date as generation number v2, we will have to load committer date to
compute generation number value anyway.

e51217e (t5000: test tar files that overflow ustar headers,
30-06-2016) introduced a test 'generate tar with future mtime' that
creates a commit with committer date of (2^36 + 1) seconds since
EPOCH. The CDAT chunk provides 34-bits for storing committer date, thus
committer time overflows into generation number (within CDAT chunk) and
has undefined behavior.

The test used to pass as fill_commit_graph_info() would not set struct
member `date` of struct commit and load committer date from the object
database, generating a tar file with the expected mtime.

However, with corrected commit date, we will load the committer date
from CDAT chunk (truncated to lower 34-bits to populate the generation
number. Thus, Git sets date and generates tar file with the truncated
mtime.

The ustar format (the header format used by most modern tar programs)
only has room for 11 (or 12, depending on some implementations) octal
digits for the size and mtime of each file.

As the CDAT chunk is overflow by 12-octal digits but not 11-octal
digits, we split the existing tests to test both implementations
separately and add a new explicit test for 11-digit implementation.

To test the 11-octal digit implementation, we create a future commit
with committer date of 2^34 - 1, which overflows 11-octal digits without
overflowing 34-bits of the Commit Date chunks.

To test the 12-octal digit implementation, the smallest committer date
possible is 2^36 + 1, which overflows the CDAT chunk and thus
commit-graph must be disabled for the test.

Signed-off-by: Abhishek Kumar <abhishekkumar8222@gmail.com>
Reviewed-by: Taylor Blau <me@ttaylorr.com>
Reviewed-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
abhishekkumar2718 authored and gitster committed Jan 19, 2021
1 parent 2f9bbb6 commit f90fca6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
27 changes: 10 additions & 17 deletions commit-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,15 +753,24 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g,
const unsigned char *commit_data;
struct commit_graph_data *graph_data;
uint32_t lex_index;
uint64_t date_high, date_low;

while (pos < g->num_commits_in_base)
g = g->base_graph;

if (pos >= g->num_commits + g->num_commits_in_base)
die(_("invalid commit position. commit-graph is likely corrupt"));

lex_index = pos - g->num_commits_in_base;
commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * lex_index;

graph_data = commit_graph_data_at(item);
graph_data->graph_pos = pos;

date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
date_low = get_be32(commit_data + g->hash_len + 12);
item->date = (timestamp_t)((date_high << 32) | date_low);

graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;
}

Expand All @@ -776,38 +785,22 @@ static int fill_commit_in_graph(struct repository *r,
{
uint32_t edge_value;
uint32_t *parent_data_ptr;
uint64_t date_low, date_high;
struct commit_list **pptr;
struct commit_graph_data *graph_data;
const unsigned char *commit_data;
uint32_t lex_index;

while (pos < g->num_commits_in_base)
g = g->base_graph;

if (pos >= g->num_commits + g->num_commits_in_base)
die(_("invalid commit position. commit-graph is likely corrupt"));
fill_commit_graph_info(item, g, pos);

/*
* Store the "full" position, but then use the
* "local" position for the rest of the calculation.
*/
graph_data = commit_graph_data_at(item);
graph_data->graph_pos = pos;
lex_index = pos - g->num_commits_in_base;

commit_data = g->chunk_commit_data + (g->hash_len + 16) * lex_index;

item->object.parsed = 1;

set_commit_tree(item, NULL);

date_high = get_be32(commit_data + g->hash_len + 8) & 0x3;
date_low = get_be32(commit_data + g->hash_len + 12);
item->date = (timestamp_t)((date_high << 32) | date_low);

graph_data->generation = get_be32(commit_data + g->hash_len + 8) >> 2;

pptr = &item->parents;

edge_value = get_be32(commit_data + g->hash_len);
Expand Down
24 changes: 21 additions & 3 deletions t/t5000-tar-tree.sh
Original file line number Diff line number Diff line change
Expand Up @@ -431,15 +431,33 @@ test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
test_cmp expect actual
'

test_expect_success TIME_IS_64BIT 'set up repository with far-future commit' '
test_expect_success TIME_IS_64BIT 'set up repository with far-future (2^34 - 1) commit' '
rm -f .git/index &&
echo foo >file &&
git add file &&
GIT_COMMITTER_DATE="@17179869183 +0000" \
git commit -m "tempori parendum"
'

test_expect_success TIME_IS_64BIT 'generate tar with far-future mtime' '
git archive HEAD >future.tar
'

test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' '
echo 2514 >expect &&
tar_info future.tar | cut -d" " -f2 >actual &&
test_cmp expect actual
'

test_expect_success TIME_IS_64BIT 'set up repository with far-far-future (2^36 + 1) commit' '
rm -f .git/index &&
echo content >file &&
git add file &&
GIT_COMMITTER_DATE="@68719476737 +0000" \
GIT_TEST_COMMIT_GRAPH=0 GIT_COMMITTER_DATE="@68719476737 +0000" \
git commit -m "tempori parendum"
'

test_expect_success TIME_IS_64BIT 'generate tar with future mtime' '
test_expect_success TIME_IS_64BIT 'generate tar with far-far-future mtime' '
git archive HEAD >future.tar
'

Expand Down

0 comments on commit f90fca6

Please sign in to comment.