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
44
45
46 package org.eclipse.jgit.internal.storage.file;
47
48 import static org.eclipse.jgit.lib.Constants.HEAD;
49 import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
50 import static org.eclipse.jgit.lib.Constants.R_HEADS;
51 import static org.eclipse.jgit.lib.Constants.R_NOTES;
52 import static org.eclipse.jgit.lib.Constants.R_REFS;
53 import static org.eclipse.jgit.lib.Constants.R_REMOTES;
54
55 import java.io.File;
56 import java.io.FileNotFoundException;
57 import java.io.FileOutputStream;
58 import java.io.IOException;
59 import java.nio.ByteBuffer;
60 import java.nio.channels.FileChannel;
61 import java.text.MessageFormat;
62
63 import org.eclipse.jgit.internal.JGitText;
64 import org.eclipse.jgit.lib.Constants;
65 import org.eclipse.jgit.lib.CoreConfig;
66 import org.eclipse.jgit.lib.ObjectId;
67 import org.eclipse.jgit.lib.PersonIdent;
68 import org.eclipse.jgit.lib.Ref;
69 import org.eclipse.jgit.lib.RefUpdate;
70 import org.eclipse.jgit.lib.ReflogEntry;
71 import org.eclipse.jgit.util.FileUtils;
72
73
74
75
76
77 public class ReflogWriter {
78
79
80
81
82
83
84
85
86
87 public static String refLockFor(String name) {
88 return name + LOCK_SUFFIX;
89 }
90
91 private final RefDirectory refdb;
92
93 private final boolean forceWrite;
94
95
96
97
98
99
100
101
102 public ReflogWriter(RefDirectory refdb) {
103 this(refdb, false);
104 }
105
106
107
108
109
110
111
112
113
114
115
116 public ReflogWriter(RefDirectory refdb, boolean forceWrite) {
117 this.refdb = refdb;
118 this.forceWrite = forceWrite;
119 }
120
121
122
123
124
125
126
127 public ReflogWriter create() throws IOException {
128 FileUtils.mkdir(refdb.logsDir);
129 FileUtils.mkdir(refdb.logsRefsDir);
130 FileUtils.mkdir(
131 new File(refdb.logsRefsDir, R_HEADS.substring(R_REFS.length())));
132 return this;
133 }
134
135
136
137
138
139
140
141
142
143
144
145 public ReflogWriter log(String refName, ReflogEntry entry)
146 throws IOException {
147 return log(refName, entry.getOldId(), entry.getNewId(), entry.getWho(),
148 entry.getComment());
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 public ReflogWriter log(String refName, ObjectId oldId,
168 ObjectId newId, PersonIdent ident, String message) throws IOException {
169 byte[] encoded = encode(oldId, newId, ident, message);
170 return log(refName, encoded);
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184
185 public ReflogWriter log(RefUpdate update, String msg,
186 boolean deref) throws IOException {
187 ObjectId oldId = update.getOldObjectId();
188 ObjectId newId = update.getNewObjectId();
189 Ref ref = update.getRef();
190
191 PersonIdent ident = update.getRefLogIdent();
192 if (ident == null)
193 ident = new PersonIdent(refdb.getRepository());
194 else
195 ident = new PersonIdent(ident);
196
197 byte[] rec = encode(oldId, newId, ident, msg);
198 if (deref && ref.isSymbolic()) {
199 log(ref.getName(), rec);
200 log(ref.getLeaf().getName(), rec);
201 } else
202 log(ref.getName(), rec);
203
204 return this;
205 }
206
207 private byte[] encode(ObjectId"../../../../../../org/eclipse/jgit/lib/ObjectId.html#ObjectId">ObjectId oldId, ObjectId newId, PersonIdent ident,
208 String message) {
209 StringBuilder r = new StringBuilder();
210 r.append(ObjectId.toString(oldId));
211 r.append(' ');
212 r.append(ObjectId.toString(newId));
213 r.append(' ');
214 r.append(ident.toExternalString());
215 r.append('\t');
216 r.append(
217 message.replace("\r\n", " ")
218 .replace("\n", " "));
219 r.append('\n');
220 return Constants.encode(r.toString());
221 }
222
223 private FileOutputStream getFileOutputStream(File log) throws IOException {
224 try {
225 return new FileOutputStream(log, true);
226 } catch (FileNotFoundException err) {
227 File dir = log.getParentFile();
228 if (dir.exists()) {
229 throw err;
230 }
231 if (!dir.mkdirs() && !dir.isDirectory()) {
232 throw new IOException(MessageFormat
233 .format(JGitText.get().cannotCreateDirectory, dir));
234 }
235 return new FileOutputStream(log, true);
236 }
237 }
238
239 private ReflogWriter log(String refName, byte[] rec) throws IOException {
240 File log = refdb.logFor(refName);
241 boolean write = forceWrite
242 || (isLogAllRefUpdates() && shouldAutoCreateLog(refName))
243 || log.isFile();
244 if (!write)
245 return this;
246
247 WriteConfig wc = refdb.getRepository().getConfig().get(WriteConfig.KEY);
248 try (FileOutputStream out = getFileOutputStream(log)) {
249 if (wc.getFSyncRefFiles()) {
250 FileChannel fc = out.getChannel();
251 ByteBuffer buf = ByteBuffer.wrap(rec);
252 while (0 < buf.remaining()) {
253 fc.write(buf);
254 }
255 fc.force(true);
256 } else {
257 out.write(rec);
258 }
259 }
260 return this;
261 }
262
263 private boolean isLogAllRefUpdates() {
264 return refdb.getRepository().getConfig().get(CoreConfig.KEY)
265 .isLogAllRefUpdates();
266 }
267
268 private boolean shouldAutoCreateLog(String refName) {
269 return refName.equals(HEAD)
270 || refName.startsWith(R_HEADS)
271 || refName.startsWith(R_REMOTES)
272 || refName.startsWith(R_NOTES);
273 }
274 }