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