View Javadoc
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  
13  package org.eclipse.jgit.lib;
14  
15  import static java.nio.charset.StandardCharsets.UTF_8;
16  
17  import java.io.FileNotFoundException;
18  import java.io.IOException;
19  import java.text.MessageFormat;
20  
21  import org.eclipse.jgit.errors.ConfigInvalidException;
22  import org.eclipse.jgit.errors.IncorrectObjectTypeException;
23  import org.eclipse.jgit.errors.MissingObjectException;
24  import org.eclipse.jgit.internal.JGitText;
25  import org.eclipse.jgit.revwalk.RevCommit;
26  import org.eclipse.jgit.revwalk.RevTree;
27  import org.eclipse.jgit.revwalk.RevWalk;
28  import org.eclipse.jgit.treewalk.TreeWalk;
29  import org.eclipse.jgit.util.RawParseUtils;
30  
31  /**
32   * Configuration file based on the blobs stored in the repository.
33   *
34   * This implementation currently only provides reading support, and is primarily
35   * useful for supporting the {@code .gitmodules} file.
36   */
37  public class BlobBasedConfig extends Config {
38  	/**
39  	 * Parse a configuration from a byte array.
40  	 *
41  	 * @param base
42  	 *            the base configuration file
43  	 * @param blob
44  	 *            the byte array, should be UTF-8 encoded text.
45  	 * @throws org.eclipse.jgit.errors.ConfigInvalidException
46  	 *             the byte array is not a valid configuration format.
47  	 */
48  	public BlobBasedConfig(Config base, byte[] blob)
49  			throws ConfigInvalidException {
50  		super(base);
51  		final String decoded;
52  		if (isUtf8(blob)) {
53  			decoded = RawParseUtils.decode(UTF_8, blob, 3, blob.length);
54  		} else {
55  			decoded = RawParseUtils.decode(blob);
56  		}
57  		fromText(decoded);
58  	}
59  
60  	/**
61  	 * Load a configuration file from a blob.
62  	 *
63  	 * @param base
64  	 *            the base configuration file
65  	 * @param db
66  	 *            the repository
67  	 * @param objectId
68  	 *            the object identifier
69  	 * @throws java.io.IOException
70  	 *             the blob cannot be read from the repository.
71  	 * @throws org.eclipse.jgit.errors.ConfigInvalidException
72  	 *             the blob is not a valid configuration format.
73  	 */
74  	public BlobBasedConfig(Config base, Repository db, AnyObjectId objectId)
75  			throws IOException, ConfigInvalidException {
76  		this(base, read(db, objectId));
77  	}
78  
79  	private static byte[] read(Repository db, AnyObjectId blobId)
80  			throws MissingObjectException, IncorrectObjectTypeException,
81  			IOException {
82  		try (ObjectReader or = db.newObjectReader()) {
83  			return read(or, blobId);
84  		}
85  	}
86  
87  	private static byte[] read(ObjectReader or, AnyObjectId blobId)
88  			throws MissingObjectException, IncorrectObjectTypeException,
89  			IOException {
90  		ObjectLoader loader = or.open(blobId, Constants.OBJ_BLOB);
91  		return loader.getCachedBytes(Integer.MAX_VALUE);
92  	}
93  
94  	/**
95  	 * Load a configuration file from a blob stored in a specific commit.
96  	 *
97  	 * @param base
98  	 *            the base configuration file
99  	 * @param db
100 	 *            the repository containing the objects.
101 	 * @param treeish
102 	 *            the tree (or commit) that contains the object
103 	 * @param path
104 	 *            the path within the tree
105 	 * @throws java.io.FileNotFoundException
106 	 *             the path does not exist in the commit's tree.
107 	 * @throws java.io.IOException
108 	 *             the tree and/or blob cannot be accessed.
109 	 * @throws org.eclipse.jgit.errors.ConfigInvalidException
110 	 *             the blob is not a valid configuration format.
111 	 */
112 	public BlobBasedConfig(Config base, Repository db, AnyObjectId treeish,
113 			String path) throws FileNotFoundException, IOException,
114 			ConfigInvalidException {
115 		this(base, read(db, treeish, path));
116 	}
117 
118 	private static byte[] read(Repository db, AnyObjectId treeish, String path)
119 			throws MissingObjectException, IncorrectObjectTypeException,
120 			IOException {
121 		try (ObjectReader or = db.newObjectReader()) {
122 			TreeWalk tree = TreeWalk.forPath(or, path, asTree(or, treeish));
123 			if (tree == null)
124 				throw new FileNotFoundException(MessageFormat.format(JGitText
125 						.get().entryNotFoundByPath, path));
126 			return read(or, tree.getObjectId(0));
127 		}
128 	}
129 
130 	private static AnyObjectId asTree(ObjectReader or, AnyObjectId treeish)
131 			throws MissingObjectException, IncorrectObjectTypeException,
132 			IOException {
133 		if (treeish instanceof RevTree)
134 			return treeish;
135 
136 		if (treeish instanceof RevCommit
137 				&& ((RevCommit) treeish).getTree() != null)
138 			return ((RevCommit) treeish).getTree();
139 
140 		try (RevWalk rw = new RevWalk(or)) {
141 			return rw.parseTree(treeish).getId();
142 		}
143 	}
144 }