mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-04 16:42:30 +00:00
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.
This commit is contained in:
parent
8ef4e11a76
commit
0fc8e1f6bd
@ -61,7 +61,7 @@ typedef struct git_index_entry {
|
||||
unsigned short flags;
|
||||
unsigned short flags_extended;
|
||||
|
||||
char *path;
|
||||
const char *path;
|
||||
} git_index_entry;
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
44
src/diff.c
44
src/diff.c
@ -515,39 +515,53 @@ int git_diff__oid_for_file(
|
||||
const char *path,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user