Commit 3a12891f by Vicent Martí

Merge pull request #243 from jpfender/symlinks2

Symlinks NEW
parents a5aa5bd1 27a1b382
......@@ -80,37 +80,52 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path)
{
int error, fd;
int error, islnk;
int fd = 0;
char full_path[GIT_PATH_MAX];
char buffer[2048];
git_off_t size;
git_odb_stream *stream;
struct stat st;
gitfo_lstat(path, &st);
islnk = S_ISLNK(st.st_mode);
if (repo->path_workdir == NULL)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. (No working directory found)");
git__joinpath(full_path, repo->path_workdir, path);
if ((fd = gitfo_open(full_path, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path);
if (!islnk) {
if ((fd = gitfo_open(full_path, O_RDONLY)) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to create blob. Could not open '%s'", full_path);
if ((size = gitfo_size(fd)) < 0 || !git__is_sizet(size)) {
gitfo_close(fd);
return git__throw(GIT_EOSERR, "Failed to create blob. '%s' appears to be corrupted", full_path);
if ((size = gitfo_size(fd)) < 0 || !git__is_sizet(size)) {
gitfo_close(fd);
return git__throw(GIT_EOSERR, "Failed to create blob. '%s' appears to be corrupted", full_path);
}
} else {
size = st.st_size;
}
if ((error = git_odb_open_wstream(&stream, repo->db, (size_t)size, GIT_OBJ_BLOB)) < GIT_SUCCESS) {
gitfo_close(fd);
if (!islnk)
gitfo_close(fd);
return git__rethrow(error, "Failed to create blob");
}
while (size > 0) {
ssize_t read_len;
read_len = read(fd, buffer, sizeof(buffer));
if (!islnk)
read_len = read(fd, buffer, sizeof(buffer));
else
read_len = readlink(full_path, buffer, sizeof(buffer));
if (read_len < 0) {
gitfo_close(fd);
if (!islnk)
gitfo_close(fd);
stream->free(stream);
return git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
}
......@@ -121,7 +136,8 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
error = stream->finalize_write(oid, stream);
stream->free(stream);
gitfo_close(fd);
if (!islnk)
gitfo_close(fd);
if (error < GIT_SUCCESS)
return git__rethrow(error, "Failed to create blob");
......
......@@ -175,6 +175,14 @@ int gitfo_exists(const char *path)
return access(path, F_OK);
}
int gitfo_shallow_exists(const char *path)
{
assert(path);
struct stat st;
return gitfo_lstat(path, &st);
}
git_off_t gitfo_size(git_file fd)
{
struct stat sb;
......
......@@ -65,6 +65,7 @@ typedef struct { /* file io buffer */
} gitfo_buf;
extern int gitfo_exists(const char *path);
extern int gitfo_shallow_exists(const char *path);
extern int gitfo_open(const char *path, int flags);
extern int gitfo_creat(const char *path, int mode);
extern int gitfo_creat_force(const char *path, int mode);
......@@ -94,6 +95,7 @@ extern int gitfo_mv_force(const char *from, const char *to);
#define gitfo_stat(p,b) stat(p, b)
#define gitfo_fstat(f,b) fstat(f, b)
#define gitfo_lstat(p,b) lstat(p,b)
#define gitfo_unlink(p) unlink(p)
#define gitfo_rmdir(p) rmdir(p)
......
......@@ -138,6 +138,15 @@ int unmerged_cmp(const void *a, const void *b)
return strcmp(info_a->path, info_b->path);
}
unsigned int index_create_mode(unsigned int mode)
{
if (S_ISLNK(mode))
return S_IFLNK;
if (S_ISDIR(mode) || (mode & S_IFMT) == 0160000)
return 0160000;
return S_IFREG | ((mode & 0100) ? 0755 : 0644);
}
static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path)
{
git_index *index;
......@@ -402,10 +411,10 @@ static int index_init_entry(git_index_entry *entry, git_index *index, const char
git__joinpath(full_path, index->repository->path_workdir, rel_path);
if (gitfo_exists(full_path) < 0)
if (gitfo_shallow_exists(full_path) < 0)
return git__throw(GIT_ENOTFOUND, "Failed to initialize entry. %s does not exist", full_path);
if (gitfo_stat(full_path, &st) < 0)
if (gitfo_lstat(full_path, &st) < 0)
return git__throw(GIT_EOSERR, "Failed to initialize entry. %s appears to be corrupted", full_path);
if (stage < 0 || stage > 3)
......@@ -419,7 +428,7 @@ static int index_init_entry(git_index_entry *entry, git_index *index, const char
/* entry.ctime.nanoseconds = st.st_ctimensec; */
entry->dev= st.st_rdev;
entry->ino = st.st_ino;
entry->mode = st.st_mode;
entry->mode = index_create_mode(st.st_mode);
entry->uid = st.st_uid;
entry->gid = st.st_gid;
entry->file_size = st.st_size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment