Paul Martin
2016-04-30 a502d96a860456ec5e8c96761db70f7cabb74751
src/main/bugtraq/com/syntevo/bugtraq/BugtraqConfig.java
@@ -29,10 +29,8 @@
 */
package com.syntevo.bugtraq;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -45,10 +43,9 @@
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileBasedConfig;
@@ -62,51 +59,98 @@
   // Constants ==============================================================
   private static final String DOT_GIT_BUGTRAQ = ".gitbugtraq";
   private static final String DOT_TGITCONFIG = ".tgitconfig";
   private static final String BUGTRAQ = "bugtraq";
   private static final String URL = "url";
   private static final String ENABLED = "enabled";
   private static final String LOG_REGEX = "logRegex";
   private static final String LOG_REGEX = "logregex";
   private static final String LOG_FILTERREGEX = "logfilterregex";
   private static final String LOG_LINKREGEX = "loglinkregex";
   private static final String LOG_LINKTEXT = "loglinktext";
   // Static =================================================================
   @Nullable
   public static BugtraqConfig read(@NotNull Repository repository) throws IOException, ConfigInvalidException {
      final Config baseConfig = getBaseConfig(repository);
      Config baseConfig = getBaseConfig(repository, DOT_GIT_BUGTRAQ);
      if (baseConfig == null) {
         baseConfig = getBaseConfig(repository, DOT_TGITCONFIG);
      }
      final Set<String> allNames = new HashSet<String>();
      final Config config = repository.getConfig();
      allNames.addAll(config.getSubsections(BUGTRAQ));
      if (baseConfig != null) {
         allNames.addAll(baseConfig.getSubsections(BUGTRAQ));
      final Config config;
      try {
         config = repository.getConfig();
      }
      catch (RuntimeException ex) {
         final Throwable cause = ex.getCause();
         if (cause instanceof IOException) {
            throw (IOException)cause;
         }
         throw ex;
      }
      if (getString(null, URL, config, baseConfig) != null) {
         allNames.add(null);
      }
      else {
         allNames.addAll(config.getSubsections(BUGTRAQ));
         if (baseConfig != null) {
            allNames.addAll(baseConfig.getSubsections(BUGTRAQ));
         }
      }
      final List<BugtraqEntry> entries = new ArrayList<BugtraqEntry>();
      for (String name : allNames) {
         final String url = getString(name, URL, config, baseConfig);
         if (url == null) {
            continue;
         }
         final String enabled = getString(name, ENABLED, config, baseConfig);
         if (enabled != null && !"true".equals(enabled)) {
            continue;
         }
         final String logIdRegex = getString(name, LOG_REGEX, config, baseConfig);
         if (url == null || logIdRegex == null) {
         String idRegex = getString(name, LOG_REGEX, config, baseConfig);
         if (idRegex == null) {
            return null;
         }
         final List<String> logIdRegexs = new ArrayList<String>();
         logIdRegexs.add(logIdRegex);
         for (int index = 1; index < Integer.MAX_VALUE; index++) {
            final String logIdRegexN = getString(name, LOG_REGEX + index, config, baseConfig);
            if (logIdRegexN == null) {
               break;
         String filterRegex = getString(name, LOG_FILTERREGEX, config, baseConfig);
         final String linkRegex = getString(name, LOG_LINKREGEX, config, baseConfig);
         if (filterRegex == null && linkRegex == null) {
            final String[] split = idRegex.split("\n", Integer.MAX_VALUE);
            if (split.length == 2) {
               // Compatibility with TortoiseGit
               filterRegex = split[0];
               idRegex = split[1];
            }
            else {
               // Backwards compatibility with specification version < 0.3
               final List<String> logIdRegexs = new ArrayList<String>();
               for (int index = 1; index < Integer.MAX_VALUE; index++) {
                  final String logIdRegexN = getString(name, LOG_REGEX + index, config, baseConfig);
                  if (logIdRegexN == null) {
                     break;
                  }
            logIdRegexs.add(logIdRegexN);
                  logIdRegexs.add(logIdRegexN);
               }
               if (logIdRegexs.size() > 1) {
                  throw new ConfigInvalidException("More than three " + LOG_REGEX + " entries found. This is not supported anymore since bugtraq version 0.3, use " + LOG_FILTERREGEX + " and " + LOG_LINKREGEX + " instead.");
               }
               else if (logIdRegexs.size() == 1) {
                  filterRegex = idRegex;
                  idRegex = logIdRegexs.get(0);
               }
            }
         }
         entries.add(new BugtraqEntry(url, logIdRegexs));
         final String linkText = getString(name, LOG_LINKTEXT, config, baseConfig);
         entries.add(new BugtraqEntry(url, idRegex, linkRegex, filterRegex, linkText));
      }
      if (entries.isEmpty()) {
@@ -137,67 +181,56 @@
   // Utils ==================================================================
   @Nullable
   private static Config getBaseConfig(Repository repository) throws IOException, ConfigInvalidException {
   private static Config getBaseConfig(@NotNull Repository repository, @NotNull String configFileName) throws IOException, ConfigInvalidException {
      final Config baseConfig;
      if (repository.isBare()) {
         // read bugtraq config directly from the repository
         String content = null;
         String head = repository.getFullBranch();
         RevWalk rw = new RevWalk(repository);
         TreeWalk tw = new TreeWalk(repository);
         tw.setFilter(PathFilterGroup.createFromStrings(DOT_GIT_BUGTRAQ));
         tw.setFilter(PathFilterGroup.createFromStrings(configFileName));
         try {
            ObjectId headId = repository.resolve(head);
            final Ref ref = repository.getRef(Constants.HEAD);
            if (ref == null) {
               return null;
            }
            ObjectId headId = ref.getTarget().getObjectId();
            if (headId == null || ObjectId.zeroId().equals(headId)) {
               return null;
            }
            RevCommit commit = rw.parseCommit(headId);
            RevTree tree = commit.getTree();
            tw.reset(tree);
            while (tw.next()) {
               if (tw.isSubtree()) {
                  tw.enterSubtree();
                  continue;
               }
               ObjectId entid = tw.getObjectId(0);
               FileMode entmode = tw.getFileMode(0);
               if (entmode == FileMode.REGULAR_FILE) {
                  RevObject ro = rw.lookupAny(entid, entmode.getObjectType());
                  rw.parseBody(ro);
                  ByteArrayOutputStream os = new ByteArrayOutputStream();
                  ObjectLoader ldr = repository.open(ro.getId(), Constants.OBJ_BLOB);
                  byte[] tmp = new byte[4096];
                  InputStream in = ldr.openStream();
                  int n;
                  while ((n = in.read(tmp)) > 0) {
                     os.write(tmp, 0, n);
                  }
                  in.close();
                  content = new String(os.toByteArray(), commit.getEncoding());
               if (FileMode.REGULAR_FILE == entmode) {
                  ObjectLoader ldr = repository.open(entid, Constants.OBJ_BLOB);
                  content = new String(ldr.getCachedBytes(), commit.getEncoding());
                  break;
               }
            }
         } finally {
         }
         finally {
            rw.dispose();
            tw.release();
            tw.close();
         }
         if (content == null) {
            // config not found
            baseConfig = null;
         } else {
            // parse the config
            Config cfg = new Config();
            cfg.fromText(content);
            baseConfig = new StoredConfig(cfg) {
               @Override
               public void save() throws IOException {
               }
               @Override
               public void load() throws IOException, ConfigInvalidException {
               }
            };
         }
      } else {
         else {
            // parse the config
            Config config = new Config();
            config.fromText(content);
            baseConfig = config;
         }
      }
      else {
         // read bugtraq config from work tree
         final File baseFile = new File(repository.getWorkTree(), DOT_GIT_BUGTRAQ);
         final File baseFile = new File(repository.getWorkTree(), configFileName);
         if (baseFile.isFile()) {
            FileBasedConfig fileConfig = new FileBasedConfig(baseFile, repository.getFS());
            fileConfig.load();
@@ -211,7 +244,7 @@
   }
   @Nullable
   private static String getString(@NotNull String subsection, @NotNull String key, @NotNull Config config, @Nullable Config baseConfig) {
   private static String getString(@Nullable String subsection, @NotNull String key, @NotNull Config config, @Nullable Config baseConfig) {
      final String value = config.getString(BUGTRAQ, subsection, key);
      if (value != null) {
         return trimMaybeNull(value);
@@ -221,8 +254,8 @@
         return trimMaybeNull(baseConfig.getString(BUGTRAQ, subsection, key));
      }
      return value;
   }
         return value;
      }
   @Nullable
   private static String trimMaybeNull(@Nullable String string) {