summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2014-04-28 14:34:55 -0700
committerRussell Belfer <rb@github.com>2014-04-28 14:50:49 -0700
commitb4ed1614b2e6ae934c18d1f25f5c3569ea0dc8e5 (patch)
treea1f51570b31509dffdcb786565596a611480fb2f
parente94d166e79a1cffb8e7616ecc8abcb1fab2c6950 (diff)
downloadlibgit2-b4ed1614b2e6ae934c18d1f25f5c3569ea0dc8e5.tar.gz
Lay groundwork for updating stat cache in diff
This reorganized the diff OID calculation to make it easier to correctly update the stat cache during a diff once the flags to do so are enabled. This includes marking the path of a git_index_entry as const so we can make a "fake" git_index_entry with a "const char *" path and not get warnings. I was a little surprised at how unobtrusive this change was, but I think it's probably a good thing.
-rw-r--r--include/git2/index.h2
-rw-r--r--src/checkout.c3
-rw-r--r--src/diff.c44
-rw-r--r--src/diff.h4
-rw-r--r--src/index.c6
5 files changed, 37 insertions, 22 deletions
diff --git a/include/git2/index.h b/include/git2/index.h
index 05e58a632..cdb87282c 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -61,7 +61,7 @@ typedef struct git_index_entry {
unsigned short flags;
unsigned short flags_extended;
- char *path;
+ const char *path;
} git_index_entry;
/**
diff --git a/src/checkout.c b/src/checkout.c
index 93d6bc9c5..d94cb0c7d 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -184,8 +184,7 @@ static bool checkout_is_workdir_modified(
if (baseitem->size && wditem->file_size != baseitem->size)
return true;
- if (git_diff__oid_for_file(
- &oid, data->diff, wditem->path, wditem->mode, wditem->file_size) < 0)
+ if (git_diff__oid_for_entry(&oid, data->diff, wditem) < 0)
return false;
return (git_oid__cmp(&baseitem->id, &oid) != 0);
diff --git a/src/diff.c b/src/diff.c
index 4c028ca4e..eae4543fc 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -516,38 +516,52 @@ int git_diff__oid_for_file(
uint16_t mode,
git_off_t size)
{
+ git_index_entry entry;
+
+ memset(&entry, 0, sizeof(entry));
+ entry.mode = mode;
+ entry.file_size = size;
+ entry.path = (char *)path;
+
+ return git_diff__oid_for_entry(out, diff, &entry);
+}
+
+int git_diff__oid_for_entry(
+ git_oid *out, git_diff *diff, const git_index_entry *src)
+{
int error = 0;
git_buf full_path = GIT_BUF_INIT;
+ git_index_entry entry = *src;
git_filter_list *fl = NULL;
memset(out, 0, sizeof(*out));
if (git_buf_joinpath(
- &full_path, git_repository_workdir(diff->repo), path) < 0)
+ &full_path, git_repository_workdir(diff->repo), entry.path) < 0)
return -1;
- if (!mode) {
+ if (!entry.mode) {
struct stat st;
GIT_PERF_INC(diff->stat_calls);
if (p_stat(full_path.ptr, &st) < 0) {
- error = git_path_set_error(errno, path, "stat");
+ error = git_path_set_error(errno, entry.path, "stat");
git_buf_free(&full_path);
return error;
}
- mode = st.st_mode;
- size = st.st_size;
+ git_index_entry__init_from_stat(
+ &entry, &st, (diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) != 0);
}
/* calculate OID for file if possible */
- if (S_ISGITLINK(mode)) {
+ if (S_ISGITLINK(entry.mode)) {
git_submodule *sm;
GIT_PERF_INC(diff->submodule_lookups);
- if (!git_submodule_lookup(&sm, diff->repo, path)) {
+ if (!git_submodule_lookup(&sm, diff->repo, entry.path)) {
const git_oid *sm_oid = git_submodule_wd_id(sm);
if (sm_oid)
git_oid_cpy(out, sm_oid);
@@ -558,14 +572,15 @@ int git_diff__oid_for_file(
*/
giterr_clear();
}
- } else if (S_ISLNK(mode)) {
+ } else if (S_ISLNK(entry.mode)) {
GIT_PERF_INC(diff->oid_calculations);
error = git_odb__hashlink(out, full_path.ptr);
- } else if (!git__is_sizet(size)) {
- giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'", path);
+ } else if (!git__is_sizet(entry.file_size)) {
+ giterr_set(GITERR_OS, "File size overflow (for 32-bits) on '%s'",
+ entry.path);
error = -1;
} else if (!(error = git_filter_list_load(
- &fl, diff->repo, NULL, path, GIT_FILTER_TO_ODB)))
+ &fl, diff->repo, NULL, entry.path, GIT_FILTER_TO_ODB)))
{
int fd = git_futils_open_ro(full_path.ptr);
if (fd < 0)
@@ -573,13 +588,15 @@ int git_diff__oid_for_file(
else {
GIT_PERF_INC(diff->oid_calculations);
error = git_odb__hashfd_filtered(
- out, fd, (size_t)size, GIT_OBJ_BLOB, fl);
+ out, fd, (size_t)entry.file_size, GIT_OBJ_BLOB, fl);
p_close(fd);
}
git_filter_list_free(fl);
}
+ /* TODO: update index for entry if requested */
+
git_buf_free(&full_path);
return error;
}
@@ -759,8 +776,7 @@ static int maybe_modified(
*/
if (modified_uncertain && git_oid_iszero(&nitem->id)) {
if (git_oid_iszero(&noid)) {
- if ((error = git_diff__oid_for_file(&noid,
- diff, nitem->path, nitem->mode, nitem->file_size)) < 0)
+ if ((error = git_diff__oid_for_entry(&noid, diff, nitem)) < 0)
return error;
}
diff --git a/src/diff.h b/src/diff.h
index 491fc4667..8fa3c9b7b 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -95,7 +95,9 @@ extern int git_diff_delta__format_file_header(
int oid_strlen);
extern int git_diff__oid_for_file(
- git_oid *oit, git_diff *, const char *, uint16_t, git_off_t);
+ git_oid *out, git_diff *, const char *, uint16_t, git_off_t);
+extern int git_diff__oid_for_entry(
+ git_oid *out, git_diff *, const git_index_entry *entry);
extern int git_diff__from_iterators(
git_diff **diff_ptr,
diff --git a/src/index.c b/src/index.c
index c044af402..8a7f29279 100644
--- a/src/index.c
+++ b/src/index.c
@@ -842,7 +842,7 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
static void index_entry_cpy(git_index_entry *tgt, const git_index_entry *src)
{
- char *tgt_path = tgt->path;
+ const char *tgt_path = tgt->path;
memcpy(tgt, src, sizeof(*tgt));
tgt->path = tgt_path; /* reset to existing path data */
}
@@ -2282,9 +2282,7 @@ static int read_tree_cb(
entry->mode == old_entry->mode &&
git_oid_equal(&entry->id, &old_entry->id))
{
- char *oldpath = entry->path;
- memcpy(entry, old_entry, sizeof(*entry));
- entry->path = oldpath;
+ index_entry_cpy(entry, old_entry);
entry->flags_extended = 0;
}