mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
Merge branch 'maint'
* maint: fsck: reduce stack footprint make sure packs to be replaced are closed beforehand
This commit is contained in:
commit
de0db42278
@ -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)
|
||||
|
@ -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));
|
||||
|
1
cache.h
1
cache.h
@ -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);
|
||||
|
31
sha1_file.c
31
sha1_file.c
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user