# SINCE 0.5.0\r
web.syndicationEntries = 25\r
\r
+# Show the size of each repository on the repositories page.\r
+# This requires recursive traversal of each repository folder. This may be\r
+# non-performant on some operating systems and/or filesystems. \r
+#\r
+# SINCE 0.5.2\r
+web.showRepositorySizes = true\r
+\r
# This is the message display above the repositories table.\r
# This can point to a file with Markdown content.\r
# Specifying "gitblit" uses the internal welcome message.\r
\r
### Current Release\r
\r
-%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] *released %BUILDDATE%*\r
+**%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] *released %BUILDDATE%*\r
\r
-- clarified SSL certificate generation and configuration for both server-side and client-side\r
-- added some more troubleshooting information to documentation\r
-- replaced JavaService with Apache Commons Daemon\r
+- optionally display repository on-disk size on repositories page<br/>**New:** *web.showRepositorySizes = true*\r
+- tone-down repository group header color\r
\r
issues & binaries @ [Google Code][googlecode]<br/>\r
sources @ [Github][gitbltsrc]\r
## Release History\r
\r
### Current Release\r
-%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] *released %BUILDDATE%*\r
+**%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] *released %BUILDDATE%*\r
+\r
+- optionally display repository on-disk size on repositories page<br/>**New:** *web.showRepositorySizes = true*\r
+- tone-down repository group header color\r
+\r
+### Older Releases\r
+**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] *released 2006-06-28*\r
\r
- clarified SSL certificate generation and configuration for both server-side and client-side\r
- added some more troubleshooting information to documentation\r
- replaced JavaService with Apache Commons Daemon\r
\r
-### Older Releases\r
-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] *released 2006-06-26*\r
+**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] *released 2006-06-26*\r
+\r
+- initial release\r
\r
[jgit]: http://eclipse.org/jgit "Eclipse JGit Site"
\ No newline at end of file
\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 = "0.5.1";\r
+ public static final String VERSION = "0.5.2-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
- public static final String VERSION_DATE = "2011-06-28";\r
+ public static final String VERSION_DATE = "PENDING";\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
import org.apache.wicket.protocol.http.WebResponse;\r
import org.eclipse.jgit.errors.RepositoryNotFoundException;\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.transport.resolver.FileResolver;\r
import org.eclipse.jgit.transport.resolver.RepositoryResolver;\r
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;\r
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;\r
+import org.eclipse.jgit.util.FS;\r
import org.eclipse.jgit.util.FileUtils;\r
import org.slf4j.Logger;\r
import org.slf4j.LoggerFactory;\r
return model;\r
}\r
\r
+ /**\r
+ * Returns the size in bytes of the repository.\r
+ * \r
+ * @param model\r
+ * @return size in bytes\r
+ */\r
+ public long calculateSize(RepositoryModel model) {\r
+ File gitDir = FileKey.resolve(new File(repositoriesFolder, model.name), FS.DETECTED);\r
+ return com.gitblit.utils.FileUtils.folderSize(gitDir);\r
+ }\r
+\r
/**\r
* Returns the gitblit string vlaue for the specified key. If key is not\r
* set, returns defaultValue.\r
}\r
return sb.toString();\r
}\r
+\r
+ /**\r
+ * Recursively traverses a folder and its subfolders to calculate the total\r
+ * size in bytes.\r
+ * \r
+ * @param directory\r
+ * @return folder size in bytes\r
+ */\r
+ public static long folderSize(File directory) {\r
+ if (directory == null || !directory.exists()) {\r
+ return -1;\r
+ }\r
+ if (directory.isFile()) {\r
+ return directory.length();\r
+ }\r
+ long length = 0;\r
+ for (File file : directory.listFiles()) {\r
+ if (file.isFile())\r
+ length += file.length();\r
+ else\r
+ length += folderSize(file);\r
+ }\r
+ return length;\r
+ }\r
}\r
<wicket:message key="gb.repository">Repository</wicket:message>\r
</th>\r
<th><wicket:message key="gb.description">Description</wicket:message></th>\r
+ <th></th>\r
<th><wicket:message key="gb.owner">Owner</wicket:message></th>\r
<th></th>\r
<th><wicket:message key="gb.lastChange">Last Change</wicket:message></th>\r
</wicket:fragment>\r
\r
<wicket:fragment wicket:id="groupRepositoryRow">\r
- <td colspan="6"><span wicket:id="groupName">[group name]</span></td>\r
+ <td colspan="7"><span wicket:id="groupName">[group name]</span></td>\r
</wicket:fragment>\r
\r
<wicket:fragment wicket:id="repositoryRow">\r
<td class="left"><div class="list" wicket:id="repositoryName">[repository name]</div></td>\r
<td><div class="list" wicket:id="repositoryDescription">[repository description]</div></td>\r
+ <td style="text-align: right;padding-right:15px;"><span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span></td>\r
<td class="author"><span wicket:id="repositoryOwner">[repository owner]</span></td>\r
<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>\r
<td><span wicket:id="repositoryLastChange">[last change]</span></td>\r
import com.gitblit.SyndicationServlet;\r
import com.gitblit.models.RepositoryModel;\r
import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.ByteFormat;\r
import com.gitblit.utils.StringUtils;\r
import com.gitblit.utils.TimeUtils;\r
import com.gitblit.wicket.GitBlitWebSession;\r
add(adminLinks.setVisible(showAdmin));\r
\r
if (GitBlit.getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {\r
+ List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();\r
Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();\r
for (RepositoryModel model : models) {\r
String rootPath = StringUtils.getRootPath(model.name);\r
- if (StringUtils.isEmpty(rootPath)) {\r
- rootPath = GitBlit.getString(Keys.web.repositoryRootGroupName, " ");\r
- }\r
- if (!groups.containsKey(rootPath)) {\r
- groups.put(rootPath, new ArrayList<RepositoryModel>());\r
+ if (StringUtils.isEmpty(rootPath)) { \r
+ // root repository\r
+ rootRepositories.add(model); \r
+ } else {\r
+ // non-root, grouped repository\r
+ if (!groups.containsKey(rootPath)) {\r
+ groups.put(rootPath, new ArrayList<RepositoryModel>());\r
+ }\r
+ groups.get(rootPath).add(model);\r
}\r
- groups.get(rootPath).add(model);\r
}\r
List<String> roots = new ArrayList<String>(groups.keySet());\r
Collections.sort(roots);\r
+ \r
+ if (rootRepositories.size() > 0) {\r
+ // inject the root repositories at the top of the page\r
+ String rootPath = GitBlit.getString(Keys.web.repositoryRootGroupName, " ");\r
+ roots.add(0, rootPath);\r
+ groups.put(rootPath, rootRepositories);\r
+ }\r
List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();\r
for (String root : roots) {\r
List<RepositoryModel> subModels = groups.get(root);\r
dp = new SortableRepositoriesProvider(models);\r
}\r
\r
+ final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);\r
+ final ByteFormat byteFormat = new ByteFormat();\r
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {\r
private static final long serialVersionUID = 1L;\r
int counter;\r
pp));\r
row.add(new LinkPanel("repositoryDescription", "list", entry.description,\r
SummaryPage.class, pp));\r
+ if (showSize) {\r
+ row.add(new Label("repositorySize", byteFormat.format(GitBlit.self().calculateSize(entry))));\r
+ } else {\r
+ row.add(new Label("repositorySize").setVisible(false));\r
+ }\r
} else {\r
// New repository\r
- row.add(new Label("repositoryName", entry.name\r
- + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));\r
+ row.add(new Label("repositoryName", entry.name));\r
row.add(new Label("repositoryDescription", entry.description));\r
+ row.add(new Label("repositorySize", "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));\r
}\r
\r
if (entry.useTickets) {\r