Commit c3da9f062d8c202b2a66b289b3570ac9fe6fc02d

Carlos Martín Nieto 2011-07-21T22:55:20

Add git_futils_readbuffer_updated This extends the git_fuitls_readbuffer function to only read in if the file's modification date is later than the given one. Some code paths want to check a file's modification date in order to decide whether they should read it or not. If they do want to read it, another stat call is done by futils. This function combines these two operations so we avoid one stat call each time we read a new or updated file. The git_futils_readbuffer functions is now a wrapper around the new function. Signed-off-by: Carlos Martín Nieto <cmn@elego.de>

diff --git a/src/fileops.c b/src/fileops.c
index 2d1915a..c7fddc6 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -141,23 +141,40 @@ git_off_t git_futils_filesize(git_file fd)
 	return sb.st_size;
 }
 
-int git_futils_readbuffer(git_fbuffer *obj, const char *path)
+int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mtime, int *updated)
 {
 	git_file fd;
 	size_t len;
-	git_off_t size;
+	struct stat st;
 	unsigned char *buff;
 
 	assert(obj && path && *path);
 
-	if ((fd = p_open(path, O_RDONLY)) < 0)
-		return git__throw(GIT_ERROR, "Failed to open %s for reading", path);
+	if (updated != NULL)
+		*updated = 0;
 
-	if (((size = git_futils_filesize(fd)) < 0) || !git__is_sizet(size+1)) {
-		p_close(fd);
+	if (p_stat(path, &st) < 0)
+		return git__throw(GIT_ENOTFOUND, "Failed to stat file %s", path);
+
+	if (S_ISDIR(st.st_mode))
+		return git__throw(GIT_ERROR, "Can't read a dir into a buffer");
+
+	/*
+	 * If we were given a time, we only want to read the file if it
+	 * has been modified.
+	 */
+	if (mtime != NULL && *mtime >= st.st_mtime)
+		return GIT_SUCCESS;
+
+	if (mtime != NULL)
+		*mtime = st.st_mtime;
+	if (!git__is_sizet(st.st_size+1))
 		return git__throw(GIT_ERROR, "Failed to read file `%s`. An error occured while calculating its size", path);
-	}
-	len = (size_t) size;
+
+	len = (size_t) st.st_size;
+
+	if ((fd = p_open(path, O_RDONLY)) < 0)
+		return git__throw(GIT_EOSERR, "Failed to open %s for reading", path);
 
 	if ((buff = git__malloc(len + 1)) == NULL) {
 		p_close(fd);
@@ -173,12 +190,22 @@ int git_futils_readbuffer(git_fbuffer *obj, const char *path)
 
 	p_close(fd);
 
+	if (mtime != NULL)
+		*mtime = st.st_mtime;
+	if (updated != NULL)
+		*updated = 1;
+
 	obj->data = buff;
 	obj->len  = len;
 
 	return GIT_SUCCESS;
 }
 
+int git_futils_readbuffer(git_fbuffer *obj, const char *path)
+{
+	return git_futils_readbuffer_updated(obj, path, NULL, NULL);
+}
+
 void git_futils_freebuffer(git_fbuffer *obj)
 {
 	assert(obj);
diff --git a/src/fileops.h b/src/fileops.h
index f1c169c..84c35e4 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -25,6 +25,7 @@ typedef struct {  /* file io buffer  */
 } git_fbuffer;
 
 extern int git_futils_readbuffer(git_fbuffer *obj, const char *path);
+extern int git_futils_readbuffer_updated(git_fbuffer *obj, const char *path, time_t *mtime, int *updated);
 extern void git_futils_freebuffer(git_fbuffer *obj);
 
 /**