BlobBasedConfig.java

  1. /*
  2.  * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
  3.  * Copyright (C) 2009, Google Inc.
  4.  * Copyright (C) 2009, JetBrains s.r.o. and others
  5.  *
  6.  * This program and the accompanying materials are made available under the
  7.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  8.  * https://www.eclipse.org/org/documents/edl-v10.php.
  9.  *
  10.  * SPDX-License-Identifier: BSD-3-Clause
  11.  */

  12. package org.eclipse.jgit.lib;

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

  14. import java.io.FileNotFoundException;
  15. import java.io.IOException;
  16. import java.text.MessageFormat;

  17. import org.eclipse.jgit.errors.ConfigInvalidException;
  18. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  19. import org.eclipse.jgit.errors.MissingObjectException;
  20. import org.eclipse.jgit.internal.JGitText;
  21. import org.eclipse.jgit.revwalk.RevCommit;
  22. import org.eclipse.jgit.revwalk.RevTree;
  23. import org.eclipse.jgit.revwalk.RevWalk;
  24. import org.eclipse.jgit.treewalk.TreeWalk;
  25. import org.eclipse.jgit.util.RawParseUtils;

  26. /**
  27.  * Configuration file based on the blobs stored in the repository.
  28.  *
  29.  * This implementation currently only provides reading support, and is primarily
  30.  * useful for supporting the {@code .gitmodules} file.
  31.  */
  32. public class BlobBasedConfig extends Config {
  33.     /**
  34.      * Parse a configuration from a byte array.
  35.      *
  36.      * @param base
  37.      *            the base configuration file
  38.      * @param blob
  39.      *            the byte array, should be UTF-8 encoded text.
  40.      * @throws org.eclipse.jgit.errors.ConfigInvalidException
  41.      *             the byte array is not a valid configuration format.
  42.      */
  43.     public BlobBasedConfig(Config base, byte[] blob)
  44.             throws ConfigInvalidException {
  45.         super(base);
  46.         final String decoded;
  47.         if (isUtf8(blob)) {
  48.             decoded = RawParseUtils.decode(UTF_8, blob, 3, blob.length);
  49.         } else {
  50.             decoded = RawParseUtils.decode(blob);
  51.         }
  52.         fromText(decoded);
  53.     }

  54.     /**
  55.      * Load a configuration file from a blob.
  56.      *
  57.      * @param base
  58.      *            the base configuration file
  59.      * @param db
  60.      *            the repository
  61.      * @param objectId
  62.      *            the object identifier
  63.      * @throws java.io.IOException
  64.      *             the blob cannot be read from the repository.
  65.      * @throws org.eclipse.jgit.errors.ConfigInvalidException
  66.      *             the blob is not a valid configuration format.
  67.      */
  68.     public BlobBasedConfig(Config base, Repository db, AnyObjectId objectId)
  69.             throws IOException, ConfigInvalidException {
  70.         this(base, read(db, objectId));
  71.     }

  72.     private static byte[] read(Repository db, AnyObjectId blobId)
  73.             throws MissingObjectException, IncorrectObjectTypeException,
  74.             IOException {
  75.         try (ObjectReader or = db.newObjectReader()) {
  76.             return read(or, blobId);
  77.         }
  78.     }

  79.     private static byte[] read(ObjectReader or, AnyObjectId blobId)
  80.             throws MissingObjectException, IncorrectObjectTypeException,
  81.             IOException {
  82.         ObjectLoader loader = or.open(blobId, Constants.OBJ_BLOB);
  83.         return loader.getCachedBytes(Integer.MAX_VALUE);
  84.     }

  85.     /**
  86.      * Load a configuration file from a blob stored in a specific commit.
  87.      *
  88.      * @param base
  89.      *            the base configuration file
  90.      * @param db
  91.      *            the repository containing the objects.
  92.      * @param treeish
  93.      *            the tree (or commit) that contains the object
  94.      * @param path
  95.      *            the path within the tree
  96.      * @throws java.io.FileNotFoundException
  97.      *             the path does not exist in the commit's tree.
  98.      * @throws java.io.IOException
  99.      *             the tree and/or blob cannot be accessed.
  100.      * @throws org.eclipse.jgit.errors.ConfigInvalidException
  101.      *             the blob is not a valid configuration format.
  102.      */
  103.     public BlobBasedConfig(Config base, Repository db, AnyObjectId treeish,
  104.             String path) throws FileNotFoundException, IOException,
  105.             ConfigInvalidException {
  106.         this(base, read(db, treeish, path));
  107.     }

  108.     private static byte[] read(Repository db, AnyObjectId treeish, String path)
  109.             throws MissingObjectException, IncorrectObjectTypeException,
  110.             IOException {
  111.         try (ObjectReader or = db.newObjectReader()) {
  112.             TreeWalk tree = TreeWalk.forPath(or, path, asTree(or, treeish));
  113.             if (tree == null)
  114.                 throw new FileNotFoundException(MessageFormat.format(JGitText
  115.                         .get().entryNotFoundByPath, path));
  116.             return read(or, tree.getObjectId(0));
  117.         }
  118.     }

  119.     private static AnyObjectId asTree(ObjectReader or, AnyObjectId treeish)
  120.             throws MissingObjectException, IncorrectObjectTypeException,
  121.             IOException {
  122.         if (treeish instanceof RevTree)
  123.             return treeish;

  124.         if (treeish instanceof RevCommit
  125.                 && ((RevCommit) treeish).getTree() != null)
  126.             return ((RevCommit) treeish).getTree();

  127.         try (RevWalk rw = new RevWalk(or)) {
  128.             return rw.parseTree(treeish).getId();
  129.         }
  130.     }
  131. }