code: package com.beijunyi.parallelgit.filesystem.utils;
  
  import java.util.regex.PatternSyntaxException;
  import javax.annotation.Nonnull;
  
  public final class GitGlobs {
  
    private static final String REGEX_META_CHARS = ".^$+{[]|()";
    private static final String GLOB_META_CHARS = "\\*?[{";
    private static final char EOL = 0;
  
    private static boolean isRegexMeta(char c) {
      return REGEX_META_CHARS.indexOf(c) != -1;
    }
    private static boolean isGlobMeta(char c) {
      return GLOB_META_CHARS.indexOf(c) != -1;
    }
  
    private static char charAt(String glob, int i) {
      return i < glob.length() ? glob.charAt(i) : EOL;
    }
  
    @Nonnull
    public static String toRegexPattern(String globPattern) {
      boolean inGroup = false;
      StringBuilder regex = new StringBuilder("^");
  
      int i = 0;
      while(i < globPattern.length()) {
        char c = globPattern.charAt(i++);
        switch(c) {
          case '\\':
            // escape special characters
            if(i == globPattern.length()) throw new PatternSyntaxException("No character to escape", globPattern, i - 1);
            char next = globPattern.charAt(i++);
            if(isGlobMeta(next) || isRegexMeta(next)) regex.append('\\');
            regex.append(next);
            break;
          case '/':
            regex.append(c);
            break;
          case '[':
            regex.append("[[^/]&&[");
            if(charAt(globPattern, i) == '^') {
              // escape the regex negation char if it appears
              regex.append("\\^");
              i++;
            } else {
              // negation
              if(charAt(globPattern, i) == '!') {
                regex.append('^');
                i++;
              }
              // hyphen allowed at start
              if(charAt(globPattern, i) == '-') {
                regex.append('-');
                i++;
              }
            }
            boolean hasRangeStart = false;
            char last = 0;
            while(i < globPattern.length()) {
              c = globPattern.charAt(i++);
              if(c == ']') break;
              if(c == '/') throw new PatternSyntaxException("Explicit 'name separator' in class", globPattern, i - 1);
              // TBD: how to specify ']' in a class?
              if(c == '\\' || c == '[' || c == '&' && charAt(globPattern, i) == '&') {
                // escape '\', '[' or "&&" for regex class
                regex.append('\\');
              }
              regex.append(c);
  
              if(c == '-') {
                if(!hasRangeStart) throw new PatternSyntaxException("Invalid range", globPattern, i - 1);
                if((c = charAt(globPattern, i++)) == EOL || c == ']') break;
                if(c < last) throw new PatternSyntaxException("Invalid range", globPattern, i - 3);
                regex.append(c);
                hasRangeStart = false;
              } else {
                hasRangeStart = true;
                last = c;
              }
            }
            if(c != ']') throw new PatternSyntaxException("Missing ']", globPattern, i - 1);
            regex.append("]]");
            break;
          case '{':
            if(inGroup) throw new PatternSyntaxException("Cannot nest groups", globPattern, i - 1);
            regex.append("(?:(?:");
            inGroup = true;
            break;
          case '}':
            if(inGroup) {
              regex.append("))");
              inGroup = false;
            } else {
              regex.append('}');
            }
            break;
          case ',':
            if(inGroup) regex.append(")|(?:");
            else regex.append(',');
            break;
          case '*':
            if(charAt(globPattern, i) == '*') { // crosses directory boundaries
              regex.append(".*");
              i++;
            } else { // within directory boundary
              regex.append("[^/]*");
            }
            break;
          case '?':
            regex.append("[^/]");
            break;
          default:
            if(isRegexMeta(c)) regex.append('\\');
            regex.append(c);
        }
      }
      if(inGroup) throw new PatternSyntaxException("Missing '}", globPattern, i - 1);
      return regex.append('$').toString();
    }
  
  }
  