]>
Commit | Line | Data |
---|---|---|
25ec7bca JH |
1 | #include "cache.h" |
2 | #include "commit.h" | |
3 | #include "config.h" | |
4 | #include "revision.h" | |
5 | #include "argv-array.h" | |
6 | #include "list-objects.h" | |
7 | #include "list-objects-filter.h" | |
8 | #include "list-objects-filter-options.h" | |
9 | ||
10 | /* | |
1dde5fa2 | 11 | * Parse value of the argument to the "filter" keyword. |
25ec7bca JH |
12 | * On the command line this looks like: |
13 | * --filter=<arg> | |
14 | * and in the pack protocol as: | |
15 | * "filter" SP <arg> | |
16 | * | |
17 | * The filter keyword will be used by many commands. | |
18 | * See Documentation/rev-list-options.txt for allowed values for <arg>. | |
19 | * | |
20 | * Capture the given arg as the "filter_spec". This can be forwarded to | |
87c2d9d3 JS |
21 | * subordinate commands when necessary (although it's better to pass it through |
22 | * expand_list_objects_filter_spec() first). We also "intern" the arg for the | |
23 | * convenience of the current command. | |
25ec7bca | 24 | */ |
1e1e39b3 JH |
25 | static int gently_parse_list_objects_filter( |
26 | struct list_objects_filter_options *filter_options, | |
27 | const char *arg, | |
28 | struct strbuf *errbuf) | |
25ec7bca JH |
29 | { |
30 | const char *v0; | |
31 | ||
1e1e39b3 JH |
32 | if (filter_options->choice) { |
33 | if (errbuf) { | |
1e1e39b3 JH |
34 | strbuf_addstr( |
35 | errbuf, | |
36 | _("multiple filter-specs cannot be combined")); | |
37 | } | |
38 | return 1; | |
39 | } | |
25ec7bca JH |
40 | |
41 | filter_options->filter_spec = strdup(arg); | |
42 | ||
43 | if (!strcmp(arg, "blob:none")) { | |
44 | filter_options->choice = LOFC_BLOB_NONE; | |
45 | return 0; | |
25ec7bca | 46 | |
1e1e39b3 JH |
47 | } else if (skip_prefix(arg, "blob:limit=", &v0)) { |
48 | if (git_parse_ulong(v0, &filter_options->blob_limit_value)) { | |
49 | filter_options->choice = LOFC_BLOB_LIMIT; | |
50 | return 0; | |
51 | } | |
25ec7bca | 52 | |
bc5975d2 | 53 | } else if (skip_prefix(arg, "tree:", &v0)) { |
c813a7c3 | 54 | if (!git_parse_ulong(v0, &filter_options->tree_exclude_depth)) { |
bc5975d2 MD |
55 | if (errbuf) { |
56 | strbuf_addstr( | |
57 | errbuf, | |
c813a7c3 | 58 | _("expected 'tree:<depth>'")); |
bc5975d2 MD |
59 | } |
60 | return 1; | |
61 | } | |
c813a7c3 | 62 | filter_options->choice = LOFC_TREE_DEPTH; |
bc5975d2 MD |
63 | return 0; |
64 | ||
1e1e39b3 | 65 | } else if (skip_prefix(arg, "sparse:oid=", &v0)) { |
25ec7bca JH |
66 | struct object_context oc; |
67 | struct object_id sparse_oid; | |
68 | ||
69 | /* | |
70 | * Try to parse <oid-expression> into an OID for the current | |
71 | * command, but DO NOT complain if we don't have the blob or | |
72 | * ref locally. | |
73 | */ | |
3a7a698e | 74 | if (!get_oid_with_context(the_repository, v0, GET_OID_BLOB, |
25ec7bca JH |
75 | &sparse_oid, &oc)) |
76 | filter_options->sparse_oid_value = oiddup(&sparse_oid); | |
77 | filter_options->choice = LOFC_SPARSE_OID; | |
78 | return 0; | |
25ec7bca | 79 | |
1e1e39b3 | 80 | } else if (skip_prefix(arg, "sparse:path=", &v0)) { |
e693237e CC |
81 | if (errbuf) { |
82 | strbuf_addstr( | |
83 | errbuf, | |
84 | _("sparse:path filters support has been dropped")); | |
85 | } | |
86 | return 1; | |
25ec7bca | 87 | } |
5a59a230 NTND |
88 | /* |
89 | * Please update _git_fetch() in git-completion.bash when you | |
90 | * add new filters | |
91 | */ | |
25ec7bca | 92 | |
cc0b05a4 | 93 | if (errbuf) |
5c03bc8b | 94 | strbuf_addf(errbuf, _("invalid filter-spec '%s'"), arg); |
cc0b05a4 | 95 | |
1e1e39b3 JH |
96 | memset(filter_options, 0, sizeof(*filter_options)); |
97 | return 1; | |
98 | } | |
99 | ||
100 | int parse_list_objects_filter(struct list_objects_filter_options *filter_options, | |
101 | const char *arg) | |
102 | { | |
103 | struct strbuf buf = STRBUF_INIT; | |
104 | if (gently_parse_list_objects_filter(filter_options, arg, &buf)) | |
105 | die("%s", buf.buf); | |
25ec7bca JH |
106 | return 0; |
107 | } | |
108 | ||
109 | int opt_parse_list_objects_filter(const struct option *opt, | |
110 | const char *arg, int unset) | |
111 | { | |
112 | struct list_objects_filter_options *filter_options = opt->value; | |
113 | ||
4875c979 | 114 | if (unset || !arg) { |
aa57b871 | 115 | list_objects_filter_set_no_filter(filter_options); |
4875c979 JH |
116 | return 0; |
117 | } | |
25ec7bca JH |
118 | |
119 | return parse_list_objects_filter(filter_options, arg); | |
120 | } | |
4875c979 | 121 | |
87c2d9d3 JS |
122 | void expand_list_objects_filter_spec( |
123 | const struct list_objects_filter_options *filter, | |
124 | struct strbuf *expanded_spec) | |
125 | { | |
126 | strbuf_init(expanded_spec, strlen(filter->filter_spec)); | |
127 | if (filter->choice == LOFC_BLOB_LIMIT) | |
128 | strbuf_addf(expanded_spec, "blob:limit=%lu", | |
129 | filter->blob_limit_value); | |
130 | else if (filter->choice == LOFC_TREE_DEPTH) | |
131 | strbuf_addf(expanded_spec, "tree:%lu", | |
132 | filter->tree_exclude_depth); | |
133 | else | |
134 | strbuf_addstr(expanded_spec, filter->filter_spec); | |
135 | } | |
136 | ||
4875c979 JH |
137 | void list_objects_filter_release( |
138 | struct list_objects_filter_options *filter_options) | |
139 | { | |
140 | free(filter_options->filter_spec); | |
141 | free(filter_options->sparse_oid_value); | |
4875c979 JH |
142 | memset(filter_options, 0, sizeof(*filter_options)); |
143 | } | |
1e1e39b3 JH |
144 | |
145 | void partial_clone_register( | |
146 | const char *remote, | |
147 | const struct list_objects_filter_options *filter_options) | |
148 | { | |
149 | /* | |
150 | * Record the name of the partial clone remote in the | |
151 | * config and in the global variable -- the latter is | |
152 | * used throughout to indicate that partial clone is | |
153 | * enabled and to expect missing objects. | |
154 | */ | |
155 | if (repository_format_partial_clone && | |
156 | *repository_format_partial_clone && | |
157 | strcmp(remote, repository_format_partial_clone)) | |
158 | die(_("cannot change partial clone promisor remote")); | |
159 | ||
160 | git_config_set("core.repositoryformatversion", "1"); | |
161 | git_config_set("extensions.partialclone", remote); | |
162 | ||
163 | repository_format_partial_clone = xstrdup(remote); | |
164 | ||
165 | /* | |
166 | * Record the initial filter-spec in the config as | |
167 | * the default for subsequent fetches from this remote. | |
168 | */ | |
169 | core_partial_clone_filter_default = | |
170 | xstrdup(filter_options->filter_spec); | |
171 | git_config_set("core.partialclonefilter", | |
172 | core_partial_clone_filter_default); | |
173 | } | |
174 | ||
175 | void partial_clone_get_default_filter_spec( | |
176 | struct list_objects_filter_options *filter_options) | |
177 | { | |
178 | /* | |
179 | * Parse default value, but silently ignore it if it is invalid. | |
180 | */ | |
cac1137d JT |
181 | if (!core_partial_clone_filter_default) |
182 | return; | |
1e1e39b3 JH |
183 | gently_parse_list_objects_filter(filter_options, |
184 | core_partial_clone_filter_default, | |
185 | NULL); | |
186 | } |