@matheusbsbs / matheus-bagliano / commits / ab90ecae99
Fork 0

convert: permit passing additional metadata to filter processes

There are a variety of situations where a filter process can make use of some additional metadata. For example, some people find the ident filter too limiting and would like to include the commit or the branch in their smudged files. This information isn't available during checkout as HEAD hasn't been updated at that point, and it wouldn't be available in archives either. Let's add a way to pass this metadata down to the filter. We pass the blob we're operating on, the treeish (preferring the commit over the tree if one exists), and the ref we're operating on. Note that we won't pass this information in all cases, such as when renormalizing or when we're performing diffs, since it doesn't make sense in those cases. The data we currently get from the filter process looks like the following: command=smudge pathname=git.c 0000 With this change, we'll get data more like this: command=smudge pathname=git.c refname=refs/tags/v2.25.1 treeish=c522f061d551c9bb8684a7c3859b2ece4499b56b blob=7be7ad34bd053884ec48923706e70c81719a8660 0000 There are a couple things to note about this approach. For operations like checkout, treeish will always be a commit, since we cannot check out individual trees, but for other operations, like archive, we can end up operating on only a particular tree, so we'll provide only a tree as the treeish. Similar comments apply for refname, since there are a variety of cases in which we won't have a ref. This commit wires up the code to print this information, but doesn't pass any of it at this point. In a future commit, we'll have various code paths pass the actual useful data down. Signed-off-by: brian m. carlson <bk2204@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Mar 16, 2020 at 18:05 UTC ab90ecae992e44e3e8303f143ad858608acabcf5
8 files changed +51 -19
apply.c
+1 -1
@@ -4349,7 +4349,7 @@ static int try_create_file(struct apply_state *state, const char *path,
4349 if (fd < 0)
4350 return 1;
4351
4352 - if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf)) {
4352 + if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf, NULL)) {
4353 size = nbuf.len;
4354 buf = nbuf.buf;
4355 }
archive.c
+1 -1
@@ -85,7 +85,7 @@ void *object_file_to_archive(const struct archiver_args *args,
85 size_t size = 0;
86
87 strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
88 - convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf);
88 + convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf, NULL);
89 if (commit)
90 format_subst(commit, buf.buf, buf.len, &buf);
91 buffer = strbuf_detach(&buf, &size);
builtin/cat-file.c
+1 -1
@@ -42,7 +42,7 @@ static int filter_object(const char *path, unsigned mode,
42 oid_to_hex(oid), path);
43 if ((type == OBJ_BLOB) && S_ISREG(mode)) {
44 struct strbuf strbuf = STRBUF_INIT;
45 - if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf)) {
45 + if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, NULL)) {
46 free(*buf);
47 *size = strbuf.len;
48 *buf = strbuf_detach(&strbuf, NULL);
convert.c
+34 -10
@@ -797,6 +797,7 @@ static void handle_filter_error(const struct strbuf *filter_status,
797 static int apply_multi_file_filter(const char *path, const char *src, size_t len,
798 int fd, struct strbuf *dst, const char *cmd,
799 const unsigned int wanted_capability,
800 + const struct checkout_metadata *meta,
801 struct delayed_checkout *dco)
802 {
803 int err;
@@ -855,6 +856,24 @@ static int apply_multi_file_filter(const char *path, const char *src, size_t len
856 if (err)
857 goto done;
858
859 + if (meta && meta->refname) {
860 + err = packet_write_fmt_gently(process->in, "ref=%s\n", meta->refname);
861 + if (err)
862 + goto done;
863 + }
864 +
865 + if (meta && !is_null_oid(&meta->treeish)) {
866 + err = packet_write_fmt_gently(process->in, "treeish=%s\n", oid_to_hex(&meta->treeish));
867 + if (err)
868 + goto done;
869 + }
870 +
871 + if (meta && !is_null_oid(&meta->blob)) {
872 + err = packet_write_fmt_gently(process->in, "blob=%s\n", oid_to_hex(&meta->blob));
873 + if (err)
874 + goto done;
875 + }
876 +
877 if ((entry->supported_capabilities & CAP_DELAY) &&
878 dco && dco->state == CE_CAN_DELAY) {
879 can_delay = 1;
@@ -971,6 +990,7 @@ static struct convert_driver {
990 static int apply_filter(const char *path, const char *src, size_t len,
991 int fd, struct strbuf *dst, struct convert_driver *drv,
992 const unsigned int wanted_capability,
993 + const struct checkout_metadata *meta,
994 struct delayed_checkout *dco)
995 {
996 const char *cmd = NULL;
@@ -990,7 +1010,7 @@ static int apply_filter(const char *path, const char *src, size_t len,
1010 return apply_single_file_filter(path, src, len, fd, dst, cmd);
1011 else if (drv->process && *drv->process)
1012 return apply_multi_file_filter(path, src, len, fd, dst,
993 - drv->process, wanted_capability, dco);
1013 + drv->process, wanted_capability, meta, dco);
1014
1015 return 0;
1016 }
@@ -1368,7 +1388,7 @@ int would_convert_to_git_filter_fd(const struct index_state *istate, const char
1388 if (!ca.drv->required)
1389 return 0;
1390
1371 - return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN, NULL);
1391 + return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN, NULL, NULL);
1392 }
1393
1394 const char *get_convert_attr_ascii(const struct index_state *istate, const char *path)
@@ -1406,7 +1426,7 @@ int convert_to_git(const struct index_state *istate,
1426
1427 convert_attrs(istate, &ca, path);
1428
1409 - ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN, NULL);
1429 + ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN, NULL, NULL);
1430 if (!ret && ca.drv && ca.drv->required)
1431 die(_("%s: clean filter '%s' failed"), path, ca.drv->name);
1432
@@ -1441,7 +1461,7 @@ void convert_to_git_filter_fd(const struct index_state *istate,
1461 assert(ca.drv);
1462 assert(ca.drv->clean || ca.drv->process);
1463
1444 - if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN, NULL))
1464 + if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN, NULL, NULL))
1465 die(_("%s: clean filter '%s' failed"), path, ca.drv->name);
1466
1467 encode_to_git(path, dst->buf, dst->len, dst, ca.working_tree_encoding, conv_flags);
@@ -1452,7 +1472,9 @@ void convert_to_git_filter_fd(const struct index_state *istate,
1472 static int convert_to_working_tree_internal(const struct index_state *istate,
1473 const char *path, const char *src,
1474 size_t len, struct strbuf *dst,
1455 - int normalizing, struct delayed_checkout *dco)
1475 + int normalizing,
1476 + const struct checkout_metadata *meta,
1477 + struct delayed_checkout *dco)
1478 {
1479 int ret = 0, ret_filter = 0;
1480 struct conv_attrs ca;
@@ -1484,7 +1506,7 @@ static int convert_to_working_tree_internal(const struct index_state *istate,
1506 }
1507
1508 ret_filter = apply_filter(
1487 - path, src, len, -1, dst, ca.drv, CAP_SMUDGE, dco);
1509 + path, src, len, -1, dst, ca.drv, CAP_SMUDGE, meta, dco);
1510 if (!ret_filter && ca.drv && ca.drv->required)
1511 die(_("%s: smudge filter %s failed"), path, ca.drv->name);
1512
@@ -1494,22 +1516,24 @@ static int convert_to_working_tree_internal(const struct index_state *istate,
1516 int async_convert_to_working_tree(const struct index_state *istate,
1517 const char *path, const char *src,
1518 size_t len, struct strbuf *dst,
1519 + const struct checkout_metadata *meta,
1520 void *dco)
1521 {
1499 - return convert_to_working_tree_internal(istate, path, src, len, dst, 0, dco);
1522 + return convert_to_working_tree_internal(istate, path, src, len, dst, 0, meta, dco);
1523 }
1524
1525 int convert_to_working_tree(const struct index_state *istate,
1526 const char *path, const char *src,
1504 - size_t len, struct strbuf *dst)
1527 + size_t len, struct strbuf *dst,
1528 + const struct checkout_metadata *meta)
1529 {
1506 - return convert_to_working_tree_internal(istate, path, src, len, dst, 0, NULL);
1530 + return convert_to_working_tree_internal(istate, path, src, len, dst, 0, meta, NULL);
1531 }
1532
1533 int renormalize_buffer(const struct index_state *istate, const char *path,
1534 const char *src, size_t len, struct strbuf *dst)
1535 {
1512 - int ret = convert_to_working_tree_internal(istate, path, src, len, dst, 1, NULL);
1536 + int ret = convert_to_working_tree_internal(istate, path, src, len, dst, 1, NULL, NULL);
1537 if (ret) {
1538 src = dst->buf;
1539 len = dst->len;
convert.h
+10 -2
@@ -4,10 +4,10 @@
4 #ifndef CONVERT_H
5 #define CONVERT_H
6
7 +#include "hash.h"
8 #include "string-list.h"
9
10 struct index_state;
10 -struct object_id;
11 struct strbuf;
12
13 #define CONV_EOL_RNDTRP_DIE (1<<0) /* Die if CRLF to LF to CRLF is different */
@@ -57,6 +57,12 @@ struct delayed_checkout {
57 struct string_list paths;
58 };
59
60 +struct checkout_metadata {
61 + const char *refname;
62 + struct object_id treeish;
63 + struct object_id blob;
64 +};
65 +
66 extern enum eol core_eol;
67 extern char *check_roundtrip_encoding;
68 const char *get_cached_convert_stats_ascii(const struct index_state *istate,
@@ -71,10 +77,12 @@ int convert_to_git(const struct index_state *istate,
77 struct strbuf *dst, int conv_flags);
78 int convert_to_working_tree(const struct index_state *istate,
79 const char *path, const char *src,
74 - size_t len, struct strbuf *dst);
80 + size_t len, struct strbuf *dst,
81 + const struct checkout_metadata *meta);
82 int async_convert_to_working_tree(const struct index_state *istate,
83 const char *path, const char *src,
84 size_t len, struct strbuf *dst,
85 + const struct checkout_metadata *meta,
86 void *dco);
87 int async_query_available_blobs(const char *cmd,
88 struct string_list *available_paths);
diff.c
+1 -1
@@ -4071,7 +4071,7 @@ static void prep_temp_blob(struct index_state *istate,
4071 if (!temp->tempfile)
4072 die_errno("unable to create temp-file");
4073 if (convert_to_working_tree(istate, path,
4074 - (const char *)blob, (size_t)size, &buf)) {
4074 + (const char *)blob, (size_t)size, &buf, NULL)) {
4075 blob = buf.buf;
4076 size = buf.len;
4077 }
entry.c
+2 -2
@@ -315,13 +315,13 @@ static int write_entry(struct cache_entry *ce,
315 */
316 if (dco && dco->state != CE_NO_DELAY) {
317 ret = async_convert_to_working_tree(state->istate, ce->name, new_blob,
318 - size, &buf, dco);
318 + size, &buf, NULL, dco);
319 if (ret && string_list_has_string(&dco->paths, ce->name)) {
320 free(new_blob);
321 goto delayed;
322 }
323 } else
324 - ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf);
324 + ret = convert_to_working_tree(state->istate, ce->name, new_blob, size, &buf, NULL);
325
326 if (ret) {
327 free(new_blob);
merge-recursive.c
+1 -1
@@ -958,7 +958,7 @@ static int update_file_flags(struct merge_options *opt,
958 if (S_ISREG(contents->mode)) {
959 struct strbuf strbuf = STRBUF_INIT;
960 if (convert_to_working_tree(opt->repo->index,
961 - path, buf, size, &strbuf)) {
961 + path, buf, size, &strbuf, NULL)) {
962 free(buf);
963 size = strbuf.len;
964 buf = strbuf_detach(&strbuf, NULL);