| /* |
| * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> |
| * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> |
| * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> |
| * and other copyright owners as documented in the project's IP log. |
| * |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Distribution License v1.0 which |
| * accompanies this distribution, is reproduced below, and is |
| * available at http://www.eclipse.org/org/documents/edl-v10.php |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * - Neither the name of the Eclipse Foundation, Inc. nor the |
| * names of its contributors may be used to endorse or promote |
| * products derived from this software without specific prior |
| * written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| package org.eclipse.jgit.lib; |
| |
| import java.io.Serializable; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.Locale; |
| import java.util.TimeZone; |
| |
| import org.eclipse.jgit.internal.JGitText; |
| import org.eclipse.jgit.util.SystemReader; |
| import org.eclipse.jgit.util.time.ProposedTimestamp; |
| |
| /** |
| * A combination of a person identity and time in Git. |
| * |
| * Git combines Name + email + time + time zone to specify who wrote or |
| * committed something. |
| */ |
| public class PersonIdent implements Serializable { |
| private static final long serialVersionUID = 1L; |
| |
| /** |
| * Get timezone object for the given offset. |
| * |
| * @param tzOffset |
| * timezone offset as in {@link #getTimeZoneOffset()}. |
| * @return time zone object for the given offset. |
| * @since 4.1 |
| */ |
| public static TimeZone getTimeZone(int tzOffset) { |
| StringBuilder tzId = new StringBuilder(8); |
| tzId.append("GMT"); //$NON-NLS-1$ |
| appendTimezone(tzId, tzOffset); |
| return TimeZone.getTimeZone(tzId.toString()); |
| } |
| |
| /** |
| * Format a timezone offset. |
| * |
| * @param r |
| * string builder to append to. |
| * @param offset |
| * timezone offset as in {@link #getTimeZoneOffset()}. |
| * @since 4.1 |
| */ |
| public static void appendTimezone(StringBuilder r, int offset) { |
| final char sign; |
| final int offsetHours; |
| final int offsetMins; |
| |
| if (offset < 0) { |
| sign = '-'; |
| offset = -offset; |
| } else { |
| sign = '+'; |
| } |
| |
| offsetHours = offset / 60; |
| offsetMins = offset % 60; |
| |
| r.append(sign); |
| if (offsetHours < 10) { |
| r.append('0'); |
| } |
| r.append(offsetHours); |
| if (offsetMins < 10) { |
| r.append('0'); |
| } |
| r.append(offsetMins); |
| } |
| |
| /** |
| * Sanitize the given string for use in an identity and append to output. |
| * <p> |
| * Trims whitespace from both ends and special characters {@code \n < >} that |
| * interfere with parsing; appends all other characters to the output. |
| * Analogous to the C git function {@code strbuf_addstr_without_crud}. |
| * |
| * @param r |
| * string builder to append to. |
| * @param str |
| * input string. |
| * @since 4.4 |
| */ |
| public static void appendSanitized(StringBuilder r, String str) { |
| // Trim any whitespace less than \u0020 as in String#trim(). |
| int i = 0; |
| while (i < str.length() && str.charAt(i) <= ' ') { |
| i++; |
| } |
| int end = str.length(); |
| while (end > i && str.charAt(end - 1) <= ' ') { |
| end--; |
| } |
| |
| for (; i < end; i++) { |
| char c = str.charAt(i); |
| switch (c) { |
| case '\n': |
| case '<': |
| case '>': |
| continue; |
| default: |
| r.append(c); |
| break; |
| } |
| } |
| } |
| |
| private final String name; |
| |
| private final String emailAddress; |
| |
| private final long when; |
| |
| private final int tzOffset; |
| |
| /** |
| * Creates new PersonIdent from config info in repository, with current time. |
| * This new PersonIdent gets the info from the default committer as available |
| * from the configuration. |
| * |
| * @param repo a {@link org.eclipse.jgit.lib.Repository} object. |
| */ |
| public PersonIdent(Repository repo) { |
| this(repo.getConfig().get(UserConfig.KEY)); |
| } |
| |
| /** |
| * Copy a {@link org.eclipse.jgit.lib.PersonIdent}. |
| * |
| * @param pi |
| * Original {@link org.eclipse.jgit.lib.PersonIdent} |
| */ |
| public PersonIdent(PersonIdent pi) { |
| this(pi.getName(), pi.getEmailAddress()); |
| } |
| |
| /** |
| * Construct a new {@link org.eclipse.jgit.lib.PersonIdent} with current |
| * time. |
| * |
| * @param aName |
| * a {@link java.lang.String} object. |
| * @param aEmailAddress |
| * a {@link java.lang.String} object. |
| */ |
| public PersonIdent(String aName, String aEmailAddress) { |
| this(aName, aEmailAddress, SystemReader.getInstance().getCurrentTime()); |
| } |
| |
| /** |
| * Construct a new {@link org.eclipse.jgit.lib.PersonIdent} with current |
| * time. |
| * |
| * @param aName |
| * a {@link java.lang.String} object. |
| * @param aEmailAddress |
| * a {@link java.lang.String} object. |
| * @param when |
| * a {@link org.eclipse.jgit.util.time.ProposedTimestamp} object. |
| * @since 4.6 |
| */ |
| public PersonIdent(String aName, String aEmailAddress, |
| ProposedTimestamp when) { |
| this(aName, aEmailAddress, when.millis()); |
| } |
| |
| /** |
| * Copy a PersonIdent, but alter the clone's time stamp |
| * |
| * @param pi |
| * original {@link org.eclipse.jgit.lib.PersonIdent} |
| * @param when |
| * local time |
| * @param tz |
| * time zone |
| */ |
| public PersonIdent(PersonIdent pi, Date when, TimeZone tz) { |
| this(pi.getName(), pi.getEmailAddress(), when, tz); |
| } |
| |
| /** |
| * Copy a {@link org.eclipse.jgit.lib.PersonIdent}, but alter the clone's |
| * time stamp |
| * |
| * @param pi |
| * original {@link org.eclipse.jgit.lib.PersonIdent} |
| * @param aWhen |
| * local time |
| */ |
| public PersonIdent(PersonIdent pi, Date aWhen) { |
| this(pi.getName(), pi.getEmailAddress(), aWhen.getTime(), pi.tzOffset); |
| } |
| |
| /** |
| * Construct a PersonIdent from simple data |
| * |
| * @param aName a {@link java.lang.String} object. |
| * @param aEmailAddress a {@link java.lang.String} object. |
| * @param aWhen |
| * local time stamp |
| * @param aTZ |
| * time zone |
| */ |
| public PersonIdent(final String aName, final String aEmailAddress, |
| final Date aWhen, final TimeZone aTZ) { |
| this(aName, aEmailAddress, aWhen.getTime(), aTZ.getOffset(aWhen |
| .getTime()) / (60 * 1000)); |
| } |
| |
| /** |
| * Copy a PersonIdent, but alter the clone's time stamp |
| * |
| * @param pi |
| * original {@link org.eclipse.jgit.lib.PersonIdent} |
| * @param aWhen |
| * local time stamp |
| * @param aTZ |
| * time zone |
| */ |
| public PersonIdent(PersonIdent pi, long aWhen, int aTZ) { |
| this(pi.getName(), pi.getEmailAddress(), aWhen, aTZ); |
| } |
| |
| private PersonIdent(final String aName, final String aEmailAddress, |
| long when) { |
| this(aName, aEmailAddress, when, SystemReader.getInstance() |
| .getTimezone(when)); |
| } |
| |
| private PersonIdent(UserConfig config) { |
| this(config.getCommitterName(), config.getCommitterEmail()); |
| } |
| |
| /** |
| * Construct a {@link org.eclipse.jgit.lib.PersonIdent}. |
| * <p> |
| * Whitespace in the name and email is preserved for the lifetime of this |
| * object, but are trimmed by {@link #toExternalString()}. This means that |
| * parsing the result of {@link #toExternalString()} may not return an |
| * equivalent instance. |
| * |
| * @param aName |
| * a {@link java.lang.String} object. |
| * @param aEmailAddress |
| * a {@link java.lang.String} object. |
| * @param aWhen |
| * local time stamp |
| * @param aTZ |
| * time zone |
| */ |
| public PersonIdent(final String aName, final String aEmailAddress, |
| final long aWhen, final int aTZ) { |
| if (aName == null) |
| throw new IllegalArgumentException( |
| JGitText.get().personIdentNameNonNull); |
| if (aEmailAddress == null) |
| throw new IllegalArgumentException( |
| JGitText.get().personIdentEmailNonNull); |
| name = aName; |
| emailAddress = aEmailAddress; |
| when = aWhen; |
| tzOffset = aTZ; |
| } |
| |
| /** |
| * Get name of person |
| * |
| * @return Name of person |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * Get email address of person |
| * |
| * @return email address of person |
| */ |
| public String getEmailAddress() { |
| return emailAddress; |
| } |
| |
| /** |
| * Get timestamp |
| * |
| * @return timestamp |
| */ |
| public Date getWhen() { |
| return new Date(when); |
| } |
| |
| /** |
| * Get this person's declared time zone |
| * |
| * @return this person's declared time zone; null if time zone is unknown. |
| */ |
| public TimeZone getTimeZone() { |
| return getTimeZone(tzOffset); |
| } |
| |
| /** |
| * Get this person's declared time zone as minutes east of UTC. |
| * |
| * @return this person's declared time zone as minutes east of UTC. If the |
| * timezone is to the west of UTC it is negative. |
| */ |
| public int getTimeZoneOffset() { |
| return tzOffset; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Hashcode is based only on the email address and timestamp. |
| */ |
| @Override |
| public int hashCode() { |
| int hc = getEmailAddress().hashCode(); |
| hc *= 31; |
| hc += (int) (when / 1000L); |
| return hc; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof PersonIdent) { |
| final PersonIdent p = (PersonIdent) o; |
| return getName().equals(p.getName()) |
| && getEmailAddress().equals(p.getEmailAddress()) |
| && when / 1000L == p.when / 1000L; |
| } |
| return false; |
| } |
| |
| /** |
| * Format for Git storage. |
| * |
| * @return a string in the git author format |
| */ |
| public String toExternalString() { |
| final StringBuilder r = new StringBuilder(); |
| appendSanitized(r, getName()); |
| r.append(" <"); //$NON-NLS-1$ |
| appendSanitized(r, getEmailAddress()); |
| r.append("> "); //$NON-NLS-1$ |
| r.append(when / 1000); |
| r.append(' '); |
| appendTimezone(r, tzOffset); |
| return r.toString(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| @SuppressWarnings("nls") |
| public String toString() { |
| final StringBuilder r = new StringBuilder(); |
| final SimpleDateFormat dtfmt; |
| dtfmt = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy Z", Locale.US); |
| dtfmt.setTimeZone(getTimeZone()); |
| |
| r.append("PersonIdent["); |
| r.append(getName()); |
| r.append(", "); |
| r.append(getEmailAddress()); |
| r.append(", "); |
| r.append(dtfmt.format(Long.valueOf(when))); |
| r.append("]"); |
| |
| return r.toString(); |
| } |
| } |
| |