package com.hubspot.blazar.discovery;

import com.google.common.collect.ImmutableSet;
import com.hubspot.blazar.base.CommitInfo;
import com.hubspot.blazar.base.DiscoveredModule;
import com.hubspot.blazar.base.DiscoveryResult;
import com.hubspot.blazar.base.GitInfo;
import com.hubspot.blazar.base.MalformedFile;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Singleton
public class CompositeModuleDiscovery implements ModuleDiscovery {
  private final Set<ModuleDiscovery> delegates;
  private final BlazarConfigModuleDiscovery configDiscovery;

  @Inject
  public CompositeModuleDiscovery(Set<ModuleDiscovery> delegates, BlazarConfigModuleDiscovery configDiscovery) {
    this.delegates = delegates;
    this.configDiscovery = configDiscovery;
  }

  @Override
  public boolean shouldRediscover(GitInfo gitInfo, CommitInfo commitInfo) throws IOException {
    for (ModuleDiscovery delegate : delegates) {
      if (delegate.shouldRediscover(gitInfo, commitInfo)) {
        return true;
      }
    }

    return configDiscovery.shouldRediscover(gitInfo, commitInfo);
  }

  @Override
  public DiscoveryResult discover(GitInfo gitInfo) throws IOException {
    Map<String, Set<DiscoveredModule>> modulesByPath = new HashMap<>();
    Set<MalformedFile> malformedFiles = new HashSet<>();

    for (ModuleDiscovery delegate : delegates) {
      DiscoveryResult result = delegate.discover(gitInfo);
      malformedFiles.addAll(result.getMalformedFiles());
      for (DiscoveredModule module : result.getModules()) {
        String folder = module.getFolder();

        Set<DiscoveredModule> modules = modulesByPath.get(folder);
        if (modules == null) {
          modules = new HashSet<>();
          modulesByPath.put(folder, modules);
        }

        modules.add(module);
      }
    }

    DiscoveryResult result = configDiscovery.discover(gitInfo);
    malformedFiles.addAll(result.getMalformedFiles());
    for (DiscoveredModule module : result.getModules()) {
      String folder = module.getFolder();

      if (!module.isActive()) {
        modulesByPath.remove(folder);
      } else if (!modulesByPath.containsKey(folder)) {
        modulesByPath.put(folder, ImmutableSet.of(module));
      }
    }

    Set<DiscoveredModule> modules = new HashSet<>();
    for (Set<DiscoveredModule> folderModules : modulesByPath.values()) {
      modules.addAll(folderModules);
    }

    return new DiscoveryResult(modules, malformedFiles);
  }
}

@@ -32,16 +32,284 @@
 overy;%0A%0A
+import java.io.IOException;%0Aimport java.util.HashMap;%0Aimport java.util.HashSet;%0Aimport java.util.Map;%0Aimport java.util.Set;%0A%0Aimport javax.inject.Inject;%0Aimport javax.inject.Singleton;%0A%0Aimport com.google.common.base.CharMatcher;%0Aimport com.google.common.base.Optional;%0A
 import c
@@ -343,24 +343,24 @@
 mutableSet;%0A
-
 import com.h
@@ -578,192 +578,8 @@
 e;%0A%0A
-import javax.inject.Inject;%0Aimport javax.inject.Singleton;%0Aimport java.io.IOException;%0Aimport java.util.HashMap;%0Aimport java.util.HashSet;%0Aimport java.util.Map;%0Aimport java.util.Set;%0A%0A
 @Sin
@@ -1499,24 +1499,260 @@
 shSet%3C%3E();%0A%0A
+    Optional%3CMalformedFile%3E malformedBranchFile = preDiscoveryBranchValidation(gitInfo);%0A    if (malformedBranchFile.isPresent()) %7B%0A      return new DiscoveryResult(ImmutableSet.of(), ImmutableSet.of(malformedBranchFile.get()));%0A    %7D%0A%0A
     for (Mod
@@ -2827,32 +2827,32 @@
 odules);%0A    %7D%0A%0A
-
     return new D
@@ -2895,11 +2895,1086 @@
 es);%0A  %7D
+%0A%0A  /**%0A   * There are certain characters which (currently) play havoc with our downstream build tooling (our executor).%0A   * In order to prevent downstream failures we validate here in order to make sure that branches we cannot handle,%0A   * are not consumed by downstream services. Ideally those services would be more resilient but at this time they are not.%0A   *%0A   * @param gitInfo The branch we are checking for validity.%0A   * @return A malformed %22file%22 representing the invalid branch name if it is invalid%0A   */%0A  private Optional%3CMalformedFile%3E preDiscoveryBranchValidation(GitInfo gitInfo) %7B%0A    String branch = gitInfo.getBranch();%0A    if (branch.contains(%22'%22) %7C%7C%0A        branch.contains(%22%5C%22%22) %7C%7C%0A        CharMatcher.ASCII.matchesAllOf(branch)) %7B%0A      String message = String.format(%22Branch %25s contained non-ascii or quotation characters not supported by Blazar.%5CnPlease re-create your branch with a new name.%22, branch);%0A      return Optional.of(new MalformedFile(gitInfo.getId().get(), %22branch-validation%22, %22/%22, message));%0A    %7D%0A%0A    return Optional.absent();%0A  %7D
 %0A%7D%0A

Add validation to prevent discovery of branches with wierd chars from totally busting blazar.