View Javadoc
1   /*
2    * Copyright (C) 2009, Google Inc. 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.revwalk;
12  
13  import java.nio.charset.Charset;
14  
15  import org.eclipse.jgit.util.RawParseUtils;
16  
17  /**
18   * Single line at the end of a message, such as a "Signed-off-by: someone".
19   * <p>
20   * These footer lines tend to be used to represent additional information about
21   * a commit, like the path it followed through reviewers before finally being
22   * accepted into the project's main repository as an immutable commit.
23   *
24   * @see RevCommit#getFooterLines()
25   */
26  public final class FooterLine {
27  	private final byte[] buffer;
28  
29  	private final Charset enc;
30  
31  	private final int keyStart;
32  
33  	private final int keyEnd;
34  
35  	private final int valStart;
36  
37  	private final int valEnd;
38  
39  	FooterLine(final byte[] b, final Charset e, final int ks, final int ke,
40  			final int vs, final int ve) {
41  		buffer = b;
42  		enc = e;
43  		keyStart = ks;
44  		keyEnd = ke;
45  		valStart = vs;
46  		valEnd = ve;
47  	}
48  
49  	/**
50  	 * Whether keys match
51  	 *
52  	 * @param key
53  	 *            key to test this line's key name against.
54  	 * @return true if {@code key.getName().equalsIgnorecase(getKey())}.
55  	 */
56  	public boolean matches(FooterKey key) {
57  		final byte[] kRaw = key.raw;
58  		final int len = kRaw.length;
59  		int bPtr = keyStart;
60  		if (keyEnd - bPtr != len)
61  			return false;
62  		for (int kPtr = 0; kPtr < len;) {
63  			byte b = buffer[bPtr++];
64  			if ('A' <= b && b <= 'Z')
65  				b += (byte) ('a' - 'A');
66  			if (b != kRaw[kPtr++])
67  				return false;
68  		}
69  		return true;
70  	}
71  
72  	/**
73  	 * Get key name of this footer.
74  	 *
75  	 * @return key name of this footer; that is the text before the ":" on the
76  	 *         line footer's line. The text is decoded according to the commit's
77  	 *         specified (or assumed) character encoding.
78  	 */
79  	public String getKey() {
80  		return RawParseUtils.decode(enc, buffer, keyStart, keyEnd);
81  	}
82  
83  	/**
84  	 * Get value of this footer.
85  	 *
86  	 * @return value of this footer; that is the text after the ":" and any
87  	 *         leading whitespace has been skipped. May be the empty string if
88  	 *         the footer has no value (line ended with ":"). The text is
89  	 *         decoded according to the commit's specified (or assumed)
90  	 *         character encoding.
91  	 */
92  	public String getValue() {
93  		return RawParseUtils.decode(enc, buffer, valStart, valEnd);
94  	}
95  
96  	/**
97  	 * Extract the email address (if present) from the footer.
98  	 * <p>
99  	 * If there is an email address looking string inside of angle brackets
100 	 * (e.g. "&lt;a@b&gt;"), the return value is the part extracted from inside the
101 	 * brackets. If no brackets are found, then {@link #getValue()} is returned
102 	 * if the value contains an '@' sign. Otherwise, null.
103 	 *
104 	 * @return email address appearing in the value of this footer, or null.
105 	 */
106 	public String getEmailAddress() {
107 		final int lt = RawParseUtils.nextLF(buffer, valStart, '<');
108 		if (valEnd <= lt) {
109 			final int at = RawParseUtils.nextLF(buffer, valStart, '@');
110 			if (valStart < at && at < valEnd)
111 				return getValue();
112 			return null;
113 		}
114 		final int gt = RawParseUtils.nextLF(buffer, lt, '>');
115 		if (valEnd < gt)
116 			return null;
117 		return RawParseUtils.decode(enc, buffer, lt, gt - 1);
118 	}
119 
120 	/** {@inheritDoc} */
121 	@Override
122 	public String toString() {
123 		return getKey() + ": " + getValue(); //$NON-NLS-1$
124 	}
125 }