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 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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. /**
  63. * A class used to execute a {@code gc} command. It has setters for all
  64. * supported options and arguments of this command and a {@link #call()} method
  65. * to finally execute the command. Each instance of this class should only be
  66. * used for one invocation of the command (means: one call to {@link #call()})
  67. *
  68. * @since 2.2
  69. * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-gc.html"
  70. * >Git documentation about gc</a>
  71. */
  72. public class GarbageCollectCommand extends GitCommand<Properties> {
  73. /**
  74. * Default value of maximum delta chain depth during aggressive garbage
  75. * collection: {@value}
  76. *
  77. * @since 3.6
  78. */
  79. public static final int DEFAULT_GC_AGGRESSIVE_DEPTH = 250;
  80. /**
  81. * Default window size during packing during aggressive garbage collection:
  82. * * {@value}
  83. *
  84. * @since 3.6
  85. */
  86. public static final int DEFAULT_GC_AGGRESSIVE_WINDOW = 250;
  87. private ProgressMonitor monitor;
  88. private Date expire;
  89. private PackConfig pconfig;
  90. /**
  91. * Constructor for GarbageCollectCommand.
  92. *
  93. * @param repo
  94. * a {@link org.eclipse.jgit.lib.Repository} object.
  95. */
  96. protected GarbageCollectCommand(Repository repo) {
  97. super(repo);
  98. pconfig = new PackConfig(repo);
  99. }
  100. /**
  101. * Set progress monitor
  102. *
  103. * @param monitor
  104. * a progress monitor
  105. * @return this instance
  106. */
  107. public GarbageCollectCommand setProgressMonitor(ProgressMonitor monitor) {
  108. this.monitor = monitor;
  109. return this;
  110. }
  111. /**
  112. * During gc() or prune() each unreferenced, loose object which has been
  113. * created or modified after <code>expire</code> will not be pruned. Only
  114. * older objects may be pruned. If set to null then every object is a
  115. * candidate for pruning. Use {@link org.eclipse.jgit.util.GitDateParser} to
  116. * parse time formats used by git gc.
  117. *
  118. * @param expire
  119. * minimal age of objects to be pruned.
  120. * @return this instance
  121. */
  122. public GarbageCollectCommand setExpire(Date expire) {
  123. this.expire = expire;
  124. return this;
  125. }
  126. /**
  127. * Whether to use aggressive mode or not. If set to true JGit behaves more
  128. * similar to native git's "git gc --aggressive". If set to
  129. * <code>true</code> compressed objects found in old packs are not reused
  130. * but every object is compressed again. Configuration variables
  131. * pack.window and pack.depth are set to 250 for this GC.
  132. *
  133. * @since 3.6
  134. * @param aggressive
  135. * whether to turn on or off aggressive mode
  136. * @return this instance
  137. */
  138. public GarbageCollectCommand setAggressive(boolean aggressive) {
  139. if (aggressive) {
  140. StoredConfig repoConfig = repo.getConfig();
  141. pconfig.setDeltaSearchWindowSize(repoConfig.getInt(
  142. ConfigConstants.CONFIG_GC_SECTION,
  143. ConfigConstants.CONFIG_KEY_AGGRESSIVE_WINDOW,
  144. DEFAULT_GC_AGGRESSIVE_WINDOW));
  145. pconfig.setMaxDeltaDepth(repoConfig.getInt(
  146. ConfigConstants.CONFIG_GC_SECTION,
  147. ConfigConstants.CONFIG_KEY_AGGRESSIVE_DEPTH,
  148. DEFAULT_GC_AGGRESSIVE_DEPTH));
  149. pconfig.setReuseObjects(false);
  150. } else
  151. pconfig = new PackConfig(repo);
  152. return this;
  153. }
  154. /**
  155. * Whether to preserve old pack files instead of deleting them.
  156. *
  157. * @since 4.7
  158. * @param preserveOldPacks
  159. * whether to preserve old pack files
  160. * @return this instance
  161. */
  162. public GarbageCollectCommand setPreserveOldPacks(boolean preserveOldPacks) {
  163. if (pconfig == null)
  164. pconfig = new PackConfig(repo);
  165. pconfig.setPreserveOldPacks(preserveOldPacks);
  166. return this;
  167. }
  168. /**
  169. * Whether to prune preserved pack files in the preserved directory.
  170. *
  171. * @since 4.7
  172. * @param prunePreserved
  173. * whether to prune preserved pack files
  174. * @return this instance
  175. */
  176. public GarbageCollectCommand setPrunePreserved(boolean prunePreserved) {
  177. if (pconfig == null)
  178. pconfig = new PackConfig(repo);
  179. pconfig.setPrunePreserved(prunePreserved);
  180. return this;
  181. }
  182. /** {@inheritDoc} */
  183. @Override
  184. public Properties call() throws GitAPIException {
  185. checkCallable();
  186. try {
  187. if (repo instanceof FileRepository) {
  188. GC gc = new GC((FileRepository) repo);
  189. gc.setPackConfig(pconfig);
  190. gc.setProgressMonitor(monitor);
  191. if (this.expire != null)
  192. gc.setExpire(expire);
  193. try {
  194. gc.gc();
  195. return toProperties(gc.getStatistics());
  196. } catch (ParseException e) {
  197. throw new JGitInternalException(JGitText.get().gcFailed, e);
  198. }
  199. } else if (repo instanceof DfsRepository) {
  200. DfsGarbageCollector gc =
  201. new DfsGarbageCollector((DfsRepository) repo);
  202. gc.setPackConfig(pconfig);
  203. gc.pack(monitor);
  204. return new Properties();
  205. } else {
  206. throw new UnsupportedOperationException(MessageFormat.format(
  207. JGitText.get().unsupportedGC,
  208. repo.getClass().toString()));
  209. }
  210. } catch (IOException e) {
  211. throw new JGitInternalException(JGitText.get().gcFailed, e);
  212. }
  213. }
  214. /**
  215. * Computes and returns the repository statistics.
  216. *
  217. * @return the repository statistics
  218. * @throws org.eclipse.jgit.api.errors.GitAPIException
  219. * thrown if the repository statistics cannot be computed
  220. * @since 3.0
  221. */
  222. public Properties getStatistics() throws GitAPIException {
  223. try {
  224. if (repo instanceof FileRepository) {
  225. GC gc = new GC((FileRepository) repo);
  226. return toProperties(gc.getStatistics());
  227. }
  228. return new Properties();
  229. } catch (IOException e) {
  230. throw new JGitInternalException(
  231. JGitText.get().couldNotGetRepoStatistics, e);
  232. }
  233. }
  234. @SuppressWarnings("boxing")
  235. private static Properties toProperties(RepoStatistics stats) {
  236. Properties p = new Properties();
  237. p.put("numberOfLooseObjects", stats.numberOfLooseObjects); //$NON-NLS-1$
  238. p.put("numberOfLooseRefs", stats.numberOfLooseRefs); //$NON-NLS-1$
  239. p.put("numberOfPackedObjects", stats.numberOfPackedObjects); //$NON-NLS-1$
  240. p.put("numberOfPackedRefs", stats.numberOfPackedRefs); //$NON-NLS-1$
  241. p.put("numberOfPackFiles", stats.numberOfPackFiles); //$NON-NLS-1$
  242. p.put("sizeOfLooseObjects", stats.sizeOfLooseObjects); //$NON-NLS-1$
  243. p.put("sizeOfPackedObjects", stats.sizeOfPackedObjects); //$NON-NLS-1$
  244. return p;
  245. }
  246. }