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:
Junio C Hamano
2021-04-02 14:43:14 -07:00
11 changed files with 277 additions and 137 deletions

143
convert.c
View File

@@ -24,17 +24,6 @@
#define CONVERT_STAT_BITS_TXT_CRLF 0x2
#define CONVERT_STAT_BITS_BIN 0x4
enum crlf_action {
CRLF_UNDEFINED,
CRLF_BINARY,
CRLF_TEXT,
CRLF_TEXT_INPUT,
CRLF_TEXT_CRLF,
CRLF_AUTO,
CRLF_AUTO_INPUT,
CRLF_AUTO_CRLF
};
struct text_stat {
/* NUL, CR, LF and CRLF counts */
unsigned nul, lonecr, lonelf, crlf;
@@ -172,7 +161,7 @@ static int text_eol_is_crlf(void)
return 0;
}
static enum eol output_eol(enum crlf_action crlf_action)
static enum eol output_eol(enum convert_crlf_action crlf_action)
{
switch (crlf_action) {
case CRLF_BINARY:
@@ -246,7 +235,7 @@ static int has_crlf_in_index(const struct index_state *istate, const char *path)
}
static int will_convert_lf_to_crlf(struct text_stat *stats,
enum crlf_action crlf_action)
enum convert_crlf_action crlf_action)
{
if (output_eol(crlf_action) != EOL_CRLF)
return 0;
@@ -499,7 +488,7 @@ static int encode_to_worktree(const char *path, const char *src, size_t src_len,
static int crlf_to_git(const struct index_state *istate,
const char *path, const char *src, size_t len,
struct strbuf *buf,
enum crlf_action crlf_action, int conv_flags)
enum convert_crlf_action crlf_action, int conv_flags)
{
struct text_stat stats;
char *dst;
@@ -585,8 +574,8 @@ static int crlf_to_git(const struct index_state *istate,
return 1;
}
static int crlf_to_worktree(const char *src, size_t len,
struct strbuf *buf, enum crlf_action crlf_action)
static int crlf_to_worktree(const char *src, size_t len, struct strbuf *buf,
enum convert_crlf_action crlf_action)
{
char *to_free = NULL;
struct text_stat stats;
@@ -1247,7 +1236,7 @@ static const char *git_path_check_encoding(struct attr_check_item *check)
return value;
}
static enum crlf_action git_path_check_crlf(struct attr_check_item *check)
static enum convert_crlf_action git_path_check_crlf(struct attr_check_item *check)
{
const char *value = check->value;
@@ -1297,18 +1286,10 @@ static int git_path_check_ident(struct attr_check_item *check)
return !!ATTR_TRUE(value);
}
struct conv_attrs {
struct convert_driver *drv;
enum crlf_action attr_action; /* What attr says */
enum crlf_action crlf_action; /* When no attr is set, use core.autocrlf */
int ident;
const char *working_tree_encoding; /* Supported encoding or default encoding if NULL */
};
static struct attr_check *check;
static void convert_attrs(const struct index_state *istate,
struct conv_attrs *ca, const char *path)
void convert_attrs(const struct index_state *istate,
struct conv_attrs *ca, const char *path)
{
struct attr_check_item *ccheck = NULL;
@@ -1465,19 +1446,16 @@ void convert_to_git_filter_fd(const struct index_state *istate,
ident_to_git(dst->buf, dst->len, dst, ca.ident);
}
static int convert_to_working_tree_internal(const struct index_state *istate,
const char *path, const char *src,
size_t len, struct strbuf *dst,
int normalizing,
const struct checkout_metadata *meta,
struct delayed_checkout *dco)
static int convert_to_working_tree_ca_internal(const struct conv_attrs *ca,
const char *path, const char *src,
size_t len, struct strbuf *dst,
int normalizing,
const struct checkout_metadata *meta,
struct delayed_checkout *dco)
{
int ret = 0, ret_filter = 0;
struct conv_attrs ca;
convert_attrs(istate, &ca, path);
ret |= ident_to_worktree(src, len, dst, ca.ident);
ret |= ident_to_worktree(src, len, dst, ca->ident);
if (ret) {
src = dst->buf;
len = dst->len;
@@ -1487,49 +1465,56 @@ static int convert_to_working_tree_internal(const struct index_state *istate,
* is a smudge or process filter (even if the process filter doesn't
* support smudge). The filters might expect CRLFs.
*/
if ((ca.drv && (ca.drv->smudge || ca.drv->process)) || !normalizing) {
ret |= crlf_to_worktree(src, len, dst, ca.crlf_action);
if ((ca->drv && (ca->drv->smudge || ca->drv->process)) || !normalizing) {
ret |= crlf_to_worktree(src, len, dst, ca->crlf_action);
if (ret) {
src = dst->buf;
len = dst->len;
}
}
ret |= encode_to_worktree(path, src, len, dst, ca.working_tree_encoding);
ret |= encode_to_worktree(path, src, len, dst, ca->working_tree_encoding);
if (ret) {
src = dst->buf;
len = dst->len;
}
ret_filter = apply_filter(
path, src, len, -1, dst, ca.drv, CAP_SMUDGE, meta, dco);
if (!ret_filter && ca.drv && ca.drv->required)
die(_("%s: smudge filter %s failed"), path, ca.drv->name);
path, src, len, -1, dst, ca->drv, CAP_SMUDGE, meta, dco);
if (!ret_filter && ca->drv && ca->drv->required)
die(_("%s: smudge filter %s failed"), path, ca->drv->name);
return ret | ret_filter;
}
int async_convert_to_working_tree(const struct index_state *istate,
const char *path, const char *src,
size_t len, struct strbuf *dst,
const struct checkout_metadata *meta,
void *dco)
int async_convert_to_working_tree_ca(const struct conv_attrs *ca,
const char *path, const char *src,
size_t len, struct strbuf *dst,
const struct checkout_metadata *meta,
void *dco)
{
return convert_to_working_tree_internal(istate, path, src, len, dst, 0, meta, dco);
return convert_to_working_tree_ca_internal(ca, path, src, len, dst, 0,
meta, dco);
}
int convert_to_working_tree(const struct index_state *istate,
const char *path, const char *src,
size_t len, struct strbuf *dst,
const struct checkout_metadata *meta)
int convert_to_working_tree_ca(const struct conv_attrs *ca,
const char *path, const char *src,
size_t len, struct strbuf *dst,
const struct checkout_metadata *meta)
{
return convert_to_working_tree_internal(istate, path, src, len, dst, 0, meta, NULL);
return convert_to_working_tree_ca_internal(ca, path, src, len, dst, 0,
meta, NULL);
}
int renormalize_buffer(const struct index_state *istate, const char *path,
const char *src, size_t len, struct strbuf *dst)
{
int ret = convert_to_working_tree_internal(istate, path, src, len, dst, 1, NULL, NULL);
struct conv_attrs ca;
int ret;
convert_attrs(istate, &ca, path);
ret = convert_to_working_tree_ca_internal(&ca, path, src, len, dst, 1,
NULL, NULL);
if (ret) {
src = dst->buf;
len = dst->len;
@@ -1956,34 +1941,25 @@ static struct stream_filter *ident_filter(const struct object_id *oid)
}
/*
* Return an appropriately constructed filter for the path, or NULL if
* Return an appropriately constructed filter for the given ca, or NULL if
* the contents cannot be filtered without reading the whole thing
* in-core.
*
* Note that you would be crazy to set CRLF, smudge/clean or ident to a
* large binary blob you would want us not to slurp into the memory!
*/
struct stream_filter *get_stream_filter(const struct index_state *istate,
const char *path,
const struct object_id *oid)
struct stream_filter *get_stream_filter_ca(const struct conv_attrs *ca,
const struct object_id *oid)
{
struct conv_attrs ca;
struct stream_filter *filter = NULL;
convert_attrs(istate, &ca, path);
if (ca.drv && (ca.drv->process || ca.drv->smudge || ca.drv->clean))
if (classify_conv_attrs(ca) != CA_CLASS_STREAMABLE)
return NULL;
if (ca.working_tree_encoding)
return NULL;
if (ca.crlf_action == CRLF_AUTO || ca.crlf_action == CRLF_AUTO_CRLF)
return NULL;
if (ca.ident)
if (ca->ident)
filter = ident_filter(oid);
if (output_eol(ca.crlf_action) == EOL_CRLF)
if (output_eol(ca->crlf_action) == EOL_CRLF)
filter = cascade_filter(filter, lf_to_crlf_filter());
else
filter = cascade_filter(filter, &null_filter_singleton);
@@ -1991,6 +1967,15 @@ struct stream_filter *get_stream_filter(const struct index_state *istate,
return filter;
}
struct stream_filter *get_stream_filter(const struct index_state *istate,
const char *path,
const struct object_id *oid)
{
struct conv_attrs ca;
convert_attrs(istate, &ca, path);
return get_stream_filter_ca(&ca, oid);
}
void free_stream_filter(struct stream_filter *filter)
{
filter->vtbl->free(filter);
@@ -2024,3 +2009,21 @@ void clone_checkout_metadata(struct checkout_metadata *dst,
if (blob)
oidcpy(&dst->blob, blob);
}
enum conv_attrs_classification classify_conv_attrs(const struct conv_attrs *ca)
{
if (ca->drv) {
if (ca->drv->process)
return CA_CLASS_INCORE_PROCESS;
if (ca->drv->smudge || ca->drv->clean)
return CA_CLASS_INCORE_FILTER;
}
if (ca->working_tree_encoding)
return CA_CLASS_INCORE;
if (ca->crlf_action == CRLF_AUTO || ca->crlf_action == CRLF_AUTO_CRLF)
return CA_CLASS_INCORE;
return CA_CLASS_STREAMABLE;
}