You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GarbageCollectCommand.java 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (C) 2012, Matthias Sohn <matthias.sohn@sap.com>
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.api;
  44. import java.io.IOException;
  45. import java.text.MessageFormat;
  46. import java.text.ParseException;
  47. import java.util.Date;
  48. import java.util.Properties;
  49. import org.eclipse.jgit.api.errors.GitAPIException;
  50. import org.eclipse.jgit.api.errors.JGitInternalException;
  51. import org.eclipse.jgit.internal.JGitText;
  52. import org.eclipse.jgit.internal.storage.dfs.DfsGarbageCollector;
  53. import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
  54. import org.eclipse.jgit.internal.storage.file.FileRepository;
  55. import org.eclipse.jgit.internal.storage.file.GC;
  56. import org.eclipse.jgit.internal.storage.file.GC.RepoStatistics;
  57. import org.eclipse.jgit.lib.ConfigConstants;
  58. import org.eclipse.jgit.lib.ProgressMonitor;
  59. import org.eclipse.jgit.lib.Repository;
  60. import org.eclipse.jgit.lib.StoredConfig;
  61. import org.eclipse.jgit.storage.pack.PackConfig;
  62. import org.eclipse.jgit.util.GitDateParser;
  63. /**
  64. * A class used to execute a {@code gc} command. It has setters for all
  65. * supported options and arguments of this command and a {@link #call()} method
  66. * to finally execute the command. Each instance of this class should only be
  67. * used for one invocation of the command (means: one call to {@link #call()})
  68. *
  69. * @since 2.2
  70. * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-gc.html"
  71. * >Git documentation about gc</a>
  72. */
  73. public class GarbageCollectCommand extends GitCommand<Properties> {
  74. /**
  75. * Default value of maximum delta chain depth during aggressive garbage
  76. * collection: {@value}
  77. *
  78. * @since 3.6
  79. */
  80. public static final int DEFAULT_GC_AGGRESSIVE_DEPTH = 250;
  81. /**
  82. * Default window size during packing during aggressive garbage collection:
  83. * * {@value}
  84. *
  85. * @since 3.6
  86. */
  87. public static final int DEFAULT_GC_AGGRESSIVE_WINDOW = 250;
  88. private ProgressMonitor monitor;
  89. private Date expire;
  90. private PackConfig pconfig;
  91. /**
  92. * @param repo
  93. */
  94. protected GarbageCollectCommand(Repository repo) {
  95. super(repo);
  96. pconfig = new PackConfig(repo);
  97. }
  98. /**
  99. * @param monitor
  100. * a progress monitor
  101. * @return this instance
  102. */
  103. public GarbageCollectCommand setProgressMonitor(ProgressMonitor monitor) {
  104. this.monitor = monitor;
  105. return this;
  106. }
  107. /**
  108. * During gc() or prune() each unreferenced, loose object which has been
  109. * created or modified after <code>expire</code> will not be pruned. Only
  110. * older objects may be pruned. If set to null then every object is a
  111. * candidate for pruning. Use {@link GitDateParser} to parse time formats
  112. * used by git gc.
  113. *
  114. * @param expire
  115. * minimal age of objects to be pruned.
  116. * @return this instance
  117. */
  118. public GarbageCollectCommand setExpire(Date expire) {
  119. this.expire = expire;
  120. return this;
  121. }
  122. /**
  123. * Whether to use aggressive mode or not. If set to true JGit behaves more
  124. * similar to native git's "git gc --aggressive". If set to
  125. * <code>true</code> compressed objects found in old packs are not reused
  126. * but every object is compressed again. Configuration variables
  127. * pack.window and pack.depth are set to 250 for this GC.
  128. *
  129. * @since 3.6
  130. * @param aggressive
  131. * whether to turn on or off aggressive mode
  132. * @return this instance
  133. */
  134. public GarbageCollectCommand setAggressive(boolean aggressive) {
  135. if (aggressive) {
  136. StoredConfig repoConfig = repo.getConfig();
  137. pconfig.setDeltaSearchWindowSize(repoConfig.getInt(
  138. ConfigConstants.CONFIG_GC_SECTION,
  139. ConfigConstants.CONFIG_KEY_AGGRESSIVE_WINDOW,
  140. DEFAULT_GC_AGGRESSIVE_WINDOW));
  141. pconfig.setMaxDeltaDepth(repoConfig.getInt(
  142. ConfigConstants.CONFIG_GC_SECTION,
  143. ConfigConstants.CONFIG_KEY_AGGRESSIVE_DEPTH,
  144. DEFAULT_GC_AGGRESSIVE_DEPTH));
  145. pconfig.setReuseObjects(false);
  146. } else
  147. pconfig = new PackConfig(repo);
  148. return this;
  149. }
  150. @Override
  151. public Properties call() throws GitAPIException {
  152. checkCallable();
  153. try {
  154. if (repo instanceof FileRepository) {
  155. GC gc = new GC((FileRepository) repo);
  156. gc.setPackConfig(pconfig);
  157. gc.setProgressMonitor(monitor);
  158. if (this.expire != null)
  159. gc.setExpire(expire);
  160. try {
  161. gc.gc();
  162. return toProperties(gc.getStatistics());
  163. } catch (ParseException e) {
  164. throw new JGitInternalException(JGitText.get().gcFailed, e);
  165. }
  166. } else if (repo instanceof DfsRepository) {
  167. DfsGarbageCollector gc =
  168. new DfsGarbageCollector((DfsRepository) repo);
  169. gc.setPackConfig(pconfig);
  170. gc.pack(monitor);
  171. return new Properties();
  172. } else {
  173. throw new UnsupportedOperationException(MessageFormat.format(
  174. JGitText.get().unsupportedGC,
  175. repo.getClass().toString()));
  176. }
  177. } catch (IOException e) {
  178. throw new JGitInternalException(JGitText.get().gcFailed, e);
  179. }
  180. }
  181. /**
  182. * Computes and returns the repository statistics.
  183. *
  184. * @return the repository statistics
  185. * @throws GitAPIException
  186. * thrown if the repository statistics cannot be computed
  187. * @since 3.0
  188. */
  189. public Properties getStatistics() throws GitAPIException {
  190. try {
  191. if (repo instanceof FileRepository) {
  192. GC gc = new GC((FileRepository) repo);
  193. return toProperties(gc.getStatistics());
  194. } else {
  195. return new Properties();
  196. }
  197. } catch (IOException e) {
  198. throw new JGitInternalException(
  199. JGitText.get().couldNotGetRepoStatistics, e);
  200. }
  201. }
  202. @SuppressWarnings("boxing")
  203. private static Properties toProperties(RepoStatistics stats) {
  204. Properties p = new Properties();
  205. p.put("numberOfLooseObjects", stats.numberOfLooseObjects); //$NON-NLS-1$
  206. p.put("numberOfLooseRefs", stats.numberOfLooseRefs); //$NON-NLS-1$
  207. p.put("numberOfPackedObjects", stats.numberOfPackedObjects); //$NON-NLS-1$
  208. p.put("numberOfPackedRefs", stats.numberOfPackedRefs); //$NON-NLS-1$
  209. p.put("numberOfPackFiles", stats.numberOfPackFiles); //$NON-NLS-1$
  210. p.put("sizeOfLooseObjects", stats.sizeOfLooseObjects); //$NON-NLS-1$
  211. p.put("sizeOfPackedObjects", stats.sizeOfPackedObjects); //$NON-NLS-1$
  212. return p;
  213. }
  214. }