]> source.dussan.org Git - gitblit.git/commitdiff
Optionally cache repository list for improved performance
authorJames Moger <james.moger@gitblit.com>
Fri, 17 Aug 2012 19:17:16 +0000 (15:17 -0400)
committerJames Moger <james.moger@gitblit.com>
Fri, 17 Aug 2012 19:17:16 +0000 (15:17 -0400)
17 files changed:
distrib/gitblit.properties
docs/02_rpc.mkd
docs/04_releases.mkd
src/com/gitblit/Constants.java
src/com/gitblit/GitBlit.java
src/com/gitblit/RpcServlet.java
src/com/gitblit/client/GitblitClient.java
src/com/gitblit/client/RepositoriesPanel.java
src/com/gitblit/utils/JGitUtils.java
src/com/gitblit/utils/ObjectCache.java
src/com/gitblit/utils/RpcUtils.java
src/com/gitblit/wicket/GitBlitWebApp.properties
src/com/gitblit/wicket/panels/RepositoriesPanel.html
src/com/gitblit/wicket/panels/RepositoriesPanel.java
src/com/gitblit/wicket/panels/TeamsPanel.html
src/com/gitblit/wicket/panels/UsersPanel.html
tests/com/gitblit/tests/RepositoryModelTest.java

index 836ac05c638ae512897e8713d53d9c2f29f94e3b..80cbb7e1ac8fa65ef1c014132305a902187a7d53 100644 (file)
 # RESTART REQUIRED\r
 git.repositoriesFolder = git\r
 \r
+# Build the available repository list at startup and cache this list for reuse.\r
+# This reduces disk io when presenting the repositories page, responding to rpcs,\r
+# etc, but it means that  Gitblit will not automatically identify repositories\r
+# added or deleted by external tools.\r
+#\r
+# For this case you can use curl, wget, etc to issue an rpc request to clear the\r
+# cache (e.g. https://localhost/rpc?req=CLEAR_REPOSITORY_CACHE)\r
+#\r
+# SINCE 1.1.0\r
+git.cacheRepositoryList = true\r
+\r
 # Search the repositories folder subfolders for other repositories.\r
 # Repositories MAY NOT be nested (i.e. one repository within another)\r
 # but they may be grouped together in subfolders.\r
@@ -24,7 +35,7 @@ git.searchRepositoriesSubfolders = true
 # Maximum number of folders to recurse into when searching for repositories.\r
 # The default value, -1, disables depth limits.\r
 #\r
-# SINCE 1.0.1\r
+# SINCE 1.1.0\r
 git.searchRecursionDepth = -1\r
 \r
 # List of regex exclusion patterns to match against folders found in\r
@@ -34,7 +45,7 @@ git.searchRecursionDepth = -1
 #\r
 # SPACE-DELIMITED\r
 # CASE-SENSITIVE\r
-# SINCE 1.0.1\r
+# SINCE 1.1.0\r
 git.searchExclusions =\r
 \r
 # List of regex url patterns for extracting a repository name when locating\r
@@ -46,7 +57,7 @@ git.searchExclusions =
 #\r
 # SPACE-DELIMITED\r
 # CASE-SENSITIVE\r
-# SINCE 1.0.1\r
+# SINCE 1.1.0\r
 git.submoduleUrlPatterns = .*?://github.com/(.*)\r
 \r
 # Allow push/pull over http/https with JGit servlet.\r
@@ -80,7 +91,7 @@ git.defaultAccessRestriction = NONE
 #  AUTHENTICATED = any authenticated user is granted restricted access\r
 #  NAMED = only named users/teams are granted restricted access\r
 #\r
-# SINCE 1.0.1\r
+# SINCE 1.1.0\r
 git.defaultAuthorizationControl = NAMED\r
 \r
 # Number of bytes of a pack file to load into memory in a single read operation.\r
index 8aa84f5b87bbab29e800140e066103eb4e8356f9..6089ac9bbde25832a14c1f9a1f38abe082499e97 100644 (file)
@@ -63,7 +63,8 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds.  The
 <tr><th>Release</th><th>Protocol Version</th></tr>\r
 <tr><td>Gitblit v0.7.0</td><td>1 (inferred version)</td></tr>\r
 <tr><td>Gitblit v0.8.0</td><td>2</td></tr>\r
-<tr><td>Gitblit v0.9.0+</td><td>3</td></tr>\r
+<tr><td>Gitblit v0.9.0 - v1.0.0</td><td>3</td></tr>\r
+<tr><td>Gitblit v1.1.0+</td><td>4</td></tr>\r
 </tbody>\r
 </table>\r
 \r
@@ -101,6 +102,7 @@ The Gitblit API includes methods for retrieving and interpreting RSS feeds.  The
 <tr><td>LIST_SETTINGS</td><td>-</td><td><em>admin</em></td><td>1</td><td>-</td><td>ServerSettings (all keys)</td></tr>\r
 <tr><td>EDIT_SETTINGS</td><td>-</td><td><em>admin</em></td><td>1</td><td>Map&lt;String, String&gt;</td><td>-</td></tr>\r
 <tr><td>LIST_STATUS</td><td>-</td><td><em>admin</em></td><td>1</td><td>-</td><td>ServerStatus (see example below)</td></tr>\r
+<tr><td>CLEAR_REPOSITORY_CACHE</td><td>-</td><td><em>admin</em></td><td>4</td><td>-</td><td>-</td></tr>\r
 </table>\r
 \r
 ### RPC/HTTP Response Codes\r
index 624cb53f62afb69f31024c2780ecbfe645e09e0b..5c89d9a4c0cc53ad15c07ddf99363b75fa2bebcb 100644 (file)
@@ -25,6 +25,8 @@ If you are updating from an earlier release AND you have indexed branches with t
 \r
 #### additions\r
 \r
+- Identified repository list is now cached by default to reduce disk io and to improve performance (issue 103)  \r
+    **New:** *git.cacheRepositoryList=true*\r
 - Preliminary bare repository submodule support  \r
     **New:** *git.submoduleUrlPatterns=*\r
     - *git.submoduleUrlPatterns* is a space-delimited list of regular expressions for extracting a repository name from a submodule url.  \r
index 181fb8f0f02adc4e591ce89ad559f2b9d94a7f9d..5f3bea9f4b909a13658679a330fbcde2fcbca858 100644 (file)
@@ -30,7 +30,7 @@ public class Constants {
 \r
        // The build script extracts this exact line so be careful editing it\r
        // and only use A-Z a-z 0-9 .-_ in the string.\r
-       public static final String VERSION = "1.0.1-SNAPSHOT";\r
+       public static final String VERSION = "1.1.0-SNAPSHOT";\r
 \r
        // The build script extracts this exact line so be careful editing it\r
        // and only use A-Z a-z 0-9 .-_ in the string.\r
@@ -248,7 +248,7 @@ public class Constants {
                LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM,\r
                LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, \r
                LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS, LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS,\r
-               EDIT_SETTINGS, LIST_STATUS;\r
+               EDIT_SETTINGS, LIST_STATUS, CLEAR_REPOSITORY_CACHE;\r
 \r
                public static RpcRequest fromName(String name) {\r
                        for (RpcRequest type : values()) {\r
index f52f229fd5f98e1f922d69baea3e6fdc719ef16b..97fb5a9531ee55e51f994c40961936569d065594 100644 (file)
@@ -39,10 +39,12 @@ import java.util.Set;
 import java.util.TimeZone;\r
 import java.util.TreeSet;\r
 import java.util.concurrent.ConcurrentHashMap;\r
+import java.util.concurrent.CopyOnWriteArrayList;\r
 import java.util.concurrent.Executors;\r
 import java.util.concurrent.ScheduledExecutorService;\r
 import java.util.concurrent.TimeUnit;\r
 import java.util.concurrent.atomic.AtomicInteger;\r
+import java.util.concurrent.atomic.AtomicReference;\r
 \r
 import javax.mail.Message;\r
 import javax.mail.MessagingException;\r
@@ -125,6 +127,10 @@ public class GitBlit implements ServletContextListener {
        private final ObjectCache<Long> repositorySizeCache = new ObjectCache<Long>();\r
 \r
        private final ObjectCache<List<Metric>> repositoryMetricsCache = new ObjectCache<List<Metric>>();\r
+       \r
+       private final List<String> repositoryListCache = new CopyOnWriteArrayList<String>();\r
+       \r
+       private final AtomicReference<String> repositoryListSettingsChecksum = new AtomicReference<String>("");\r
 \r
        private RepositoryResolver<Void> repositoryResolver;\r
 \r
@@ -723,15 +729,73 @@ public class GitBlit implements ServletContextListener {
        public boolean deleteTeam(String teamname) {\r
                return userService.deleteTeam(teamname);\r
        }\r
+       \r
+       /**\r
+        * Adds the repository to the list of cached repositories if Gitblit is\r
+        * configured to cache the repository list.\r
+        * \r
+        * @param name\r
+        */\r
+       private void addToCachedRepositoryList(String name) {\r
+               if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {\r
+                       repositoryListCache.add(name);\r
+               }\r
+       }\r
 \r
        /**\r
         * Clears all the cached data for the specified repository.\r
         * \r
         * @param repositoryName\r
+        * @param isDeleted\r
         */\r
-       public void clearRepositoryCache(String repositoryName) {\r
+       private void clearRepositoryCache(String repositoryName, boolean isDeleted) {\r
                repositorySizeCache.remove(repositoryName);\r
                repositoryMetricsCache.remove(repositoryName);\r
+               \r
+               if (isDeleted) {\r
+                       repositoryListCache.remove(repositoryName);\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * Resets the repository list cache.\r
+        * \r
+        */\r
+       public void resetRepositoryListCache() {\r
+               logger.info("Repository cache manually reset");\r
+               repositoryListCache.clear();\r
+       }\r
+       \r
+       /**\r
+        * Calculate the checksum of settings that affect the repository list cache.\r
+        * @return a checksum\r
+        */\r
+       private String getRepositoryListSettingsChecksum() {\r
+               StringBuilder ns = new StringBuilder();\r
+               ns.append(settings.getString(Keys.git.cacheRepositoryList, "")).append('\n');\r
+               ns.append(settings.getString(Keys.git.onlyAccessBareRepositories, "")).append('\n');\r
+               ns.append(settings.getString(Keys.git.searchRepositoriesSubfolders, "")).append('\n');\r
+               ns.append(settings.getString(Keys.git.searchRecursionDepth, "")).append('\n');\r
+               ns.append(settings.getString(Keys.git.searchExclusions, "")).append('\n');\r
+               String checksum = StringUtils.getSHA1(ns.toString());\r
+               return checksum;\r
+       }\r
+       \r
+       /**\r
+        * Compare the last repository list setting checksum to the current checksum.\r
+        * If different then clear the cache so that it may be rebuilt.\r
+        * \r
+        * @return true if the cached repository list is valid since the last check\r
+        */\r
+       private boolean isValidRepositoryList() {\r
+               String newChecksum = getRepositoryListSettingsChecksum();\r
+               boolean valid = newChecksum.equals(repositoryListSettingsChecksum.get());\r
+               repositoryListSettingsChecksum.set(newChecksum);\r
+               if (!valid && settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {\r
+                       logger.info("Repository list settings have changed. Clearing repository list cache.");\r
+                       repositoryListCache.clear();\r
+               }\r
+               return valid;\r
        }\r
 \r
        /**\r
@@ -741,11 +805,46 @@ public class GitBlit implements ServletContextListener {
         * @return list of all repositories\r
         */\r
        public List<String> getRepositoryList() {\r
-               return JGitUtils.getRepositoryList(repositoriesFolder, \r
-                               settings.getBoolean(Keys.git.onlyAccessBareRepositories, false),\r
-                               settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true),\r
-                               settings.getInteger(Keys.git.searchRecursionDepth, -1),\r
-                               settings.getStrings(Keys.git.searchExclusions));\r
+               if (repositoryListCache.size() == 0 || !isValidRepositoryList()) {\r
+                       // we are not caching OR we have not yet cached OR the cached list is invalid\r
+                       long startTime = System.currentTimeMillis();\r
+                       List<String> repositories = JGitUtils.getRepositoryList(repositoriesFolder, \r
+                                       settings.getBoolean(Keys.git.onlyAccessBareRepositories, false),\r
+                                       settings.getBoolean(Keys.git.searchRepositoriesSubfolders, true),\r
+                                       settings.getInteger(Keys.git.searchRecursionDepth, -1),\r
+                                       settings.getStrings(Keys.git.searchExclusions));\r
+\r
+                       if (!settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {\r
+                               // we are not caching\r
+                               StringUtils.sortRepositorynames(repositories);\r
+                               return repositories;\r
+                       } else {\r
+                               // we are caching this list\r
+                               String msg = "{0} repositories identified in {1} msecs";\r
+\r
+                               // optionally (re)calculate repository sizes\r
+                               if (getBoolean(Keys.web.showRepositorySizes, true)) {\r
+                                       msg = "{0} repositories identified with calculated folder sizes in {1} msecs";\r
+                                       for (String repository : repositories) {\r
+                                               RepositoryModel model = getRepositoryModel(repository);\r
+                                               if (!model.skipSizeCalculation) {\r
+                                                       calculateSize(model);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
+                               // update cache\r
+                               repositoryListCache.addAll(repositories);\r
+                               \r
+                               long duration = System.currentTimeMillis() - startTime;\r
+                               logger.info(MessageFormat.format(msg, repositoryListCache.size(), duration));\r
+                       }\r
+               }\r
+               \r
+               // return sorted copy of cached list\r
+               List<String> list = new ArrayList<String>(repositoryListCache);         \r
+               StringUtils.sortRepositorynames(list);\r
+               return list;\r
        }\r
 \r
        /**\r
@@ -804,6 +903,7 @@ public class GitBlit implements ServletContextListener {
         * @return list of repository models accessible to user\r
         */\r
        public List<RepositoryModel> getRepositoryModels(UserModel user) {\r
+               long methodStart = System.currentTimeMillis();\r
                List<String> list = getRepositoryList();\r
                List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();\r
                for (String repo : list) {\r
@@ -823,9 +923,15 @@ public class GitBlit implements ServletContextListener {
                                }\r
                        }\r
                        long duration = System.currentTimeMillis() - startTime;\r
-                       logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs",\r
+                       if (duration > 250) {\r
+                               // only log calcualtion time if > 250 msecs\r
+                               logger.info(MessageFormat.format("{0} repository sizes calculated in {1} msecs",\r
                                        repoCount, duration));\r
+                       }\r
                }\r
+               long duration = System.currentTimeMillis() - methodStart;\r
+               logger.info(MessageFormat.format("{0} repository models loaded for {1} in {2} msecs",\r
+                               repositories.size(), user.username, duration));\r
                return repositories;\r
        }\r
 \r
@@ -869,7 +975,8 @@ public class GitBlit implements ServletContextListener {
                model.hasCommits = JGitUtils.hasCommits(r);\r
                model.lastChange = JGitUtils.getLastChange(r);\r
                model.isBare = r.isBare();\r
-               StoredConfig config = JGitUtils.readConfig(r);\r
+               \r
+               StoredConfig config = r.getConfig();\r
                if (config != null) {\r
                        model.description = getConfig(config, "description", "");\r
                        model.owner = getConfig(config, "owner", "");\r
@@ -1062,6 +1169,9 @@ public class GitBlit implements ServletContextListener {
                        // create repository\r
                        logger.info("create repository " + repository.name);\r
                        r = JGitUtils.createRepository(repositoriesFolder, repository.name);\r
+                       \r
+                       // add name to cache\r
+                       addToCachedRepositoryList(repository.name);\r
                } else {\r
                        // rename repository\r
                        if (!repositoryName.equalsIgnoreCase(repository.name)) {\r
@@ -1101,7 +1211,10 @@ public class GitBlit implements ServletContextListener {
                                }\r
 \r
                                // clear the cache\r
-                               clearRepositoryCache(repositoryName);\r
+                               clearRepositoryCache(repositoryName, true);\r
+                               \r
+                               // add new name to repository list cache\r
+                               addToCachedRepositoryList(repository.name);\r
                        }\r
 \r
                        // load repository\r
@@ -1129,7 +1242,7 @@ public class GitBlit implements ServletContextListener {
                                                repository.name, currentRef, repository.HEAD));\r
                                if (JGitUtils.setHEADtoRef(r, repository.HEAD)) {\r
                                        // clear the cache\r
-                                       clearRepositoryCache(repository.name);\r
+                                       clearRepositoryCache(repository.name, false);\r
                                }\r
                        }\r
 \r
@@ -1137,7 +1250,7 @@ public class GitBlit implements ServletContextListener {
                        r.close();\r
                }\r
        }\r
-\r
+       \r
        /**\r
         * Updates the Gitblit configuration for the specified repository.\r
         * \r
@@ -1147,7 +1260,7 @@ public class GitBlit implements ServletContextListener {
         *            the Gitblit repository model\r
         */\r
        public void updateConfiguration(Repository r, RepositoryModel repository) {\r
-               StoredConfig config = JGitUtils.readConfig(r);\r
+               StoredConfig config = r.getConfig();\r
                config.setString(Constants.CONFIG_GITBLIT, null, "description", repository.description);\r
                config.setString(Constants.CONFIG_GITBLIT, null, "owner", repository.owner);\r
                config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);\r
@@ -1225,6 +1338,9 @@ public class GitBlit implements ServletContextListener {
        public boolean deleteRepository(String repositoryName) {\r
                try {\r
                        closeRepository(repositoryName);\r
+                       // clear the repository cache\r
+                       clearRepositoryCache(repositoryName, true);                     \r
+\r
                        File folder = new File(repositoriesFolder, repositoryName);\r
                        if (folder.exists() && folder.isDirectory()) {\r
                                FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY);\r
@@ -1232,9 +1348,6 @@ public class GitBlit implements ServletContextListener {
                                        return true;\r
                                }\r
                        }\r
-\r
-                       // clear the repository cache\r
-                       clearRepositoryCache(repositoryName);\r
                } catch (Throwable t) {\r
                        logger.error(MessageFormat.format("Failed to delete repository {0}", repositoryName), t);\r
                }\r
@@ -1953,6 +2066,15 @@ public class GitBlit implements ServletContextListener {
                repositoriesFolder = getRepositoriesFolder();\r
                logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath());\r
                repositoryResolver = new FileResolver<Void>(repositoriesFolder, true);\r
+\r
+               // calculate repository list settings checksum for future config changes\r
+               repositoryListSettingsChecksum.set(getRepositoryListSettingsChecksum());\r
+\r
+               // build initial repository list\r
+               if (settings.getBoolean(Keys.git.cacheRepositoryList,  true)) {\r
+                       logger.info("Identifying available repositories...");\r
+                       getRepositoryList();\r
+               }\r
                \r
                logTimezone("JVM", TimeZone.getDefault());\r
                logTimezone(Constants.NAME, getTimezone());\r
index 31ee5ad0454804eb632e3ed8ce6033d9b33c4265..929e9cc67c0403a663eb20d01908b67171452700 100644 (file)
@@ -49,7 +49,7 @@ public class RpcServlet extends JsonServlet {
 \r
        private static final long serialVersionUID = 1L;\r
 \r
-       public static final int PROTOCOL_VERSION = 3;\r
+       public static final int PROTOCOL_VERSION = 4;\r
 \r
        public RpcServlet() {\r
                super();\r
@@ -319,6 +319,13 @@ public class RpcServlet extends JsonServlet {
                        } else {\r
                                response.sendError(notAllowedCode);\r
                        }\r
+               } else if (RpcRequest.CLEAR_REPOSITORY_CACHE.equals(reqType)) {\r
+                       // clear the repository list cache\r
+                       if (allowAdmin) {\r
+                               GitBlit.self().resetRepositoryListCache();\r
+                       } else {\r
+                               response.sendError(notAllowedCode);\r
+                       }\r
                }\r
 \r
                // send the result of the request\r
index 5e05fa49b90df8fe46d6ad530177ac9ef20a23fc..52d4e06dffe4945823e7745a7a69f026f88afc36 100644 (file)
@@ -578,6 +578,10 @@ public class GitblitClient implements Serializable {
        public boolean deleteRepository(RepositoryModel repository) throws IOException {\r
                return RpcUtils.deleteRepository(repository, url, account, password);\r
        }\r
+       \r
+       public boolean clearRepositoryCache() throws IOException {\r
+               return RpcUtils.clearRepositoryCache(url, account, password);\r
+       }\r
 \r
        public boolean createUser(UserModel user) throws IOException {\r
                return RpcUtils.createUser(user, url, account, password);\r
index cbe187432c9e083e7bce788f87a899d4d64831e1..54158e8e90cf69ee581d9e2663573fe6f9fb8a6b 100644 (file)
@@ -82,6 +82,8 @@ public abstract class RepositoriesPanel extends JPanel {
 \r
        private JTextField filterTextfield;\r
 \r
+       private JButton clearCache;\r
+\r
        public RepositoriesPanel(GitblitClient gitblit) {\r
                super();\r
                this.gitblit = gitblit;\r
@@ -105,6 +107,13 @@ public abstract class RepositoriesPanel extends JPanel {
                                refreshRepositories();\r
                        }\r
                });\r
+               \r
+               clearCache = new JButton(Translation.get("gb.clearCache"));\r
+               clearCache.addActionListener(new ActionListener() {\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               clearCache();\r
+                       }\r
+               });\r
 \r
                createRepository = new JButton(Translation.get("gb.create"));\r
                createRepository.addActionListener(new ActionListener() {\r
@@ -242,6 +251,7 @@ public abstract class RepositoriesPanel extends JPanel {
                repositoryTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);\r
 \r
                JPanel repositoryControls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));\r
+               repositoryControls.add(clearCache);\r
                repositoryControls.add(refreshRepositories);\r
                repositoryControls.add(browseRepository);\r
                repositoryControls.add(createRepository);\r
@@ -285,6 +295,7 @@ public abstract class RepositoriesPanel extends JPanel {
        protected abstract void updateTeamsTable();\r
 \r
        protected void disableManagement() {\r
+               clearCache.setVisible(false);\r
                createRepository.setVisible(false);\r
                editRepository.setVisible(false);\r
                delRepository.setVisible(false);\r
@@ -348,6 +359,26 @@ public abstract class RepositoriesPanel extends JPanel {
                };\r
                worker.execute();\r
        }\r
+       \r
+       protected void clearCache() {\r
+               GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this,\r
+                               RpcRequest.CLEAR_REPOSITORY_CACHE) {\r
+                       @Override\r
+                       protected Boolean doRequest() throws IOException {\r
+                               if (gitblit.clearRepositoryCache()) {\r
+                                       gitblit.refreshRepositories();\r
+                                       return true;\r
+                               }\r
+                               return false;\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onSuccess() {\r
+                               updateTable(false);\r
+                       }\r
+               };\r
+               worker.execute();\r
+       }\r
 \r
        /**\r
         * Displays the create repository dialog and fires a SwingWorker to update\r
index 5eb83edb545bd66c0f77353dcb0b58998e055ca7..a78a771690e84416923e2da2369bf9c590f4b3fa 100644 (file)
@@ -47,7 +47,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.StopWalkException;\r
 import org.eclipse.jgit.lib.BlobBasedConfig;\r
 import org.eclipse.jgit.lib.CommitBuilder;\r
-import org.eclipse.jgit.lib.Config;\r
 import org.eclipse.jgit.lib.Constants;\r
 import org.eclipse.jgit.lib.FileMode;\r
 import org.eclipse.jgit.lib.ObjectId;\r
@@ -59,7 +58,6 @@ import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.lib.RepositoryCache.FileKey;\r
-import org.eclipse.jgit.lib.StoredConfig;\r
 import org.eclipse.jgit.lib.TreeFormatter;\r
 import org.eclipse.jgit.revwalk.RevBlob;\r
 import org.eclipse.jgit.revwalk.RevCommit;\r
@@ -1708,24 +1706,6 @@ public class JGitUtils {
                return success;\r
        }\r
 \r
-       /**\r
-        * Returns a StoredConfig object for the repository.\r
-        * \r
-        * @param repository\r
-        * @return the StoredConfig of the repository\r
-        */\r
-       public static StoredConfig readConfig(Repository repository) {\r
-               StoredConfig c = repository.getConfig();\r
-               try {\r
-                       c.load();\r
-               } catch (ConfigInvalidException cex) {\r
-                       error(cex, repository, "{0} configuration is invalid!");\r
-               } catch (IOException cex) {\r
-                       error(cex, repository, "Could not open configuration for {0}!");\r
-               }\r
-               return c;\r
-       }\r
-\r
        /**\r
         * Zips the contents of the tree at the (optionally) specified revision and\r
         * the (optionally) specified basepath to the supplied outputstream.\r
index 3bbf4d19aa3cb66471466e6fba31334c0e177660..38f2e59a66ff680f2f4eb4f2106585a6e3b180bd 100644 (file)
@@ -91,4 +91,8 @@ public class ObjectCache<X> implements Serializable {
                }\r
                return null;\r
        }\r
+       \r
+       public int size() {\r
+               return cache.size();\r
+       }\r
 }\r
index 02a63a481c1099401070020b74602ae3b3996519..2b80e2af1ec645f670af22a8195efd822cced679 100644 (file)
@@ -231,6 +231,21 @@ public class RpcUtils {
                                password);\r
 \r
        }\r
+       \r
+       /**\r
+        * Clears the repository cache on the Gitblit server.\r
+        * \r
+        * @param serverUrl\r
+        * @param account\r
+        * @param password\r
+        * @return true if the action succeeded\r
+        * @throws IOException\r
+        */\r
+       public static boolean clearRepositoryCache(String serverUrl, String account, \r
+                       char[] password) throws IOException {\r
+               return doAction(RpcRequest.CLEAR_REPOSITORY_CACHE, null, null, serverUrl, account,\r
+                               password);\r
+       }\r
 \r
        /**\r
         * Create a user on the Gitblit server.\r
index f9480a8f4fbe1f76c2c0a95cc47d927cd92be614..2a31f8bed4cca1a326d5aaeaecd495b87d4cc75e 100644 (file)
@@ -313,4 +313,5 @@ gb.duration.years = {0} years
 gb.authorizationControl = authorization control\r
 gb.allowAuthenticatedDescription = grant restricted access to all authenticated users\r
 gb.allowNamedDescription = grant restricted access to named users or teams\r
-gb.markdownFailure = Failed to parse Markdown content!
\ No newline at end of file
+gb.markdownFailure = Failed to parse Markdown content!\r
+gb.clearCache = clear cache
\ No newline at end of file
index 5b53d77278bcaa1dcdd7c52b58267172f73e9d41..99bedc632b9a259f29271cc42bd4ef9120469625 100644 (file)
        <wicket:fragment wicket:id="adminLinks">\r
                <!-- page nav links --> \r
                <div class="admin_nav">\r
-                       <img style="vertical-align: middle;" src="add_16x16.png"/>\r
-                       <a wicket:id="newRepository">\r
+                       <a class="btn-small" wicket:id="clearCache">\r
+                               <i class="icon icon-remove"></i>\r
+                               <wicket:message key="gb.clearCache"></wicket:message>\r
+                       </a>                    \r
+                       <a class="btn-small" wicket:id="newRepository" style="padding-right:0px;">\r
+                               <i class="icon icon-plus-sign"></i>\r
                                <wicket:message key="gb.newRepository"></wicket:message>\r
                        </a>\r
                </div>  \r
index 9664e05b33037413a6307f3f24ee438f2b09712c..8c8e1e5e791baa2dcfec7f65f4fa619e5b36d306 100644 (file)
@@ -54,6 +54,7 @@ import com.gitblit.wicket.WicketUtils;
 import com.gitblit.wicket.pages.BasePage;\r
 import com.gitblit.wicket.pages.EditRepositoryPage;\r
 import com.gitblit.wicket.pages.EmptyRepositoryPage;\r
+import com.gitblit.wicket.pages.RepositoriesPage;\r
 import com.gitblit.wicket.pages.SummaryPage;\r
 \r
 public class RepositoriesPanel extends BasePanel {\r
@@ -73,6 +74,16 @@ public class RepositoriesPanel extends BasePanel {
                final IDataProvider<RepositoryModel> dp;\r
 \r
                Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);\r
+               adminLinks.add(new Link<Void>("clearCache") {\r
+\r
+                       private static final long serialVersionUID = 1L;\r
+\r
+                       @Override\r
+                       public void onClick() {\r
+                               GitBlit.self().resetRepositoryListCache();\r
+                               setResponsePage(RepositoriesPage.class);\r
+                       }\r
+               }.setVisible(GitBlit.getBoolean(Keys.git.cacheRepositoryList, true)));\r
                adminLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));\r
                add(adminLinks.setVisible(showAdmin));\r
 \r
index c6a73cd7ffcfb26bebb5b967036ed91d8091651f..ff6892926fcc5452be00c9be63f827f79e1cca7e 100644 (file)
@@ -32,8 +32,8 @@
        <wicket:fragment wicket:id="adminLinks">\r
                <!-- page nav links --> \r
                <div class="admin_nav">\r
-                       <img style="vertical-align: middle;" src="add_16x16.png"/>\r
-                       <a wicket:id="newTeam">\r
+                       <a class="btn-small" wicket:id="newTeam" style="padding-right:0px;">\r
+                               <i class="icon icon-plus-sign"></i>\r
                                <wicket:message key="gb.newTeam"></wicket:message>\r
                        </a>\r
                </div>  \r
index 8e0ed1f1fe0c162a3bd85a498fad3c699c8e0f33..aed985c1cd262463246165bbc122c77b338d2319 100644 (file)
@@ -38,8 +38,8 @@
        <wicket:fragment wicket:id="adminLinks">\r
                <!-- page nav links --> \r
                <div class="admin_nav">\r
-                       <img style="vertical-align: middle;" src="add_16x16.png"/>\r
-                       <a wicket:id="newUser">\r
+                       <a class="btn-small" wicket:id="newUser" style="padding-right:0px;">\r
+                               <i class="icon icon-plus-sign"></i>\r
                                <wicket:message key="gb.newUser"></wicket:message>\r
                        </a>\r
                </div>  \r
index d49cb434ab3aca8226f9a957ce4cf5ea6172c931..1fe3fbd0aa719a1337bb692e80d01f5d5b4cd217 100644 (file)
@@ -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();