1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.transport;
11
12 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_DEEPEN_RELATIVE;
13 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER;
14 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;
15 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_INCLUDE_TAG;
16 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
17 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
18 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SERVER_OPTION;
19 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDEBAND_ALL;
20 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
21 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
22 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WANT_REF;
23
24 import java.io.IOException;
25 import java.text.MessageFormat;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.function.Consumer;
29
30 import org.eclipse.jgit.errors.PackProtocolException;
31 import org.eclipse.jgit.internal.JGitText;
32 import org.eclipse.jgit.lib.ObjectId;
33
34
35
36
37
38
39
40
41 final class ProtocolV2Parser {
42
43 private final TransferConfig transferConfig;
44
45 ProtocolV2Parser(TransferConfig transferConfig) {
46 this.transferConfig = transferConfig;
47 }
48
49
50
51
52
53
54
55 private static String consumeCapabilities(PacketLineIn pckIn,
56 Consumer<String> serverOptionConsumer,
57 Consumer<String> agentConsumer) throws IOException {
58
59 String serverOptionPrefix = OPTION_SERVER_OPTION + '=';
60 String agentPrefix = OPTION_AGENT + '=';
61
62 String line = pckIn.readString();
63 while (!PacketLineIn.isDelimiter(line) && !PacketLineIn.isEnd(line)) {
64 if (line.startsWith(serverOptionPrefix)) {
65 serverOptionConsumer
66 .accept(line.substring(serverOptionPrefix.length()));
67 } else if (line.startsWith(agentPrefix)) {
68 agentConsumer.accept(line.substring(agentPrefix.length()));
69 } else {
70
71 }
72 line = pckIn.readString();
73 }
74
75 return line;
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 FetchV2Request parseFetchRequest(PacketLineIn pckIn)
93 throws PackProtocolException, IOException {
94 FetchV2Request.Builder reqBuilder = FetchV2Request.builder();
95
96
97
98 reqBuilder.addClientCapability(OPTION_SIDE_BAND_64K);
99
100 String line = consumeCapabilities(pckIn,
101 serverOption -> reqBuilder.addServerOption(serverOption),
102 agent -> reqBuilder.setAgent(agent));
103
104 if (PacketLineIn.isEnd(line)) {
105 return reqBuilder.build();
106 }
107
108 if (!PacketLineIn.isDelimiter(line)) {
109 throw new PackProtocolException(
110 MessageFormat.format(JGitText.get().unexpectedPacketLine,
111 line));
112 }
113
114 boolean filterReceived = false;
115 for (String line2 : pckIn.readStrings()) {
116 if (line2.startsWith("want ")) {
117 reqBuilder.addWantId(ObjectId.fromString(line2.substring(5)));
118 } else if (transferConfig.isAllowRefInWant()
119 && line2.startsWith(OPTION_WANT_REF + " ")) {
120 reqBuilder.addWantedRef(
121 line2.substring(OPTION_WANT_REF.length() + 1));
122 } else if (line2.startsWith("have ")) {
123 reqBuilder.addPeerHas(ObjectId.fromString(line2.substring(5)));
124 } else if (line2.equals("done")) {
125 reqBuilder.setDoneReceived();
126 } else if (line2.equals(OPTION_THIN_PACK)) {
127 reqBuilder.addClientCapability(OPTION_THIN_PACK);
128 } else if (line2.equals(OPTION_NO_PROGRESS)) {
129 reqBuilder.addClientCapability(OPTION_NO_PROGRESS);
130 } else if (line2.equals(OPTION_INCLUDE_TAG)) {
131 reqBuilder.addClientCapability(OPTION_INCLUDE_TAG);
132 } else if (line2.equals(OPTION_OFS_DELTA)) {
133 reqBuilder.addClientCapability(OPTION_OFS_DELTA);
134 } else if (line2.startsWith("shallow ")) {
135 reqBuilder.addClientShallowCommit(
136 ObjectId.fromString(line2.substring(8)));
137 } else if (line2.startsWith("deepen ")) {
138 int parsedDepth = Integer.parseInt(line2.substring(7));
139 if (parsedDepth <= 0) {
140 throw new PackProtocolException(
141 MessageFormat.format(JGitText.get().invalidDepth,
142 Integer.valueOf(parsedDepth)));
143 }
144 if (reqBuilder.getDeepenSince() != 0) {
145 throw new PackProtocolException(
146 JGitText.get().deepenSinceWithDeepen);
147 }
148 if (reqBuilder.hasDeepenNotRefs()) {
149 throw new PackProtocolException(
150 JGitText.get().deepenNotWithDeepen);
151 }
152 reqBuilder.setDepth(parsedDepth);
153 } else if (line2.startsWith("deepen-not ")) {
154 reqBuilder.addDeepenNotRef(line2.substring(11));
155 if (reqBuilder.getDepth() != 0) {
156 throw new PackProtocolException(
157 JGitText.get().deepenNotWithDeepen);
158 }
159 } else if (line2.equals(OPTION_DEEPEN_RELATIVE)) {
160 reqBuilder.addClientCapability(OPTION_DEEPEN_RELATIVE);
161 } else if (line2.startsWith("deepen-since ")) {
162 int ts = Integer.parseInt(line2.substring(13));
163 if (ts <= 0) {
164 throw new PackProtocolException(MessageFormat
165 .format(JGitText.get().invalidTimestamp, line2));
166 }
167 if (reqBuilder.getDepth() != 0) {
168 throw new PackProtocolException(
169 JGitText.get().deepenSinceWithDeepen);
170 }
171 reqBuilder.setDeepenSince(ts);
172 } else if (transferConfig.isAllowFilter()
173 && line2.startsWith(OPTION_FILTER + ' ')) {
174 if (filterReceived) {
175 throw new PackProtocolException(
176 JGitText.get().tooManyFilters);
177 }
178 filterReceived = true;
179 reqBuilder.setFilterSpec(FilterSpec.fromFilterLine(
180 line2.substring(OPTION_FILTER.length() + 1)));
181 } else if (transferConfig.isAllowSidebandAll()
182 && line2.equals(OPTION_SIDEBAND_ALL)) {
183 reqBuilder.setSidebandAll(true);
184 } else if (line2.startsWith("packfile-uris ")) {
185 for (String s : line2.substring(14).split(",")) {
186 reqBuilder.addPackfileUriProtocol(s);
187 }
188 } else {
189 throw new PackProtocolException(MessageFormat
190 .format(JGitText.get().unexpectedPacketLine, line2));
191 }
192 }
193
194 return reqBuilder.build();
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 LsRefsV2Request parseLsRefsRequest(PacketLineIn pckIn)
215 throws PackProtocolException, IOException {
216 LsRefsV2Request.Builder builder = LsRefsV2Request.builder();
217 List<String> prefixes = new ArrayList<>();
218
219 String line = consumeCapabilities(pckIn,
220 serverOption -> builder.addServerOption(serverOption),
221 agent -> builder.setAgent(agent));
222
223 if (PacketLineIn.isEnd(line)) {
224 return builder.build();
225 }
226
227 if (!PacketLineIn.isDelimiter(line)) {
228 throw new PackProtocolException(MessageFormat
229 .format(JGitText.get().unexpectedPacketLine, line));
230 }
231
232 for (String line2 : pckIn.readStrings()) {
233 if (line2.equals("peel")) {
234 builder.setPeel(true);
235 } else if (line2.equals("symrefs")) {
236 builder.setSymrefs(true);
237 } else if (line2.startsWith("ref-prefix ")) {
238 prefixes.add(line2.substring("ref-prefix ".length()));
239 } else {
240 throw new PackProtocolException(MessageFormat
241 .format(JGitText.get().unexpectedPacketLine, line2));
242 }
243 }
244
245 return builder.setRefPrefixes(prefixes).build();
246 }
247
248 }