Merge branch 'mt/parallel-checkout-part-1'
Preparatory API changes for parallel checkout. * mt/parallel-checkout-part-1: entry: add checkout_entry_ca() taking preloaded conv_attrs entry: move conv_attrs lookup up to checkout_entry() entry: extract update_ce_after_write() from write_entry() entry: make fstat_output() and read_blob_entry() public entry: extract a header file for entry.c functions convert: add classification for conv_attrs struct convert: add get_stream_filter_ca() variant convert: add [async_]convert_to_working_tree_ca() variants convert: make convert_attrs() and convert structs public
This commit is contained in:
85
entry.c
85
entry.c
@ -6,6 +6,7 @@
|
||||
#include "submodule.h"
|
||||
#include "progress.h"
|
||||
#include "fsmonitor.h"
|
||||
#include "entry.h"
|
||||
|
||||
static void create_directories(const char *path, int path_len,
|
||||
const struct checkout *state)
|
||||
@ -83,7 +84,7 @@ static int create_file(const char *path, unsigned int mode)
|
||||
return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
|
||||
}
|
||||
|
||||
static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
|
||||
void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
|
||||
{
|
||||
enum object_type type;
|
||||
void *blob_data = read_object_file(&ce->oid, &type, size);
|
||||
@ -108,7 +109,7 @@ static int open_output_fd(char *path, const struct cache_entry *ce, int to_tempf
|
||||
}
|
||||
}
|
||||
|
||||
static int fstat_output(int fd, const struct checkout *state, struct stat *st)
|
||||
int fstat_checkout_output(int fd, const struct checkout *state, struct stat *st)
|
||||
{
|
||||
/* use fstat() only when path == ce->name */
|
||||
if (fstat_is_reliable() &&
|
||||
@ -131,7 +132,7 @@ static int streaming_write_entry(const struct cache_entry *ce, char *path,
|
||||
return -1;
|
||||
|
||||
result |= stream_blob_to_fd(fd, &ce->oid, filter, 1);
|
||||
*fstat_done = fstat_output(fd, state, statbuf);
|
||||
*fstat_done = fstat_checkout_output(fd, state, statbuf);
|
||||
result |= close(fd);
|
||||
|
||||
if (result)
|
||||
@ -250,8 +251,21 @@ int finish_delayed_checkout(struct checkout *state, int *nr_checkouts)
|
||||
return errs;
|
||||
}
|
||||
|
||||
static int write_entry(struct cache_entry *ce,
|
||||
char *path, const struct checkout *state, int to_tempfile)
|
||||
void update_ce_after_write(const struct checkout *state, struct cache_entry *ce,
|
||||
struct stat *st)
|
||||
{
|
||||
if (state->refresh_cache) {
|
||||
assert(state->istate);
|
||||
fill_stat_cache_info(state->istate, ce, st);
|
||||
ce->ce_flags |= CE_UPDATE_IN_BASE;
|
||||
mark_fsmonitor_invalid(state->istate, ce);
|
||||
state->istate->cache_changed |= CE_ENTRY_CHANGED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: ca is used (and required) iff the entry refers to a regular file. */
|
||||
static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca,
|
||||
const struct checkout *state, int to_tempfile)
|
||||
{
|
||||
unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
|
||||
struct delayed_checkout *dco = state->delayed_checkout;
|
||||
@ -268,8 +282,7 @@ static int write_entry(struct cache_entry *ce,
|
||||
clone_checkout_metadata(&meta, &state->meta, &ce->oid);
|
||||
|
||||
if (ce_mode_s_ifmt == S_IFREG) {
|
||||
struct stream_filter *filter = get_stream_filter(state->istate, ce->name,
|
||||
&ce->oid);
|
||||
struct stream_filter *filter = get_stream_filter_ca(ca, &ce->oid);
|
||||
if (filter &&
|
||||
!streaming_write_entry(ce, path, filter,
|
||||
state, to_tempfile,
|
||||
@ -316,14 +329,17 @@ static int write_entry(struct cache_entry *ce,
|
||||
* Convert from git internal format to working tree format
|
||||
*/
|
||||
if (dco && dco->state != CE_NO_DELAY) {
|
||||
ret = async_convert_to_working_tree(state->istate, ce->name, new_blob,
|
||||
size, &buf, &meta, dco);
|
||||
ret = async_convert_to_working_tree_ca(ca, ce->name,
|
||||
new_blob, size,
|
||||
&buf, &meta, dco);
|
||||
if (ret && string_list_has_string(&dco->paths, ce->name)) {
|
||||
free(new_blob);
|
||||
goto delayed;
|
||||
}
|
||||
} else
|
||||
ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, &meta);
|
||||
} else {
|
||||
ret = convert_to_working_tree_ca(ca, ce->name, new_blob,
|
||||
size, &buf, &meta);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
free(new_blob);
|
||||
@ -345,7 +361,7 @@ static int write_entry(struct cache_entry *ce,
|
||||
|
||||
wrote = write_in_full(fd, new_blob, size);
|
||||
if (!to_tempfile)
|
||||
fstat_done = fstat_output(fd, state, &st);
|
||||
fstat_done = fstat_checkout_output(fd, state, &st);
|
||||
close(fd);
|
||||
free(new_blob);
|
||||
if (wrote < 0)
|
||||
@ -370,15 +386,10 @@ static int write_entry(struct cache_entry *ce,
|
||||
|
||||
finish:
|
||||
if (state->refresh_cache) {
|
||||
assert(state->istate);
|
||||
if (!fstat_done)
|
||||
if (lstat(ce->name, &st) < 0)
|
||||
return error_errno("unable to stat just-written file %s",
|
||||
ce->name);
|
||||
fill_stat_cache_info(state->istate, ce, &st);
|
||||
ce->ce_flags |= CE_UPDATE_IN_BASE;
|
||||
mark_fsmonitor_invalid(state->istate, ce);
|
||||
state->istate->cache_changed |= CE_ENTRY_CHANGED;
|
||||
if (!fstat_done && lstat(ce->name, &st) < 0)
|
||||
return error_errno("unable to stat just-written file %s",
|
||||
ce->name);
|
||||
update_ce_after_write(state, ce , &st);
|
||||
}
|
||||
delayed:
|
||||
return 0;
|
||||
@ -429,19 +440,13 @@ static void mark_colliding_entries(const struct checkout *state,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the contents from ce out to the working tree.
|
||||
*
|
||||
* When topath[] is not NULL, instead of writing to the working tree
|
||||
* file named by ce, a temporary file is created by this function and
|
||||
* its name is returned in topath[], which must be able to hold at
|
||||
* least TEMPORARY_FILENAME_LENGTH bytes long.
|
||||
*/
|
||||
int checkout_entry(struct cache_entry *ce, const struct checkout *state,
|
||||
char *topath, int *nr_checkouts)
|
||||
int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
||||
const struct checkout *state, char *topath,
|
||||
int *nr_checkouts)
|
||||
{
|
||||
static struct strbuf path = STRBUF_INIT;
|
||||
struct stat st;
|
||||
struct conv_attrs ca_buf;
|
||||
|
||||
if (ce->ce_flags & CE_WT_REMOVE) {
|
||||
if (topath)
|
||||
@ -454,8 +459,13 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (topath)
|
||||
return write_entry(ce, topath, state, 1);
|
||||
if (topath) {
|
||||
if (S_ISREG(ce->ce_mode) && !ca) {
|
||||
convert_attrs(state->istate, &ca_buf, ce->name);
|
||||
ca = &ca_buf;
|
||||
}
|
||||
return write_entry(ce, topath, ca, state, 1);
|
||||
}
|
||||
|
||||
strbuf_reset(&path);
|
||||
strbuf_add(&path, state->base_dir, state->base_dir_len);
|
||||
@ -517,9 +527,16 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state,
|
||||
return 0;
|
||||
|
||||
create_directories(path.buf, path.len, state);
|
||||
|
||||
if (nr_checkouts)
|
||||
(*nr_checkouts)++;
|
||||
return write_entry(ce, path.buf, state, 0);
|
||||
|
||||
if (S_ISREG(ce->ce_mode) && !ca) {
|
||||
convert_attrs(state->istate, &ca_buf, ce->name);
|
||||
ca = &ca_buf;
|
||||
}
|
||||
|
||||
return write_entry(ce, path.buf, ca, state, 0);
|
||||
}
|
||||
|
||||
void unlink_entry(const struct cache_entry *ce)
|
||||
|
Reference in New Issue
Block a user