Skip to content

Commit 8408c1b

Browse files
committed
Merge branch 'ls/filter-process-delayed' into pu
The filter-process interface learned to allow a process with long latency give a "delayed" response. * ls/filter-process-delayed: convert: add "status=delayed" to filter process protocol convert: move multiple file filter error handling to separate function t0021: write "OUT" only on success t0021: make debug log file name configurable t0021: keep filter log files on comparison
2 parents 2ad67e7 + 4165f0f commit 8408c1b

File tree

9 files changed

+559
-145
lines changed

9 files changed

+559
-145
lines changed

Documentation/gitattributes.txt

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,8 +425,8 @@ packet: git< capability=clean
425425
packet: git< capability=smudge
426426
packet: git< 0000
427427
------------------------
428-
Supported filter capabilities in version 2 are "clean" and
429-
"smudge".
428+
Supported filter capabilities in version 2 are "clean", "smudge",
429+
and "delay".
430430

431431
Afterwards Git sends a list of "key=value" pairs terminated with
432432
a flush packet. The list will contain at least the filter command
@@ -512,12 +512,69 @@ the protocol then Git will stop the filter process and restart it
512512
with the next file that needs to be processed. Depending on the
513513
`filter.<driver>.required` flag Git will interpret that as error.
514514

515-
After the filter has processed a blob it is expected to wait for
516-
the next "key=value" list containing a command. Git will close
515+
After the filter has processed a command it is expected to wait for
516+
a "key=value" list containing the next command. Git will close
517517
the command pipe on exit. The filter is expected to detect EOF
518518
and exit gracefully on its own. Git will wait until the filter
519519
process has stopped.
520520

521+
Delay
522+
^^^^^
523+
524+
If the filter supports the "delay" capability, then Git can send the
525+
flag "can-delay" after the filter command and pathname. This flag
526+
denotes that the filter can delay filtering the current blob (e.g. to
527+
compensate network latencies) by responding with no content but with
528+
the status "delayed" and a flush packet.
529+
------------------------
530+
packet: git> command=smudge
531+
packet: git> pathname=path/testfile.dat
532+
packet: git> can-delay=1
533+
packet: git> 0000
534+
packet: git> CONTENT
535+
packet: git> 0000
536+
packet: git< status=delayed
537+
packet: git< 0000
538+
------------------------
539+
540+
If the filter supports the "delay" capability then it must support the
541+
"list_available_blobs" command. If Git sends this command, then the
542+
filter is expected to return a list of pathnames of blobs that are
543+
available. The list must be terminated with a flush packet followed
544+
by a "success" status that is also terminated with a flush packet. If
545+
no blobs for the delayed paths are available, yet, then the filter is
546+
expected to block the response until at least one blob becomes
547+
available. The filter can tell Git that it has no more delayed blobs
548+
by sending an empty list.
549+
------------------------
550+
packet: git> command=list_available_blobs
551+
packet: git> 0000
552+
packet: git< pathname=path/testfile.dat
553+
packet: git< pathname=path/otherfile.dat
554+
packet: git< 0000
555+
packet: git< status=success
556+
packet: git< 0000
557+
------------------------
558+
559+
After Git received the pathnames, it will request the corresponding
560+
blobs again. These requests contain a pathname and an empty content
561+
section. The filter is expected to respond with the smudged content
562+
in the usual way as explained above.
563+
------------------------
564+
packet: git> command=smudge
565+
packet: git> pathname=path/testfile.dat
566+
packet: git> 0000
567+
packet: git> 0000 # empty content!
568+
packet: git< status=success
569+
packet: git< 0000
570+
packet: git< SMUDGED_CONTENT
571+
packet: git< 0000
572+
packet: git< 0000 # empty list, keep "status=success" unchanged!
573+
------------------------
574+
575+
Example
576+
^^^^^^^
577+
521578
A long running filter demo implementation can be found in
522579
`contrib/long-running-filter/example.pl` located in the Git
523580
core repository. If you develop your own long running filter

builtin/checkout.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ static int checkout_paths(const struct checkout_opts *opts,
357357
state.force = 1;
358358
state.refresh_cache = 1;
359359
state.istate = &the_index;
360+
361+
enable_delayed_checkout(&state);
360362
for (pos = 0; pos < active_nr; pos++) {
361363
struct cache_entry *ce = active_cache[pos];
362364
if (ce->ce_flags & CE_MATCHED) {
@@ -371,6 +373,7 @@ static int checkout_paths(const struct checkout_opts *opts,
371373
pos = skip_same_name(ce, pos) - 1;
372374
}
373375
}
376+
errs |= finish_delayed_checkout(&state);
374377

375378
if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
376379
die(_("unable to write new index file"));

cache.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1556,16 +1556,20 @@ extern int ident_cmp(const struct ident_split *, const struct ident_split *);
15561556
struct checkout {
15571557
struct index_state *istate;
15581558
const char *base_dir;
1559+
struct delayed_checkout *delayed_checkout;
15591560
int base_dir_len;
15601561
unsigned force:1,
15611562
quiet:1,
15621563
not_new:1,
15631564
refresh_cache:1;
15641565
};
1565-
#define CHECKOUT_INIT { NULL, "" }
1566+
#define CHECKOUT_INIT { NULL, "", NULL }
1567+
15661568

15671569
#define TEMPORARY_FILENAME_LENGTH 25
15681570
extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath);
1571+
extern void enable_delayed_checkout(struct checkout *state);
1572+
extern int finish_delayed_checkout(struct checkout *state);
15691573

15701574
struct cache_def {
15711575
struct strbuf path;

0 commit comments

Comments
 (0)