1 /*
2 * Copyright (C) 2013, Christian Halstrick <christian.halstrick@sap.com> and others
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Distribution License v. 1.0 which is available at
6 * https://www.eclipse.org/org/documents/edl-v10.php.
7 *
8 * SPDX-License-Identifier: BSD-3-Clause
9 */
10
11 package org.eclipse.jgit.lib;
12
13 import java.text.MessageFormat;
14
15 import org.eclipse.jgit.errors.IllegalTodoFileModification;
16 import org.eclipse.jgit.internal.JGitText;
17
18 /**
19 * Describes a single line in a file formatted like the git-rebase-todo file.
20 *
21 * @since 3.2
22 */
23 public class RebaseTodoLine {
24 /**
25 * Describes rebase actions
26 */
27 @SuppressWarnings("nls")
28 public enum Action {
29 /** Use commit */
30 PICK("pick", "p"),
31
32 /** Use commit, but edit the commit message */
33 REWORD("reword", "r"),
34
35 /** Use commit, but stop for amending */
36 EDIT("edit", "e"),
37
38 /** Use commit, but meld into previous commit */
39 SQUASH("squash", "s"),
40
41 /** like "squash", but discard this commit's log message */
42 FIXUP("fixup", "f"),
43
44 /**
45 * A comment in the file. Also blank lines (or lines containing only
46 * whitespaces) are reported as comments
47 */
48 COMMENT("comment", "#");
49
50 private final String token;
51
52 private final String shortToken;
53
54 private Action(String token, String shortToken) {
55 this.token = token;
56 this.shortToken = shortToken;
57 }
58
59 /**
60 * @return full action token name
61 */
62 public String toToken() {
63 return this.token;
64 }
65
66 @Override
67 public String toString() {
68 return "Action[" + token + "]";
69 }
70
71 /**
72 * @param token
73 * @return the Action
74 */
75 public static Action parse(String token) {
76 for (Action action : Action.values()) {
77 if (action.token.equals(token)
78 || action.shortToken.equals(token))
79 return action;
80 }
81 throw new IllegalArgumentException(MessageFormat.format(
82 JGitText.get().unknownOrUnsupportedCommand, token,
83 Action.values()));
84 }
85 }
86
87 Action action;
88
89 final AbbreviatedObjectId commit;
90
91 String shortMessage;
92
93 String comment;
94
95 /**
96 * Create a new comment line
97 *
98 * @param newComment
99 * the new comment
100 */
101 public RebaseTodoLine(String newComment) {
102 this.action = Action.COMMENT;
103 setComment(newComment);
104 this.commit = null;
105 this.shortMessage = null;
106 }
107
108 /**
109 * Create a new non-comment line
110 *
111 * @param action
112 * a {@link org.eclipse.jgit.lib.RebaseTodoLine.Action} object.
113 * @param commit
114 * a {@link org.eclipse.jgit.lib.AbbreviatedObjectId} object.
115 * @param shortMessage
116 * a {@link java.lang.String} object.
117 */
118 public RebaseTodoLine(Action action, AbbreviatedObjectId commit,
119 String shortMessage) {
120 this.action = action;
121 this.commit = commit;
122 this.shortMessage = shortMessage;
123 this.comment = null;
124 }
125
126 /**
127 * Get rebase action type
128 *
129 * @return rebase action type
130 */
131 public Action getAction() {
132 return action;
133 }
134
135 /**
136 * Set the action. It's not allowed to set a non-comment action on a line
137 * which was a comment line before. But you are allowed to set the comment
138 * action on a non-comment line and afterwards change the action back to
139 * non-comment.
140 *
141 * @param newAction
142 * a {@link org.eclipse.jgit.lib.RebaseTodoLine.Action} object.
143 * @throws org.eclipse.jgit.errors.IllegalTodoFileModification
144 * on attempt to set a non-comment action on a line which was a
145 * comment line before.
146 */
147 public void setAction(Action newAction) throws IllegalTodoFileModification {
148 if (!Action.COMMENT.equals(action) && Action.COMMENT.equals(newAction)) {
149 // transforming from non-comment to comment
150 if (comment == null)
151 // no comment was explicitly set. Take the old line as comment
152 // text
153 comment = "# " + action.token + " " //$NON-NLS-1$ //$NON-NLS-2$
154 + ((commit == null) ? "null" : commit.name()) + " " //$NON-NLS-1$ //$NON-NLS-2$
155 + ((shortMessage == null) ? "null" : shortMessage); //$NON-NLS-1$
156 } else if (Action.COMMENT.equals(action) && !Action.COMMENT.equals(newAction)) {
157 // transforming from comment to non-comment
158 if (commit == null)
159 throw new IllegalTodoFileModification(MessageFormat.format(
160 JGitText.get().cannotChangeActionOnComment, action,
161 newAction));
162 }
163 this.action = newAction;
164 }
165
166 /**
167 * <p>
168 * Set a comment for this line that is used if this line's
169 * {@link org.eclipse.jgit.lib.RebaseTodoLine#action} is a {@link org.eclipse.jgit.lib.RebaseTodoLine.Action#COMMENT}
170 * </p>
171 * It's allowed to unset the comment by calling
172 * <code>setComment(null)</code> <br>
173 * A valid comment either starts with a hash (i.e. <code>'#'</code>), is an
174 * empty string, or consists of only spaces and tabs.<br>
175 * If the argument <code>newComment</code> doesn't match these requirements
176 * an Exception is thrown.
177 *
178 * @param newComment
179 * the comment
180 */
181 public void setComment(String newComment) {
182 if (newComment == null) {
183 this.comment = null;
184 return;
185 }
186
187 if (newComment.contains("\n") || newComment.contains("\r")) //$NON-NLS-1$ //$NON-NLS-2$
188 throw createInvalidCommentException(newComment);
189
190 if (newComment.trim().length() == 0 || newComment.startsWith("#")) { //$NON-NLS-1$
191 this.comment = newComment;
192 return;
193 }
194
195 throw createInvalidCommentException(newComment);
196 }
197
198 private static IllegalArgumentException createInvalidCommentException(
199 String newComment) {
200 return new IllegalArgumentException(
201 MessageFormat.format(
202 JGitText.get().argumentIsNotAValidCommentString, newComment));
203 }
204
205 /**
206 * Get abbreviated commit SHA-1 of commit that action will be performed on
207 *
208 * @return abbreviated commit SHA-1 of commit that action will be performed
209 * on
210 */
211 public AbbreviatedObjectId getCommit() {
212 return commit;
213 }
214
215 /**
216 * Get the first line of the commit message of the commit the action will be
217 * performed on.
218 *
219 * @return the first line of the commit message of the commit the action
220 * will be performed on.
221 */
222 public String getShortMessage() {
223 return shortMessage;
224 }
225
226 /**
227 * Set short message
228 *
229 * @param shortMessage
230 * a short message.
231 */
232 public void setShortMessage(String shortMessage) {
233 this.shortMessage = shortMessage;
234 }
235
236 /**
237 * Get a comment
238 *
239 * @return a comment. If the line is a comment line then the comment is
240 * returned. Lines starting with # or blank lines or lines
241 * containing only spaces and tabs are considered as comment lines.
242 * The complete line is returned (e.g. including the '#')
243 */
244 public String getComment() {
245 return comment;
246 }
247
248 /** {@inheritDoc} */
249 @SuppressWarnings("nls")
250 @Override
251 public String toString() {
252 return "Step["
253 + action
254 + ", "
255 + ((commit == null) ? "null" : commit)
256 + ", "
257 + ((shortMessage == null) ? "null" : shortMessage)
258 + ", "
259 + ((comment == null) ? "" : comment) + "]";
260 }
261 }