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.pgm;
47
48 import java.io.BufferedOutputStream;
49 import java.io.IOException;
50 import java.text.DateFormat;
51 import java.text.MessageFormat;
52 import java.text.SimpleDateFormat;
53 import java.util.Locale;
54 import java.util.TimeZone;
55
56 import org.eclipse.jgit.diff.DiffFormatter;
57 import org.eclipse.jgit.diff.RawTextComparator;
58 import org.eclipse.jgit.diff.RenameDetector;
59 import org.eclipse.jgit.errors.CorruptObjectException;
60 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
61 import org.eclipse.jgit.errors.MissingObjectException;
62 import org.eclipse.jgit.lib.Constants;
63 import org.eclipse.jgit.lib.FileMode;
64 import org.eclipse.jgit.lib.ObjectId;
65 import org.eclipse.jgit.lib.PersonIdent;
66 import org.eclipse.jgit.lib.Repository;
67 import org.eclipse.jgit.pgm.internal.CLIText;
68 import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
69 import org.eclipse.jgit.revwalk.RevCommit;
70 import org.eclipse.jgit.revwalk.RevObject;
71 import org.eclipse.jgit.revwalk.RevTag;
72 import org.eclipse.jgit.revwalk.RevTree;
73 import org.eclipse.jgit.revwalk.RevWalk;
74 import org.eclipse.jgit.treewalk.TreeWalk;
75 import org.eclipse.jgit.treewalk.filter.TreeFilter;
76 import org.kohsuke.args4j.Argument;
77 import org.kohsuke.args4j.Option;
78
79 @Command(common = true, usage = "usage_show")
80 class Show extends TextBuiltin {
81 private final TimeZone myTZ = TimeZone.getDefault();
82
83 private final DateFormat fmt;
84
85 private DiffFormatter diffFmt;
86
87 @Argument(index = 0, metaVar = "metaVar_object")
88 private String objectName;
89
90 @Option(name = "--", metaVar = "metaVar_path", multiValued = true, handler = PathTreeFilterHandler.class)
91 protected TreeFilter pathFilter = TreeFilter.ALL;
92
93
94 @Option(name = "-p", usage = "usage_showPatch")
95 boolean showPatch;
96
97 @Option(name = "-M", usage = "usage_detectRenames")
98 private Boolean detectRenames;
99
100 @Option(name = "--no-renames", usage = "usage_noRenames")
101 void noRenames(@SuppressWarnings("unused") boolean on) {
102 detectRenames = Boolean.FALSE;
103 }
104
105 @Option(name = "-l", usage = "usage_renameLimit")
106 private Integer renameLimit;
107
108 @Option(name = "--name-status", usage = "usage_nameStatus")
109 private boolean showNameAndStatusOnly;
110
111 @Option(name = "--ignore-space-at-eol")
112 void ignoreSpaceAtEol(@SuppressWarnings("unused") boolean on) {
113 diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_TRAILING);
114 }
115
116 @Option(name = "--ignore-leading-space")
117 void ignoreLeadingSpace(@SuppressWarnings("unused") boolean on) {
118 diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_LEADING);
119 }
120
121 @Option(name = "-b", aliases = { "--ignore-space-change" })
122 void ignoreSpaceChange(@SuppressWarnings("unused") boolean on) {
123 diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_CHANGE);
124 }
125
126 @Option(name = "-w", aliases = { "--ignore-all-space" })
127 void ignoreAllSpace(@SuppressWarnings("unused") boolean on) {
128 diffFmt.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);
129 }
130
131 @Option(name = "-U", aliases = { "--unified" }, metaVar = "metaVar_linesOfContext")
132 void unified(int lines) {
133 diffFmt.setContext(lines);
134 }
135
136 @Option(name = "--abbrev", metaVar = "metaVar_n")
137 void abbrev(int lines) {
138 diffFmt.setAbbreviationLength(lines);
139 }
140
141 @Option(name = "--full-index")
142 void abbrev(@SuppressWarnings("unused") boolean on) {
143 diffFmt.setAbbreviationLength(Constants.OBJECT_ID_STRING_LENGTH);
144 }
145
146 @Option(name = "--src-prefix", usage = "usage_srcPrefix")
147 void sourcePrefix(String path) {
148 diffFmt.setOldPrefix(path);
149 }
150
151 @Option(name = "--dst-prefix", usage = "usage_dstPrefix")
152 void dstPrefix(String path) {
153 diffFmt.setNewPrefix(path);
154 }
155
156 @Option(name = "--no-prefix", usage = "usage_noPrefix")
157 void noPrefix(@SuppressWarnings("unused") boolean on) {
158 diffFmt.setOldPrefix("");
159 diffFmt.setNewPrefix("");
160 }
161
162
163
164 Show() {
165 fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy ZZZZZ", Locale.US);
166 }
167
168 @Override
169 protected void init(final Repository repository, final String gitDir) {
170 super.init(repository, gitDir);
171 diffFmt = new DiffFormatter(new BufferedOutputStream(outs));
172 }
173
174 @SuppressWarnings("boxing")
175 @Override
176 protected void run() throws Exception {
177 diffFmt.setRepository(db);
178 try {
179 diffFmt.setPathFilter(pathFilter);
180 if (detectRenames != null)
181 diffFmt.setDetectRenames(detectRenames.booleanValue());
182 if (renameLimit != null && diffFmt.isDetectRenames()) {
183 RenameDetector rd = diffFmt.getRenameDetector();
184 rd.setRenameLimit(renameLimit.intValue());
185 }
186
187 ObjectId objectId;
188 if (objectName == null)
189 objectId = db.resolve(Constants.HEAD);
190 else
191 objectId = db.resolve(objectName);
192
193 try (RevWalk rw = new RevWalk(db)) {
194 RevObject obj = rw.parseAny(objectId);
195 while (obj instanceof RevTag) {
196 show((RevTag) obj);
197 obj = ((RevTag) obj).getObject();
198 rw.parseBody(obj);
199 }
200
201 switch (obj.getType()) {
202 case Constants.OBJ_COMMIT:
203 show(rw, (RevCommit) obj);
204 break;
205
206 case Constants.OBJ_TREE:
207 outw.print("tree ");
208 outw.print(objectName);
209 outw.println();
210 outw.println();
211 show((RevTree) obj);
212 break;
213
214 case Constants.OBJ_BLOB:
215 db.open(obj, obj.getType()).copyTo(System.out);
216 outw.flush();
217 break;
218
219 default:
220 throw die(MessageFormat.format(
221 CLIText.get().cannotReadBecause, obj.name(),
222 obj.getType()));
223 }
224 }
225 } finally {
226 diffFmt.close();
227 }
228 }
229
230 private void show(RevTag tag) throws IOException {
231 outw.print(CLIText.get().tagLabel);
232 outw.print(" ");
233 outw.print(tag.getTagName());
234 outw.println();
235
236 final PersonIdent tagger = tag.getTaggerIdent();
237 if (tagger != null) {
238 outw.println(MessageFormat.format(CLIText.get().taggerInfo,
239 tagger.getName(), tagger.getEmailAddress()));
240
241 final TimeZone taggerTZ = tagger.getTimeZone();
242 fmt.setTimeZone(taggerTZ != null ? taggerTZ : myTZ);
243 outw.println(MessageFormat.format(CLIText.get().dateInfo,
244 fmt.format(tagger.getWhen())));
245 }
246
247 outw.println();
248 final String[] lines = tag.getFullMessage().split("\n");
249 for (final String s : lines) {
250 outw.print(" ");
251 outw.print(s);
252 outw.println();
253 }
254
255 outw.println();
256 }
257
258 private void show(RevTree obj) throws MissingObjectException,
259 IncorrectObjectTypeException, CorruptObjectException, IOException {
260 try (final TreeWalk walk = new TreeWalk(db)) {
261 walk.reset();
262 walk.addTree(obj);
263
264 while (walk.next()) {
265 outw.print(walk.getPathString());
266 final FileMode mode = walk.getFileMode(0);
267 if (mode == FileMode.TREE)
268 outw.print("/");
269 outw.println();
270 }
271 }
272 }
273
274 private void show(RevWalk rw, final RevCommit c) throws Exception {
275 char[] outbuffer = new char[Constants.OBJECT_ID_LENGTH * 2];
276
277 outw.print(CLIText.get().commitLabel);
278 outw.print(" ");
279 c.getId().copyTo(outbuffer, outw);
280 outw.println();
281
282 final PersonIdent author = c.getAuthorIdent();
283 outw.println(MessageFormat.format(CLIText.get().authorInfo,
284 author.getName(), author.getEmailAddress()));
285
286 final TimeZone authorTZ = author.getTimeZone();
287 fmt.setTimeZone(authorTZ != null ? authorTZ : myTZ);
288 outw.println(MessageFormat.format(CLIText.get().dateInfo,
289 fmt.format(author.getWhen())));
290
291 outw.println();
292 final String[] lines = c.getFullMessage().split("\n");
293 for (final String s : lines) {
294 outw.print(" ");
295 outw.print(s);
296 outw.println();
297 }
298
299 outw.println();
300 if (c.getParentCount() == 1) {
301 rw.parseHeaders(c.getParent(0));
302 showDiff(c);
303 }
304 outw.flush();
305 }
306
307 private void showDiff(RevCommit c) throws IOException {
308 final RevTree a = c.getParent(0).getTree();
309 final RevTree b = c.getTree();
310
311 if (showNameAndStatusOnly)
312 Diff.nameStatus(outw, diffFmt.scan(a, b));
313 else {
314 outw.flush();
315 diffFmt.format(a, b);
316 diffFmt.flush();
317 }
318 outw.println();
319 }
320 }