1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.transport;
44
45 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_DEEPEN_RELATIVE;
46 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_FILTER;
47 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_INCLUDE_TAG;
48 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_NO_PROGRESS;
49 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_OFS_DELTA;
50 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_SIDE_BAND_64K;
51 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_THIN_PACK;
52 import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_WANT_REF;
53
54 import java.io.IOException;
55 import java.text.MessageFormat;
56
57 import org.eclipse.jgit.errors.PackProtocolException;
58 import org.eclipse.jgit.internal.JGitText;
59 import org.eclipse.jgit.lib.ObjectId;
60
61
62
63
64
65
66
67
68 final class ProtocolV2Parser {
69
70 private final TransferConfig transferConfig;
71
72 ProtocolV2Parser(TransferConfig transferConfig) {
73 this.transferConfig = transferConfig;
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 FetchV2Request parseFetchRequest(PacketLineIn pckIn)
91 throws PackProtocolException, IOException {
92 FetchV2Request.Builder reqBuilder = FetchV2Request.builder();
93
94
95
96 reqBuilder.addOption(OPTION_SIDE_BAND_64K);
97
98 String line;
99
100
101
102 if ((line = pckIn.readString()) != PacketLineIn.DELIM) {
103 throw new PackProtocolException(MessageFormat
104 .format(JGitText.get().unexpectedPacketLine, line));
105 }
106
107 boolean filterReceived = false;
108 while ((line = pckIn.readString()) != PacketLineIn.END) {
109 if (line.startsWith("want ")) {
110 reqBuilder.addWantsId(ObjectId.fromString(line.substring(5)));
111 } else if (transferConfig.isAllowRefInWant()
112 && line.startsWith(OPTION_WANT_REF + " ")) {
113 reqBuilder.addWantedRef(line.substring(OPTION_WANT_REF.length() + 1));
114 } else if (line.startsWith("have ")) {
115 reqBuilder.addPeerHas(ObjectId.fromString(line.substring(5)));
116 } else if (line.equals("done")) {
117 reqBuilder.setDoneReceived();
118 } else if (line.equals(OPTION_THIN_PACK)) {
119 reqBuilder.addOption(OPTION_THIN_PACK);
120 } else if (line.equals(OPTION_NO_PROGRESS)) {
121 reqBuilder.addOption(OPTION_NO_PROGRESS);
122 } else if (line.equals(OPTION_INCLUDE_TAG)) {
123 reqBuilder.addOption(OPTION_INCLUDE_TAG);
124 } else if (line.equals(OPTION_OFS_DELTA)) {
125 reqBuilder.addOption(OPTION_OFS_DELTA);
126 } else if (line.startsWith("shallow ")) {
127 reqBuilder.addClientShallowCommit(
128 ObjectId.fromString(line.substring(8)));
129 } else if (line.startsWith("deepen ")) {
130 int parsedDepth = Integer.parseInt(line.substring(7));
131 if (parsedDepth <= 0) {
132 throw new PackProtocolException(
133 MessageFormat.format(JGitText.get().invalidDepth,
134 Integer.valueOf(parsedDepth)));
135 }
136 if (reqBuilder.getDeepenSince() != 0) {
137 throw new PackProtocolException(
138 JGitText.get().deepenSinceWithDeepen);
139 }
140 if (reqBuilder.hasDeepenNotRefs()) {
141 throw new PackProtocolException(
142 JGitText.get().deepenNotWithDeepen);
143 }
144 reqBuilder.setDepth(parsedDepth);
145 } else if (line.startsWith("deepen-not ")) {
146 reqBuilder.addDeepenNotRef(line.substring(11));
147 if (reqBuilder.getDepth() != 0) {
148 throw new PackProtocolException(
149 JGitText.get().deepenNotWithDeepen);
150 }
151 } else if (line.equals(OPTION_DEEPEN_RELATIVE)) {
152 reqBuilder.addOption(OPTION_DEEPEN_RELATIVE);
153 } else if (line.startsWith("deepen-since ")) {
154 int ts = Integer.parseInt(line.substring(13));
155 if (ts <= 0) {
156 throw new PackProtocolException(MessageFormat
157 .format(JGitText.get().invalidTimestamp, line));
158 }
159 if (reqBuilder.getDepth() != 0) {
160 throw new PackProtocolException(
161 JGitText.get().deepenSinceWithDeepen);
162 }
163 reqBuilder.setDeepenSince(ts);
164 } else if (transferConfig.isAllowFilter()
165 && line.startsWith(OPTION_FILTER + ' ')) {
166 if (filterReceived) {
167 throw new PackProtocolException(
168 JGitText.get().tooManyFilters);
169 }
170 filterReceived = true;
171 reqBuilder.setFilterBlobLimit(filterLine(
172 line.substring(OPTION_FILTER.length() + 1)));
173 } else {
174 throw new PackProtocolException(MessageFormat
175 .format(JGitText.get().unexpectedPacketLine, line));
176 }
177 }
178
179 return reqBuilder.build();
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193 static long filterLine(String blobLine) throws PackProtocolException {
194 long blobLimit = -1;
195
196 if (blobLine.equals("blob:none")) {
197 blobLimit = 0;
198 } else if (blobLine.startsWith("blob:limit=")) {
199 try {
200 blobLimit = Long
201 .parseLong(blobLine.substring("blob:limit=".length()));
202 } catch (NumberFormatException e) {
203 throw new PackProtocolException(MessageFormat
204 .format(JGitText.get().invalidFilter, blobLine));
205 }
206 }
207
208
209
210
211
212 if (blobLimit < 0) {
213 throw new PackProtocolException(
214 MessageFormat.format(JGitText.get().invalidFilter, blobLine));
215 }
216
217 return blobLimit;
218 }
219
220 }