1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.transport;
12
13 import static java.nio.charset.StandardCharsets.UTF_8;
14
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.io.OutputStreamWriter;
18 import java.io.Writer;
19 import java.text.MessageFormat;
20 import java.util.HashSet;
21 import java.util.Map;
22 import java.util.Set;
23 import java.util.TreeMap;
24
25 import org.eclipse.jgit.internal.JGitText;
26 import org.eclipse.jgit.internal.storage.pack.PackWriter;
27 import org.eclipse.jgit.lib.AnyObjectId;
28 import org.eclipse.jgit.lib.Constants;
29 import org.eclipse.jgit.lib.ObjectId;
30 import org.eclipse.jgit.lib.ObjectReader;
31 import org.eclipse.jgit.lib.ProgressMonitor;
32 import org.eclipse.jgit.lib.Ref;
33 import org.eclipse.jgit.lib.Repository;
34 import org.eclipse.jgit.revwalk.RevCommit;
35 import org.eclipse.jgit.storage.pack.PackConfig;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class BundleWriter {
55 private final Repository db;
56
57 private final ObjectReader reader;
58
59 private final Map<String, ObjectId> include;
60
61 private final Set<RevCommit> assume;
62
63 private final Set<ObjectId> tagTargets;
64
65 private PackConfig packConfig;
66
67 private ObjectCountCallback callback;
68
69
70
71
72
73
74
75 public BundleWriter(Repository repo) {
76 db = repo;
77 reader = null;
78 include = new TreeMap<>();
79 assume = new HashSet<>();
80 tagTargets = new HashSet<>();
81 }
82
83
84
85
86
87
88
89
90
91
92 public BundleWriter(ObjectReader or) {
93 db = null;
94 reader = or;
95 include = new TreeMap<>();
96 assume = new HashSet<>();
97 tagTargets = new HashSet<>();
98 }
99
100
101
102
103
104
105
106
107
108 public void setPackConfig(PackConfig pc) {
109 this.packConfig = pc;
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123 public void include(String name, AnyObjectId id) {
124 boolean validRefName = Repository.isValidRefName(name) || Constants.HEAD.equals(name);
125 if (!validRefName)
126 throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidRefName, name));
127 if (include.containsKey(name))
128 throw new IllegalStateException(JGitText.get().duplicateRef + name);
129 include.put(name, id.toObjectId());
130 }
131
132
133
134
135
136
137
138
139
140
141 public void include(Ref r) {
142 include(r.getName(), r.getObjectId());
143
144 if (r.getPeeledObjectId() != null)
145 tagTargets.add(r.getPeeledObjectId());
146
147 else if (r.getObjectId() != null
148 && r.getName().startsWith(Constants.R_HEADS))
149 tagTargets.add(r.getObjectId());
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public void assume(RevCommit c) {
165 if (c != null)
166 assume.add(c);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public void writeBundle(ProgressMonitor monitor, OutputStream os)
186 throws IOException {
187 try (PackWriter packWriter = newPackWriter()) {
188 packWriter.setObjectCountCallback(callback);
189
190 final HashSet<ObjectId> inc = new HashSet<>();
191 final HashSet<ObjectId> exc = new HashSet<>();
192 inc.addAll(include.values());
193 for (RevCommit r : assume)
194 exc.add(r.getId());
195 packWriter.setIndexDisabled(true);
196 packWriter.setDeltaBaseAsOffset(true);
197 packWriter.setThin(!exc.isEmpty());
198 packWriter.setReuseValidatingObjects(false);
199 if (exc.isEmpty()) {
200 packWriter.setTagTargets(tagTargets);
201 }
202 packWriter.preparePack(monitor, inc, exc);
203
204 final Writer w = new OutputStreamWriter(os, UTF_8);
205 w.write(TransportBundle.V2_BUNDLE_SIGNATURE);
206 w.write('\n');
207
208 final char[] tmp = new char[Constants.OBJECT_ID_STRING_LENGTH];
209 for (RevCommit a : assume) {
210 w.write('-');
211 a.copyTo(tmp, w);
212 if (a.getRawBuffer() != null) {
213 w.write(' ');
214 w.write(a.getShortMessage());
215 }
216 w.write('\n');
217 }
218 for (Map.Entry<String, ObjectId> e : include.entrySet()) {
219 e.getValue().copyTo(tmp, w);
220 w.write(' ');
221 w.write(e.getKey());
222 w.write('\n');
223 }
224
225 w.write('\n');
226 w.flush();
227 packWriter.writePack(monitor, monitor, os);
228 }
229 }
230
231 private PackWriter newPackWriter() {
232 PackConfig pc = packConfig;
233 if (pc == null) {
234 pc = db != null ? new PackConfig/PackConfig.html#PackConfig">PackConfig(db) : new PackConfig();
235 }
236 return new PackWriter(pc, reader != null ? reader : db.newObjectReader());
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 public BundleWriter setObjectCountCallback(ObjectCountCallback callback) {
254 this.callback = callback;
255 return this;
256 }
257 }