diff options
| author | Vicent Martà <tanoku@gmail.com> | 2011-06-07 07:07:45 -0700 |
|---|---|---|
| committer | Vicent Martà <tanoku@gmail.com> | 2011-06-07 07:07:45 -0700 |
| commit | 3a12891f53cd5c349c0eed2ace7a9a900432aa5e (patch) | |
| tree | 32bc8719c8e0c066f95672970be46469f69e2dcf /src | |
| parent | a5aa5bd1d111e7b2cd2e807664cef6f1e91718cc (diff) | |
| parent | 27a1b382c186dd4267924728344213de2a3692c3 (diff) | |
| download | libgit2-3a12891f53cd5c349c0eed2ace7a9a900432aa5e.tar.gz | |
Merge pull request #243 from jpfender/symlinks2
Symlinks NEW
Diffstat (limited to 'src')
| -rw-r--r-- | src/blob.c | 36 | ||||
| -rw-r--r-- | src/fileops.c | 8 | ||||
| -rw-r--r-- | src/fileops.h | 2 | ||||
| -rw-r--r-- | src/index.c | 15 |
4 files changed, 48 insertions, 13 deletions
diff --git a/src/blob.c b/src/blob.c index 6ab58d6b2..12f468ef7 100644 --- a/src/blob.c +++ b/src/blob.c @@ -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"); diff --git a/src/fileops.c b/src/fileops.c index 8292843d1..2e5717e9e 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -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; diff --git a/src/fileops.h b/src/fileops.h index c114508db..e20ce6f28 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -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) diff --git a/src/index.c b/src/index.c index e25c899a3..798d9e918 100644 --- a/src/index.c +++ b/src/index.c @@ -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; |
