diff --git a/include/git2/blob.h b/include/git2/blob.h index e366ce880..1cfff841d 100644 --- a/include/git2/blob.h +++ b/include/git2/blob.h @@ -119,7 +119,7 @@ GIT_EXTERN(int) git_blob_rawsize(git_blob *blob); * relative to the repository's working dir * @return 0 on success; error code otherwise */ -GIT_EXTERN(int) git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path); +GIT_EXTERN(int) git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path, struct stat st); /** diff --git a/src/blob.c b/src/blob.c index 6ab58d6b2..b00fc25af 100644 --- a/src/blob.c +++ b/src/blob.c @@ -78,39 +78,51 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b return GIT_SUCCESS; } -int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path) +int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *path, struct stat st) { - 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; + 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 +133,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"); diff --git a/src/index.c b/src/index.c index e25c899a3..6aefe4432 100644 --- a/src/index.c +++ b/src/index.c @@ -425,7 +425,7 @@ static int index_init_entry(git_index_entry *entry, git_index *index, const char entry->file_size = st.st_size; /* write the blob to disk and get the oid */ - if ((error = git_blob_create_fromfile(&entry->oid, index->repository, rel_path)) < GIT_SUCCESS) + if ((error = git_blob_create_fromfile(&entry->oid, index->repository, rel_path, st)) < GIT_SUCCESS) return git__rethrow(error, "Failed to initialize index entry"); entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT);