1 /*
2 * Copyright (C) 2006-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
5 * and other copyright owners as documented in the project's IP log.
6 *
7 * This program and the accompanying materials are made available
8 * under the terms of the Eclipse Distribution License v1.0 which
9 * accompanies this distribution, is reproduced below, and is
10 * available at http://www.eclipse.org/org/documents/edl-v10.php
11 *
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or
15 * without modification, are permitted provided that the following
16 * conditions are met:
17 *
18 * - Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
25 *
26 * - Neither the name of the Eclipse Foundation, Inc. nor the
27 * names of its contributors may be used to endorse or promote
28 * products derived from this software without specific prior
29 * written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
32 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
33 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
36 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
38 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
40 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
43 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 */
45
46 package org.eclipse.jgit.lib;
47
48 import static java.nio.charset.StandardCharsets.UTF_8;
49
50 import java.io.ByteArrayOutputStream;
51 import java.io.IOException;
52 import java.io.OutputStreamWriter;
53
54 import org.eclipse.jgit.revwalk.RevObject;
55
56 /**
57 * Mutable builder to construct an annotated tag recording a project state.
58 *
59 * Applications should use this object when they need to manually construct a
60 * tag and want precise control over its fields.
61 *
62 * To read a tag object, construct a {@link org.eclipse.jgit.revwalk.RevWalk}
63 * and obtain a {@link org.eclipse.jgit.revwalk.RevTag} instance by calling
64 * {@link org.eclipse.jgit.revwalk.RevWalk#parseTag(AnyObjectId)}.
65 */
66 public class TagBuilder {
67 private ObjectId object;
68
69 private int type = Constants.OBJ_BAD;
70
71 private String tag;
72
73 private PersonIdent tagger;
74
75 private String message;
76
77 /**
78 * Get the type of object this tag refers to.
79 *
80 * @return the type of object this tag refers to.
81 */
82 public int getObjectType() {
83 return type;
84 }
85
86 /**
87 * Get the object this tag refers to.
88 *
89 * @return the object this tag refers to.
90 */
91 public ObjectId getObjectId() {
92 return object;
93 }
94
95 /**
96 * Set the object this tag refers to, and its type.
97 *
98 * @param obj
99 * the object.
100 * @param objType
101 * the type of {@code obj}. Must be a valid type code.
102 */
103 public void setObjectId(AnyObjectId obj, int objType) {
104 object = obj.copy();
105 type = objType;
106 }
107
108 /**
109 * Set the object this tag refers to, and infer its type.
110 *
111 * @param obj
112 * the object the tag will refer to.
113 */
114 public void setObjectId(RevObject obj) {
115 setObjectId(obj, obj.getType());
116 }
117
118 /**
119 * Get short name of the tag (no {@code refs/tags/} prefix).
120 *
121 * @return short name of the tag (no {@code refs/tags/} prefix).
122 */
123 public String getTag() {
124 return tag;
125 }
126
127 /**
128 * Set the name of this tag.
129 *
130 * @param shortName
131 * new short name of the tag. This short name should not start
132 * with {@code refs/} as typically a tag is stored under the
133 * reference derived from {@code "refs/tags/" + getTag()}.
134 */
135 public void setTag(String shortName) {
136 this.tag = shortName;
137 }
138
139 /**
140 * Get creator of this tag.
141 *
142 * @return creator of this tag. May be null.
143 */
144 public PersonIdent getTagger() {
145 return tagger;
146 }
147
148 /**
149 * Set the creator of this tag.
150 *
151 * @param taggerIdent
152 * the creator. May be null.
153 */
154 public void setTagger(PersonIdent taggerIdent) {
155 tagger = taggerIdent;
156 }
157
158 /**
159 * Get the complete commit message.
160 *
161 * @return the complete commit message.
162 */
163 public String getMessage() {
164 return message;
165 }
166
167 /**
168 * Set the tag's message.
169 *
170 * @param newMessage
171 * the tag's message.
172 */
173 public void setMessage(String newMessage) {
174 message = newMessage;
175 }
176
177 /**
178 * Format this builder's state as an annotated tag object.
179 *
180 * @return this object in the canonical annotated tag format, suitable for
181 * storage in a repository.
182 */
183 public byte[] build() {
184 ByteArrayOutputStream os = new ByteArrayOutputStream();
185 try (OutputStreamWriter w = new OutputStreamWriter(os,
186 UTF_8)) {
187 w.write("object "); //$NON-NLS-1$
188 getObjectId().copyTo(w);
189 w.write('\n');
190
191 w.write("type "); //$NON-NLS-1$
192 w.write(Constants.typeString(getObjectType()));
193 w.write("\n"); //$NON-NLS-1$
194
195 w.write("tag "); //$NON-NLS-1$
196 w.write(getTag());
197 w.write("\n"); //$NON-NLS-1$
198
199 if (getTagger() != null) {
200 w.write("tagger "); //$NON-NLS-1$
201 w.write(getTagger().toExternalString());
202 w.write('\n');
203 }
204
205 w.write('\n');
206 if (getMessage() != null)
207 w.write(getMessage());
208 } catch (IOException err) {
209 // This should never occur, the only way to get it above is
210 // for the ByteArrayOutputStream to throw, but it doesn't.
211 //
212 throw new RuntimeException(err);
213 }
214 return os.toByteArray();
215 }
216
217 /**
218 * Format this builder's state as an annotated tag object.
219 *
220 * @return this object in the canonical annotated tag format, suitable for
221 * storage in a repository.
222 */
223 public byte[] toByteArray() {
224 return build();
225 }
226
227 /** {@inheritDoc} */
228 @SuppressWarnings("nls")
229 @Override
230 public String toString() {
231 StringBuilder r = new StringBuilder();
232 r.append("Tag");
233 r.append("={\n");
234
235 r.append("object ");
236 r.append(object != null ? object.name() : "NOT_SET");
237 r.append("\n");
238
239 r.append("type ");
240 r.append(object != null ? Constants.typeString(type) : "NOT_SET");
241 r.append("\n");
242
243 r.append("tag ");
244 r.append(tag != null ? tag : "NOT_SET");
245 r.append("\n");
246
247 if (tagger != null) {
248 r.append("tagger ");
249 r.append(tagger);
250 r.append("\n");
251 }
252
253 r.append("\n");
254 r.append(message != null ? message : "");
255 r.append("}");
256 return r.toString();
257 }
258 }