From 5c284113a1a458db0d3440de351034503b3d52b3 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Mon, 11 Jul 2011 16:29:20 -0400
Subject: [PATCH] Optionally display repository on-disk size on repositories page.

---
 src/com/gitblit/GitBlit.java                         |   13 ++++++
 docs/04_releases.mkd                                 |   13 +++++-
 src/com/gitblit/wicket/panels/RepositoriesPanel.html |    4 +
 distrib/gitblit.properties                           |    7 +++
 docs/00_index.mkd                                    |    7 +--
 src/com/gitblit/utils/FileUtils.java                 |   24 ++++++++++++
 src/com/gitblit/wicket/panels/RepositoriesPanel.java |   35 +++++++++++++----
 src/com/gitblit/Constants.java                       |    4 +-
 8 files changed, 89 insertions(+), 18 deletions(-)

diff --git a/distrib/gitblit.properties b/distrib/gitblit.properties
index 953baa1..2ae3d01 100644
--- a/distrib/gitblit.properties
+++ b/distrib/gitblit.properties
@@ -97,6 +97,13 @@
 # SINCE 0.5.0
 web.syndicationEntries = 25
 
+# Show the size of each repository on the repositories page.
+# This requires recursive traversal of each repository folder.  This may be
+# non-performant on some operating systems and/or filesystems. 
+#
+# SINCE 0.5.2
+web.showRepositorySizes = true
+
 # This is the message display above the repositories table.
 # This can point to a file with Markdown content.
 # Specifying "gitblit" uses the internal welcome message.
diff --git a/docs/00_index.mkd b/docs/00_index.mkd
index d645793..edb058d 100644
--- a/docs/00_index.mkd
+++ b/docs/00_index.mkd
@@ -21,11 +21,10 @@
  
 ### Current Release
 
-%VERSION% ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%)|[war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*
+**%VERSION%** ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%)|[war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*
 
-- clarified SSL certificate generation and configuration for both server-side and client-side
-- added some more troubleshooting information to documentation
-- replaced JavaService with Apache Commons Daemon
+- optionally display repository on-disk size on repositories page<br/>**New:** *web.showRepositorySizes = true*
+- tone-down repository group header color
 
 issues & binaries @ [Google Code][googlecode]<br/>
 sources @ [Github][gitbltsrc]
diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index debab78..94aaa1a 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -1,13 +1,20 @@
 ## Release History
 
 ### Current Release
-%VERSION% ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%)|[war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*
+**%VERSION%** ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%)|[war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*
+
+- optionally display repository on-disk size on repositories page<br/>**New:** *web.showRepositorySizes = true*
+- tone-down repository group header color
+
+### Older Releases
+**0.5.1** ([go](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.1.zip)|[war](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.1.war)) based on [JGit 1.0.0 (201106090707-r)][jgit] &nbsp; *released 2006-06-28*
 
 - clarified SSL certificate generation and configuration for both server-side and client-side
 - added some more troubleshooting information to documentation
 - replaced JavaService with Apache Commons Daemon
 
-### Older Releases
-0.5.0 ([go](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.0.zip)|[war](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.0.war)) based on [JGit 1.0.0 (201106090707-r)][jgit] &nbsp; *released 2006-06-26*
+**0.5.0** ([go](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.0.zip)|[war](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.5.0.war)) based on [JGit 1.0.0 (201106090707-r)][jgit] &nbsp; *released 2006-06-26*
+
+- initial release
 
 [jgit]: http://eclipse.org/jgit "Eclipse JGit Site"
\ No newline at end of file
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index 08ffb9b..766f7c2 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -29,11 +29,11 @@
 
 	// 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 = "0.5.1";
+	public static final String VERSION = "0.5.2-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.
-	public static final String VERSION_DATE = "2011-06-28";
+	public static final String VERSION_DATE = "PENDING";
 
 	// The build script extracts this exact line so be careful editing it
 	// and only use A-Z a-z 0-9 .-_ in the string.
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 9fe6d20..968034d 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -32,11 +32,13 @@
 import org.apache.wicket.protocol.http.WebResponse;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryCache.FileKey;
 import org.eclipse.jgit.lib.StoredConfig;
 import org.eclipse.jgit.transport.resolver.FileResolver;
 import org.eclipse.jgit.transport.resolver.RepositoryResolver;
 import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
 import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.util.FS;
 import org.eclipse.jgit.util.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -451,6 +453,17 @@
 	}
 
 	/**
+	 * Returns the size in bytes of the repository.
+	 * 
+	 * @param model
+	 * @return size in bytes
+	 */
+	public long calculateSize(RepositoryModel model) {
+		File gitDir = FileKey.resolve(new File(repositoriesFolder, model.name), FS.DETECTED);
+		return com.gitblit.utils.FileUtils.folderSize(gitDir);
+	}
+
+	/**
 	 * Returns the gitblit string vlaue for the specified key. If key is not
 	 * set, returns defaultValue.
 	 * 
diff --git a/src/com/gitblit/utils/FileUtils.java b/src/com/gitblit/utils/FileUtils.java
index 468b2a8..ce8cdf9 100644
--- a/src/com/gitblit/utils/FileUtils.java
+++ b/src/com/gitblit/utils/FileUtils.java
@@ -56,4 +56,28 @@
 		}
 		return sb.toString();
 	}
+
+	/**
+	 * Recursively traverses a folder and its subfolders to calculate the total
+	 * size in bytes.
+	 * 
+	 * @param directory
+	 * @return folder size in bytes
+	 */
+	public static long folderSize(File directory) {
+		if (directory == null || !directory.exists()) {
+			return -1;
+		}
+		if (directory.isFile()) {
+			return directory.length();
+		}
+		long length = 0;
+		for (File file : directory.listFiles()) {
+			if (file.isFile())
+				length += file.length();
+			else
+				length += folderSize(file);
+		}
+		return length;
+	}
 }
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.html b/src/com/gitblit/wicket/panels/RepositoriesPanel.html
index 7e090e8..a4f5d12 100644
--- a/src/com/gitblit/wicket/panels/RepositoriesPanel.html
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.html
@@ -57,6 +57,7 @@
 				<wicket:message key="gb.repository">Repository</wicket:message>
 			</th>
 			<th><wicket:message key="gb.description">Description</wicket:message></th>
+			<th></th>
 			<th><wicket:message key="gb.owner">Owner</wicket:message></th>
 			<th></th>
 			<th><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
@@ -65,12 +66,13 @@
 	</wicket:fragment>
 	
 	<wicket:fragment wicket:id="groupRepositoryRow">
-        <td colspan="6"><span wicket:id="groupName">[group name]</span></td>
+        <td colspan="7"><span wicket:id="groupName">[group name]</span></td>
 	</wicket:fragment>
 		
 	<wicket:fragment wicket:id="repositoryRow">
         <td class="left"><div class="list" wicket:id="repositoryName">[repository name]</div></td>
         <td><div class="list" wicket:id="repositoryDescription">[repository description]</div></td>
+        <td style="text-align: right;padding-right:15px;"><span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span></td>
         <td class="author"><span wicket:id="repositoryOwner">[repository owner]</span></td>
         <td style="text-align: right;padding-right:10px;"><img class="inlineIcon" wicket:id="ticketsIcon" /><img class="inlineIcon" wicket:id="docsIcon" /><img class="inlineIcon" wicket:id="frozenIcon" /><img class="inlineIcon" wicket:id="accessRestrictionIcon" /></td>
         <td><span wicket:id="repositoryLastChange">[last change]</span></td>
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
index c744148..fa6c661 100644
--- a/src/com/gitblit/wicket/panels/RepositoriesPanel.java
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -47,6 +47,7 @@
 import com.gitblit.SyndicationServlet;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.ByteFormat;
 import com.gitblit.utils.StringUtils;
 import com.gitblit.utils.TimeUtils;
 import com.gitblit.wicket.GitBlitWebSession;
@@ -71,19 +72,30 @@
 		add(adminLinks.setVisible(showAdmin));
 
 		if (GitBlit.getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
+			List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();
 			Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
 			for (RepositoryModel model : models) {
 				String rootPath = StringUtils.getRootPath(model.name);
-				if (StringUtils.isEmpty(rootPath)) {
-					rootPath = GitBlit.getString(Keys.web.repositoryRootGroupName, " ");
+				if (StringUtils.isEmpty(rootPath)) { 
+					// root repository
+					rootRepositories.add(model);					
+				} else {
+					// non-root, grouped repository
+					if (!groups.containsKey(rootPath)) {
+						groups.put(rootPath, new ArrayList<RepositoryModel>());
+					}
+					groups.get(rootPath).add(model);
 				}
-				if (!groups.containsKey(rootPath)) {
-					groups.put(rootPath, new ArrayList<RepositoryModel>());
-				}
-				groups.get(rootPath).add(model);
 			}
 			List<String> roots = new ArrayList<String>(groups.keySet());
 			Collections.sort(roots);
+			
+			if (rootRepositories.size() > 0) {
+				// inject the root repositories at the top of the page
+				String rootPath = GitBlit.getString(Keys.web.repositoryRootGroupName, " ");
+				roots.add(0, rootPath);
+				groups.put(rootPath, rootRepositories);
+			}
 			List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
 			for (String root : roots) {
 				List<RepositoryModel> subModels = groups.get(root);
@@ -95,6 +107,8 @@
 			dp = new SortableRepositoriesProvider(models);
 		}
 
+		final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);
+		final ByteFormat byteFormat = new ByteFormat();
 		DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
 			private static final long serialVersionUID = 1L;
 			int counter;
@@ -123,11 +137,16 @@
 							pp));
 					row.add(new LinkPanel("repositoryDescription", "list", entry.description,
 							SummaryPage.class, pp));
+					if (showSize) {
+						row.add(new Label("repositorySize", byteFormat.format(GitBlit.self().calculateSize(entry))));
+					} else {
+						row.add(new Label("repositorySize").setVisible(false));
+					}
 				} else {
 					// New repository
-					row.add(new Label("repositoryName", entry.name
-							+ "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
+					row.add(new Label("repositoryName", entry.name));
 					row.add(new Label("repositoryDescription", entry.description));
+					row.add(new Label("repositorySize", "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
 				}
 
 				if (entry.useTickets) {

--
Gitblit v1.9.1