/*
 * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
 * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
 * Copyright (C) 2008-2010, Google Inc.
 * Copyright (C) 2009, Google, Inc.
 * Copyright (C) 2009, JetBrains s.r.o.
 * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
 * Copyright (C) 2008, Thad Hughes <thadh@thad.corp.google.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.lib;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.File;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.events.ConfigChangedEvent;
import org.eclipse.jgit.events.ConfigChangedListener;
import org.eclipse.jgit.events.ListenerHandle;
import org.eclipse.jgit.events.ListenerList;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.RawParseUtils;

/**
 * Git style {@code .config}, {@code .gitconfig}, {@code .gitmodules} file.
 */
public class Config {

	private static final String[] EMPTY_STRING_ARRAY = {};

	static final long KiB = 1024;
	static final long MiB = 1024 * KiB;
	static final long GiB = 1024 * MiB;
	private static final int MAX_DEPTH = 10;

	private static final TypedConfigGetter DEFAULT_GETTER = new DefaultTypedConfigGetter();

	private static TypedConfigGetter typedGetter = DEFAULT_GETTER;

	/** the change listeners */
	private final ListenerList listeners = new ListenerList();

	/**
	 * Immutable current state of the configuration data.
	 * <p>
	 * This state is copy-on-write. It should always contain an immutable list
	 * of the configuration keys/values.
	 */
	private final AtomicReference<ConfigSnapshot> state;

	private final Config baseConfig;

	/**
	 * Magic value indicating a missing entry.
	 * <p>
	 * This value is tested for reference equality in some contexts, so we
	 * must ensure it is a special copy of the empty string.  It also must
	 * be treated like the empty string.
	 */
	private static final String MISSING_ENTRY = new String();

	/**
	 * Create a configuration with no default fallback.
	 */
	public Config() {
		this(null);
	}

	/**
	 * Create an empty configuration with a fallback for missing keys.
	 *
	 * @param defaultConfig
	 *            the base configuration to be consulted when a key is missing
	 *            from this configuration instance.
	 */
	public Config(Config defaultConfig) {
		baseConfig = defaultConfig;
		state = new AtomicReference<>(newState());
	}

	/**
	 * Retrieves this config's base config.
	 *
	 * @return the base configuration of this config.
	 *
	 * @since 5.5.2
	 */
	public Config getBaseConfig() {
		return baseConfig;
	}

	/**
	 * Check if a given string is the "missing" value.
	 *
	 * @param value
	 *            string to be checked.
	 * @return true if the given string is the "missing" value.
	 * @since 5.4
	 */
	@SuppressWarnings({ "ReferenceEquality", "StringEquality" })
	public static boolean isMissing(String value) {
		return value == MISSING_ENTRY;
	}

	/**
	 * Globally sets a {@link org.eclipse.jgit.lib.TypedConfigGetter} that is
	 * subsequently used to read typed values from all git configs.
	 *
	 * @param getter
	 *            to use; if {@code null} use the default getter.
	 * @since 4.9
	 */
	public static void setTypedConfigGetter(TypedConfigGetter getter) {
		typedGetter = getter == null ? DEFAULT_GETTER : getter;
	}

	/**
	 * Escape the value before saving
	 *
	 * @param x
	 *            the value to escape
	 * @return the escaped value
	 */
	static String escapeValue(String x) {
		if (x.isEmpty()) {
			return ""; //$NON-NLS-1$
		}

		boolean needQuote = x.charAt(0) == ' ' || x.charAt(x.length() - 1) == ' ';
		StringBuilder r = new StringBuilder(x.length());
		for (int k = 0; k < x.length(); k++) {
			char c = x.charAt(k);
			// git-config(1) lists the limited set of supported escape sequences, but
			// the documentation is otherwise not especially normative. In particular,
			// which ones of these produce and/or require escaping and/or quoting
			// around them is not documented and was discovered by trial and error.
			// In summary:
			//
			// * Quotes are only required if there is leading/trailing whitespace or a
			//   comment character.
			// * Bytes that have a supported escape sequence are escaped, except for
			//   \b for some reason which isn't.
			// * Needing an escape sequence is not sufficient reason to quote the
			//   value.
			switch (c) {
			case '\0':
				// Unix command line calling convention cannot pass a '\0' as an
				// argument, so there is no equivalent way in C git to store a null byte
				// in a config value.
				throw new IllegalArgumentException(
						JGitText.get().configValueContainsNullByte);

			case '\n':
				r.append('\\').append('n');
				break;

			case '\t':
				r.append('\\').append('t');
				break;

			case '\b':
				// Doesn't match `git config foo.bar $'x\by'`, which doesn't escape the
				// \x08, but since both escaped and unescaped forms are readable, we'll
				// prefer internal consistency here.
				r.append('\\').append('b');
				break;

			case '\\':
				r.append('\\').append('\\');
				break;

			case '"':
				r.append('\\').append('"');
				break;

			case '#':
			case ';':
				needQuote = true;
				r.append(c);
				break;

			default:
				r.append(c);
				break;
			}
		}

		return needQuote ? '"' + r.toString() + '"' : r.toString();
	}

	static String escapeSubsection(String x) {
		if (x.isEmpty()) {
			return "\"\""; //$NON-NLS-1$
		}

		StringBuilder r = new StringBuilder(x.length() + 2).append('"');
		for (int k = 0; k < x.length(); k++) {
			char c = x.charAt(k);

			// git-config(1) lists the limited set of supported escape sequences
			// (which is even more limited for subsection names than for values).
			switch (c) {
			case '\0':
				throw new IllegalArgumentException(
						JGitText.get().configSubsectionContainsNullByte);

			case '\n':
				throw new IllegalArgumentException(
						JGitText.get().configSubsectionContainsNewline);

			case '\\':
			case '"':
				r.append('\\').append(c);
				break;

			default:
				r.append(c);
				break;
			}
		}

		return r.append('"').toString();
	}

	/**
	 * Obtain an integer value from the configuration.
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return an integer value from the configuration, or defaultValue.
	 */
	public int getInt(final String section, final String name,
			final int defaultValue) {
		return typedGetter.getInt(this, section, null, name, defaultValue);
	}

	/**
	 * Obtain an integer value from the configuration.
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param subsection
	 *            subsection name, such a remote or branch name.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return an integer value from the configuration, or defaultValue.
	 */
	public int getInt(final String section, String subsection,
			final String name, final int defaultValue) {
		return typedGetter.getInt(this, section, subsection, name,
				defaultValue);
	}

	/**
	 * Obtain an integer value from the configuration.
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return an integer value from the configuration, or defaultValue.
	 */
	public long getLong(String section, String name, long defaultValue) {
		return typedGetter.getLong(this, section, null, name, defaultValue);
	}

	/**
	 * Obtain an integer value from the configuration.
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param subsection
	 *            subsection name, such a remote or branch name.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return an integer value from the configuration, or defaultValue.
	 */
	public long getLong(final String section, String subsection,
			final String name, final long defaultValue) {
		return typedGetter.getLong(this, section, subsection, name,
				defaultValue);
	}

	/**
	 * Get a boolean value from the git config
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return true if any value or defaultValue is true, false for missing or
	 *         explicit false
	 */
	public boolean getBoolean(final String section, final String name,
			final boolean defaultValue) {
		return typedGetter.getBoolean(this, section, null, name, defaultValue);
	}

	/**
	 * Get a boolean value from the git config
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param subsection
	 *            subsection name, such a remote or branch name.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return true if any value or defaultValue is true, false for missing or
	 *         explicit false
	 */
	public boolean getBoolean(final String section, String subsection,
			final String name, final boolean defaultValue) {
		return typedGetter.getBoolean(this, section, subsection, name,
				defaultValue);
	}

	/**
	 * Parse an enumeration from the configuration.
	 *
	 * @param section
	 *            section the key is grouped within.
	 * @param subsection
	 *            subsection name, such a remote or branch name.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return the selected enumeration value, or {@code defaultValue}.
	 */
	public <T extends Enum<?>> T getEnum(final String section,
			final String subsection, final String name, final T defaultValue) {
		final T[] all = allValuesOf(defaultValue);
		return typedGetter.getEnum(this, all, section, subsection, name,
				defaultValue);
	}

	@SuppressWarnings("unchecked")
	private static <T> T[] allValuesOf(T value) {
		try {
			return (T[]) value.getClass().getMethod("values").invoke(null); //$NON-NLS-1$
		} catch (Exception err) {
			String typeName = value.getClass().getName();
			String msg = MessageFormat.format(
					JGitText.get().enumValuesNotAvailable, typeName);
			throw new IllegalArgumentException(msg, err);
		}
	}

	/**
	 * Parse an enumeration from the configuration.
	 *
	 * @param all
	 *            all possible values in the enumeration which should be
	 *            recognized. Typically {@code EnumType.values()}.
	 * @param section
	 *            section the key is grouped within.
	 * @param subsection
	 *            subsection name, such a remote or branch name.
	 * @param name
	 *            name of the key to get.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @return the selected enumeration value, or {@code defaultValue}.
	 */
	public <T extends Enum<?>> T getEnum(final T[] all, final String section,
			final String subsection, final String name, final T defaultValue) {
		return typedGetter.getEnum(this, all, section, subsection, name,
				defaultValue);
	}

	/**
	 * Get string value or null if not found.
	 *
	 * @param section
	 *            the section
	 * @param subsection
	 *            the subsection for the value
	 * @param name
	 *            the key name
	 * @return a String value from the config, <code>null</code> if not found
	 */
	public String getString(final String section, String subsection,
			final String name) {
		return getRawString(section, subsection, name);
	}

	/**
	 * Get a list of string values
	 * <p>
	 * If this instance was created with a base, the base's values are returned
	 * first (if any).
	 *
	 * @param section
	 *            the section
	 * @param subsection
	 *            the subsection for the value
	 * @param name
	 *            the key name
	 * @return array of zero or more values from the configuration.
	 */
	public String[] getStringList(final String section, String subsection,
			final String name) {
		String[] base;
		if (baseConfig != null)
			base = baseConfig.getStringList(section, subsection, name);
		else
			base = EMPTY_STRING_ARRAY;

		String[] self = getRawStringList(section, subsection, name);
		if (self == null)
			return base;
		if (base.length == 0)
			return self;
		String[] res = new String[base.length + self.length];
		int n = base.length;
		System.arraycopy(base, 0, res, 0, n);
		System.arraycopy(self, 0, res, n, self.length);
		return res;
	}

	/**
	 * Parse a numerical time unit, such as "1 minute", from the configuration.
	 *
	 * @param section
	 *            section the key is in.
	 * @param subsection
	 *            subsection the key is in, or null if not in a subsection.
	 * @param name
	 *            the key name.
	 * @param defaultValue
	 *            default value to return if no value was present.
	 * @param wantUnit
	 *            the units of {@code defaultValue} and the return value, as
	 *            well as the units to assume if the value does not contain an
	 *            indication of the units.
	 * @return the value, or {@code defaultValue} if not set, expressed in
	 *         {@code units}.
	 * @since 4.5
	 */
	public long getTimeUnit(String section, String subsection, String name,
			long defaultValue, TimeUnit wantUnit) {
		return typedGetter.getTimeUnit(this, section, subsection, name,
				defaultValue, wantUnit);
	}

	/**
	 * Parse a string value and treat it as a file path, replacing a ~/ prefix
	 * by the user's home directory.
	 * <p>
	 * <b>Note:</b> this may throw {@link InvalidPathException} if the string is
	 * not a valid path.
	 * </p>
	 *
	 * @param section
	 *            section the key is in.
	 * @param subsection
	 *            subsection the key is in, or null if not in a subsection.
	 * @param name
	 *            the key name.
	 * @param fs
	 *            to use to convert the string into a path.
	 * @param resolveAgainst
	 *            directory to resolve the path against if it is a relative
	 *            path; {@code null} to use the Java process's current
	 *            directory.
	 * @param defaultValue
	 *            to return if no value was present
	 * @return the {@link Path}, or {@code defaultValue} if not set
	 * @since 5.10
	 */
	public Path getPath(String section, String subsection, String name,
			@NonNull FS fs, File resolveAgainst, Path defaultValue) {
		return typedGetter.getPath(this, section, subsection, name, fs,
				resolveAgainst, defaultValue);
	}

	/**
	 * Parse a list of {@link org.eclipse.jgit.transport.RefSpec}s from the
	 * configuration.
	 *
	 * @param section
	 *            section the key is in.
	 * @param subsection
	 *            subsection the key is in, or null if not in a subsection.
	 * @param name
	 *            the key name.
	 * @return a possibly empty list of
	 *         {@link org.eclipse.jgit.transport.RefSpec}s
	 * @since 4.9
	 */
	public List<RefSpec> getRefSpecs(String section, String subsection,
			String name) {
		return typedGetter.getRefSpecs(this, section, subsection, name);
	}

	/**
	 * Get set of all subsections of specified section within this configuration
	 * and its base configuration
	 *
	 * @param section
	 *            section to search for.
	 * @return set of all subsections of specified section within this
	 *         configuration and its base configuration; may be empty if no
	 *         subsection exists. The set's iterator returns sections in the
	 *         order they are declared by the configuration starting from this
	 *         instance and progressing through the base.
	 */
	public Set<String> getSubsections(String section) {
		return getState().getSubsections(section);
	}

	/**
	 * Get the sections defined in this {@link org.eclipse.jgit.lib.Config}.
	 *
	 * @return the sections defined in this {@link org.eclipse.jgit.lib.Config}.
	 *         The set's iterator returns sections in the order they are
	 *         declared by the configuration starting from this instance and
	 *         progressing through the base.
	 */
	public Set<String> getSections() {
		return getState().getSections();
	}

	/**
	 * Get the list of names defined for this section
	 *
	 * @param section
	 *            the section
	 * @return the list of names defined for this section
	 */
	public Set<String> getNames(String section) {
		return getNames(section, null);
	}

	/**
	 * Get the list of names defined for this subsection
	 *
	 * @param section
	 *            the section
	 * @param subsection
	 *            the subsection
	 * @return the list of names defined for this subsection
	 */
	public Set<String> getNames(String section, String subsection) {
		return getState().getNames(section, subsection);
	}

	/**
	 * Get the list of names defined for this section
	 *
	 * @param section
	 *            the section
	 * @param recursive
	 *            if {@code true} recursively adds the names defined in all base
	 *            configurations
	 * @return the list of names defined for this section
	 * @since 3.2
	 */
	public Set<String> getNames(String section, boolean recursive) {
		return getState().getNames(section, null, recursive);
	}

	/**
	 * Get the list of names defined for this section
	 *
	 * @param section
	 *            the section
	 * @param subsection
	 *            the subsection
	 * @param recursive
	 *            if {@code true} recursively adds the names defined in all base
	 *            configurations
	 * @return the list of names defined for this subsection
	 * @since 3.2
	 */
	public Set<String> getNames(String section, String subsection,
			boolean recursive) {
		return getState().getNames(section, subsection, recursive);
	}

	/**
	 * Obtain a handle to a parsed set of configuration values.
	 *
	 * @param <T>
	 *            type of configuration model to return.
	 * @param parser
	 *            parser which can create the model if it is not already
	 *            available in this configuration file. The parser is also used
	 *            as the key into a cache and must obey the hashCode and equals
	 *            contract in order to reuse a parsed model.
	 * @return the parsed object instance, which is cached inside this config.
	 */
	@SuppressWarnings("unchecked")
	public <T> T get(SectionParser<T> parser) {
		final ConfigSnapshot myState = getState();
		T obj = (T) myState.cache.get(parser);
		if (obj == null) {
			obj = parser.parse(this);
			myState.cache.put(parser, obj);
		}
		return obj;
	}

	/**
	 * Remove a cached configuration object.
	 * <p>
	 * If the associated configuration object has not yet been cached, this
	 * method has no effect.
	 *
	 * @param parser
	 *            parser used to obtain the configuration object.
	 * @see #get(SectionParser)
	 */
	public void uncache(SectionParser<?> parser) {
		state.get().cache.remove(parser);
	}

	/**
	 * Adds a listener to be notified about changes.
	 * <p>
	 * Clients are supposed to remove the listeners after they are done with
	 * them using the {@link org.eclipse.jgit.events.ListenerHandle#remove()}
	 * method
	 *
	 * @param listener
	 *            the listener
	 * @return the handle to the registered listener
	 */
	public ListenerHandle addChangeListener(ConfigChangedListener listener) {
		return listeners.addConfigChangedListener(listener);
	}

	/**
	 * Determine whether to issue change events for transient changes.
	 * <p>
	 * If <code>true</code> is returned (which is the default behavior),
	 * {@link #fireConfigChangedEvent()} will be called upon each change.
	 * <p>
	 * Subclasses that override this to return <code>false</code> are
	 * responsible for issuing {@link #fireConfigChangedEvent()} calls
	 * themselves.
	 *
	 * @return <code></code>
	 */
	protected boolean notifyUponTransientChanges() {
		return true;
	}

	/**
	 * Notifies the listeners
	 */
	protected void fireConfigChangedEvent() {
		listeners.dispatch(new ConfigChangedEvent());
	}

	String getRawString(final String section, final String subsection,
			final String name) {
		String[] lst = getRawStringList(section, subsection, name);
		if (lst != null) {
			return lst[lst.length - 1];
		} else if (baseConfig != null) {
			return baseConfig.getRawString(section, subsection, name);
		} else {
			return null;
		}
	}

	private String[] getRawStringList(String section, String subsection,
			String name) {
		return state.get().get(section, subsection, name);
	}

	private ConfigSnapshot getState() {
		ConfigSnapshot cur, upd;
		do {
			cur = state.get();
			final ConfigSnapshot base = getBaseState();
			if (cur.baseState == base)
				return cur;
			upd = new ConfigSnapshot(cur.entryList, base);
		} while (!state.compareAndSet(cur, upd));
		return upd;
	}

	private ConfigSnapshot getBaseState() {
		return baseConfig != null ? baseConfig.getState() : null;
	}

	/**
	 * Add or modify a configuration value. The parameters will result in a
	 * configuration entry like this.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param value
	 *            parameter value
	 */
	public void setInt(final String section, final String subsection,
			final String name, final int value) {
		setLong(section, subsection, name, value);
	}

	/**
	 * Add or modify a configuration value. The parameters will result in a
	 * configuration entry like this.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param value
	 *            parameter value
	 */
	public void setLong(final String section, final String subsection,
			final String name, final long value) {
		final String s;

		if (value >= GiB && (value % GiB) == 0)
			s = String.valueOf(value / GiB) + "g"; //$NON-NLS-1$
		else if (value >= MiB && (value % MiB) == 0)
			s = String.valueOf(value / MiB) + "m"; //$NON-NLS-1$
		else if (value >= KiB && (value % KiB) == 0)
			s = String.valueOf(value / KiB) + "k"; //$NON-NLS-1$
		else
			s = String.valueOf(value);

		setString(section, subsection, name, s);
	}

	/**
	 * Add or modify a configuration value. The parameters will result in a
	 * configuration entry like this.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param value
	 *            parameter value
	 */
	public void setBoolean(final String section, final String subsection,
			final String name, final boolean value) {
		setString(section, subsection, name, value ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Add or modify a configuration value. The parameters will result in a
	 * configuration entry like this.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param value
	 *            parameter value
	 */
	public <T extends Enum<?>> void setEnum(final String section,
			final String subsection, final String name, final T value) {
		String n;
		if (value instanceof ConfigEnum)
			n = ((ConfigEnum) value).toConfigValue();
		else
			n = value.name().toLowerCase(Locale.ROOT).replace('_', ' ');
		setString(section, subsection, name, n);
	}

	/**
	 * Add or modify a configuration value. The parameters will result in a
	 * configuration entry like this.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param value
	 *            parameter value, e.g. "true"
	 */
	public void setString(final String section, final String subsection,
			final String name, final String value) {
		setStringList(section, subsection, name, Collections
				.singletonList(value));
	}

	/**
	 * Remove a configuration value.
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 */
	public void unset(final String section, final String subsection,
			final String name) {
		setStringList(section, subsection, name, Collections
				.<String> emptyList());
	}

	/**
	 * Remove all configuration values under a single section.
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 */
	public void unsetSection(String section, String subsection) {
		ConfigSnapshot src, res;
		do {
			src = state.get();
			res = unsetSection(src, section, subsection);
		} while (!state.compareAndSet(src, res));
	}

	private ConfigSnapshot unsetSection(final ConfigSnapshot srcState,
			final String section,
			final String subsection) {
		final int max = srcState.entryList.size();
		final ArrayList<ConfigLine> r = new ArrayList<>(max);

		boolean lastWasMatch = false;
		for (ConfigLine e : srcState.entryList) {
			if (e.includedFrom == null && e.match(section, subsection)) {
				// Skip this record, it's for the section we are removing.
				lastWasMatch = true;
				continue;
			}

			if (lastWasMatch && e.section == null && e.subsection == null)
				continue; // skip this padding line in the section.
			r.add(e);
		}

		return newState(r);
	}

	/**
	 * Set a configuration value.
	 *
	 * <pre>
	 * [section &quot;subsection&quot;]
	 *         name = value1
	 *         name = value2
	 * </pre>
	 *
	 * @param section
	 *            section name, e.g "branch"
	 * @param subsection
	 *            optional subsection value, e.g. a branch name
	 * @param name
	 *            parameter name, e.g. "filemode"
	 * @param values
	 *            list of zero or more values for this key.
	 */
	public void setStringList(final String section, final String subsection,
			final String name, final List<String> values) {
		ConfigSnapshot src, res;
		do {
			src = state.get();
			res = replaceStringList(src, section, subsection, name, values);
		} while (!state.compareAndSet(src, res));
		if (notifyUponTransientChanges())
			fireConfigChangedEvent();
	}

	private ConfigSnapshot replaceStringList(final ConfigSnapshot srcState,
			final String section, final String subsection, final String name,
			final List<String> values) {
		final List<ConfigLine> entries = copy(srcState, values);
		int entryIndex = 0;
		int valueIndex = 0;
		int insertPosition = -1;

		// Reset the first n Entry objects that match this input name.
		//
		while (entryIndex < entries.size() && valueIndex < values.size()) {
			final ConfigLine e = entries.get(entryIndex);
			if (e.includedFrom == null && e.match(section, subsection, name)) {
				entries.set(entryIndex, e.forValue(values.get(valueIndex++)));
				insertPosition = entryIndex + 1;
			}
			entryIndex++;
		}

		// Remove any extra Entry objects that we no longer need.
		//
		if (valueIndex == values.size() && entryIndex < entries.size()) {
			while (entryIndex < entries.size()) {
				final ConfigLine e = entries.get(entryIndex++);
				if (e.includedFrom == null
						&& e.match(section, subsection, name))
					entries.remove(--entryIndex);
			}
		}

		// Insert new Entry objects for additional/new values.
		//
		if (valueIndex < values.size() && entryIndex == entries.size()) {
			if (insertPosition < 0) {
				// We didn't find a matching key above, but maybe there
				// is already a section available that matches. Insert
				// after the last key of that section.
				//
				insertPosition = findSectionEnd(entries, section, subsection,
						true);
			}
			if (insertPosition < 0) {
				// We didn't find any matching section header for this key,
				// so we must create a new section header at the end.
				//
				final ConfigLine e = new ConfigLine();
				e.section = section;
				e.subsection = subsection;
				entries.add(e);
				insertPosition = entries.size();
			}
			while (valueIndex < values.size()) {
				final ConfigLine e = new ConfigLine();
				e.section = section;
				e.subsection = subsection;
				e.name = name;
				e.value = values.get(valueIndex++);
				entries.add(insertPosition++, e);
			}
		}

		return newState(entries);
	}

	private static List<ConfigLine> copy(final ConfigSnapshot src,
			final List<String> values) {
		// At worst we need to insert 1 line for each value, plus 1 line
		// for a new section header. Assume that and allocate the space.
		//
		final int max = src.entryList.size() + values.size() + 1;
		final ArrayList<ConfigLine> r = new ArrayList<>(max);
		r.addAll(src.entryList);
		return r;
	}

	private static int findSectionEnd(final List<ConfigLine> entries,
			final String section, final String subsection,
			boolean skipIncludedLines) {
		for (int i = 0; i < entries.size(); i++) {
			ConfigLine e = entries.get(i);
			if (e.includedFrom != null && skipIncludedLines) {
				continue;
			}

			if (e.match(section, subsection, null)) {
				i++;
				while (i < entries.size()) {
					e = entries.get(i);
					if (e.match(section, subsection, e.name))
						i++;
					else
						break;
				}
				return i;
			}
		}
		return -1;
	}

	/**
	 * Get this configuration, formatted as a Git style text file.
	 *
	 * @return this configuration, formatted as a Git style text file.
	 */
	public String toText() {
		final StringBuilder out = new StringBuilder();
		for (ConfigLine e : state.get().entryList) {
			if (e.includedFrom != null)
				continue;
			if (e.prefix != null)
				out.append(e.prefix);
			if (e.section != null && e.name == null) {
				out.append('[');
				out.append(e.section);
				if (e.subsection != null) {
					out.append(' ');
					String escaped = escapeValue(e.subsection);
					// make sure to avoid double quotes here
					boolean quoted = escaped.startsWith("\"") //$NON-NLS-1$
							&& escaped.endsWith("\""); //$NON-NLS-1$
					if (!quoted)
						out.append('"');
					out.append(escaped);
					if (!quoted)
						out.append('"');
				}
				out.append(']');
			} else if (e.section != null && e.name != null) {
				if (e.prefix == null || "".equals(e.prefix)) //$NON-NLS-1$
					out.append('\t');
				out.append(e.name);
				if (!isMissing(e.value)) {
					out.append(" ="); //$NON-NLS-1$
					if (e.value != null) {
						out.append(' ');
						out.append(escapeValue(e.value));
					}
				}
				if (e.suffix != null)
					out.append(' ');
			}
			if (e.suffix != null)
				out.append(e.suffix);
			out.append('\n');
		}
		return out.toString();
	}

	/**
	 * Clear this configuration and reset to the contents of the parsed string.
	 *
	 * @param text
	 *            Git style text file listing configuration properties.
	 * @throws org.eclipse.jgit.errors.ConfigInvalidException
	 *             the text supplied is not formatted correctly. No changes were
	 *             made to {@code this}.
	 */
	public void fromText(String text) throws ConfigInvalidException {
		state.set(newState(fromTextRecurse(text, 1, null)));
	}

	private List<ConfigLine> fromTextRecurse(String text, int depth,
			String includedFrom) throws ConfigInvalidException {
		if (depth > MAX_DEPTH) {
			throw new ConfigInvalidException(
					JGitText.get().tooManyIncludeRecursions);
		}
		final List<ConfigLine> newEntries = new ArrayList<>();
		final StringReader in = new StringReader(text);
		ConfigLine last = null;
		ConfigLine e = new ConfigLine();
		e.includedFrom = includedFrom;
		for (;;) {
			int input = in.read();
			if (-1 == input) {
				if (e.section != null)
					newEntries.add(e);
				break;
			}

			final char c = (char) input;
			if ('\n' == c) {
				// End of this entry.
				newEntries.add(e);
				if (e.section != null)
					last = e;
				e = new ConfigLine();
				e.includedFrom = includedFrom;
			} else if (e.suffix != null) {
				// Everything up until the end-of-line is in the suffix.
				e.suffix += c;

			} else if (';' == c || '#' == c) {
				// The rest of this line is a comment; put into suffix.
				e.suffix = String.valueOf(c);

			} else if (e.section == null && Character.isWhitespace(c)) {
				// Save the leading whitespace (if any).
				if (e.prefix == null)
					e.prefix = ""; //$NON-NLS-1$
				e.prefix += c;

			} else if ('[' == c) {
				// This is a section header.
				e.section = readSectionName(in);
				input = in.read();
				if ('"' == input) {
					e.subsection = readSubsectionName(in);
					input = in.read();
				}
				if (']' != input)
					throw new ConfigInvalidException(JGitText.get().badGroupHeader);
				e.suffix = ""; //$NON-NLS-1$

			} else if (last != null) {
				// Read a value.
				e.section = last.section;
				e.subsection = last.subsection;
				in.reset();
				e.name = readKeyName(in);
				if (e.name.endsWith("\n")) { //$NON-NLS-1$
					e.name = e.name.substring(0, e.name.length() - 1);
					e.value = MISSING_ENTRY;
				} else
					e.value = readValue(in);

				if (e.section.equalsIgnoreCase("include")) { //$NON-NLS-1$
					addIncludedConfig(newEntries, e, depth);
				}
			} else
				throw new ConfigInvalidException(JGitText.get().invalidLineInConfigFile);
		}

		return newEntries;
	}

	/**
	 * Read the included config from the specified (possibly) relative path
	 *
	 * @param relPath
	 *            possibly relative path to the included config, as specified in
	 *            this config
	 * @return the read bytes, or null if the included config should be ignored
	 * @throws org.eclipse.jgit.errors.ConfigInvalidException
	 *             if something went wrong while reading the config
	 * @since 4.10
	 */
	protected byte[] readIncludedConfig(String relPath)
			throws ConfigInvalidException {
		return null;
	}

	private void addIncludedConfig(final List<ConfigLine> newEntries,
			ConfigLine line, int depth) throws ConfigInvalidException {
		if (!line.name.equalsIgnoreCase("path") || //$NON-NLS-1$
				line.value == null || line.value.equals(MISSING_ENTRY)) {
			throw new ConfigInvalidException(MessageFormat.format(
					JGitText.get().invalidLineInConfigFileWithParam, line));
		}
		byte[] bytes = readIncludedConfig(line.value);
		if (bytes == null) {
			return;
		}

		String decoded;
		if (isUtf8(bytes)) {
			decoded = RawParseUtils.decode(UTF_8, bytes, 3, bytes.length);
		} else {
			decoded = RawParseUtils.decode(bytes);
		}
		try {
			newEntries.addAll(fromTextRecurse(decoded, depth + 1, line.value));
		} catch (ConfigInvalidException e) {
			throw new ConfigInvalidException(MessageFormat
					.format(JGitText.get().cannotReadFile, line.value), e);
		}
	}

	private ConfigSnapshot newState() {
		return new ConfigSnapshot(Collections.<ConfigLine> emptyList(),
				getBaseState());
	}

	private ConfigSnapshot newState(List<ConfigLine> entries) {
		return new ConfigSnapshot(Collections.unmodifiableList(entries),
				getBaseState());
	}

	/**
	 * Clear the configuration file
	 */
	protected void clear() {
		state.set(newState());
	}

	/**
	 * Check if bytes should be treated as UTF-8 or not.
	 *
	 * @param bytes
	 *            the bytes to check encoding for.
	 * @return true if bytes should be treated as UTF-8, false otherwise.
	 * @since 4.4
	 */
	protected boolean isUtf8(final byte[] bytes) {
		return bytes.length >= 3 && bytes[0] == (byte) 0xEF
				&& bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF;
	}

	private static String readSectionName(StringReader in)
			throws ConfigInvalidException {
		final StringBuilder name = new StringBuilder();
		for (;;) {
			int c = in.read();
			if (c < 0)
				throw new ConfigInvalidException(JGitText.get().unexpectedEndOfConfigFile);

			if (']' == c) {
				in.reset();
				break;
			}

			if (' ' == c || '\t' == c) {
				for (;;) {
					c = in.read();
					if (c < 0)
						throw new ConfigInvalidException(JGitText.get().unexpectedEndOfConfigFile);

					if ('"' == c) {
						in.reset();
						break;
					}

					if (' ' == c || '\t' == c)
						continue; // Skipped...
					throw new ConfigInvalidException(MessageFormat.format(JGitText.get().badSectionEntry, name));
				}
				break;
			}

			if (Character.isLetterOrDigit((char) c) || '.' == c || '-' == c)
				name.append((char) c);
			else
				throw new ConfigInvalidException(MessageFormat.format(JGitText.get().badSectionEntry, name));
		}
		return name.toString();
	}

	private static String readKeyName(StringReader in)
			throws ConfigInvalidException {
		final StringBuilder name = new StringBuilder();
		for (;;) {
			int c = in.read();
			if (c < 0)
				throw new ConfigInvalidException(JGitText.get().unexpectedEndOfConfigFile);

			if ('=' == c)
				break;

			if (' ' == c || '\t' == c) {
				for (;;) {
					c = in.read();
					if (c < 0)
						throw new ConfigInvalidException(JGitText.get().unexpectedEndOfConfigFile);

					if ('=' == c)
						break;

					if (';' == c || '#' == c || '\n' == c) {
						in.reset();
						break;
					}

					if (' ' == c || '\t' == c)
						continue; // Skipped...
					throw new ConfigInvalidException(JGitText.get().badEntryDelimiter);
				}
				break;
			}

			if (Character.isLetterOrDigit((char) c) || c == '-') {
				// From the git-config man page:
				// The variable names are case-insensitive and only
				// alphanumeric characters and - are allowed.
				name.append((char) c);
			} else if ('\n' == c) {
				in.reset();
				name.append((char) c);
				break;
			} else
				throw new ConfigInvalidException(MessageFormat.format(JGitText.get().badEntryName, name));
		}
		return name.toString();
	}

	private static String readSubsectionName(StringReader in)
			throws ConfigInvalidException {
		StringBuilder r = new StringBuilder();
		for (;;) {
			int c = in.read();
			if (c < 0) {
				break;
			}

			if ('\n' == c) {
				throw new ConfigInvalidException(
						JGitText.get().newlineInQuotesNotAllowed);
			}
			if ('\\' == c) {
				c = in.read();
				switch (c) {
				case -1:
					throw new ConfigInvalidException(JGitText.get().endOfFileInEscape);

				case '\\':
				case '"':
					r.append((char) c);
					continue;

				default:
					// C git simply drops backslashes if the escape sequence is not
					// recognized.
					r.append((char) c);
					continue;
				}
			}
			if ('"' == c) {
				break;
			}

			r.append((char) c);
		}
		return r.toString();
	}

	private static String readValue(StringReader in)
			throws ConfigInvalidException {
		StringBuilder value = new StringBuilder();
		StringBuilder trailingSpaces = null;
		boolean quote = false;
		boolean inLeadingSpace = true;

		for (;;) {
			int c = in.read();
			if (c < 0) {
				break;
			}
			if ('\n' == c) {
				if (quote) {
					throw new ConfigInvalidException(
							JGitText.get().newlineInQuotesNotAllowed);
				}
				in.reset();
				break;
			}

			if (!quote && (';' == c || '#' == c)) {
				if (trailingSpaces != null) {
					trailingSpaces.setLength(0);
				}
				in.reset();
				break;
			}

			char cc = (char) c;
			if (Character.isWhitespace(cc)) {
				if (inLeadingSpace) {
					continue;
				}
				if (trailingSpaces == null) {
					trailingSpaces = new StringBuilder();
				}
				trailingSpaces.append(cc);
				continue;
			}
			inLeadingSpace = false;
			if (trailingSpaces != null) {
				value.append(trailingSpaces);
				trailingSpaces.setLength(0);
			}

			if ('\\' == c) {
				c = in.read();
				switch (c) {
				case -1:
					throw new ConfigInvalidException(JGitText.get().endOfFileInEscape);
				case '\n':
					continue;
				case 't':
					value.append('\t');
					continue;
				case 'b':
					value.append('\b');
					continue;
				case 'n':
					value.append('\n');
					continue;
				case '\\':
					value.append('\\');
					continue;
				case '"':
					value.append('"');
					continue;
				case '\r': {
					int next = in.read();
					if (next == '\n') {
						continue; // CR-LF
					} else if (next >= 0) {
						in.reset();
					}
					break;
				}
				default:
					break;
				}
				throw new ConfigInvalidException(
						MessageFormat.format(JGitText.get().badEscape,
								Character.isAlphabetic(c)
										? Character.valueOf(((char) c))
										: toUnicodeLiteral(c)));
			}

			if ('"' == c) {
				quote = !quote;
				continue;
			}

			value.append(cc);
		}
		return value.length() > 0 ? value.toString() : null;
	}

	private static String toUnicodeLiteral(int c) {
		return String.format("\\u%04x", //$NON-NLS-1$
				Integer.valueOf(c));
	}

	/**
	 * Parses a section of the configuration into an application model object.
	 * <p>
	 * Instances must implement hashCode and equals such that model objects can
	 * be cached by using the {@code SectionParser} as a key of a HashMap.
	 * <p>
	 * As the {@code SectionParser} itself is used as the key of the internal
	 * HashMap applications should be careful to ensure the SectionParser key
	 * does not retain unnecessary application state which may cause memory to
	 * be held longer than expected.
	 *
	 * @param <T>
	 *            type of the application model created by the parser.
	 */
	public static interface SectionParser<T> {
		/**
		 * Create a model object from a configuration.
		 *
		 * @param cfg
		 *            the configuration to read values from.
		 * @return the application model instance.
		 */
		T parse(Config cfg);
	}

	private static class StringReader {
		private final char[] buf;

		private int pos;

		StringReader(String in) {
			buf = in.toCharArray();
		}

		int read() {
			if (pos >= buf.length) {
				return -1;
			}
			return buf[pos++];
		}

		void reset() {
			pos--;
		}
	}

	/**
	 * Converts enumeration values into configuration options and vice-versa,
	 * allowing to match a config option with an enum value.
	 *
	 */
	public static interface ConfigEnum {
		/**
		 * Converts enumeration value into a string to be save in config.
		 *
		 * @return the enum value as config string
		 */
		String toConfigValue();

		/**
		 * Checks if the given string matches with enum value.
		 *
		 * @param in
		 *            the string to match
		 * @return true if the given string matches enum value, false otherwise
		 */
		boolean matchConfigValue(String in);
	}
}
