From fee0600989ccc271e3f3b44a06599682698c425f Mon Sep 17 00:00:00 2001 From: James Moger Date: Fri, 17 Aug 2012 15:17:16 -0400 Subject: [PATCH] Optionally cache repository list for improved performance --- distrib/gitblit.properties | 19 ++- docs/02_rpc.mkd | 4 +- docs/04_releases.mkd | 2 + src/com/gitblit/Constants.java | 4 +- src/com/gitblit/GitBlit.java | 152 ++++++++++++++++-- src/com/gitblit/RpcServlet.java | 9 +- src/com/gitblit/client/GitblitClient.java | 4 + src/com/gitblit/client/RepositoriesPanel.java | 31 ++++ src/com/gitblit/utils/JGitUtils.java | 20 --- src/com/gitblit/utils/ObjectCache.java | 4 + src/com/gitblit/utils/RpcUtils.java | 15 ++ .../gitblit/wicket/GitBlitWebApp.properties | 3 +- .../wicket/panels/RepositoriesPanel.html | 8 +- .../wicket/panels/RepositoriesPanel.java | 11 ++ src/com/gitblit/wicket/panels/TeamsPanel.html | 4 +- src/com/gitblit/wicket/panels/UsersPanel.html | 4 +- .../gitblit/tests/RepositoryModelTest.java | 5 +- 17 files changed, 246 insertions(+), 53 deletions(-) diff --git a/distrib/gitblit.properties b/distrib/gitblit.properties index 836ac05c..80cbb7e1 100644 --- a/distrib/gitblit.properties +++ b/distrib/gitblit.properties @@ -12,6 +12,17 @@ # RESTART REQUIRED git.repositoriesFolder = git +# Build the available repository list at startup and cache this list for reuse. +# This reduces disk io when presenting the repositories page, responding to rpcs, +# etc, but it means that Gitblit will not automatically identify repositories +# added or deleted by external tools. +# +# For this case you can use curl, wget, etc to issue an rpc request to clear the +# cache (e.g. https://localhost/rpc?req=CLEAR_REPOSITORY_CACHE) +# +# SINCE 1.1.0 +git.cacheRepositoryList = true + # Search the repositories folder subfolders for other repositories. # Repositories MAY NOT be nested (i.e. one repository within another) # but they may be grouped together in subfolders. @@ -24,7 +35,7 @@ git.searchRepositoriesSubfolders = true # Maximum number of folders to recurse into when searching for repositories. # The default value, -1, disables depth limits. # -# SINCE 1.0.1 +# SINCE 1.1.0 git.searchRecursionDepth = -1 # List of regex exclusion patterns to match against folders found in @@ -34,7 +45,7 @@ git.searchRecursionDepth = -1 # # SPACE-DELIMITED # CASE-SENSITIVE -# SINCE 1.0.1 +# SINCE 1.1.0 git.searchExclusions = # List of regex url patterns for extracting a repository name when locating @@ -46,7 +57,7 @@ git.searchExclusions = # # SPACE-DELIMITED # CASE-SENSITIVE -# SINCE 1.0.1 +# SINCE 1.1.0 git.submoduleUrlPatterns = .*?://github.com/(.*) # Allow push/pull over http/https with JGit servlet. @@ -80,7 +91,7 @@ git.defaultAccessRestriction = NONE # AUTHENTICATED = any authenticated user is granted restricted access # NAMED = only named users/teams are granted restricted access # -# SINCE 1.0.1 +# SINCE 1.1.0 git.defaultAuthorizationControl = NAMED # Number of bytes of a pack file to load into memory in a single read operation. diff --git a/docs/02_rpc.mkd b/docs/02_rpc.mkd index 8aa84f5b..6089ac9b 100644 --- a/docs/02_rpc.mkd +++ b/docs/02_rpc.mkd @@ -63,7 +63,8 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds. The ReleaseProtocol Version Gitblit v0.7.01 (inferred version) Gitblit v0.8.02 -Gitblit v0.9.0+3 +Gitblit v0.9.0 - v1.0.03 +Gitblit v1.1.0+4 @@ -101,6 +102,7 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds. The LIST_SETTINGS-admin1-ServerSettings (all keys) EDIT_SETTINGS-admin1Map<String, String>- LIST_STATUS-admin1-ServerStatus (see example below) +CLEAR_REPOSITORY_CACHE-admin4-- ### RPC/HTTP Response Codes diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd index 624cb53f..5c89d9a4 100644 --- a/docs/04_releases.mkd +++ b/docs/04_releases.mkd @@ -25,6 +25,8 @@ If you are updating from an earlier release AND you have indexed branches with t #### additions +- Identified repository list is now cached by default to reduce disk io and to improve performance (issue 103) + **New:** *git.cacheRepositoryList=true* - Preliminary bare repository submodule support **New:** *git.submoduleUrlPatterns=* - *git.submoduleUrlPatterns* is a space-delimited list of regular expressions for extracting a repository name from a submodule url. diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java index 181fb8f0..5f3bea9f 100644 --- a/src/com/gitblit/Constants.java +++ b/src/com/gitblit/Constants.java @@ -30,7 +30,7 @@ public class Constants { // The build script extracts this exact line so be careful editing it // and only use A-Z a-z 0-9 .-_ in the string. - public static final String VERSION = "1.0.1-SNAPSHOT"; + public static final String VERSION = "1.1.0-SNAPSHOT"; // The build script extracts this exact line so be careful editing it // and only use A-Z a-z 0-9 .-_ in the string. @@ -248,7 +248,7 @@ public class Constants { LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM, LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS, LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, - EDIT_SETTINGS, LIST_STATUS; + EDIT_SETTINGS, LIST_STATUS, CLEAR_REPOSITORY_CACHE; public static RpcRequest fromName(String name) { for (RpcRequest type : values()) { diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index f52f229f..97fb5a95 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -39,10 +39,12 @@ import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import javax.mail.Message; import javax.mail.MessagingException; @@ -125,6 +127,10 @@ public class GitBlit implements ServletContextListener { private final ObjectCache repositorySizeCache = new ObjectCache(); private final ObjectCache> repositoryMetricsCache = new ObjectCache>(); + + private final List repositoryListCache = new CopyOnWriteArrayList(); + + private final AtomicReference repositoryListSettingsChecksum = new AtomicReference(""); private RepositoryResolver repositoryResolver; @@ -723,15 +729,73 @@ public class GitBlit implements ServletContextListener { public boolean deleteTeam(String teamname) { return userService.deleteTeam(teamname); } + + /** + * Adds the repository to the list of cached repositories if Gitblit is + * configured to cache the repository list. + * + * @param name + */ + private void addToCachedRepositoryList(String name) { + if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { + repositoryListCache.add(name); + } + } /** * Clears all the cached data for the specified repository. * * @param repositoryName + * @param isDeleted */ - public void clearRepositoryCache(String repositoryName) { + private void clearRepositoryCache(String repositoryName, boolean isDeleted) { repositorySizeCache.remove(repositoryName); repositoryMetricsCache.remove(repositoryName); + + if (isDeleted) { + repositoryListCache.remove(repositoryName); + } + } + + /** + * Resets the repository list cache. + * + */ + public void resetRepositoryListCache() { + logger.info("Repository cache manually reset"); + repositoryListCache.clear(); + } + + /** + * Calculate the checksum of settings that affect the repository list cache. + * @return a checksum + */ + private String getRepositoryListSettingsChecksum() { + StringBuilder ns = new StringBuilder(); + ns.append(settings.getString(Keys.git.cacheRepositoryList, "")).append('\n'); + ns.append(settings.getString(Keys.git.onlyAccessBareRepositories, "")).append('\n'); + ns.append(settings.getString(Keys.git.searchRepositoriesSubfolders, "")).append('\n'); + ns.append(settings.getString(Keys.git.searchRecursionDepth, "")).append('\n'); + ns.append(settings.getString(Keys.git.searchExclusions, "")).append('\n'); + String checksum = StringUtils.getSHA1(ns.toString()); + return checksum; + } + + /** + * Compare the last repository list setting checksum to the current checksum. + * If different then clear the cache so that it may be rebuilt. + * + * @return true if the cached repository list is valid since the last check + */ + private boolean isValidRepositoryList() { + String newChecksum = getRepositoryListSettingsChecksum(); + boolean valid = newChecksum.equals(repositoryListSettingsChecksum.get()); + repositoryListSettingsChecksum.set(newChecksum); + if (!valid && settings.getBoolean(Keys.git.cacheRepositoryList, true)) { + logger.info("Repository list settings have changed. Clearing repository list cache."); + repositoryListCache.clear(); + } + return valid; } /** @@ -741,11 +805,46 @@ public class GitBlit implements ServletContextListener { * @return list of all repositories */ public List getRepositoryList() { - return JGitUtils.getRepositoryList(repositoriesFolder, - settings.getBoolean(Keys.git.onlyAccessBareRepositories, false), - settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true), - settings.getInteger(Keys.git.searchRecursionDepth, -1), - settings.getStrings(Keys.git.searchExclusions)); + if (repositoryListCache.size() == 0 || !isValidRepositoryList()) { + // we are not caching OR we have not yet cached OR the cached list is invalid + long startTime = System.currentTimeMillis(); + List repositories = JGitUtils.getRepositoryList(repositoriesFolder, + settings.getBoolean(Keys.git.onlyAccessBareRepositories, false), + settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true), + settings.getInteger(Keys.git.searchRecursionDepth, -1), + settings.getStrings(Keys.git.searchExclusions)); + + if (!settings.getBoolean(Keys.git.cacheRepositoryList, true)) { + // we are not caching + StringUtils.sortRepositorynames(repositories); + return repositories; + } else { + // we are caching this list + String msg = "{0} repositories identified in {1} msecs"; + + // optionally (re)calculate repository sizes + if (getBoolean(Keys.web.showRepositorySizes, true)) { + msg = "{0} repositories identified with calculated folder sizes in {1} msecs"; + for (String repository : repositories) { + RepositoryModel model = getRepositoryModel(repository); + if (!model.skipSizeCalculation) { + calculateSize(model); + } + } + } + + // update cache + repositoryListCache.addAll(repositories); + + long duration = System.currentTimeMillis() - startTime; + logger.info(MessageFormat.format(msg, repositoryListCache.size(), duration)); + } + } + + // return sorted copy of cached list + List list = new ArrayList(repositoryListCache); + StringUtils.sortRepositorynames(list); + return list; } /** @@ -804,6 +903,7 @@ public class GitBlit implements ServletContextListener { * @return list of repository models accessible to user */ public List getRepositoryModels(UserModel user) { + long methodStart = System.currentTimeMillis(); List list = getRepositoryList(); List repositories = new ArrayList(); for (String repo : list) { @@ -823,9 +923,15 @@ public class GitBlit implements ServletContextListener { } } long duration = System.currentTimeMillis() - startTime; - logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs", + if (duration > 250) { + // only log calcualtion time if > 250 msecs + logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs", repoCount, duration)); + } } + long duration = System.currentTimeMillis() - methodStart; + logger.info(MessageFormat.format("{0} repository models loaded for {1} in {2} msecs", + repositories.size(), user.username, duration)); return repositories; } @@ -869,7 +975,8 @@ public class GitBlit implements ServletContextListener { model.hasCommits = JGitUtils.hasCommits(r); model.lastChange = JGitUtils.getLastChange(r); model.isBare = r.isBare(); - StoredConfig config = JGitUtils.readConfig(r); + + StoredConfig config = r.getConfig(); if (config != null) { model.description = getConfig(config, "description", ""); model.owner = getConfig(config, "owner", ""); @@ -1062,6 +1169,9 @@ public class GitBlit implements ServletContextListener { // create repository logger.info("create repository " + repository.name); r = JGitUtils.createRepository(repositoriesFolder, repository.name); + + // add name to cache + addToCachedRepositoryList(repository.name); } else { // rename repository if (!repositoryName.equalsIgnoreCase(repository.name)) { @@ -1101,7 +1211,10 @@ public class GitBlit implements ServletContextListener { } // clear the cache - clearRepositoryCache(repositoryName); + clearRepositoryCache(repositoryName, true); + + // add new name to repository list cache + addToCachedRepositoryList(repository.name); } // load repository @@ -1129,7 +1242,7 @@ public class GitBlit implements ServletContextListener { repository.name, currentRef, repository.HEAD)); if (JGitUtils.setHEADtoRef(r, repository.HEAD)) { // clear the cache - clearRepositoryCache(repository.name); + clearRepositoryCache(repository.name, false); } } @@ -1137,7 +1250,7 @@ public class GitBlit implements ServletContextListener { r.close(); } } - + /** * Updates the Gitblit configuration for the specified repository. * @@ -1147,7 +1260,7 @@ public class GitBlit implements ServletContextListener { * the Gitblit repository model */ public void updateConfiguration(Repository r, RepositoryModel repository) { - StoredConfig config = JGitUtils.readConfig(r); + StoredConfig config = r.getConfig(); config.setString(Constants.CONFIG_GITBLIT, null, "description", repository.description); config.setString(Constants.CONFIG_GITBLIT, null, "owner", repository.owner); config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets); @@ -1225,6 +1338,9 @@ public class GitBlit implements ServletContextListener { public boolean deleteRepository(String repositoryName) { try { closeRepository(repositoryName); + // clear the repository cache + clearRepositoryCache(repositoryName, true); + File folder = new File(repositoriesFolder, repositoryName); if (folder.exists() && folder.isDirectory()) { FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY); @@ -1232,9 +1348,6 @@ public class GitBlit implements ServletContextListener { return true; } } - - // clear the repository cache - clearRepositoryCache(repositoryName); } catch (Throwable t) { logger.error(MessageFormat.format("Failed to delete repository {0}", repositoryName), t); } @@ -1953,6 +2066,15 @@ public class GitBlit implements ServletContextListener { repositoriesFolder = getRepositoriesFolder(); logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath()); repositoryResolver = new FileResolver(repositoriesFolder, true); + + // calculate repository list settings checksum for future config changes + repositoryListSettingsChecksum.set(getRepositoryListSettingsChecksum()); + + // build initial repository list + if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { + logger.info("Identifying available repositories..."); + getRepositoryList(); + } logTimezone("JVM", TimeZone.getDefault()); logTimezone(Constants.NAME, getTimezone()); diff --git a/src/com/gitblit/RpcServlet.java b/src/com/gitblit/RpcServlet.java index 31ee5ad0..929e9cc6 100644 --- a/src/com/gitblit/RpcServlet.java +++ b/src/com/gitblit/RpcServlet.java @@ -49,7 +49,7 @@ public class RpcServlet extends JsonServlet { private static final long serialVersionUID = 1L; - public static final int PROTOCOL_VERSION = 3; + public static final int PROTOCOL_VERSION = 4; public RpcServlet() { super(); @@ -319,6 +319,13 @@ public class RpcServlet extends JsonServlet { } else { response.sendError(notAllowedCode); } + } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) { + // clear the repository list cache + if (allowAdmin) { + GitBlit.self().resetRepositoryListCache(); + } else { + response.sendError(notAllowedCode); + } } // send the result of the request diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java index 5e05fa49..52d4e06d 100644 --- a/src/com/gitblit/client/GitblitClient.java +++ b/src/com/gitblit/client/GitblitClient.java @@ -578,6 +578,10 @@ public class GitblitClient implements Serializable { public boolean deleteRepository(RepositoryModel repository) throws IOException { return RpcUtils.deleteRepository(repository, url, account, password); } + + public boolean clearRepositoryCache() throws IOException { + return RpcUtils.clearRepositoryCache(url, account, password); + } public boolean createUser(UserModel user) throws IOException { return RpcUtils.createUser(user, url, account, password); diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java index cbe18743..54158e8e 100644 --- a/src/com/gitblit/client/RepositoriesPanel.java +++ b/src/com/gitblit/client/RepositoriesPanel.java @@ -82,6 +82,8 @@ public abstract class RepositoriesPanel extends JPanel { private JTextField filterTextfield; + private JButton clearCache; + public RepositoriesPanel(GitblitClient gitblit) { super(); this.gitblit = gitblit; @@ -105,6 +107,13 @@ public abstract class RepositoriesPanel extends JPanel { refreshRepositories(); } }); + + clearCache = new JButton(Translation.get("gb.clearCache")); + clearCache.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + clearCache(); + } + }); createRepository = new JButton(Translation.get("gb.create")); createRepository.addActionListener(new ActionListener() { @@ -242,6 +251,7 @@ public abstract class RepositoriesPanel extends JPanel { repositoryTablePanel.add(new JScrollPane(table), BorderLayout.CENTER); JPanel repositoryControls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0)); + repositoryControls.add(clearCache); repositoryControls.add(refreshRepositories); repositoryControls.add(browseRepository); repositoryControls.add(createRepository); @@ -285,6 +295,7 @@ public abstract class RepositoriesPanel extends JPanel { protected abstract void updateTeamsTable(); protected void disableManagement() { + clearCache.setVisible(false); createRepository.setVisible(false); editRepository.setVisible(false); delRepository.setVisible(false); @@ -348,6 +359,26 @@ public abstract class RepositoriesPanel extends JPanel { }; worker.execute(); } + + protected void clearCache() { + GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this, + RpcRequest.CLEAR_REPOSITORY_CACHE) { + @Override + protected Boolean doRequest() throws IOException { + if (gitblit.clearRepositoryCache()) { + gitblit.refreshRepositories(); + return true; + } + return false; + } + + @Override + protected void onSuccess() { + updateTable(false); + } + }; + worker.execute(); + } /** * Displays the create repository dialog and fires a SwingWorker to update diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java index 5eb83edb..a78a7716 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -47,7 +47,6 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.StopWalkException; import org.eclipse.jgit.lib.BlobBasedConfig; import org.eclipse.jgit.lib.CommitBuilder; -import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; @@ -59,7 +58,6 @@ import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.RefUpdate.Result; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryCache.FileKey; -import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.lib.TreeFormatter; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; @@ -1708,24 +1706,6 @@ public class JGitUtils { return success; } - /** - * Returns a StoredConfig object for the repository. - * - * @param repository - * @return the StoredConfig of the repository - */ - public static StoredConfig readConfig(Repository repository) { - StoredConfig c = repository.getConfig(); - try { - c.load(); - } catch (ConfigInvalidException cex) { - error(cex, repository, "{0} configuration is invalid!"); - } catch (IOException cex) { - error(cex, repository, "Could not open configuration for {0}!"); - } - return c; - } - /** * Zips the contents of the tree at the (optionally) specified revision and * the (optionally) specified basepath to the supplied outputstream. diff --git a/src/com/gitblit/utils/ObjectCache.java b/src/com/gitblit/utils/ObjectCache.java index 3bbf4d19..38f2e59a 100644 --- a/src/com/gitblit/utils/ObjectCache.java +++ b/src/com/gitblit/utils/ObjectCache.java @@ -91,4 +91,8 @@ public class ObjectCache implements Serializable { } return null; } + + public int size() { + return cache.size(); + } } diff --git a/src/com/gitblit/utils/RpcUtils.java b/src/com/gitblit/utils/RpcUtils.java index 02a63a48..2b80e2af 100644 --- a/src/com/gitblit/utils/RpcUtils.java +++ b/src/com/gitblit/utils/RpcUtils.java @@ -231,6 +231,21 @@ public class RpcUtils { password); } + + /** + * Clears the repository cache on the Gitblit server. + * + * @param serverUrl + * @param account + * @param password + * @return true if the action succeeded + * @throws IOException + */ + public static boolean clearRepositoryCache(String serverUrl, String account, + char[] password) throws IOException { + return doAction(RpcRequest.CLEAR_REPOSITORY_CACHE, null, null, serverUrl, account, + password); + } /** * Create a user on the Gitblit server. diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index f9480a8f..2a31f8be 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -313,4 +313,5 @@ gb.duration.years = {0} years gb.authorizationControl = authorization control gb.allowAuthenticatedDescription = grant restricted access to all authenticated users gb.allowNamedDescription = grant restricted access to named users or teams -gb.markdownFailure = Failed to parse Markdown content! \ No newline at end of file +gb.markdownFailure = Failed to parse Markdown content! +gb.clearCache = clear cache \ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.html b/src/com/gitblit/wicket/panels/RepositoriesPanel.html index 5b53d772..99bedc63 100644 --- a/src/com/gitblit/wicket/panels/RepositoriesPanel.html +++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.html @@ -21,8 +21,12 @@ diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/com/gitblit/wicket/panels/RepositoriesPanel.java index 9664e05b..8c8e1e5e 100644 --- a/src/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -54,6 +54,7 @@ import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BasePage; import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.EmptyRepositoryPage; +import com.gitblit.wicket.pages.RepositoriesPage; import com.gitblit.wicket.pages.SummaryPage; public class RepositoriesPanel extends BasePanel { @@ -73,6 +74,16 @@ public class RepositoriesPanel extends BasePanel { final IDataProvider dp; Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this); + adminLinks.add(new Link("clearCache") { + + private static final long serialVersionUID = 1L; + + @Override + public void onClick() { + GitBlit.self().resetRepositoryListCache(); + setResponsePage(RepositoriesPage.class); + } + }.setVisible(GitBlit.getBoolean(Keys.git.cacheRepositoryList, true))); adminLinks.add(new BookmarkablePageLink("newRepository", EditRepositoryPage.class)); add(adminLinks.setVisible(showAdmin)); diff --git a/src/com/gitblit/wicket/panels/TeamsPanel.html b/src/com/gitblit/wicket/panels/TeamsPanel.html index c6a73cd7..ff689292 100644 --- a/src/com/gitblit/wicket/panels/TeamsPanel.html +++ b/src/com/gitblit/wicket/panels/TeamsPanel.html @@ -32,8 +32,8 @@ diff --git a/src/com/gitblit/wicket/panels/UsersPanel.html b/src/com/gitblit/wicket/panels/UsersPanel.html index 8e0ed1f1..aed985c1 100644 --- a/src/com/gitblit/wicket/panels/UsersPanel.html +++ b/src/com/gitblit/wicket/panels/UsersPanel.html @@ -38,8 +38,8 @@ diff --git a/tests/com/gitblit/tests/RepositoryModelTest.java b/tests/com/gitblit/tests/RepositoryModelTest.java index d49cb434..1fe3fbd0 100644 --- a/tests/com/gitblit/tests/RepositoryModelTest.java +++ b/tests/com/gitblit/tests/RepositoryModelTest.java @@ -29,7 +29,6 @@ import org.junit.Test; import com.gitblit.Constants; import com.gitblit.GitBlit; import com.gitblit.models.RepositoryModel; -import com.gitblit.utils.JGitUtils; public class RepositoryModelTest { @@ -49,7 +48,7 @@ public class RepositoryModelTest { @Before public void initializeConfiguration() throws Exception{ Repository r = GitBlitSuite.getHelloworldRepository(); - StoredConfig config = JGitUtils.readConfig(r); + StoredConfig config = r.getConfig(); config.unsetSection(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS); config.setString(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS, "commitMessageRegEx", "\\d"); @@ -61,7 +60,7 @@ public class RepositoryModelTest { @After public void teardownConfiguration() throws Exception { Repository r = GitBlitSuite.getHelloworldRepository(); - StoredConfig config = JGitUtils.readConfig(r); + StoredConfig config = r.getConfig(); config.unsetSection(Constants.CONFIG_GITBLIT, Constants.CONFIG_CUSTOM_FIELDS); config.save(); -- 2.39.5