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 <nico@cam.org>
Tested-by: Johannes Sixt <j6t@kdbg.org> (MinGW)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Nicolas Pitre 2008-12-09 14:26:52 -05:00 committed by Junio C Hamano
parent aa971cb9bf
commit c74faea19e
3 changed files with 33 additions and 0 deletions

View File

@ -520,6 +520,7 @@ static void write_pack_file(void)
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack", snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
base_name, sha1_to_hex(sha1)); base_name, sha1_to_hex(sha1));
free_pack_by_name(tmpname);
if (adjust_perm(pack_tmp_name, mode)) if (adjust_perm(pack_tmp_name, mode))
die("unable to make temporary pack file readable: %s", die("unable to make temporary pack file readable: %s",
strerror(errno)); strerror(errno));

View File

@ -738,6 +738,7 @@ extern int open_pack_index(struct packed_git *);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *); extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
extern void close_pack_windows(struct packed_git *); extern void close_pack_windows(struct packed_git *);
extern void unuse_pack(struct pack_window **); extern void unuse_pack(struct pack_window **);
extern void free_pack_by_name(const char *);
extern struct packed_git *add_packed_git(const char *, int, int); extern struct packed_git *add_packed_git(const char *, int, int);
extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t); extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t); extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);

View File

@ -659,6 +659,37 @@ void unuse_pack(struct pack_window **w_cursor)
} }
} }
/*
* This is used by git-repack in case a newly created pack happens to
* contain the same set of objects as an existing one. In that case
* the resulting file might be different even if its name would be the
* same. It is best to close any reference to the old pack before it is
* replaced on disk. Of course no index pointers nor windows for given pack
* must subsist at this point. If ever objects from this pack are requested
* again, the new version of the pack will be reinitialized through
* reprepare_packed_git().
*/
void free_pack_by_name(const char *pack_name)
{
struct packed_git *p, **pp = &packed_git;
while (*pp) {
p = *pp;
if (strcmp(pack_name, p->pack_name) == 0) {
close_pack_windows(p);
if (p->pack_fd != -1)
close(p->pack_fd);
if (p->index_data)
munmap((void *)p->index_data, p->index_size);
free(p->bad_object_sha1);
*pp = p->next;
free(p);
return;
}
pp = &p->next;
}
}
/* /*
* Do not call this directly as this leaks p->pack_fd on error return; * Do not call this directly as this leaks p->pack_fd on error return;
* call open_packed_git() instead. * call open_packed_git() instead.