Skip to content

Commit c74faea

Browse files
Nicolas Pitregitster
authored andcommitted
make sure packs to be replaced are closed beforehand
Especially on Windows where an opened file cannot be replaced, make sure pack-objects always close packs it is about to replace. Even on non Windows systems, this could save potential bad results if ever objects were to be read from the new pack file using offset from the old index. This should fix t5303 on Windows. Signed-off-by: Nicolas Pitre <[email protected]> Tested-by: Johannes Sixt <[email protected]> (MinGW) Signed-off-by: Junio C Hamano <[email protected]>
1 parent aa971cb commit c74faea

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

builtin-pack-objects.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ static void write_pack_file(void)
520520

521521
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
522522
base_name, sha1_to_hex(sha1));
523+
free_pack_by_name(tmpname);
523524
if (adjust_perm(pack_tmp_name, mode))
524525
die("unable to make temporary pack file readable: %s",
525526
strerror(errno));

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ extern int open_pack_index(struct packed_git *);
738738
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
739739
extern void close_pack_windows(struct packed_git *);
740740
extern void unuse_pack(struct pack_window **);
741+
extern void free_pack_by_name(const char *);
741742
extern struct packed_git *add_packed_git(const char *, int, int);
742743
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
743744
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);

sha1_file.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,37 @@ void unuse_pack(struct pack_window **w_cursor)
659659
}
660660
}
661661

662+
/*
663+
* This is used by git-repack in case a newly created pack happens to
664+
* contain the same set of objects as an existing one. In that case
665+
* the resulting file might be different even if its name would be the
666+
* same. It is best to close any reference to the old pack before it is
667+
* replaced on disk. Of course no index pointers nor windows for given pack
668+
* must subsist at this point. If ever objects from this pack are requested
669+
* again, the new version of the pack will be reinitialized through
670+
* reprepare_packed_git().
671+
*/
672+
void free_pack_by_name(const char *pack_name)
673+
{
674+
struct packed_git *p, **pp = &packed_git;
675+
676+
while (*pp) {
677+
p = *pp;
678+
if (strcmp(pack_name, p->pack_name) == 0) {
679+
close_pack_windows(p);
680+
if (p->pack_fd != -1)
681+
close(p->pack_fd);
682+
if (p->index_data)
683+
munmap((void *)p->index_data, p->index_size);
684+
free(p->bad_object_sha1);
685+
*pp = p->next;
686+
free(p);
687+
return;
688+
}
689+
pp = &p->next;
690+
}
691+
}
692+
662693
/*
663694
* Do not call this directly as this leaks p->pack_fd on error return;
664695
* call open_packed_git() instead.

0 commit comments

Comments
 (0)