// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.project;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.gerrit.entities.Permission.isPermission;
import static com.google.gerrit.entities.Project.DEFAULT_SUBMIT_TYPE;
import static com.google.gerrit.server.permissions.PluginPermissionsUtil.isValidPluginPermission;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Shorts;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.AccountsSection;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.BranchOrderSection;
import com.google.gerrit.entities.CachedProjectConfig;
import com.google.gerrit.entities.ConfiguredMimeTypes;
import com.google.gerrit.entities.ContributorAgreement;
import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.LabelFunction;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelValue;
import com.google.gerrit.entities.NotifyConfig;
import com.google.gerrit.entities.NotifyConfig.NotifyType;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.PermissionRule;
import com.google.gerrit.entities.PermissionRule.Action;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.entities.StoredCommentLinkInfo;
import com.google.gerrit.entities.SubmitRequirement;
import com.google.gerrit.entities.SubmitRequirementExpression;
import com.google.gerrit.entities.SubscribeSection;
import com.google.gerrit.exceptions.InvalidNameException;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.AllProjectsConfigProvider;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.ValidationError;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevWalk;

public class ProjectConfig extends VersionedMetaData implements ValidationError.Sink {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static final String COMMENTLINK = "commentlink";
  public static final String LABEL = "label";
  public static final String KEY_FUNCTION = "function";
  public static final String KEY_DEFAULT_VALUE = "defaultValue";
  public static final String KEY_COPY_MIN_SCORE = "copyMinScore";
  public static final String KEY_ALLOW_POST_SUBMIT = "allowPostSubmit";
  public static final String KEY_IGNORE_SELF_APPROVAL = "ignoreSelfApproval";
  public static final String KEY_COPY_ANY_SCORE = "copyAnyScore";
  public static final String KEY_COPY_CONDITION = "copyCondition";
  public static final String KEY_COPY_MAX_SCORE = "copyMaxScore";
  public static final String KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE =
      "copyAllScoresIfListOfFilesDidNotChange";
  public static final String KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE =
      "copyAllScoresOnMergeFirstParentUpdate";
  public static final String KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE = "copyAllScoresOnTrivialRebase";
  public static final String KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE = "copyAllScoresIfNoCodeChange";
  public static final String KEY_COPY_ALL_SCORES_IF_NO_CHANGE = "copyAllScoresIfNoChange";
  public static final String KEY_COPY_VALUE = "copyValue";
  public static final String KEY_VALUE = "value";
  public static final String KEY_CAN_OVERRIDE = "canOverride";
  public static final String KEY_BRANCH = "branch";

  public static final String SUBMIT_REQUIREMENT = "submit-requirement";
  public static final String KEY_SR_DESCRIPTION = "description";
  public static final String KEY_SR_APPLICABILITY_EXPRESSION = "applicableIf";
  public static final String KEY_SR_SUBMITTABILITY_EXPRESSION = "submittableIf";
  public static final String KEY_SR_OVERRIDE_EXPRESSION = "overrideIf";
  public static final String KEY_SR_OVERRIDE_IN_CHILD_PROJECTS = "canOverrideInChildProjects";

  public static final String KEY_MATCH = "match";
  private static final String KEY_HTML = "html";
  public static final String KEY_LINK = "link";
  public static final String KEY_ENABLED = "enabled";

  public static final String PROJECT_CONFIG = "project.config";

  private static final String PROJECT = "project";
  private static final String KEY_DESCRIPTION = "description";

  public static final String ACCESS = "access";
  private static final String KEY_INHERIT_FROM = "inheritFrom";
  private static final String KEY_GROUP_PERMISSIONS = "exclusiveGroupPermissions";

  private static final String ACCOUNTS = "accounts";
  private static final String KEY_SAME_GROUP_VISIBILITY = "sameGroupVisibility";

  private static final String BRANCH_ORDER = "branchOrder";
  private static final String BRANCH = "branch";

  private static final String CONTRIBUTOR_AGREEMENT = "contributor-agreement";
  private static final String KEY_ACCEPTED = "accepted";
  private static final String KEY_AUTO_VERIFY = "autoVerify";
  private static final String KEY_AGREEMENT_URL = "agreementUrl";
  private static final String KEY_MATCH_PROJECTS = "matchProjects";
  private static final String KEY_EXCLUDE_PROJECTS = "excludeProjects";

  private static final String NOTIFY = "notify";
  private static final String KEY_EMAIL = "email";
  private static final String KEY_FILTER = "filter";
  private static final String KEY_TYPE = "type";
  private static final String KEY_HEADER = "header";

  private static final String CAPABILITY = "capability";

  private static final String RECEIVE = "receive";
  private static final String KEY_CHECK_RECEIVED_OBJECTS = "checkReceivedObjects";

  private static final String SUBMIT = "submit";
  private static final String KEY_ACTION = "action";
  private static final String KEY_STATE = "state";

  private static final String KEY_MAX_OBJECT_SIZE_LIMIT = "maxObjectSizeLimit";

  private static final String SUBSCRIBE_SECTION = "allowSuperproject";
  private static final String SUBSCRIBE_MATCH_REFS = "matching";
  private static final String SUBSCRIBE_MULTI_MATCH_REFS = "all";

  private static final String DASHBOARD = "dashboard";
  private static final String KEY_DEFAULT = "default";
  private static final String KEY_LOCAL_DEFAULT = "local-default";

  private static final String LEGACY_PERMISSION_PUSH_TAG = "pushTag";
  private static final String LEGACY_PERMISSION_PUSH_SIGNED_TAG = "pushSignedTag";

  private static final String PLUGIN = "plugin";

  private static final ProjectState DEFAULT_STATE_VALUE = ProjectState.ACTIVE;

  private static final String EXTENSION_PANELS = "extension-panels";
  private static final String KEY_PANEL = "panel";

  private static final Pattern EXCLUSIVE_PERMISSIONS_SPLIT_PATTERN = Pattern.compile("[, \t]{1,}");

  // Don't use an assisted factory, since instances created by an assisted factory retain references
  // to their enclosing injector. Instances of ProjectConfig are cached for a long time in the
  // ProjectCache, so this would retain lots more memory.
  @Singleton
  public static class Factory {
    private final AllProjectsName allProjectsName;
    private final AllProjectsConfigProvider allProjectsConfigProvider;

    @Inject
    Factory(AllProjectsName allProjectsName, AllProjectsConfigProvider allProjectsConfigProvider) {
      this.allProjectsName = allProjectsName;
      this.allProjectsConfigProvider = allProjectsConfigProvider;
    }

    public ProjectConfig create(Project.NameKey projectName) {
      return new ProjectConfig(
          projectName,
          projectName.equals(allProjectsName)
              ? allProjectsConfigProvider.get(allProjectsName)
              : Optional.empty(),
          allProjectsName);
    }

    public ProjectConfig read(MetaDataUpdate update) throws IOException, ConfigInvalidException {
      ProjectConfig r = create(update.getProjectName());
      r.load(update);
      return r;
    }

    public ProjectConfig read(MetaDataUpdate update, ObjectId id)
        throws IOException, ConfigInvalidException {
      ProjectConfig r = create(update.getProjectName());
      r.load(update, id);
      return r;
    }

    @UsedAt(UsedAt.Project.COLLABNET)
    public ProjectConfig read(Repository repo, Project.NameKey name)
        throws IOException, ConfigInvalidException {
      ProjectConfig r = create(name);
      r.load(repo);
      return r;
    }
  }

  private final Optional<StoredConfig> baseConfig;
  private final AllProjectsName allProjectsName;

  private Project project;
  private AccountsSection accountsSection;
  private GroupList groupList;
  private Map<String, AccessSection> accessSections;
  private BranchOrderSection branchOrderSection;
  private Map<String, ContributorAgreement> contributorAgreements;
  private Map<String, NotifyConfig> notifySections;
  private Map<String, LabelType> labelSections;
  private Map<String, SubmitRequirement> submitRequirementSections;
  private ConfiguredMimeTypes mimeTypes;
  private Map<Project.NameKey, SubscribeSection> subscribeSections;
  private Map<String, StoredCommentLinkInfo> commentLinkSections;
  private List<ValidationError> validationErrors;
  private ObjectId rulesId;
  private long maxObjectSizeLimit;
  private Map<String, Config> pluginConfigs;
  private Map<String, Config> projectLevelConfigs;
  private boolean checkReceivedObjects;
  private Set<String> sectionsWithUnknownPermissions;
  private boolean hasLegacyPermissions;
  private Map<String, List<String>> extensionPanelSections;

  /** Returns an immutable, thread-safe representation of this object that can be cached. */
  public CachedProjectConfig getCacheable() {
    CachedProjectConfig.Builder builder =
        CachedProjectConfig.builder()
            .setProject(project)
            .setAccountsSection(accountsSection)
            .setBranchOrderSection(Optional.ofNullable(branchOrderSection))
            .setMimeTypes(mimeTypes)
            .setRulesId(Optional.ofNullable(rulesId))
            .setRevision(Optional.ofNullable(getRevision()))
            .setMaxObjectSizeLimit(maxObjectSizeLimit)
            .setCheckReceivedObjects(checkReceivedObjects)
            .setExtensionPanelSections(extensionPanelSections);
    groupList.byUUID().values().forEach(g -> builder.addGroup(g));
    contributorAgreements.values().forEach(c -> builder.addContributorAgreement(c));
    notifySections.values().forEach(n -> builder.addNotifySection(n));
    subscribeSections.values().forEach(s -> builder.addSubscribeSection(s));
    commentLinkSections.values().forEach(c -> builder.addCommentLinkSection(c));
    labelSections.values().forEach(l -> builder.addLabelSection(l));
    submitRequirementSections.values().forEach(sr -> builder.addSubmitRequirementSection(sr));
    pluginConfigs
        .entrySet()
        .forEach(c -> builder.addPluginConfig(c.getKey(), c.getValue().toText()));
    projectLevelConfigs
        .entrySet()
        .forEach(c -> builder.addProjectLevelConfig(c.getKey(), c.getValue().toText()));

    if (projectName.equals(allProjectsName)) {
      // Filter out permissions that aren't allowed to be set on All-Projects
      accessSections
          .values()
          .forEach(
              a -> {
                List<Permission.Builder> copy = new ArrayList<>();
                for (Permission p : a.getPermissions()) {
                  if (Permission.canBeOnAllProjects(a.getName(), p.getName())) {
                    copy.add(p.toBuilder());
                  }
                }
                AccessSection section =
                    AccessSection.builder(a.getName())
                        .modifyPermissions(permissions -> permissions.addAll(copy))
                        .build();
                builder.addAccessSection(section);
              });
    } else {
      accessSections.values().forEach(a -> builder.addAccessSection(a));
    }
    return builder.build();
  }

  public static StoredCommentLinkInfo buildCommentLink(Config cfg, String name, boolean allowRaw)
      throws IllegalArgumentException {
    String match = cfg.getString(COMMENTLINK, name, KEY_MATCH);
    if (match != null) {
      // Unfortunately this validation isn't entirely complete. Clients
      // can have exceptions trying to evaluate the pattern if they don't
      // support a token used, even if the server does support the token.
      //
      // At the minimum, we can trap problems related to unmatched groups.
      Pattern.compile(match);
    }

    String link = cfg.getString(COMMENTLINK, name, KEY_LINK);
    String html = cfg.getString(COMMENTLINK, name, KEY_HTML);
    boolean hasHtml = !Strings.isNullOrEmpty(html);

    String rawEnabled = cfg.getString(COMMENTLINK, name, KEY_ENABLED);
    Boolean enabled;
    if (rawEnabled != null) {
      enabled = cfg.getBoolean(COMMENTLINK, name, KEY_ENABLED, true);
    } else {
      enabled = null;
    }
    checkArgument(allowRaw || !hasHtml, "Raw html replacement not allowed");

    if (Strings.isNullOrEmpty(match)
        && Strings.isNullOrEmpty(link)
        && !hasHtml
        && enabled != null) {
      if (enabled) {
        return StoredCommentLinkInfo.enabled(name);
      }
      return StoredCommentLinkInfo.disabled(name);
    }
    return StoredCommentLinkInfo.builder(name)
        .setMatch(match)
        .setLink(link)
        .setHtml(html)
        .setEnabled(enabled)
        .setOverrideOnly(false)
        .build();
  }

  public void addCommentLinkSection(StoredCommentLinkInfo commentLink) {
    commentLinkSections.put(commentLink.getName(), commentLink);
  }

  public void removeCommentLinkSection(String name) {
    requireNonNull(name);
    requireNonNull(commentLinkSections.remove(name));
  }

  private ProjectConfig(
      Project.NameKey projectName,
      Optional<StoredConfig> baseConfig,
      AllProjectsName allProjectsName) {
    this.projectName = projectName;
    this.baseConfig = baseConfig;
    this.allProjectsName = allProjectsName;
  }

  public void load(Repository repo) throws IOException, ConfigInvalidException {
    super.load(projectName, repo);
  }

  public void load(Repository repo, @Nullable ObjectId revision)
      throws IOException, ConfigInvalidException {
    super.load(projectName, repo, revision);
  }

  public void load(RevWalk rw, @Nullable ObjectId revision)
      throws IOException, ConfigInvalidException {
    super.load(projectName, rw, revision);
  }

  public Project.NameKey getName() {
    return projectName;
  }

  public Project getProject() {
    return project;
  }

  public void setProject(Project.Builder project) {
    this.project = project.build();
  }

  public void updateProject(Consumer<Project.Builder> update) {
    Project.Builder builder = project.toBuilder();
    update.accept(builder);
    project = builder.build();
  }

  public AccountsSection getAccountsSection() {
    return accountsSection;
  }

  public void setAccountsSection(AccountsSection accountsSection) {
    this.accountsSection = accountsSection;
  }

  /** Returns an access section, {@code name} typically is a ref pattern. */
  public AccessSection getAccessSection(String name) {
    return accessSections.get(name);
  }

  public void upsertAccessSection(String name, Consumer<AccessSection.Builder> update) {
    AccessSection.Builder accessSectionBuilder =
        accessSections.containsKey(name)
            ? accessSections.get(name).toBuilder()
            : AccessSection.builder(name);
    update.accept(accessSectionBuilder);
    accessSections.put(name, accessSectionBuilder.build());
  }

  public Collection<AccessSection> getAccessSections() {
    return sort(accessSections.values());
  }

  public BranchOrderSection getBranchOrderSection() {
    return branchOrderSection;
  }

  public void setBranchOrderSection(BranchOrderSection branchOrderSection) {
    this.branchOrderSection = branchOrderSection;
  }

  public Map<Project.NameKey, SubscribeSection> getSubscribeSections() {
    return subscribeSections;
  }

  public void addSubscribeSection(SubscribeSection s) {
    subscribeSections.put(s.project(), s);
  }

  public void remove(AccessSection section) {
    if (section != null) {
      String name = section.getName();
      if (sectionsWithUnknownPermissions.contains(name)) {
        AccessSection.Builder a = accessSections.get(name).toBuilder();
        a.modifyPermissions(List::clear);
        accessSections.put(name, a.build());
      } else {
        accessSections.remove(name);
      }
    }
  }

  public void remove(AccessSection section, Permission permission) {
    if (permission == null) {
      remove(section);
    } else if (section != null) {
      AccessSection a =
          accessSections.get(section.getName()).toBuilder().remove(permission.toBuilder()).build();
      accessSections.put(section.getName(), a);
      if (a.getPermissions().isEmpty()) {
        remove(a);
      }
    }
  }

  public void remove(AccessSection section, Permission permission, PermissionRule rule) {
    if (rule == null) {
      remove(section, permission);
    } else if (section != null && permission != null) {
      AccessSection a = accessSections.get(section.getName());
      if (a == null) {
        return;
      }
      Permission p = a.getPermission(permission.getName());
      if (p == null) {
        return;
      }
      AccessSection.Builder accessSectionBuilder = a.toBuilder();
      Permission.Builder permissionBuilder =
          accessSectionBuilder.upsertPermission(permission.getName());
      permissionBuilder.remove(rule);
      if (permissionBuilder.build().getRules().isEmpty()) {
        accessSectionBuilder.remove(permissionBuilder);
      }
      a = accessSectionBuilder.build();
      accessSections.put(section.getName(), a);
      if (a.getPermissions().isEmpty()) {
        remove(a);
      }
    }
  }

  public ContributorAgreement getContributorAgreement(String name) {
    return contributorAgreements.get(name);
  }

  public Collection<ContributorAgreement> getContributorAgreements() {
    return sort(contributorAgreements.values());
  }

  public void remove(ContributorAgreement section) {
    if (section != null) {
      accessSections.remove(section.getName());
    }
  }

  public void replace(ContributorAgreement section) {
    ContributorAgreement.Builder ca = section.toBuilder();
    ca.setAutoVerify(resolve(section.getAutoVerify()));
    ImmutableList.Builder<PermissionRule> newRules = ImmutableList.builder();
    for (PermissionRule rule : section.getAccepted()) {
      newRules.add(rule.toBuilder().setGroup(resolve(rule.getGroup())).build());
    }
    ca.setAccepted(newRules.build());

    contributorAgreements.put(section.getName(), ca.build());
  }

  public Collection<NotifyConfig> getNotifyConfigs() {
    return notifySections.values();
  }

  public void putNotifyConfig(String name, NotifyConfig nc) {
    notifySections.put(name, nc);
  }

  public Map<String, LabelType> getLabelSections() {
    return labelSections;
  }

  public Map<String, SubmitRequirement> getSubmitRequirementSections() {
    return submitRequirementSections;
  }

  public void upsertSubmitRequirement(SubmitRequirement requirement) {
    submitRequirementSections.put(requirement.name(), requirement);
  }

  /** Adds or replaces the given {@link LabelType} in this config. */
  public void upsertLabelType(LabelType labelType) {
    labelSections.put(labelType.getName(), labelType);
  }

  /** Allows a mutation of an existing {@link LabelType}. */
  public void updateLabelType(String name, Consumer<LabelType.Builder> update) {
    LabelType labelType = labelSections.get(name);
    checkState(labelType != null, "labelType must not be null");
    LabelType.Builder builder = labelSections.get(name).toBuilder();
    update.accept(builder);
    upsertLabelType(builder.build());
  }

  /** Adds or replaces the given {@link ContributorAgreement} in this config. */
  public void upsertContributorAgreement(ContributorAgreement ca) {
    contributorAgreements.remove(ca.getName());
    contributorAgreements.put(ca.getName(), ca);
  }

  public Collection<StoredCommentLinkInfo> getCommentLinkSections() {
    return commentLinkSections.values();
  }

  public ConfiguredMimeTypes getMimeTypes() {
    return mimeTypes;
  }

  public GroupReference resolve(GroupReference group) {
    return groupList.resolve(group);
  }

  public void renameGroup(AccountGroup.UUID uuid, String newName) {
    groupList.renameGroup(uuid, newName);
  }

  /** Returns the group reference, if the group is used by at least one rule. */
  public GroupReference getGroup(AccountGroup.UUID uuid) {
    return groupList.byUUID(uuid);
  }

  /**
   * Returns the group reference corresponding to the specified group name if the group is used by
   * at least one rule or plugin value.
   */
  public GroupReference getGroup(String groupName) {
    return groupList.byName(groupName);
  }

  /**
   * Returns the project's rules.pl ObjectId, if present in the branch. Null if it doesn't exist.
   */
  public ObjectId getRulesId() {
    return rulesId;
  }

  /** Returns the maxObjectSizeLimit configured on this project, or zero if not configured. */
  public long getMaxObjectSizeLimit() {
    return maxObjectSizeLimit;
  }

  /** Returns the checkReceivedObjects for this project, default is true. */
  public boolean getCheckReceivedObjects() {
    return checkReceivedObjects;
  }

  /**
   * Check all GroupReferences use current group name, repairing stale ones.
   *
   * @param groupBackend cache to use when looking up group information by UUID.
   * @return true if one or more group names was stale.
   */
  public boolean updateGroupNames(GroupBackend groupBackend) {
    boolean dirty = false;
    for (GroupReference ref : groupList.references()) {
      GroupDescription.Basic g = groupBackend.get(ref.getUUID());
      if (g != null && !g.getName().equals(ref.getName())) {
        dirty = true;
        groupList.renameGroup(ref.getUUID(), g.getName());
      }
    }
    return dirty;
  }

  /**
   * Get the validation errors, if any were discovered during load.
   *
   * @return list of errors; empty list if there are no errors.
   */
  public List<ValidationError> getValidationErrors() {
    if (validationErrors != null) {
      return Collections.unmodifiableList(validationErrors);
    }
    return Collections.emptyList();
  }

  @Override
  protected String getRefName() {
    return RefNames.REFS_CONFIG;
  }

  @Override
  protected void onLoad() throws IOException, ConfigInvalidException {
    if (baseConfig.isPresent()) {
      baseConfig.get().load();
    }
    readGroupList();

    rulesId = getObjectId("rules.pl");
    Config rc = readConfig(PROJECT_CONFIG, baseConfig);
    Project.Builder p = Project.builder(projectName);
    p.setDescription(Strings.nullToEmpty(rc.getString(PROJECT, null, KEY_DESCRIPTION)));
    if (revision != null) {
      p.setConfigRefState(revision.toObjectId().name());
    }

    if (rc.getStringList(ACCESS, null, KEY_INHERIT_FROM).length > 1) {
      // The config must not contain more than one parent to inherit from
      // as there is no guarantee which of the parents would be used then.
      error("Cannot inherit from multiple projects");
    }
    p.setParent(rc.getString(ACCESS, null, KEY_INHERIT_FROM));

    for (BooleanProjectConfig config : BooleanProjectConfig.values()) {
      p.setBooleanConfig(
          config,
          getEnum(
              rc,
              config.getSection(),
              config.getSubSection(),
              config.getName(),
              InheritableBoolean.INHERIT));
    }

    p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT));

    p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, DEFAULT_SUBMIT_TYPE));
    p.setState(getEnum(rc, PROJECT, null, KEY_STATE, DEFAULT_STATE_VALUE));

    p.setDefaultDashboard(rc.getString(DASHBOARD, null, KEY_DEFAULT));
    p.setLocalDefaultDashboard(rc.getString(DASHBOARD, null, KEY_LOCAL_DEFAULT));
    this.project = p.build();

    loadAccountsSection(rc);
    loadContributorAgreements(rc);
    loadAccessSections(rc);
    loadBranchOrderSection(rc);
    loadNotifySections(rc);
    loadLabelSections(rc);
    loadSubmitRequirementSections(rc);
    loadCommentLinkSections(rc);
    loadSubscribeSections(rc);
    mimeTypes = ConfiguredMimeTypes.create(projectName.get(), rc);
    loadPluginSections(rc);
    loadProjectLevelConfigs();
    loadReceiveSection(rc);
    loadExtensionPanelSections(rc);
  }

  private void loadAccountsSection(Config rc) {
    accountsSection =
        AccountsSection.create(
            loadPermissionRules(rc, ACCOUNTS, null, KEY_SAME_GROUP_VISIBILITY, false));
  }

  private void loadExtensionPanelSections(Config rc) {
    Map<String, String> lowerNames = Maps.newHashMapWithExpectedSize(2);
    extensionPanelSections = new LinkedHashMap<>();
    for (String name : rc.getSubsections(EXTENSION_PANELS)) {
      String lower = name.toLowerCase();
      if (lowerNames.containsKey(lower)) {
        error(
            String.format(
                "Extension Panels \"%s\" conflicts with \"%s\"", name, lowerNames.get(lower)));
      }
      lowerNames.put(lower, name);
      extensionPanelSections.put(
          name,
          new ArrayList<>(Arrays.asList(rc.getStringList(EXTENSION_PANELS, name, KEY_PANEL))));
    }
  }

  private void loadContributorAgreements(Config rc) {
    contributorAgreements = new HashMap<>();
    for (String name : rc.getSubsections(CONTRIBUTOR_AGREEMENT)) {
      ContributorAgreement.Builder ca = ContributorAgreement.builder(name);
      ca.setDescription(rc.getString(CONTRIBUTOR_AGREEMENT, name, KEY_DESCRIPTION));
      ca.setAgreementUrl(rc.getString(CONTRIBUTOR_AGREEMENT, name, KEY_AGREEMENT_URL));
      ca.setAccepted(loadPermissionRules(rc, CONTRIBUTOR_AGREEMENT, name, KEY_ACCEPTED, false));
      ca.setExcludeProjectsRegexes(
          loadPatterns(rc, CONTRIBUTOR_AGREEMENT, name, KEY_EXCLUDE_PROJECTS));
      ca.setMatchProjectsRegexes(loadPatterns(rc, CONTRIBUTOR_AGREEMENT, name, KEY_MATCH_PROJECTS));

      List<PermissionRule> rules =
          loadPermissionRules(rc, CONTRIBUTOR_AGREEMENT, name, KEY_AUTO_VERIFY, false);
      if (rules.isEmpty()) {
        ca.setAutoVerify(null);
      } else if (rules.size() > 1) {
        error(
            String.format(
                "Invalid rule in %s.%s.%s: at most one group may be set",
                CONTRIBUTOR_AGREEMENT, name, KEY_AUTO_VERIFY));
      } else if (rules.get(0).getAction() != Action.ALLOW) {
        error(
            String.format(
                "Invalid rule in %s.%s.%s: the group must be allowed",
                CONTRIBUTOR_AGREEMENT, name, KEY_AUTO_VERIFY));
      } else {
        ca.setAutoVerify(rules.get(0).getGroup());
      }
      contributorAgreements.put(name, ca.build());
    }
  }

  /**
   * Parses the [notify] sections out of the configuration file.
   *
   * <pre>
   *   [notify "reviewers"]
   *     email = group Reviewers
   *     type = new_changes
   *
   *   [notify "dev-team"]
   *     email = dev-team@example.com
   *     filter = branch:master
   *
   *   [notify "qa"]
   *     email = qa@example.com
   *     filter = branch:\"^(maint|stable)-.*\"
   *     type = submitted_changes
   * </pre>
   */
  private void loadNotifySections(Config rc) {
    notifySections = new HashMap<>();
    for (String sectionName : rc.getSubsections(NOTIFY)) {
      NotifyConfig.Builder n = NotifyConfig.builder();
      n.setName(sectionName);
      n.setFilter(rc.getString(NOTIFY, sectionName, KEY_FILTER));

      EnumSet<NotifyType> types = EnumSet.noneOf(NotifyType.class);
      types.addAll(ConfigUtil.getEnumList(rc, NOTIFY, sectionName, KEY_TYPE, NotifyType.ALL));
      n.setNotify(types);
      n.setHeader(rc.getEnum(NOTIFY, sectionName, KEY_HEADER, NotifyConfig.Header.BCC));

      for (String dst : rc.getStringList(NOTIFY, sectionName, KEY_EMAIL)) {
        String groupName = GroupReference.extractGroupName(dst);
        if (groupName != null) {
          GroupReference ref = groupList.byName(groupName);
          if (ref == null) {
            ref = groupList.resolve(GroupReference.create(groupName));
          }
          if (ref.getUUID() != null) {
            n.addGroup(ref);
          } else {
            error(String.format("group \"%s\" not in %s", ref.getName(), GroupList.FILE_NAME));
          }
        } else if (dst.startsWith("user ")) {
          error(String.format("%s not supported", dst));
        } else {
          try {
            n.addAddress(Address.parse(dst));
          } catch (IllegalArgumentException err) {
            error(
                String.format("notify section \"%s\" has invalid email \"%s\"", sectionName, dst));
          }
        }
      }
      notifySections.put(sectionName, n.build());
    }
  }

  private void loadAccessSections(Config rc) {
    accessSections = new HashMap<>();
    sectionsWithUnknownPermissions = new HashSet<>();
    for (String refName : rc.getSubsections(ACCESS)) {
      if (AccessSection.isValidRefSectionName(refName) && isValidRegex(refName)) {
        upsertAccessSection(
            refName,
            as -> {
              for (String varName : rc.getStringList(ACCESS, refName, KEY_GROUP_PERMISSIONS)) {
                for (String n : Splitter.on(EXCLUSIVE_PERMISSIONS_SPLIT_PATTERN).split(varName)) {
                  n = convertLegacyPermission(n);
                  if (isCoreOrPluginPermission(n)) {
                    as.upsertPermission(n).setExclusiveGroup(true);
                  }
                }
              }

              for (String varName : rc.getNames(ACCESS, refName)) {
                String convertedName = convertLegacyPermission(varName);
                if (isCoreOrPluginPermission(convertedName)) {
                  Permission.Builder perm = as.upsertPermission(convertedName);
                  loadPermissionRules(
                      rc, ACCESS, refName, varName, perm, Permission.hasRange(convertedName));
                } else {
                  sectionsWithUnknownPermissions.add(as.getName());
                }
              }
            });
      }
    }

    AccessSection.Builder capability = null;
    for (String varName : rc.getNames(CAPABILITY)) {
      if (capability == null) {
        capability = AccessSection.builder(AccessSection.GLOBAL_CAPABILITIES);
        accessSections.put(AccessSection.GLOBAL_CAPABILITIES, capability.build());
      }
      Permission.Builder perm = capability.upsertPermission(varName);
      loadPermissionRules(rc, CAPABILITY, null, varName, perm, GlobalCapability.hasRange(varName));
      accessSections.put(AccessSection.GLOBAL_CAPABILITIES, capability.build());
    }
  }

  private boolean isCoreOrPluginPermission(String permission) {
    // Since plugins are loaded dynamically, here we can't load all plugin permissions and verify
    // their existence.
    return isPermission(permission) || isValidPluginPermission(permission);
  }

  private boolean isValidRegex(String refPattern) {
    try {
      RefPattern.validateRegExp(refPattern);
    } catch (InvalidNameException e) {
      error(String.format("Invalid ref name: %s", e.getMessage()));
      return false;
    }
    return true;
  }

  private void loadBranchOrderSection(Config rc) {
    if (rc.getSections().contains(BRANCH_ORDER)) {
      branchOrderSection =
          BranchOrderSection.create(Arrays.asList(rc.getStringList(BRANCH_ORDER, null, BRANCH)));
    }
  }

  private void saveBranchOrderSection(Config rc) {
    if (branchOrderSection != null) {
      rc.setStringList(BRANCH_ORDER, null, BRANCH, branchOrderSection.order());
    }
  }

  private ImmutableList<String> loadPatterns(
      Config rc, String section, String subsection, String varName) {
    ImmutableList.Builder<String> patterns = ImmutableList.builder();
    for (String patternString : rc.getStringList(section, subsection, varName)) {
      try {
        // While one could just use getStringList directly, compiling first will cause the server
        // to fail fast if any of the patterns are invalid.
        patterns.add(Pattern.compile(patternString).pattern());
      } catch (PatternSyntaxException e) {
        error(String.format("Invalid regular expression: %s", e.getMessage()));
        continue;
      }
    }
    return patterns.build();
  }

  private ImmutableList<PermissionRule> loadPermissionRules(
      Config rc, String section, String subsection, String varName, boolean useRange) {
    Permission.Builder perm = Permission.builder(varName);
    loadPermissionRules(rc, section, subsection, varName, perm, useRange);
    return ImmutableList.copyOf(perm.build().getRules());
  }

  private void loadPermissionRules(
      Config rc,
      String section,
      String subsection,
      String varName,
      Permission.Builder perm,
      boolean useRange) {
    for (String ruleString : rc.getStringList(section, subsection, varName)) {
      PermissionRule rule;
      try {
        rule = PermissionRule.fromString(ruleString, useRange);
      } catch (IllegalArgumentException notRule) {
        error(
            String.format(
                "Invalid rule in %s.%s: %s",
                section + (subsection != null ? "." + subsection : ""),
                varName,
                notRule.getMessage()));
        continue;
      }

      GroupReference ref = groupList.byName(rule.getGroup().getName());
      if (ref == null) {
        // The group wasn't mentioned in the groups table, so there is
        // no valid UUID for it. Pool the reference anyway so at least
        // all rules in the same file share the same GroupReference.
        //
        ref = groupList.resolve(rule.getGroup());
        error(String.format("group \"%s\" not in %s", ref.getName(), GroupList.FILE_NAME));
      }

      perm.add(rule.toBuilder().setGroup(ref));
    }
  }

  private static LabelValue parseLabelValue(String src) {
    List<String> parts =
        ImmutableList.copyOf(
            Splitter.on(CharMatcher.whitespace()).omitEmptyStrings().limit(2).split(src));
    if (parts.isEmpty()) {
      throw new IllegalArgumentException("empty value");
    }
    String valueText = parts.size() > 1 ? parts.get(1) : "";
    return LabelValue.create(Shorts.checkedCast(PermissionRule.parseInt(parts.get(0))), valueText);
  }

  private void loadSubmitRequirementSections(Config rc) {
    Map<String, String> lowerNames = new HashMap<>();
    submitRequirementSections = new LinkedHashMap<>();
    for (String name : rc.getSubsections(SUBMIT_REQUIREMENT)) {
      String lower = name.toLowerCase();
      if (lowerNames.containsKey(lower)) {
        error(
            String.format(
                "Submit requirement '%s' conflicts with '%s'.", name, lowerNames.get(lower)));
        continue;
      }
      lowerNames.put(lower, name);
      String description = rc.getString(SUBMIT_REQUIREMENT, name, KEY_SR_DESCRIPTION);
      String appExpr = rc.getString(SUBMIT_REQUIREMENT, name, KEY_SR_APPLICABILITY_EXPRESSION);
      String blockExpr = rc.getString(SUBMIT_REQUIREMENT, name, KEY_SR_SUBMITTABILITY_EXPRESSION);
      String overrideExpr = rc.getString(SUBMIT_REQUIREMENT, name, KEY_SR_OVERRIDE_EXPRESSION);
      boolean canInherit =
          rc.getBoolean(SUBMIT_REQUIREMENT, name, KEY_SR_OVERRIDE_IN_CHILD_PROJECTS, false);

      if (blockExpr == null) {
        error(
            String.format(
                "Submit requirement '%s' does not define a submittability expression.", name));
        continue;
      }

      // TODO(SR): add expressions validation. Expressions are stored as strings so we need to
      // validate their syntax.

      SubmitRequirement submitRequirement =
          SubmitRequirement.builder()
              .setName(name)
              .setDescription(Optional.ofNullable(description))
              .setApplicabilityExpression(SubmitRequirementExpression.of(appExpr))
              .setSubmittabilityExpression(SubmitRequirementExpression.create(blockExpr))
              .setOverrideExpression(SubmitRequirementExpression.of(overrideExpr))
              .setAllowOverrideInChildProjects(canInherit)
              .build();

      submitRequirementSections.put(name, submitRequirement);
    }
  }

  private void loadLabelSections(Config rc) {
    Map<String, String> lowerNames = Maps.newHashMapWithExpectedSize(2);
    labelSections = new LinkedHashMap<>();
    for (String name : rc.getSubsections(LABEL)) {
      String lower = name.toLowerCase();
      if (lowerNames.containsKey(lower)) {
        error(String.format("Label \"%s\" conflicts with \"%s\"", name, lowerNames.get(lower)));
      }
      lowerNames.put(lower, name);

      List<LabelValue> values = new ArrayList<>();
      Set<Short> allValues = new HashSet<>();
      for (String value : rc.getStringList(LABEL, name, KEY_VALUE)) {
        try {
          LabelValue labelValue = parseLabelValue(value);
          if (allValues.add(labelValue.getValue())) {
            values.add(labelValue);
          } else {
            error(String.format("Duplicate %s \"%s\" for label \"%s\"", KEY_VALUE, value, name));
          }
        } catch (IllegalArgumentException notValue) {
          error(
              String.format(
                  "Invalid %s \"%s\" for label \"%s\": %s",
                  KEY_VALUE, value, name, notValue.getMessage()));
        }
      }

      LabelType.Builder label;
      try {
        label = LabelType.builder(name, values);
      } catch (IllegalArgumentException badName) {
        error(String.format("Invalid label \"%s\"", name));
        continue;
      }

      String functionName = rc.getString(LABEL, name, KEY_FUNCTION);
      Optional<LabelFunction> function =
          functionName != null
              ? LabelFunction.parse(functionName)
              : Optional.of(LabelFunction.MAX_WITH_BLOCK);
      if (!function.isPresent()) {
        error(
            String.format(
                "Invalid %s for label \"%s\". Valid names are: %s",
                KEY_FUNCTION, name, Joiner.on(", ").join(LabelFunction.ALL.keySet())));
      }
      label.setFunction(function.orElse(null));
      label.setCopyCondition(rc.getString(LABEL, name, KEY_COPY_CONDITION));

      if (!values.isEmpty()) {
        short dv = (short) rc.getInt(LABEL, name, KEY_DEFAULT_VALUE, 0);
        if (isInRange(dv, values)) {
          label.setDefaultValue(dv);
        } else {
          error(String.format("Invalid %s \"%s\" for label \"%s\"", KEY_DEFAULT_VALUE, dv, name));
        }
      }
      label.setAllowPostSubmit(
          rc.getBoolean(LABEL, name, KEY_ALLOW_POST_SUBMIT, LabelType.DEF_ALLOW_POST_SUBMIT));
      label.setIgnoreSelfApproval(
          rc.getBoolean(LABEL, name, KEY_IGNORE_SELF_APPROVAL, LabelType.DEF_IGNORE_SELF_APPROVAL));
      label.setCopyAnyScore(
          rc.getBoolean(LABEL, name, KEY_COPY_ANY_SCORE, LabelType.DEF_COPY_ANY_SCORE));
      label.setCopyMinScore(
          rc.getBoolean(LABEL, name, KEY_COPY_MIN_SCORE, LabelType.DEF_COPY_MIN_SCORE));
      label.setCopyMaxScore(
          rc.getBoolean(LABEL, name, KEY_COPY_MAX_SCORE, LabelType.DEF_COPY_MAX_SCORE));
      label.setCopyAllScoresIfListOfFilesDidNotChange(
          rc.getBoolean(
              LABEL,
              name,
              KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE,
              LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE));
      label.setCopyAllScoresOnMergeFirstParentUpdate(
          rc.getBoolean(
              LABEL,
              name,
              KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE,
              LabelType.DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE));
      label.setCopyAllScoresOnTrivialRebase(
          rc.getBoolean(
              LABEL,
              name,
              KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE,
              LabelType.DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE));
      label.setCopyAllScoresIfNoCodeChange(
          rc.getBoolean(
              LABEL,
              name,
              KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE,
              LabelType.DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE));
      label.setCopyAllScoresIfNoChange(
          rc.getBoolean(
              LABEL,
              name,
              KEY_COPY_ALL_SCORES_IF_NO_CHANGE,
              LabelType.DEF_COPY_ALL_SCORES_IF_NO_CHANGE));
      Set<Short> copyValues = new HashSet<>();
      for (String value : rc.getStringList(LABEL, name, KEY_COPY_VALUE)) {
        try {
          short copyValue = Shorts.checkedCast(PermissionRule.parseInt(value));
          if (!copyValues.add(copyValue)) {
            error(
                String.format("Duplicate %s \"%s\" for label \"%s\"", KEY_COPY_VALUE, value, name));
          }
        } catch (IllegalArgumentException notValue) {
          error(
              String.format(
                  "Invalid %s \"%s\" for label \"%s\": %s",
                  KEY_COPY_VALUE, value, name, notValue.getMessage()));
        }
      }
      label.setCopyValues(copyValues);
      label.setCanOverride(
          rc.getBoolean(LABEL, name, KEY_CAN_OVERRIDE, LabelType.DEF_CAN_OVERRIDE));
      List<String> refPatterns = getStringListOrNull(rc, LABEL, name, KEY_BRANCH);
      label.setRefPatterns(refPatterns == null ? null : ImmutableList.copyOf(refPatterns));
      labelSections.put(name, label.build());
    }
  }

  private boolean isInRange(short value, List<LabelValue> labelValues) {
    for (LabelValue lv : labelValues) {
      if (lv.getValue() == value) {
        return true;
      }
    }
    return false;
  }

  private List<String> getStringListOrNull(
      Config rc, String section, String subSection, String name) {
    String[] ac = rc.getStringList(section, subSection, name);
    return ac.length == 0 ? null : Arrays.asList(ac);
  }

  private void loadCommentLinkSections(Config rc) {
    Set<String> subsections = rc.getSubsections(COMMENTLINK);
    commentLinkSections = new LinkedHashMap<>(subsections.size());
    for (String name : subsections) {
      try {
        commentLinkSections.put(name, buildCommentLink(rc, name, false));
      } catch (PatternSyntaxException e) {
        error(
            String.format(
                "Invalid pattern \"%s\" in commentlink.%s.match: %s",
                rc.getString(COMMENTLINK, name, KEY_MATCH), name, e.getMessage()));
      } catch (IllegalArgumentException e) {
        error(
            String.format(
                "Error in pattern \"%s\" in commentlink.%s.match: %s",
                rc.getString(COMMENTLINK, name, KEY_MATCH), name, e.getMessage()));
      }
    }
  }

  private void loadSubscribeSections(Config rc) throws ConfigInvalidException {
    Set<String> subsections = rc.getSubsections(SUBSCRIBE_SECTION);
    subscribeSections = new HashMap<>();
    try {
      for (String projectName : subsections) {
        Project.NameKey p = Project.nameKey(projectName);
        SubscribeSection.Builder ss = SubscribeSection.builder(p);
        for (String s :
            rc.getStringList(SUBSCRIBE_SECTION, projectName, SUBSCRIBE_MULTI_MATCH_REFS)) {
          ss.addMultiMatchRefSpec(s);
        }
        for (String s : rc.getStringList(SUBSCRIBE_SECTION, projectName, SUBSCRIBE_MATCH_REFS)) {
          ss.addMatchingRefSpec(s);
        }
        subscribeSections.put(p, ss.build());
      }
    } catch (IllegalArgumentException e) {
      throw new ConfigInvalidException(e.getMessage());
    }
  }

  private void loadReceiveSection(Config rc) {
    checkReceivedObjects = rc.getBoolean(RECEIVE, KEY_CHECK_RECEIVED_OBJECTS, true);
    maxObjectSizeLimit = rc.getLong(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT, 0);
  }

  private void loadPluginSections(Config rc) {
    pluginConfigs = new HashMap<>();
    for (String plugin : rc.getSubsections(PLUGIN)) {
      Config pluginConfig = new Config();
      pluginConfigs.put(plugin, pluginConfig);
      for (String name : rc.getNames(PLUGIN, plugin)) {
        String value = rc.getString(PLUGIN, plugin, name);
        String groupName = GroupReference.extractGroupName(value);
        if (groupName != null) {
          GroupReference ref = groupList.byName(groupName);
          if (ref == null) {
            error(String.format("group \"%s\" not in %s", groupName, GroupList.FILE_NAME));
          }
          rc.setString(PLUGIN, plugin, name, value);
        }
        pluginConfig.setStringList(
            PLUGIN, plugin, name, Arrays.asList(rc.getStringList(PLUGIN, plugin, name)));
      }
    }
  }

  public void updatePluginConfig(
      String pluginName, Consumer<PluginConfig.Update> pluginConfigUpdate) {
    Config pluginConfig = pluginConfigs.get(pluginName);
    if (pluginConfig == null) {
      pluginConfig = new Config();
      pluginConfigs.put(pluginName, pluginConfig);
    }
    pluginConfigUpdate.accept(new PluginConfig.Update(pluginName, pluginConfig, Optional.of(this)));
  }

  public PluginConfig getPluginConfig(String pluginName) {
    Config pluginConfig = pluginConfigs.getOrDefault(pluginName, new Config());
    return PluginConfig.create(pluginName, pluginConfig, getCacheable());
  }

  private void loadProjectLevelConfigs() throws IOException {
    projectLevelConfigs = new HashMap<>();
    if (revision == null) {
      return;
    }
    for (PathInfo pathInfo : getPathInfos(true)) {
      if (pathInfo.path.endsWith(".config") && !PROJECT_CONFIG.equals(pathInfo.path)) {
        String cfg = readUTF8(pathInfo.path);
        Config parsedConfig = new Config();
        try {
          parsedConfig.fromText(cfg);
          projectLevelConfigs.put(pathInfo.path, parsedConfig);
        } catch (ConfigInvalidException e) {
          logger.atWarning().withCause(e).log("Unable to parse config");
        }
      }
    }
  }

  private void readGroupList() throws IOException {
    groupList = GroupList.parse(projectName, readUTF8(GroupList.FILE_NAME), this);
  }

  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
    if (commit.getMessage() == null || "".equals(commit.getMessage())) {
      commit.setMessage("Updated project configuration\n");
    }

    Config rc = readConfig(PROJECT_CONFIG);
    Project p = project;

    if (p.getDescription() != null && !p.getDescription().isEmpty()) {
      rc.setString(PROJECT, null, KEY_DESCRIPTION, p.getDescription());
    } else {
      rc.unset(PROJECT, null, KEY_DESCRIPTION);
    }
    set(rc, ACCESS, null, KEY_INHERIT_FROM, p.getParentName());

    for (BooleanProjectConfig config : BooleanProjectConfig.values()) {
      set(
          rc,
          config.getSection(),
          config.getSubSection(),
          config.getName(),
          p.getBooleanConfig(config),
          InheritableBoolean.INHERIT);
    }

    set(
        rc,
        RECEIVE,
        null,
        KEY_MAX_OBJECT_SIZE_LIMIT,
        validMaxObjectSizeLimit(p.getMaxObjectSizeLimit()));

    set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), DEFAULT_SUBMIT_TYPE);

    set(rc, PROJECT, null, KEY_STATE, p.getState(), DEFAULT_STATE_VALUE);

    set(rc, DASHBOARD, null, KEY_DEFAULT, p.getDefaultDashboard());
    set(rc, DASHBOARD, null, KEY_LOCAL_DEFAULT, p.getLocalDefaultDashboard());

    Set<AccountGroup.UUID> keepGroups = new HashSet<>();
    saveAccountsSection(rc, keepGroups);
    saveContributorAgreements(rc, keepGroups);
    saveAccessSections(rc, keepGroups);
    saveNotifySections(rc, keepGroups);
    savePluginSections(rc, keepGroups);
    groupList.retainUUIDs(keepGroups);
    saveLabelSections(rc);
    saveSubmitRequirementSections(rc);
    saveCommentLinkSections(rc);
    saveSubscribeSections(rc);
    saveBranchOrderSection(rc);

    saveConfig(PROJECT_CONFIG, rc);
    saveGroupList();
    return true;
  }

  public static String validMaxObjectSizeLimit(String value) throws ConfigInvalidException {
    if (value == null) {
      return null;
    }
    value = value.trim();
    if (value.isEmpty()) {
      return null;
    }
    Config cfg = new Config();
    cfg.fromText("[s]\nn=" + value);
    try {
      long s = cfg.getLong("s", "n", 0);
      if (s < 0) {
        throw new ConfigInvalidException(
            String.format(
                "Negative value '%s' not allowed as %s", value, KEY_MAX_OBJECT_SIZE_LIMIT));
      }
      if (s == 0) {
        // return null for the default so that it is not persisted
        return null;
      }
      return value;
    } catch (IllegalArgumentException e) {
      throw new ConfigInvalidException(
          String.format("Value '%s' not parseable as a Long", value), e);
    }
  }

  private void saveAccountsSection(Config rc, Set<AccountGroup.UUID> keepGroups) {
    unsetSection(rc, ACCOUNTS);
    if (accountsSection != null) {
      rc.setStringList(
          ACCOUNTS,
          null,
          KEY_SAME_GROUP_VISIBILITY,
          ruleToStringList(accountsSection.getSameGroupVisibility(), keepGroups));
    }
  }

  private void saveCommentLinkSections(Config rc) {
    unsetSection(rc, COMMENTLINK);
    if (commentLinkSections != null) {
      for (StoredCommentLinkInfo cm : commentLinkSections.values()) {
        rc.setString(COMMENTLINK, cm.getName(), KEY_MATCH, cm.getMatch());
        if (!Strings.isNullOrEmpty(cm.getHtml())) {
          rc.setString(COMMENTLINK, cm.getName(), KEY_HTML, cm.getHtml());
        }
        if (!Strings.isNullOrEmpty(cm.getLink())) {
          rc.setString(COMMENTLINK, cm.getName(), KEY_LINK, cm.getLink());
        }
        if (cm.getEnabled() != null && !cm.getEnabled()) {
          rc.setBoolean(COMMENTLINK, cm.getName(), KEY_ENABLED, cm.getEnabled());
        }
      }
    }
  }

  private void saveContributorAgreements(Config rc, Set<AccountGroup.UUID> keepGroups) {
    unsetSection(rc, CONTRIBUTOR_AGREEMENT);
    for (ContributorAgreement ca : sort(contributorAgreements.values())) {
      set(rc, CONTRIBUTOR_AGREEMENT, ca.getName(), KEY_DESCRIPTION, ca.getDescription());
      set(rc, CONTRIBUTOR_AGREEMENT, ca.getName(), KEY_AGREEMENT_URL, ca.getAgreementUrl());

      if (ca.getAutoVerify() != null) {
        if (ca.getAutoVerify().getUUID() != null) {
          keepGroups.add(ca.getAutoVerify().getUUID());
        }
        String autoVerify = PermissionRule.create(ca.getAutoVerify()).asString(false);
        set(rc, CONTRIBUTOR_AGREEMENT, ca.getName(), KEY_AUTO_VERIFY, autoVerify);
      } else {
        rc.unset(CONTRIBUTOR_AGREEMENT, ca.getName(), KEY_AUTO_VERIFY);
      }

      rc.setStringList(
          CONTRIBUTOR_AGREEMENT,
          ca.getName(),
          KEY_ACCEPTED,
          ruleToStringList(ca.getAccepted(), keepGroups));
      rc.setStringList(
          CONTRIBUTOR_AGREEMENT,
          ca.getName(),
          KEY_EXCLUDE_PROJECTS,
          patternToStringList(ca.getExcludeProjectsRegexes()));
      rc.setStringList(
          CONTRIBUTOR_AGREEMENT,
          ca.getName(),
          KEY_MATCH_PROJECTS,
          patternToStringList(ca.getMatchProjectsRegexes()));
    }
  }

  private void saveNotifySections(Config rc, Set<AccountGroup.UUID> keepGroups) {
    unsetSection(rc, NOTIFY);
    for (NotifyConfig nc : sort(notifySections.values())) {
      nc.getGroups().stream()
          .map(GroupReference::getUUID)
          .filter(Objects::nonNull)
          .forEach(keepGroups::add);
      List<String> email =
          nc.getGroups().stream()
              .map(gr -> PermissionRule.create(gr).asString(false))
              .sorted()
              .collect(toList());

      // Separate stream operation so that emails list contains 2 sorted sub-lists.
      nc.getAddresses().stream().map(Address::toString).sorted().forEach(email::add);

      set(rc, NOTIFY, nc.getName(), KEY_HEADER, nc.getHeader(), NotifyConfig.Header.BCC);
      if (email.isEmpty()) {
        rc.unset(NOTIFY, nc.getName(), KEY_EMAIL);
      } else {
        rc.setStringList(NOTIFY, nc.getName(), KEY_EMAIL, email);
      }

      if (nc.getNotify().equals(Sets.immutableEnumSet(NotifyType.ALL))) {
        rc.unset(NOTIFY, nc.getName(), KEY_TYPE);
      } else {
        List<String> types = new ArrayList<>(4);
        for (NotifyType t : NotifyType.values()) {
          if (nc.isNotify(t)) {
            types.add(t.name().toLowerCase(Locale.US));
          }
        }
        rc.setStringList(NOTIFY, nc.getName(), KEY_TYPE, types);
      }

      set(rc, NOTIFY, nc.getName(), KEY_FILTER, nc.getFilter());
    }
  }

  private List<String> patternToStringList(List<String> list) {
    return list;
  }

  private List<String> ruleToStringList(
      List<PermissionRule> list, Set<AccountGroup.UUID> keepGroups) {
    List<String> rules = new ArrayList<>();
    for (PermissionRule rule : sort(list)) {
      if (rule.getGroup().getUUID() != null) {
        keepGroups.add(rule.getGroup().getUUID());
      }
      rules.add(rule.asString(false));
    }
    return rules;
  }

  private void saveAccessSections(Config rc, Set<AccountGroup.UUID> keepGroups) {
    unsetSection(rc, CAPABILITY);
    AccessSection capability = accessSections.get(AccessSection.GLOBAL_CAPABILITIES);
    if (capability != null) {
      Set<String> have = new HashSet<>();
      for (Permission permission : sort(capability.getPermissions())) {
        have.add(permission.getName().toLowerCase());

        boolean needRange = GlobalCapability.hasRange(permission.getName());
        List<String> rules = new ArrayList<>();
        for (PermissionRule rule : sort(permission.getRules())) {
          GroupReference group = resolve(rule.getGroup());
          if (group.getUUID() != null) {
            keepGroups.add(group.getUUID());
          }
          rules.add(rule.toBuilder().setGroup(group).build().asString(needRange));
        }
        rc.setStringList(CAPABILITY, null, permission.getName(), rules);
      }
      for (String varName : rc.getNames(CAPABILITY)) {
        if (!have.contains(varName.toLowerCase())) {
          rc.unset(CAPABILITY, null, varName);
        }
      }
    } else {
      rc.unsetSection(CAPABILITY, null);
    }

    for (AccessSection as : sort(accessSections.values())) {
      String refName = as.getName();
      if (AccessSection.GLOBAL_CAPABILITIES.equals(refName)) {
        continue;
      }

      StringBuilder doNotInherit = new StringBuilder();
      for (Permission perm : sort(as.getPermissions())) {
        if (perm.getExclusiveGroup()) {
          if (0 < doNotInherit.length()) {
            doNotInherit.append(' ');
          }
          doNotInherit.append(perm.getName());
        }
      }
      if (0 < doNotInherit.length()) {
        rc.setString(ACCESS, refName, KEY_GROUP_PERMISSIONS, doNotInherit.toString());
      } else {
        rc.unset(ACCESS, refName, KEY_GROUP_PERMISSIONS);
      }

      Set<String> have = new HashSet<>();
      for (Permission permission : sort(as.getPermissions())) {
        have.add(permission.getName().toLowerCase());

        boolean needRange = Permission.hasRange(permission.getName());
        List<String> rules = new ArrayList<>();
        for (PermissionRule rule : sort(permission.getRules())) {
          GroupReference group = resolve(rule.getGroup());
          if (group.getUUID() != null) {
            keepGroups.add(group.getUUID());
          }
          rules.add(rule.toBuilder().setGroup(group).build().asString(needRange));
        }
        rc.setStringList(ACCESS, refName, permission.getName(), rules);
      }

      for (String varName : rc.getNames(ACCESS, refName)) {
        if (isCoreOrPluginPermission(convertLegacyPermission(varName))
            && !have.contains(varName.toLowerCase())) {
          rc.unset(ACCESS, refName, varName);
        }
      }
    }

    for (String name : rc.getSubsections(ACCESS)) {
      if (AccessSection.isValidRefSectionName(name) && !accessSections.containsKey(name)) {
        rc.unsetSection(ACCESS, name);
      }
    }
  }

  private void saveLabelSections(Config rc) {
    List<String> existing = new ArrayList<>(rc.getSubsections(LABEL));
    if (!new ArrayList<>(labelSections.keySet()).equals(existing)) {
      // Order of sections changed, remove and rewrite them all.
      unsetSection(rc, LABEL);
    }

    Set<String> toUnset = new HashSet<>(existing);
    for (Map.Entry<String, LabelType> e : labelSections.entrySet()) {
      String name = e.getKey();
      LabelType label = e.getValue();
      toUnset.remove(name);
      rc.setString(LABEL, name, KEY_FUNCTION, label.getFunction().getFunctionName());
      rc.setInt(LABEL, name, KEY_DEFAULT_VALUE, label.getDefaultValue());

      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_ALLOW_POST_SUBMIT,
          label.isAllowPostSubmit(),
          LabelType.DEF_ALLOW_POST_SUBMIT);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_IGNORE_SELF_APPROVAL,
          label.isIgnoreSelfApproval(),
          LabelType.DEF_IGNORE_SELF_APPROVAL);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ANY_SCORE,
          label.isCopyAnyScore(),
          LabelType.DEF_COPY_ANY_SCORE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_MIN_SCORE,
          label.isCopyMinScore(),
          LabelType.DEF_COPY_MIN_SCORE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_MAX_SCORE,
          label.isCopyMaxScore(),
          LabelType.DEF_COPY_MAX_SCORE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ALL_SCORES_ON_TRIVIAL_REBASE,
          label.isCopyAllScoresOnTrivialRebase(),
          LabelType.DEF_COPY_ALL_SCORES_ON_TRIVIAL_REBASE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ALL_SCORES_IF_NO_CODE_CHANGE,
          label.isCopyAllScoresIfNoCodeChange(),
          LabelType.DEF_COPY_ALL_SCORES_IF_NO_CODE_CHANGE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ALL_SCORES_IF_NO_CHANGE,
          label.isCopyAllScoresIfNoChange(),
          LabelType.DEF_COPY_ALL_SCORES_IF_NO_CHANGE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE,
          label.isCopyAllScoresIfListOfFilesDidNotChange(),
          LabelType.DEF_COPY_ALL_SCORES_IF_LIST_OF_FILES_DID_NOT_CHANGE);
      setBooleanConfigKey(
          rc,
          LABEL,
          name,
          KEY_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE,
          label.isCopyAllScoresOnMergeFirstParentUpdate(),
          LabelType.DEF_COPY_ALL_SCORES_ON_MERGE_FIRST_PARENT_UPDATE);
      rc.setStringList(
          LABEL,
          name,
          KEY_COPY_VALUE,
          label.getCopyValues().stream().map(LabelValue::formatValue).collect(toList()));
      setBooleanConfigKey(
          rc, LABEL, name, KEY_CAN_OVERRIDE, label.isCanOverride(), LabelType.DEF_CAN_OVERRIDE);
      List<String> values = new ArrayList<>(label.getValues().size());
      for (LabelValue value : label.getValues()) {
        values.add(value.format().trim());
      }
      rc.setStringList(LABEL, name, KEY_VALUE, values);
      if (label.getCopyCondition().isPresent()) {
        rc.setString(LABEL, name, KEY_COPY_CONDITION, label.getCopyCondition().get());
      } else {
        rc.unset(LABEL, name, KEY_COPY_CONDITION);
      }

      List<String> refPatterns = label.getRefPatterns();
      if (refPatterns != null && !refPatterns.isEmpty()) {
        rc.setStringList(LABEL, name, KEY_BRANCH, refPatterns);
      } else {
        rc.unset(LABEL, name, KEY_BRANCH);
      }
    }

    for (String name : toUnset) {
      rc.unsetSection(LABEL, name);
    }
  }

  private void saveSubmitRequirementSections(Config rc) {
    unsetSection(rc, SUBMIT_REQUIREMENT);

    if (submitRequirementSections != null) {
      for (Map.Entry<String, SubmitRequirement> entry : submitRequirementSections.entrySet()) {
        String name = entry.getKey();
        SubmitRequirement sr = entry.getValue();

        if (sr.description().isPresent()) {
          rc.setString(SUBMIT_REQUIREMENT, name, KEY_SR_DESCRIPTION, sr.description().get());
        }
        if (sr.applicabilityExpression().isPresent()) {
          rc.setString(
              SUBMIT_REQUIREMENT,
              name,
              KEY_SR_APPLICABILITY_EXPRESSION,
              sr.applicabilityExpression().get().expressionString());
        }
        rc.setString(
            SUBMIT_REQUIREMENT,
            name,
            KEY_SR_SUBMITTABILITY_EXPRESSION,
            sr.submittabilityExpression().expressionString());
        if (sr.overrideExpression().isPresent()) {
          rc.setString(
              SUBMIT_REQUIREMENT,
              name,
              KEY_SR_OVERRIDE_EXPRESSION,
              sr.overrideExpression().get().expressionString());
        }
        rc.setBoolean(
            SUBMIT_REQUIREMENT,
            name,
            KEY_SR_OVERRIDE_IN_CHILD_PROJECTS,
            sr.allowOverrideInChildProjects());
      }
    }
  }

  private static void setBooleanConfigKey(
      Config rc, String section, String name, String key, boolean value, boolean defaultValue) {
    if (value == defaultValue) {
      rc.unset(section, name, key);
    } else {
      rc.setBoolean(section, name, key, value);
    }
  }

  private void savePluginSections(Config rc, Set<AccountGroup.UUID> keepGroups) {
    unsetSection(rc, PLUGIN);
    for (Map.Entry<String, Config> e : pluginConfigs.entrySet()) {
      String plugin = e.getKey();
      Config pluginConfig = e.getValue();
      for (String name : pluginConfig.getNames(PLUGIN, plugin)) {
        String value = pluginConfig.getString(PLUGIN, plugin, name);
        String groupName = GroupReference.extractGroupName(value);
        if (groupName != null) {
          GroupReference ref = groupList.byName(groupName);
          if (ref != null && ref.getUUID() != null) {
            keepGroups.add(ref.getUUID());
            pluginConfig.setString(PLUGIN, plugin, name, "group " + ref.getName());
          }
        }
        rc.setStringList(
            PLUGIN, plugin, name, Arrays.asList(pluginConfig.getStringList(PLUGIN, plugin, name)));
      }
    }
  }

  private void saveGroupList() throws IOException {
    saveUTF8(GroupList.FILE_NAME, groupList.asText());
  }

  private void saveSubscribeSections(Config rc) {
    for (Project.NameKey p : subscribeSections.keySet()) {
      SubscribeSection s = subscribeSections.get(p);
      List<String> matchings = new ArrayList<>();
      for (String r : s.matchingRefSpecsAsString()) {
        matchings.add(r);
      }
      rc.setStringList(SUBSCRIBE_SECTION, p.get(), SUBSCRIBE_MATCH_REFS, matchings);

      List<String> multimatchs = new ArrayList<>();
      for (String r : s.multiMatchRefSpecsAsString()) {
        multimatchs.add(r);
      }
      rc.setStringList(SUBSCRIBE_SECTION, p.get(), SUBSCRIBE_MULTI_MATCH_REFS, multimatchs);
    }
  }

  private void unsetSection(Config rc, String sectionName) {
    for (String subSectionName : rc.getSubsections(sectionName)) {
      rc.unsetSection(sectionName, subSectionName);
    }
    rc.unsetSection(sectionName, null);
  }

  private <E extends Enum<?>> E getEnum(
      Config rc, String section, String subsection, String name, E defaultValue) {
    try {
      return rc.getEnum(section, subsection, name, defaultValue);
    } catch (IllegalArgumentException err) {
      error(err.getMessage());
      return defaultValue;
    }
  }

  private void error(String errorMessage) {
    error(ValidationError.create(PROJECT_CONFIG, errorMessage));
  }

  @Override
  public void error(ValidationError error) {
    if (validationErrors == null) {
      validationErrors = new ArrayList<>(4);
    }
    validationErrors.add(error);
  }

  private static <T extends Comparable<? super T>> ImmutableList<T> sort(Collection<T> m) {
    return m.stream().sorted().collect(toImmutableList());
  }

  @UsedAt(UsedAt.Project.GOOGLE)
  public boolean hasLegacyPermissions() {
    return hasLegacyPermissions;
  }

  private String convertLegacyPermission(String permissionName) {
    switch (permissionName) {
      case LEGACY_PERMISSION_PUSH_TAG:
        hasLegacyPermissions = true;
        return Permission.CREATE_TAG;
      case LEGACY_PERMISSION_PUSH_SIGNED_TAG:
        hasLegacyPermissions = true;
        return Permission.CREATE_SIGNED_TAG;
      default:
        return permissionName;
    }
  }
}
