Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

FileRepository.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
  3. * Copyright (C) 2008-2010, Google Inc.
  4. * Copyright (C) 2006-2010, Robin Rosenberg <robin.rosenberg@dewire.com>
  5. * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org>
  6. * and other copyright owners as documented in the project's IP log.
  7. *
  8. * This program and the accompanying materials are made available
  9. * under the terms of the Eclipse Distribution License v1.0 which
  10. * accompanies this distribution, is reproduced below, and is
  11. * available at http://www.eclipse.org/org/documents/edl-v10.php
  12. *
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or
  16. * without modification, are permitted provided that the following
  17. * conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. *
  22. * - Redistributions in binary form must reproduce the above
  23. * copyright notice, this list of conditions and the following
  24. * disclaimer in the documentation and/or other materials provided
  25. * with the distribution.
  26. *
  27. * - Neither the name of the Eclipse Foundation, Inc. nor the
  28. * names of its contributors may be used to endorse or promote
  29. * products derived from this software without specific prior
  30. * written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  33. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  34. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  35. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  37. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  39. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  40. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  41. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  42. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  43. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  44. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. */
  46. package org.eclipse.jgit.storage.file;
  47. import java.io.File;
  48. import java.io.IOException;
  49. import java.text.MessageFormat;
  50. import java.util.HashSet;
  51. import java.util.Set;
  52. import org.eclipse.jgit.JGitText;
  53. import org.eclipse.jgit.errors.ConfigInvalidException;
  54. import org.eclipse.jgit.lib.BaseRepositoryBuilder;
  55. import org.eclipse.jgit.lib.ConfigConstants;
  56. import org.eclipse.jgit.lib.Constants;
  57. import org.eclipse.jgit.lib.ObjectId;
  58. import org.eclipse.jgit.lib.Ref;
  59. import org.eclipse.jgit.lib.RefDatabase;
  60. import org.eclipse.jgit.lib.RefUpdate;
  61. import org.eclipse.jgit.lib.Repository;
  62. import org.eclipse.jgit.storage.file.FileObjectDatabase.AlternateHandle;
  63. import org.eclipse.jgit.storage.file.FileObjectDatabase.AlternateRepository;
  64. import org.eclipse.jgit.util.SystemReader;
  65. /**
  66. * Represents a Git repository. A repository holds all objects and refs used for
  67. * managing source code (could by any type of file, but source code is what
  68. * SCM's are typically used for).
  69. *
  70. * In Git terms all data is stored in GIT_DIR, typically a directory called
  71. * .git. A work tree is maintained unless the repository is a bare repository.
  72. * Typically the .git directory is located at the root of the work dir.
  73. *
  74. * <ul>
  75. * <li>GIT_DIR
  76. * <ul>
  77. * <li>objects/ - objects</li>
  78. * <li>refs/ - tags and heads</li>
  79. * <li>config - configuration</li>
  80. * <li>info/ - more configurations</li>
  81. * </ul>
  82. * </li>
  83. * </ul>
  84. * <p>
  85. * This class is thread-safe.
  86. * <p>
  87. * This implementation only handles a subtly undocumented subset of git features.
  88. *
  89. */
  90. public class FileRepository extends Repository {
  91. private final FileBasedConfig userConfig;
  92. private final FileBasedConfig repoConfig;
  93. private final RefDatabase refs;
  94. private final ObjectDirectory objectDatabase;
  95. /**
  96. * Construct a representation of a Git repository.
  97. * <p>
  98. * The work tree, object directory, alternate object directories and index
  99. * file locations are deduced from the given git directory and the default
  100. * rules by running {@link FileRepositoryBuilder}. This constructor is the
  101. * same as saying:
  102. *
  103. * <pre>
  104. * new FileRepositoryBuilder().setGitDir(gitDir).build()
  105. * </pre>
  106. *
  107. * @param gitDir
  108. * GIT_DIR (the location of the repository metadata).
  109. * @throws IOException
  110. * the repository appears to already exist but cannot be
  111. * accessed.
  112. * @see FileRepositoryBuilder
  113. */
  114. public FileRepository(final File gitDir) throws IOException {
  115. this(new FileRepositoryBuilder().setGitDir(gitDir).setup());
  116. }
  117. /**
  118. * Create a repository using the local file system.
  119. *
  120. * @param options
  121. * description of the repository's important paths.
  122. * @throws IOException
  123. * the user configuration file or repository configuration file
  124. * cannot be accessed.
  125. */
  126. public FileRepository(final BaseRepositoryBuilder options) throws IOException {
  127. super(options);
  128. userConfig = SystemReader.getInstance().openUserConfig(getFS());
  129. repoConfig = new FileBasedConfig(userConfig, getFS().resolve(getDirectory(), "config"));
  130. loadUserConfig();
  131. loadRepoConfig();
  132. refs = new RefDirectory(this);
  133. objectDatabase = new ObjectDirectory(repoConfig, //
  134. options.getObjectDirectory(), //
  135. options.getAlternateObjectDirectories(), //
  136. getFS());
  137. getListenerList().addConfigChangedListener(objectDatabase);
  138. if (objectDatabase.exists()) {
  139. final String repositoryFormatVersion = getConfig().getString(
  140. ConfigConstants.CONFIG_CORE_SECTION, null,
  141. ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION);
  142. if (!"0".equals(repositoryFormatVersion)) {
  143. throw new IOException(MessageFormat.format(
  144. JGitText.get().unknownRepositoryFormat2,
  145. repositoryFormatVersion));
  146. }
  147. }
  148. }
  149. private void loadUserConfig() throws IOException {
  150. try {
  151. userConfig.load();
  152. } catch (ConfigInvalidException e1) {
  153. IOException e2 = new IOException(MessageFormat.format(JGitText
  154. .get().userConfigFileInvalid, userConfig.getFile()
  155. .getAbsolutePath(), e1));
  156. e2.initCause(e1);
  157. throw e2;
  158. }
  159. }
  160. private void loadRepoConfig() throws IOException {
  161. try {
  162. repoConfig.load();
  163. } catch (ConfigInvalidException e1) {
  164. IOException e2 = new IOException(JGitText.get().unknownRepositoryFormat);
  165. e2.initCause(e1);
  166. throw e2;
  167. }
  168. }
  169. /**
  170. * Create a new Git repository initializing the necessary files and
  171. * directories.
  172. *
  173. * @param bare
  174. * if true, a bare repository is created.
  175. *
  176. * @throws IOException
  177. * in case of IO problem
  178. */
  179. public void create(boolean bare) throws IOException {
  180. final FileBasedConfig cfg = getConfig();
  181. if (cfg.getFile().exists()) {
  182. throw new IllegalStateException(MessageFormat.format(
  183. JGitText.get().repositoryAlreadyExists, getDirectory()));
  184. }
  185. getDirectory().mkdirs();
  186. refs.create();
  187. objectDatabase.create();
  188. new File(getDirectory(), "branches").mkdir();
  189. RefUpdate head = updateRef(Constants.HEAD);
  190. head.disableRefLog();
  191. head.link(Constants.R_HEADS + Constants.MASTER);
  192. cfg.setInt(ConfigConstants.CONFIG_CORE_SECTION, null,
  193. ConfigConstants.CONFIG_KEY_REPO_FORMAT_VERSION, 0);
  194. cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  195. ConfigConstants.CONFIG_KEY_FILEMODE, true);
  196. if (bare)
  197. cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  198. ConfigConstants.CONFIG_KEY_BARE, true);
  199. cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  200. ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, !bare);
  201. cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  202. ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
  203. cfg.save();
  204. }
  205. /**
  206. * @return the directory containing the objects owned by this repository.
  207. */
  208. public File getObjectsDirectory() {
  209. return objectDatabase.getDirectory();
  210. }
  211. /**
  212. * @return the object database which stores this repository's data.
  213. */
  214. public ObjectDirectory getObjectDatabase() {
  215. return objectDatabase;
  216. }
  217. /** @return the reference database which stores the reference namespace. */
  218. public RefDatabase getRefDatabase() {
  219. return refs;
  220. }
  221. /**
  222. * @return the configuration of this repository
  223. */
  224. public FileBasedConfig getConfig() {
  225. if (userConfig.isOutdated()) {
  226. try {
  227. loadUserConfig();
  228. } catch (IOException e) {
  229. throw new RuntimeException(e);
  230. }
  231. }
  232. if (repoConfig.isOutdated()) {
  233. try {
  234. loadRepoConfig();
  235. } catch (IOException e) {
  236. throw new RuntimeException(e);
  237. }
  238. }
  239. return repoConfig;
  240. }
  241. /**
  242. * Objects known to exist but not expressed by {@link #getAllRefs()}.
  243. * <p>
  244. * When a repository borrows objects from another repository, it can
  245. * advertise that it safely has that other repository's references, without
  246. * exposing any other details about the other repository. This may help
  247. * a client trying to push changes avoid pushing more than it needs to.
  248. *
  249. * @return unmodifiable collection of other known objects.
  250. */
  251. public Set<ObjectId> getAdditionalHaves() {
  252. HashSet<ObjectId> r = new HashSet<ObjectId>();
  253. for (AlternateHandle d : objectDatabase. myAlternates()) {
  254. if (d instanceof AlternateRepository) {
  255. Repository repo;
  256. repo = ((AlternateRepository) d).repository;
  257. for (Ref ref : repo.getAllRefs().values())
  258. r.add(ref.getObjectId());
  259. r.addAll(repo.getAdditionalHaves());
  260. }
  261. }
  262. return r;
  263. }
  264. /**
  265. * Add a single existing pack to the list of available pack files.
  266. *
  267. * @param pack
  268. * path of the pack file to open.
  269. * @param idx
  270. * path of the corresponding index file.
  271. * @throws IOException
  272. * index file could not be opened, read, or is not recognized as
  273. * a Git pack file index.
  274. */
  275. public void openPack(final File pack, final File idx) throws IOException {
  276. objectDatabase.openPack(pack, idx);
  277. }
  278. /**
  279. * Force a scan for changed refs.
  280. *
  281. * @throws IOException
  282. */
  283. public void scanForRepoChanges() throws IOException {
  284. getAllRefs(); // This will look for changes to refs
  285. if (!isBare())
  286. getIndex(); // This will detect changes in the index
  287. }
  288. /**
  289. * @param refName
  290. * @return a {@link ReflogReader} for the supplied refname, or null if the
  291. * named ref does not exist.
  292. * @throws IOException the ref could not be accessed.
  293. */
  294. public ReflogReader getReflogReader(String refName) throws IOException {
  295. Ref ref = getRef(refName);
  296. if (ref != null)
  297. return new ReflogReader(this, ref.getName());
  298. return null;
  299. }
  300. }