* This handles basic git sha1 object files - packing, unpacking,
* creation etc.
*/
-#include <sys/types.h>
-#include <dirent.h>
#include "cache.h"
#include "delta.h"
#include "pack.h"
int safe_create_leading_directories(char *path)
{
char *pos = path;
+ struct stat st;
+
if (*pos == '/')
pos++;
if (!pos)
break;
*pos = 0;
- if (mkdir(path, 0777) < 0) {
- if (errno != EEXIST) {
+ if (!stat(path, &st)) {
+ /* path exists */
+ if (!S_ISDIR(st.st_mode)) {
*pos = '/';
- return -1;
+ return -3;
}
}
+ else if (mkdir(path, 0777)) {
+ *pos = '/';
+ return -1;
+ }
else if (adjust_shared_perm(path)) {
*pos = '/';
return -2;
for ( ; cp < ep && *cp != sep; cp++)
;
if (last != cp) {
+ struct stat st;
struct alternate_object_database *alt;
/* 43 = 40-byte + 2 '/' + terminating NUL */
int pfxlen = cp - last;
}
else
memcpy(ent->base, last, pfxlen);
+
ent->name = ent->base + pfxlen + 1;
- ent->base[pfxlen] = ent->base[pfxlen + 3] = '/';
- ent->base[entlen-1] = 0;
+ ent->base[pfxlen + 3] = '/';
+ ent->base[pfxlen] = ent->base[entlen-1] = 0;
+
+ /* Detect cases where alternate disappeared */
+ if (stat(ent->base, &st) || !S_ISDIR(st.st_mode)) {
+ error("object directory %s does not exist; "
+ "check .git/objects/info/alternates.",
+ ent->base);
+ goto bad;
+ }
+ ent->base[pfxlen] = '/';
/* Prevent the common mistake of listing the same
* thing twice, or object directory itself.
sprintf(path, "%s/pack", objdir);
len = strlen(path);
dir = opendir(path);
- if (!dir)
+ if (!dir) {
+ if (errno != ENOENT)
+ error("unable to open object pack directory: %s: %s",
+ path, strerror(errno));
return;
+ }
path[len++] = '/';
while ((de = readdir(dir)) != NULL) {
int namelen = strlen(de->d_name);
* the result size.
*/
data = delta_head;
- get_delta_hdr_size(&data); /* ignore base size */
+
+ /* ignore base size */
+ get_delta_hdr_size(&data, delta_head+sizeof(delta_head));
/* Read the result size */
- result_size = get_delta_hdr_size(&data);
+ result_size = get_delta_hdr_size(&data, delta_head+sizeof(delta_head));
*sizep = result_size;
}
return 0;
return offset;
}
+int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
+ unsigned char *base, unsigned long *sizep,
+ enum object_type *kindp)
+{
+ unsigned long ptr;
+ int status = -1;
+
+ use_packed_git(p);
+ ptr = offset;
+ ptr = unpack_object_header(p, ptr, kindp, sizep);
+ if (*kindp != OBJ_DELTA)
+ goto done;
+ memcpy(base, p->pack_base + ptr, 20);
+ status = 0;
+ done:
+ unuse_packed_git(p);
+ return status;
+}
+
void packed_object_info_detail(struct pack_entry *e,
char *type,
unsigned long *size,
local = mkstemp(tmpfile);
if (local < 0)
- return error("Couldn't open %s for %s\n", tmpfile, sha1_to_hex(sha1));
+ return error("Couldn't open %s for %s",
+ tmpfile, sha1_to_hex(sha1));
memset(&stream, 0, sizeof(stream));
}
if (memcmp(sha1, real_sha1, 20)) {
unlink(tmpfile);
- return error("File %s has bad hash\n", sha1_to_hex(sha1));
+ return error("File %s has bad hash", sha1_to_hex(sha1));
}
return move_temp_to_file(tmpfile, sha1_file_name(sha1));