496
497
#define CAP_CLEAN (1u<<0)
498
#define CAP_SMUDGE (1u<<1)
499
+#define CAP_DELAY (1u<<2)
500
501
struct cmd2process {
502
struct subprocess_entry subprocess; /* must be the first member! */
522
} known_caps[] = {
523
{ "clean", CAP_CLEAN },
524
{ "smudge", CAP_SMUDGE },
525
+ { "delay", CAP_DELAY },
526
};
527
528
sigchain_push(SIGPIPE, SIG_IGN);
607
608
static int apply_multi_file_filter(const char *path, const char *src, size_t len,
609
int fd, struct strbuf *dst, const char *cmd,
608
- const unsigned int wanted_capability)
610
+ const unsigned int wanted_capability,
611
+ struct delayed_checkout *dco)
612
{
613
int err;
614
+ int can_delay = 0;
615
struct cmd2process *entry;
616
struct child_process *process;
617
struct strbuf nbuf = STRBUF_INIT;
666
if (err)
667
goto done;
668
669
+ if ((entry->supported_capabilities & CAP_DELAY) &&
670
+ dco && dco->state == CE_CAN_DELAY) {
671
+ can_delay = 1;
672
+ err = packet_write_fmt_gently(process->in, "can-delay=1\n");
673
+ if (err)
674
+ goto done;
675
+ }
676
+
677
err = packet_flush_gently(process->in);
678
if (err)
679
goto done;
689
if (err)
690
goto done;
691
680
- err = strcmp(filter_status.buf, "success");
692
+ if (can_delay && !strcmp(filter_status.buf, "delayed")) {
693
+ string_list_insert(&dco->filters, cmd);
694
+ string_list_insert(&dco->paths, path);
695
+ } else {
696
+ /* The filter got the blob and wants to send us a response. */
697
+ err = strcmp(filter_status.buf, "success");
698
+ if (err)
699
+ goto done;
700
+
701
+ err = read_packetized_to_strbuf(process->out, &nbuf) < 0;
702
+ if (err)
703
+ goto done;
704
+
705
+ err = subprocess_read_status(process->out, &filter_status);
706
+ if (err)
707
+ goto done;
708
+
709
+ err = strcmp(filter_status.buf, "success");
710
+ }
711
+
712
+done:
713
+ sigchain_pop(SIGPIPE);
714
+
715
+ if (err)
716
+ handle_filter_error(&filter_status, entry, wanted_capability);
717
+ else
718
+ strbuf_swap(dst, &nbuf);
719
+ strbuf_release(&nbuf);
720
+ return !err;
721
+}
722
+
723
+
724
+int async_query_available_blobs(const char *cmd, struct string_list *available_paths)
725
+{
726
+ int err;
727
+ char *line;
728
+ struct cmd2process *entry;
729
+ struct child_process *process;
730
+ struct strbuf filter_status = STRBUF_INIT;
731
+
732
+ assert(subprocess_map_initialized);
733
+ entry = (struct cmd2process *)subprocess_find_entry(&subprocess_map, cmd);
734
+ if (!entry) {
735
+ error("external filter '%s' is not available anymore although "
736
+ "not all paths have been filtered", cmd);
737
+ return 0;
738
+ }
739
+ process = &entry->subprocess.process;
740
+ sigchain_push(SIGPIPE, SIG_IGN);
741
+
742
+ err = packet_write_fmt_gently(
743
+ process->in, "command=list_available_blobs\n");
744
if (err)
745
goto done;
746
684
- err = read_packetized_to_strbuf(process->out, &nbuf) < 0;
747
+ err = packet_flush_gently(process->in);
748
if (err)
749
goto done;
750
751
+ while ((line = packet_read_line(process->out, NULL))) {
752
+ const char *path;
753
+ if (skip_prefix(line, "pathname=", &path))
754
+ string_list_insert(available_paths, xstrdup(path));
755
+ else
756
+ ; /* ignore unknown keys */
757
+ }
758
+
759
err = subprocess_read_status(process->out, &filter_status);
760
if (err)
761
goto done;
766
sigchain_pop(SIGPIPE);
767
768
if (err)
698
- handle_filter_error(&filter_status, entry, wanted_capability);
699
- else
700
- strbuf_swap(dst, &nbuf);
701
- strbuf_release(&nbuf);
769
+ handle_filter_error(&filter_status, entry, 0);
770
return !err;
771
}
772
781
782
static int apply_filter(const char *path, const char *src, size_t len,
783
int fd, struct strbuf *dst, struct convert_driver *drv,
716
- const unsigned int wanted_capability)
784
+ const unsigned int wanted_capability,
785
+ struct delayed_checkout *dco)
786
{
787
const char *cmd = NULL;
788
800
if (cmd && *cmd)
801
return apply_single_file_filter(path, src, len, fd, dst, cmd);
802
else if (drv->process && *drv->process)
734
- return apply_multi_file_filter(path, src, len, fd, dst, drv->process, wanted_capability);
803
+ return apply_multi_file_filter(path, src, len, fd, dst,
804
+ drv->process, wanted_capability, dco);
805
806
return 0;
807
}
1142
if (!ca.drv->required)
1143
return 0;
1144
1075
- return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN);
1145
+ return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN, NULL);
1146
}
1147
1148
const char *get_convert_attr_ascii(const char *path)
1179
1180
convert_attrs(&ca, path);
1181
1112
- ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN);
1182
+ ret |= apply_filter(path, src, len, -1, dst, ca.drv, CAP_CLEAN, NULL);
1183
if (!ret && ca.drv && ca.drv->required)
1184
die("%s: clean filter '%s' failed", path, ca.drv->name);
1185
1204
assert(ca.drv);
1205
assert(ca.drv->clean || ca.drv->process);
1206
1137
- if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN))
1207
+ if (!apply_filter(path, NULL, 0, fd, dst, ca.drv, CAP_CLEAN, NULL))
1208
die("%s: clean filter '%s' failed", path, ca.drv->name);
1209
1210
crlf_to_git(path, dst->buf, dst->len, dst, ca.crlf_action, checksafe);
1213
1214
static int convert_to_working_tree_internal(const char *path, const char *src,
1215
size_t len, struct strbuf *dst,
1146
- int normalizing)
1216
+ int normalizing, struct delayed_checkout *dco)
1217
{
1218
int ret = 0, ret_filter = 0;
1219
struct conv_attrs ca;
1238
}
1239
}
1240
1171
- ret_filter = apply_filter(path, src, len, -1, dst, ca.drv, CAP_SMUDGE);
1241
+ ret_filter = apply_filter(
1242
+ path, src, len, -1, dst, ca.drv, CAP_SMUDGE, dco);
1243
if (!ret_filter && ca.drv && ca.drv->required)
1244
die("%s: smudge filter %s failed", path, ca.drv->name);
1245
1246
return ret | ret_filter;
1247
}
1248
1249
+int async_convert_to_working_tree(const char *path, const char *src,
1250
+ size_t len, struct strbuf *dst,
1251
+ void *dco)
1252
+{
1253
+ return convert_to_working_tree_internal(path, src, len, dst, 0, dco);
1254
+}
1255
+
1256
int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
1257
{
1180
- return convert_to_working_tree_internal(path, src, len, dst, 0);
1258
+ return convert_to_working_tree_internal(path, src, len, dst, 0, NULL);
1259
}
1260
1261
int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst)
1262
{
1185
- int ret = convert_to_working_tree_internal(path, src, len, dst, 1);
1263
+ int ret = convert_to_working_tree_internal(path, src, len, dst, 1, NULL);
1264
if (ret) {
1265
src = dst->buf;
1266
len = dst->len;