Merge branch 'maint'

* maint:
  fsck: reduce stack footprint
  make sure packs to be replaced are closed beforehand
This commit is contained in:
Junio C Hamano 2008-12-11 00:36:31 -08:00
commit de0db42278
4 changed files with 64 additions and 7 deletions

View File

@ -64,11 +64,11 @@ static int fsck_error_func(struct object *obj, int type, const char *err, ...)
return (type == FSCK_WARN) ? 0 : 1;
}
static struct object_array pending;
static int mark_object(struct object *obj, int type, void *data)
{
struct tree *tree = NULL;
struct object *parent = data;
int result;
if (!obj) {
printf("broken link from %7s %s\n",
@ -96,6 +96,20 @@ static int mark_object(struct object *obj, int type, void *data)
return 1;
}
add_object_array(obj, (void *) parent, &pending);
return 0;
}
static void mark_object_reachable(struct object *obj)
{
mark_object(obj, OBJ_ANY, 0);
}
static int traverse_one_object(struct object *obj, struct object *parent)
{
int result;
struct tree *tree = NULL;
if (obj->type == OBJ_TREE) {
obj->parsed = 0;
tree = (struct tree *)obj;
@ -107,15 +121,22 @@ static int mark_object(struct object *obj, int type, void *data)
free(tree->buffer);
tree->buffer = NULL;
}
if (result < 0)
result = 1;
return result;
}
static void mark_object_reachable(struct object *obj)
static int traverse_reachable(void)
{
mark_object(obj, OBJ_ANY, 0);
int result = 0;
while (pending.nr) {
struct object_array_entry *entry;
struct object *obj, *parent;
entry = pending.objects + --pending.nr;
obj = entry->item;
parent = (struct object *) entry->name;
result |= traverse_one_object(obj, parent);
}
return !!result;
}
static int mark_used(struct object *obj, int type, void *data)
@ -237,6 +258,9 @@ static void check_connectivity(void)
{
int i, max;
/* Traverse the pending reachable objects */
traverse_reachable();
/* Look up all the requirements, warn about missing objects.. */
max = get_max_object_index();
if (verbose)

View File

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

View File

@ -820,6 +820,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 void close_pack_windows(struct packed_git *);
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 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);

View File

@ -672,6 +672,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;
* call open_packed_git() instead.