Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/checkout.c17
-rw-r--r--src/index.c18
-rw-r--r--src/unix/posix.h3
-rw-r--r--src/win32/posix.h3
-rw-r--r--src/win32/posix_w32.c38
-rw-r--r--src/win32/w32_util.h10
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,