git-convert-cache: fix up mode conversion
The old mode conversion was not only complex, it also refused to change the length of a mode, which made it fragile. By moving the mode conversion around a bit, we can not only simplify it, it also ends up being more powerful. Also fix a memory leak that made it impossible to convert huge archives without tons and tons of memory. Signed-off-by: Linus Torvalds <torvalds@osdl.org>maint
parent
de2eb7f694
commit
4e81304afc
|
@ -60,11 +60,21 @@ static void convert_ascii_sha1(void *buffer)
|
||||||
struct entry *entry;
|
struct entry *entry;
|
||||||
|
|
||||||
if (get_sha1_hex(buffer, sha1))
|
if (get_sha1_hex(buffer, sha1))
|
||||||
die("bad sha1");
|
die("expected sha1, got '%s'", buffer);
|
||||||
entry = convert_entry(sha1);
|
entry = convert_entry(sha1);
|
||||||
memcpy(buffer, sha1_to_hex(entry->new_sha1), 40);
|
memcpy(buffer, sha1_to_hex(entry->new_sha1), 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int convert_mode(unsigned int mode)
|
||||||
|
{
|
||||||
|
unsigned int newmode;
|
||||||
|
|
||||||
|
newmode = mode & S_IFMT;
|
||||||
|
if (S_ISREG(mode))
|
||||||
|
newmode |= (mode & 0100) ? 0755 : 0644;
|
||||||
|
return newmode;
|
||||||
|
}
|
||||||
|
|
||||||
static int write_subdirectory(void *buffer, unsigned long size, const char *base, int baselen, unsigned char *result_sha1)
|
static int write_subdirectory(void *buffer, unsigned long size, const char *base, int baselen, unsigned char *result_sha1)
|
||||||
{
|
{
|
||||||
char *new = xmalloc(size);
|
char *new = xmalloc(size);
|
||||||
|
@ -81,6 +91,7 @@ static int write_subdirectory(void *buffer, unsigned long size, const char *base
|
||||||
|
|
||||||
if (!path || sscanf(buffer, "%o", &mode) != 1)
|
if (!path || sscanf(buffer, "%o", &mode) != 1)
|
||||||
die("bad tree conversion");
|
die("bad tree conversion");
|
||||||
|
mode = convert_mode(mode);
|
||||||
path++;
|
path++;
|
||||||
if (memcmp(path, base, baselen))
|
if (memcmp(path, base, baselen))
|
||||||
break;
|
break;
|
||||||
|
@ -116,34 +127,6 @@ static int write_subdirectory(void *buffer, unsigned long size, const char *base
|
||||||
return used;
|
return used;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int convert_mode(char *buffer)
|
|
||||||
{
|
|
||||||
char *end;
|
|
||||||
unsigned short mode = strtoul(buffer, &end, 8);
|
|
||||||
unsigned short newmode;
|
|
||||||
char num[10];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (*end != ' ')
|
|
||||||
die("corrupt tree object");
|
|
||||||
switch (mode) {
|
|
||||||
case S_IFREG | 0644:
|
|
||||||
case S_IFREG | 0755:
|
|
||||||
case S_IFLNK:
|
|
||||||
case S_IFDIR:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
newmode = 0;
|
|
||||||
if (S_ISREG(mode))
|
|
||||||
newmode = (mode & 0100) ? 0755 : 0644;
|
|
||||||
newmode |= mode & S_IFMT;
|
|
||||||
len = sprintf(num, "%o", newmode);
|
|
||||||
if (len != end - buffer)
|
|
||||||
return error("unable to convert tree entry mode %o to %o", mode, newmode);
|
|
||||||
memcpy(buffer, num, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void convert_tree(void *buffer, unsigned long size, unsigned char *result_sha1)
|
static void convert_tree(void *buffer, unsigned long size, unsigned char *result_sha1)
|
||||||
{
|
{
|
||||||
void *orig_buffer = buffer;
|
void *orig_buffer = buffer;
|
||||||
|
@ -152,7 +135,6 @@ static void convert_tree(void *buffer, unsigned long size, unsigned char *result
|
||||||
while (size) {
|
while (size) {
|
||||||
int len = 1+strlen(buffer);
|
int len = 1+strlen(buffer);
|
||||||
|
|
||||||
convert_mode(buffer);
|
|
||||||
convert_binary_sha1(buffer + len);
|
convert_binary_sha1(buffer + len);
|
||||||
|
|
||||||
len += 20;
|
len += 20;
|
||||||
|
@ -289,6 +271,8 @@ static void convert_commit(void *buffer, unsigned long size, unsigned char *resu
|
||||||
void *orig_buffer = buffer;
|
void *orig_buffer = buffer;
|
||||||
unsigned long orig_size = size;
|
unsigned long orig_size = size;
|
||||||
|
|
||||||
|
if (memcmp(buffer, "tree ", 5))
|
||||||
|
die("Bad commit '%s'", buffer);
|
||||||
convert_ascii_sha1(buffer+5);
|
convert_ascii_sha1(buffer+5);
|
||||||
buffer += 46; /* "tree " + "hex sha1" + "\n" */
|
buffer += 46; /* "tree " + "hex sha1" + "\n" */
|
||||||
while (!memcmp(buffer, "parent ", 7)) {
|
while (!memcmp(buffer, "parent ", 7)) {
|
||||||
|
@ -324,6 +308,7 @@ static struct entry * convert_entry(unsigned char *sha1)
|
||||||
die("unknown object type '%s' in %s", type, sha1_to_hex(sha1));
|
die("unknown object type '%s' in %s", type, sha1_to_hex(sha1));
|
||||||
entry->converted = 1;
|
entry->converted = 1;
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
free(data);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue