diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/checkout.c | 17 | ||||
-rw-r--r-- | src/index.c | 18 | ||||
-rw-r--r-- | src/unix/posix.h | 3 | ||||
-rw-r--r-- | src/win32/posix.h | 3 | ||||
-rw-r--r-- | src/win32/posix_w32.c | 38 | ||||
-rw-r--r-- | src/win32/w32_util.h | 10 |
6 files changed, 86 insertions, 3 deletions
diff --git a/src/checkout.c b/src/checkout.c index cc73e483f..fd2b19a95 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -150,6 +150,15 @@ static int checkout_notify( } } +GIT_INLINE(bool) is_workdir_base_or_new( + const git_oid *workdir_id, + const git_diff_file *baseitem, + const git_diff_file *newitem) +{ + return (git_oid__cmp(&baseitem->id, workdir_id) == 0 || + git_oid__cmp(&newitem->id, workdir_id) == 0); +} + static bool checkout_is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, @@ -193,8 +202,7 @@ static bool checkout_is_workdir_modified( if (wditem->mtime.seconds == ie->mtime.seconds && wditem->mtime.nanoseconds == ie->mtime.nanoseconds && wditem->file_size == ie->file_size) - return (git_oid__cmp(&baseitem->id, &ie->id) != 0 && - git_oid_cmp(&newitem->id, &ie->id) != 0); + return !is_workdir_base_or_new(&ie->id, baseitem, newitem); } /* depending on where base is coming from, we may or may not know @@ -206,7 +214,10 @@ static bool checkout_is_workdir_modified( if (git_diff__oid_for_entry(&oid, data->diff, wditem, NULL) < 0) return false; - return (git_oid__cmp(&baseitem->id, &oid) != 0); + /* Allow the checkout if the workdir is not modified *or* if the checkout + * target's contents are already in the working directory. + */ + return !is_workdir_base_or_new(&oid, baseitem, newitem); } #define CHECKOUT_ACTION_IF(FLAG,YES,NO) \ diff --git a/src/index.c b/src/index.c index 14d8d3684..a931f048a 100644 --- a/src/index.c +++ b/src/index.c @@ -658,11 +658,29 @@ int git_index__changed_relative_to( index->stamp.ino != fs->ino); } +/* + * Force the next diff to take a look at those entries which have the + * same timestamp as the current index. + */ +static void truncate_racily_clean(git_index *index) +{ + size_t i; + git_index_entry *entry; + git_time_t ts = index->stamp.mtime; + + git_vector_foreach(&index->entries, i, entry) { + if (entry->mtime.seconds == ts || ts == 0) + entry->file_size = 0; + } +} + int git_index_write(git_index *index) { git_indexwriter writer = GIT_INDEXWRITER_INIT; int error; + truncate_racily_clean(index); + if ((error = git_indexwriter_init(&writer, index)) == 0) error = git_indexwriter_commit(&writer); diff --git a/src/unix/posix.h b/src/unix/posix.h index 8b4f427f7..425e6bb1b 100644 --- a/src/unix/posix.h +++ b/src/unix/posix.h @@ -19,6 +19,9 @@ typedef int GIT_SOCKET; #define p_lstat(p,b) lstat(p,b) #define p_stat(p,b) stat(p, b) +#define p_utimes(f, t) utimes(f, t) +#define p_futimes(f, t) futimes(f, t) + #define p_readlink(a, b, c) readlink(a, b, c) #define p_symlink(o,n) symlink(o, n) #define p_link(o,n) link(o, n) diff --git a/src/win32/posix.h b/src/win32/posix.h index bf35c8125..ac98fd864 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -20,6 +20,9 @@ typedef SOCKET GIT_SOCKET; extern int p_lstat(const char *file_name, struct stat *buf); extern int p_stat(const char* path, struct stat* buf); +extern int p_utimes(const char *filename, const struct timeval times[2]); +extern int p_futimes(int fd, const struct timeval times[2]); + extern int p_readlink(const char *path, char *buf, size_t bufsiz); extern int p_symlink(const char *old, const char *new); extern int p_link(const char *old, const char *new); diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 332ea233c..504562b0e 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -201,6 +201,44 @@ int p_lstat_posixly(const char *filename, struct stat *buf) return do_lstat(filename, buf, true); } +int p_utimes(const char *filename, const struct timeval times[2]) +{ + int fd, error; + + if ((fd = p_open(filename, O_RDWR)) < 0) + return fd; + + error = p_futimes(fd, times); + + close(fd); + return error; +} + +int p_futimes(int fd, const struct timeval times[2]) +{ + HANDLE handle; + FILETIME atime = {0}, mtime = {0}; + + if (times == NULL) { + SYSTEMTIME st; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &atime); + SystemTimeToFileTime(&st, &mtime); + } else { + git_win32__timeval_to_filetime(&atime, times[0]); + git_win32__timeval_to_filetime(&mtime, times[1]); + } + + if ((handle = (HANDLE)_get_osfhandle(fd)) == INVALID_HANDLE_VALUE) + return -1; + + if (SetFileTime(handle, NULL, &atime, &mtime) == 0) + return -1; + + return 0; +} + int p_readlink(const char *path, char *buf, size_t bufsiz) { git_win32_path path_w, target_w; diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h index 8cb0f5b94..377d651a8 100644 --- a/src/win32/w32_util.h +++ b/src/win32/w32_util.h @@ -79,6 +79,16 @@ GIT_INLINE(time_t) git_win32__filetime_to_time_t(const FILETIME *ft) return (time_t)winTime; } +GIT_INLINE(void) git_win32__timeval_to_filetime( + FILETIME *ft, const struct timeval tv) +{ + long long ticks = (tv.tv_sec * 10000000LL) + + (tv.tv_usec * 10LL) + 116444736000000000LL; + + ft->dwHighDateTime = ((ticks >> 32) & 0xffffffffLL); + ft->dwLowDateTime = (ticks & 0xffffffffLL); +} + GIT_INLINE(int) git_win32__file_attribute_to_stat( struct stat *st, const WIN32_FILE_ATTRIBUTE_DATA *attrdata, |