1010#include "diff.h"
1111#include "revision.h"
1212#include "list-objects.h"
13+ #include "list-objects-filter.h"
14+ #include "list-objects-filter-options.h"
1315#include "run-command.h"
1416#include "connect.h"
1517#include "sigchain.h"
1820#include "parse-options.h"
1921#include "argv-array.h"
2022#include "prio-queue.h"
23+ #include "quote.h"
2124
2225static const char * const upload_pack_usage [] = {
2326 N_ ("git upload-pack [<options>] <dir>" ),
@@ -64,6 +67,10 @@ static int advertise_refs;
6467static int stateless_rpc ;
6568static const char * pack_objects_hook ;
6669
70+ static int filter_capability_requested ;
71+ static int filter_advertise ;
72+ static struct list_objects_filter_options filter_options ;
73+
6774static void reset_timeout (void )
6875{
6976 alarm (timeout );
@@ -131,6 +138,12 @@ static void create_pack_file(void)
131138 argv_array_push (& pack_objects .args , "--delta-base-offset" );
132139 if (use_include_tag )
133140 argv_array_push (& pack_objects .args , "--include-tag" );
141+ if (filter_options .filter_spec ) {
142+ struct strbuf buf = STRBUF_INIT ;
143+ sq_quote_buf (& buf , filter_options .filter_spec );
144+ argv_array_pushf (& pack_objects .args , "--filter=%s" , buf .buf );
145+ strbuf_release (& buf );
146+ }
134147
135148 pack_objects .in = -1 ;
136149 pack_objects .out = -1 ;
@@ -794,6 +807,12 @@ static void receive_needs(void)
794807 deepen_rev_list = 1 ;
795808 continue ;
796809 }
810+ if (skip_prefix (line , "filter " , & arg )) {
811+ if (!filter_capability_requested )
812+ die ("git upload-pack: filtering capability not negotiated" );
813+ parse_list_objects_filter (& filter_options , arg );
814+ continue ;
815+ }
797816 if (!skip_prefix (line , "want " , & arg ) ||
798817 get_oid_hex (arg , & oid_buf ))
799818 die ("git upload-pack: protocol error, "
@@ -821,6 +840,8 @@ static void receive_needs(void)
821840 no_progress = 1 ;
822841 if (parse_feature_request (features , "include-tag" ))
823842 use_include_tag = 1 ;
843+ if (parse_feature_request (features , "filter" ))
844+ filter_capability_requested = 1 ;
824845
825846 o = parse_object (& oid_buf );
826847 if (!o ) {
@@ -940,7 +961,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
940961 struct strbuf symref_info = STRBUF_INIT ;
941962
942963 format_symref_info (& symref_info , cb_data );
943- packet_write_fmt (1 , "%s %s%c%s%s%s%s%s agent=%s\n" ,
964+ packet_write_fmt (1 , "%s %s%c%s%s%s%s%s%s agent=%s\n" ,
944965 oid_to_hex (oid ), refname_nons ,
945966 0 , capabilities ,
946967 (allow_unadvertised_object_request & ALLOW_TIP_SHA1 ) ?
@@ -949,6 +970,7 @@ static int send_ref(const char *refname, const struct object_id *oid,
949970 " allow-reachable-sha1-in-want" : "" ,
950971 stateless_rpc ? " no-done" : "" ,
951972 symref_info .buf ,
973+ filter_advertise ? " filter" : "" ,
952974 git_user_agent_sanitized ());
953975 strbuf_release (& symref_info );
954976 } else {
@@ -1027,6 +1049,8 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
10271049 } else if (current_config_scope () != CONFIG_SCOPE_REPO ) {
10281050 if (!strcmp ("uploadpack.packobjectshook" , var ))
10291051 return git_config_string (& pack_objects_hook , var , value );
1052+ } else if (!strcmp ("uploadpack.allowfilter" , var )) {
1053+ filter_advertise = git_config_bool (var , value );
10301054 }
10311055 return parse_hide_refs_config (var , value , "uploadpack" );
10321056}
0 commit comments