James Moger
2011-06-18 5450d08e4cd11176bcc50a5b3d001d291bd8982c
Mostly stable war build.

Reorganization of resources. Dropped most hard-coded webapp
configuration in favor of common web.xml file. Still contemplating
configuring git servlet from web.xml too.
3 files added
49 files renamed
39 files modified
1 files deleted
899 ■■■■■ changed files
.gitignore 2 ●●●●● patch | view | raw | blame | history
build.xml 100 ●●●● patch | view | raw | blame | history
distrib/gitblit.properties 31 ●●●● patch | view | raw | blame | history
docs/00_index.mkd 19 ●●●● patch | view | raw | blame | history
docs/00_setup.mkd 4 ●●●● patch | view | raw | blame | history
docs/01_faq.mkd 19 ●●●●● patch | view | raw | blame | history
resources/add_16x16.png patch | view | raw | blame | history
resources/arrow_down.png patch | view | raw | blame | history
resources/arrow_off.png patch | view | raw | blame | history
resources/arrow_up.png patch | view | raw | blame | history
resources/background.png patch | view | raw | blame | history
resources/blank.png patch | view | raw | blame | history
resources/book_16x16.png patch | view | raw | blame | history
resources/bug_16x16.png patch | view | raw | blame | history
resources/bullet_error.png patch | view | raw | blame | history
resources/cold_16x16.png patch | view | raw | blame | history
resources/commit_branch_16x16.png patch | view | raw | blame | history
resources/commit_divide_16x16.png patch | view | raw | blame | history
resources/commit_join_16x16.png patch | view | raw | blame | history
resources/commit_merge_16x16.png patch | view | raw | blame | history
resources/commit_up_16x16.png patch | view | raw | blame | history
resources/feed_16x16.png patch | view | raw | blame | history
resources/file_16x16.png patch | view | raw | blame | history
resources/file_acrobat_16x16.png patch | view | raw | blame | history
resources/file_c_16x16.png patch | view | raw | blame | history
resources/file_code_16x16.png patch | view | raw | blame | history
resources/file_cpp_16x16.png patch | view | raw | blame | history
resources/file_cs_16x16.png patch | view | raw | blame | history
resources/file_doc_16x16.png patch | view | raw | blame | history
resources/file_excel_16x16.png patch | view | raw | blame | history
resources/file_h_16x16.png patch | view | raw | blame | history
resources/file_java_16x16.png patch | view | raw | blame | history
resources/file_php_16x16.png patch | view | raw | blame | history
resources/file_ppt_16x16.png patch | view | raw | blame | history
resources/file_ruby_16x16.png patch | view | raw | blame | history
resources/file_settings_16x16.png patch | view | raw | blame | history
resources/file_vs_16x16.png patch | view | raw | blame | history
resources/file_world_16x16.png patch | view | raw | blame | history
resources/file_zip_16x16.png patch | view | raw | blame | history
resources/folder_16x16.png patch | view | raw | blame | history
resources/gitblit.css 2 ●●● patch | view | raw | blame | history
resources/gitblt-favicon.png patch | view | raw | blame | history
resources/gitblt-logo.png patch | view | raw | blame | history
resources/gitblt2.png patch | view | raw | blame | history
resources/gitblt_25.png patch | view | raw | blame | history
resources/gitweb-favicon.png patch | view | raw | blame | history
resources/lock_16x16.png patch | view | raw | blame | history
resources/lock_go_16x16.png patch | view | raw | blame | history
resources/lock_pull_16x16.png patch | view | raw | blame | history
resources/markdown.css patch | view | raw | blame | history
resources/pixel.png patch | view | raw | blame | history
resources/search-icon.png patch | view | raw | blame | history
resources/shield_16x16.png patch | view | raw | blame | history
resources/tag_16x16.png patch | view | raw | blame | history
resources/user_16x16.png patch | view | raw | blame | history
resources/welcome.mkd patch | view | raw | blame | history
src/WEB-INF/web.xml 125 ●●●●● patch | view | raw | blame | history
src/com/gitblit/AccessRestrictionFilter.java 17 ●●●●● patch | view | raw | blame | history
src/com/gitblit/Build.java 12 ●●●● patch | view | raw | blame | history
src/com/gitblit/BuildWebXml.java 80 ●●●●● patch | view | raw | blame | history
src/com/gitblit/Constants.java 8 ●●●●● patch | view | raw | blame | history
src/com/gitblit/DownloadZipServlet.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/FileLoginService.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/GitBlit.java 59 ●●●● patch | view | raw | blame | history
src/com/gitblit/GitBlitServer.java 78 ●●●● patch | view | raw | blame | history
src/com/gitblit/GitFilter.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/ILoginService.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/IStoredSettings.java 18 ●●●●● patch | view | raw | blame | history
src/com/gitblit/SyndicationServlet.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/utils/JGitUtils.java 27 ●●●●● patch | view | raw | blame | history
src/com/gitblit/utils/StringUtils.java 17 ●●●● patch | view | raw | blame | history
src/com/gitblit/utils/SyndicationUtils.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.properties 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/WicketUtils.java 4 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/BasePage.html 14 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/BasePage.java 6 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/DocsPage.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/LoginPage.html 10 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/MarkdownPage.html 6 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/MarkdownPage.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoriesPage.html 4 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoriesPage.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.html 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.java 102 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.html 4 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/SummaryPage.java 2 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/RepositoriesPanel.html 14 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/SearchPanel.html 4 ●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/SearchPanel.java 8 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/UsersPanel.html 8 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/resources/gitblt-favicon.png patch | view | raw | blame | history
src/log4j.properties 66 ●●●●● patch | view | raw | blame | history
.gitignore
@@ -10,3 +10,5 @@
/git
/target
/build.properties
/war
/*.war
build.xml
@@ -5,17 +5,16 @@
    <property name="project.jar" value="gitblit.jar" />
    <property name="project.mainclass" value="com.gitblit.Launcher" />
    <property name="project.build.dir" value="${basedir}/build" />
    <property name="project.resources.dir" value="${basedir}/resources" />
    <loadproperties srcfile="${basedir}/build.properties" />
    <!-- Build Gitblit -->
    <target name="main" description="Compiles Gitblit from source to website">
    <target name="buildinfo">
        <!-- build date -->
        <tstamp>
            <format property="gb.buildDate" pattern="yyyy-MM-dd" />
        </tstamp>
        <!-- extract Gitblit version number from source code -->
        <loadfile property="gb.version" srcfile="${basedir}/src/com/gitblit/Constants.java">
            <filterchain>
@@ -30,7 +29,7 @@
                </tokenfilter>
            </filterchain>
        </loadfile>
        <!-- extract JGit version number from source code -->
        <loadfile property="jgit.version" srcfile="${basedir}/src/com/gitblit/Constants.java">
            <filterchain>
@@ -46,6 +45,13 @@
            </filterchain>
        </loadfile>
        <echo>Building Gitblit ${gb.version}</echo>
        <property name="distribution.zipfile" value="gitblit-${gb.version}.zip" />
        <property name="distribution.warfile" value="gitblit-${gb.version}.war" />
    </target>
    <!-- Build Gitblit GO -->
    <target name="main" description="Compiles Gitblit from source to website" depends="buildinfo">
        <!-- copy required distribution files to project folder -->
        <copy todir="${basedir}" overwrite="false">
@@ -62,8 +68,9 @@
        <mkdir dir="${project.build.dir}" />
        <javac srcdir="${basedir}/src" destdir="${project.build.dir}">
            <include name="com/gitblit/Build.java" />
            <include name="com/gitblit/BuildWebXml.java" />
            <include name="com/gitblit/Constants.java" />
            <include name="com/gitblit/utils/StringUtils.java" />
            <include name="com/gitblit/utils/StringUtils.java" />
        </javac>
        <java classpath="${project.build.dir}" classname="com.gitblit.Build" />
@@ -87,6 +94,9 @@
            <fileset dir="${project.build.dir}">
                <include name="**/*" />
            </fileset>
            <fileset dir="${project.resources.dir}">
                <exclude name="thumbs.db" />
            </fileset>
            <manifest>
                <attribute name="Main-Class" value="${project.mainclass}" />
            </manifest>
@@ -97,7 +107,7 @@
        <mkdir dir="${basedir}/site" />
        <copy todir="${basedir}/site">
            <!-- Copy selected Gitblit resources -->
            <fileset dir="${basedir}/src/com/gitblit/wicket/resources">
            <fileset dir="${project.resources.dir}">
                <include name="background.png" />
                <include name="gitblit.css" />
                <include name="markdown.css" />
@@ -211,7 +221,7 @@
        <mkdir dir="${basedir}/deploy/docs" />
        <copy todir="${basedir}/deploy/docs">
            <!-- Copy selected Gitblit resources -->
            <fileset dir="${basedir}/src/com/gitblit/wicket/resources">
            <fileset dir="${project.resources.dir}">
                <include name="background.png" />
                <include name="gitblit.css" />
                <include name="markdown.css" />
@@ -284,8 +294,7 @@
        </java>
        
        <!-- Create Zip deployment -->
        <property name="distribution.zipfile" value="gitblit-${gb.version}.zip" />
        <!-- Create Zip deployment -->
        <zip destfile="${distribution.zipfile}">
            <fileset dir="${basedir}/deploy">
                <include name="**/*" />
@@ -306,6 +315,67 @@
    </target>
        
    
    <!-- Build Gitblit WAR -->
    <target name="buildWAR" description="Build the Gitblit WAR" depends="buildinfo">
        <path id="master-classpath">
            <fileset dir="${basedir}/ext">
                <include name="*.jar" />
            </fileset>
        </path>
        <delete dir="${basedir}/war" />
        <mkdir dir="${basedir}/war/WEB-INF/lib"/>
        <!-- Gitblit web.xml -->
        <java classpath="${project.build.dir}" classname="com.gitblit.BuildWebXml">
            <classpath refid="master-classpath" />
        </java>
        <!-- Gitblit resources -->
        <copy todir="${basedir}/war">
            <fileset dir="${project.resources.dir}">
                <exclude name="thumbs.db" />
            </fileset>
        </copy>
        <!-- Gitblit library dependencies -->
        <copy todir="${basedir}/war/WEB-INF/lib">
            <fileset dir="${basedir}/ext">
                <exclude name="*-sources.jar" />
                <exclude name="*-javadoc.jar" />
                <exclude name="jcommander*.jar" />
                <exclude name="jetty*.jar" />
                <exclude name="junit*.jar" />
                <exclude name="servlet*.jar" />
            </fileset>
        </copy>
        <!-- Gitblit classes -->
        <mkdir dir="${basedir}/war/WEB-INF/classes"/>
        <copy todir="${basedir}/war/WEB-INF/classes">
            <fileset dir="${basedir}/bin">
                <exclude name="WEB-INF/web.xml" />
                <exclude name="com/gitblit/tests/" />
                <exclude name="com/gitblit/Build*.class" />
                <exclude name="com/gitblit/GitBlitServer*.class" />
                <exclude name="com/gitblit/Launcher*.class" />
                <exclude name="com/gitblit/MakeCertificate*.class" />
                <exclude name="com/gitblit/Thumbnailer*.class" />
            </fileset>
        </copy>
        <!-- Build the WAR file -->
        <jar basedir="${basedir}/war" destfile="${distribution.warfile}" compress="true" />
    </target>
    <!-- Publish binaries to github -->
    <target name="publishBinaries" description="Publish the Gitblit distribution to Github">
        <!-- TODO -->
        <!-- https://github.com/oyvindkinsey/GitHubUploadTask -->
    </target>
    <!-- Publish site to hosting service -->
    <!-- You must add ext/commons-net-1.4.0.jar to your    ANT classpath. -->
    <target name="publishSite" description="Publish the Gitblit site to a webserver (requires ext/commons-net-1.4.0.jar)">
@@ -318,11 +388,5 @@
        <fileset dir="${basedir}/site" />
        </ftp>
    </target>
    
    <!-- Publish distribution to github -->
    <target name="publishDistribution" description="Publish the Gitblit distribution to Github">
        <!-- TODO -->
        <!-- https://github.com/oyvindkinsey/GitHubUploadTask -->
    </target>
</project>
</project>
distrib/gitblit.properties
@@ -2,8 +2,7 @@
# Git Servlet Settings
#
# Allow push/pull over http/https with JGit servlet
# Changing this value requires a server restart.
# Allow push/pull over http/https with JGit servlet.
git.enableGitServlet = true
# Base folder for repositories
@@ -11,11 +10,6 @@
# Use forward slashes even on Windows!!
# e.g. c:/gitrepos
git.repositoriesFolder = git
# Export all repositories
# Changing this value requires a server restart.
# if false, each exported repository must have a .git/git-daemon-export-ok file
git.exportAll = true
# Search the repositories folder subfolders for other repositories.
# Repositories MAY NOT be nested (i.e. one repository within another)
@@ -36,7 +30,9 @@
# Changing this value requires a server restart.
web.authenticateAdminPages = true
# Simple user realm file to authenticate users
# Either a simple user realm file to authenticate users
# OR a fully qualified class name that implements the ILoginService interface.
# Any custom implementation must have a public default constructor.
# Changing this value requires a server restart.
realm.realmFile = users.properties
@@ -154,11 +150,11 @@
# Example global regex substitutions
# Use !!! to separate the search pattern and the replace pattern
# searchpattern!!!replacepattern
#regex.global.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://somehost/bug/$3">Bug-Id: $3</a>
#regex.global.changeid = \\b(Change-Id:\\s*)([A-Za-z0-9]*)\\b!!!<a href="http://somehost/changeid/$2">Change-Id: $2</a>
regex.global.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://somehost/bug/$3">Bug-Id: $3</a>
regex.global.changeid = \\b(Change-Id:\\s*)([A-Za-z0-9]*)\\b!!!<a href="http://somehost/changeid/$2">Change-Id: $2</a>
# Example per-repository regex substitutions overrides global
#regex.myrepository.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://elsewhere/bug/$3">Bug-Id: $3</a>
regex.myrepository.bug = \\b(Bug:)(\\s*[#]?|-){0,1}(\\d+)\\b!!!<a href="http://elsewhere/bug/$3">Bug-Id: $3</a>
#
# Server Settings
@@ -167,19 +163,6 @@
# The temporary folder to decompress the gitblit webapp. 
server.tempFolder = temp
# The common log4j logging pattern
# http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
server.log4jPattern = %-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n
# Alternatively, you may specify a logging pattern for your OS.
# If the os pattern is blank, the common pattern is used.
# This windows pattern fits (mostly) within the fixed bounds of a command prompt.
server.log4jPattern.windows = %-5p %m%n
server.log4jPattern.linux =
#
# Jetty Settings
docs/00_index.mkd
@@ -4,7 +4,7 @@
 
### Current Release
[%VERSION%](http://gitblit.com/%DISTRIBUTION%) based on [%JGIT%][jgit] &nbsp; (*%BUILDDATE%*)
%VERSION% ([go](http://gitblit.com/%GO%)|[war](http://gitblit.com/%WAR%)) based on [%JGIT%][jgit] &nbsp; (*%BUILDDATE%*)
sources @ [Github][gitbltsrc]
@@ -13,8 +13,7 @@
2. Offer useful features for serving Git repositories.  If feature is complex, refer to #1.
3. All dependencies must be retrievable from a publicly accessible [Maven](http://maven.apache.org) repository.<br/>This is to ensure authenticity of dependencies and to keep the Gitblit distribution svelte.  
### Features
- Out-of-the-box integrated stack requiring minimal configuration
### Gitblit Features
- JGit SmartHTTP servlet
- Browser and git client authentication
- Four repository access control configurations and a Read-Only flag
@@ -29,7 +28,6 @@
- Administrators may create, edit, rename, or delete repositories through the web UI
- Administrators may create, edit, rename, or delete users through the web UI
- Repository Owners may edit repositories through the web UI
- Automatically generates a self-signed certificate for https communications
- Git-notes support
- Branch metrics (uses Google Charts)
- HEAD and branch RSS feeds
@@ -41,7 +39,6 @@
- Markdown file view support
- Syntax highlighting for popular source code types
- Customizable regular expression substitution for commit messages (i.e. bug or code review link integration)
- Single text file for server configuration
- Single text file for users configuration
- Optional utility pages
    <ul class='noBullets'>
@@ -49,12 +46,15 @@
    <li>![tickets](bug_16x16.png) Ticgit ticket pages *(based on last MIT release bf57b032 2009-01-27)*</li>
    </ul>
### Gitblit-Go Features
- Out-of-the-box integrated stack requiring minimal configuration
- Automatically generates a self-signed certificate for https communications
- Single text file for server configuration
### Limitations
- [%JGIT%][jgit] does not currently [garbage collect or repack](http://www.kernel.org/pub/software/scm/git/docs/git-gc.html)
- HTTP/HTTPS are the only supported protocols
- Access controls are not path-based, they are repository-based
- Only Administrators can create, rename or delete repositories
- Gitblit is an integrated, full-stack solution.  There is no WAR build at this time.
### Caveats
- Gitblit may eat your data.  Use at your own risk.
@@ -64,7 +64,6 @@
- Code documentation
- Unit testing
- Update Build.java to JGit 1.0.0, when its released
- WAR solution
### Idea List
- Consider clone remote repository feature
@@ -90,7 +89,7 @@
![block diagram](architecture.png "Gitblit Architecture")
### Bundled Dependencies
The following dependencies are bundled with the Gitblit zip distribution file.
The following dependencies are bundled with Gitblit.
- [google-code-prettify](http://code.google.com/p/google-code-prettify) (Apache 2.0)
- [JavaService](http://forge.ow2.org/projects/javaservice) (BSD and LGPL)
@@ -99,7 +98,7 @@
- other icons courtesy of [FatCow Hosting](http://www.fatcow.com/free-icons) (Creative Commons CC-BY)
### Downloaded Dependencies
The following dependencies are automatically downloaded from the Apache Maven repository and from the Eclipse Maven repository when Gitblit is launched for the first time.
The following dependencies are automatically downloaded by Gitblit-Go (or already bundled with the WAR) from the Apache Maven repository and from the Eclipse Maven repository when Gitblit is launched for the first time.
- [JGit][jgit] (EDL 1.0)
- [Wicket](http://wicket.apache.org) (Apache 2.0)
docs/00_setup.mkd
@@ -1,6 +1,6 @@
## Server Setup and Configuration
## Gitblit-Go Setup and Configuration
1. Download and unzip [Gitblit %VERSION%](http://gitblit.com/%DISTRIBUTION%).<br/>
1. Download and unzip [Gitblit-Go %VERSION%](http://gitblit.com/%GO%).<br/>
*Its best to eliminate spaces in the path name as that can cause troubleshooting headaches.* 
2. The server itself is configured through a simple text file.<br/>
Open `gitblit.properties` in your favorite text editor and make sure to review and set:
docs/01_faq.mkd
@@ -12,10 +12,10 @@
3. The repository is clone-restricted and your password changed.
4. A regression in Gitblit.  :(
### Why can't I access Gitblit from another machine?
### Why can't I access Gitblit-Go from another machine?
Please check *server.httpBindInterface* and *server.httpsBindInterface* in `gitblit.properties`.
### How do I run Gitblit on port 80 or 443 in Linux?
### How do I run Gitblit-Go on port 80 or 443 in Linux?
Linux requires root permissions to serve on ports < 1024.<br/>
Run the server as *root* (security concern) or change the ports you are serving to 8080 (http) and/or 8443 (https). 
@@ -47,21 +47,11 @@
No.  Gitblit is based on [JGit][jgit] which is a pure Java implementation of the [Git version control system][git].<br/>
Everything you need for Gitblit is either in the zip distribution file or automatically downloaded on execution.
### What about periodic Git garbage collection (git-gc)?
Good question.  I'm not sure.
Git repositories grow and grow and periodically need to be repacked every once in a while.  Git calls this process [garbage collection](http://www.kernel.org/pub/software/scm/git/docs/git-gc.html) (which is not to be confused with [garbage collection](http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)).)
[JGit's][jgit] documentation is sparse and its unclear whether or not JGit performs this function.
### Can I run Gitblit in conjunction with my existing Git tooling?
Yes.  You can configure Gitblit to only be a repository viewer.
Yes.
### Do I need a JDK or can I use a JRE?
Gitblit will run just fine with a JRE.  Gitblit can optionally use `keytool` from the JDK to generate self-signed certificates, but normally Gitblit uses [BouncyCastle][bouncycastle] for that need.
### I want to deploy Gitblit into my own servlet container.  Where is the WAR?
At this time there is no WAR build available.
### Does Gitblit use a database to store its data?
No.  Gitblit stores its repository configuration information within the `.git/config` file and its user information in `users.properties` or whatever filename is configured in `gitblit.properties`.
@@ -76,6 +66,9 @@
Gitblit's simple authentication and authorization mechanism can be used to facilitate one or more of the [workflows outlined here](http://progit.org/book/ch5-1.html).  Should you require more fine-grained access controls you might consider using [gitolite](https://github.com/sitaramc/gitolite).
### Can I authenticate users against XYZ?
Yes.  The login service is pluggable.  You may write your own authentication module by implementing the *ILoginService* interface.  Set the fully qualified classname as the *realm.realmFile* property.
### Why doesn't Gitblit support SSH?
Gitblit could integrate [Apache Mina][mina] to provide SSH access.  However, doing so violates Gitblit's first design principle: [KISS](http://en.wikipedia.org/wiki/KISS_principle).<br/>
SSH support requires creating, exchanging, and managing SSH keys (arguably not more complicated than managing users).  While this is possible, JGit's SmartHTTP implementation is a simpler and universal transport mechanism.
resources/add_16x16.png

resources/arrow_down.png

resources/arrow_off.png

resources/arrow_up.png

resources/background.png

resources/blank.png

resources/book_16x16.png

resources/bug_16x16.png

resources/bullet_error.png

resources/cold_16x16.png

resources/commit_branch_16x16.png

resources/commit_divide_16x16.png

resources/commit_join_16x16.png

resources/commit_merge_16x16.png

resources/commit_up_16x16.png

resources/feed_16x16.png

resources/file_16x16.png

resources/file_acrobat_16x16.png

resources/file_c_16x16.png

resources/file_code_16x16.png

resources/file_cpp_16x16.png

resources/file_cs_16x16.png

resources/file_doc_16x16.png

resources/file_excel_16x16.png

resources/file_h_16x16.png

resources/file_java_16x16.png

resources/file_php_16x16.png

resources/file_ppt_16x16.png

resources/file_ruby_16x16.png

resources/file_settings_16x16.png

resources/file_vs_16x16.png

resources/file_world_16x16.png

resources/file_zip_16x16.png

resources/folder_16x16.png

resources/gitblit.css
File was renamed from src/com/gitblit/wicket/resources/gitblit.css
@@ -221,7 +221,7 @@
div.search input {
    vertical-align: top;
    background: url(/com/gitblit/wicket/resources/search-icon.png) no-repeat 4px center;
    background: url(search-icon.png) no-repeat 4px center;
    color: #ddd;
    background-color: #000070;
    border: 1px solid transparent;
resources/gitblt-favicon.png
resources/gitblt-logo.png

resources/gitblt2.png

resources/gitblt_25.png

resources/gitweb-favicon.png

resources/lock_16x16.png

resources/lock_go_16x16.png

resources/lock_pull_16x16.png

resources/markdown.css
resources/pixel.png

resources/search-icon.png

resources/shield_16x16.png

resources/tag_16x16.png

resources/user_16x16.png

resources/welcome.mkd
src/WEB-INF/web.xml
New file
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <!-- PARAMS -->
    <!-- Gitblit Context Listener --><!-- STRIP
    <listener>
         <listener-class>com.gitblit.GitBlit</listener-class>
     </listener>STRIP -->
    <!-- Git Servlet
         <url-pattern> MUST match:
            * GitFilter
            * com.gitblit.Constants.GIT_PATH
            * Wicket Filter ignorePaths parameter --><!-- STRIP
    <servlet>
        <servlet-name>GitServlet</servlet-name>
        <servlet-class>org.jgit.http.transport.GitServlet</servlet-class>
        <init-param>
            <param-name>base-path</param-name>
            <param-value>c:/git</param-value>
        </init-param>
        <init-param>
            <param-name>export-all</param-name>
            <param-value>1</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>GitServlet</servlet-name>
        <url-pattern>/git/*</url-pattern>
    </servlet-mapping>STRIP -->
    <!-- Syndication Servlet
         <url-pattern> MUST match:
            * SyndicationFilter
            * com.gitblit.Constants.SYNDICATION_PATH
            * Wicket Filter ignorePaths parameter -->
    <servlet>
        <servlet-name>SyndicationServlet</servlet-name>
        <servlet-class>com.gitblit.SyndicationServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SyndicationServlet</servlet-name>
        <url-pattern>/feed/*</url-pattern>
    </servlet-mapping>
    <!-- Zip Servlet
         <url-pattern> MUST match:
            * ZipServlet
            * com.gitblit.Constants.ZIP_PATH
            * Wicket Filter ignorePaths parameter -->
    <servlet>
        <servlet-name>ZipServlet</servlet-name>
        <servlet-class>com.gitblit.DownloadZipServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ZipServlet</servlet-name>
        <url-pattern>/zip/*</url-pattern>
    </servlet-mapping>
    <!-- Git Access Restriction Filter
         <url-pattern> MUST match:
            * GitServlet
            * com.gitblit.Constants.GIT_PATH
            * Wicket Filter ignorePaths parameter -->
    <filter>
        <filter-name>GitFilter</filter-name>
        <filter-class>com.gitblit.GitFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>GitFilter</filter-name>
        <url-pattern>/git/*</url-pattern>
    </filter-mapping>
    <!-- Syndication Restriction Filter
         <url-pattern> MUST match:
            * SyndicationServlet
            * com.gitblit.Constants.SYNDICATION_PATH
            * Wicket Filter ignorePaths parameter -->
    <filter>
        <filter-name>SyndicationFilter</filter-name>
        <filter-class>com.gitblit.SyndicationFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>SyndicationFilter</filter-name>
        <url-pattern>/feed/*</url-pattern>
    </filter-mapping>
    <!-- Wicket Filter -->
    <filter>
        <filter-name>wicketFilter</filter-name>
        <filter-class>
            org.apache.wicket.protocol.http.WicketFilter
        </filter-class>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.gitblit.wicket.GitBlitWebApp</param-value>
        </init-param>
        <init-param>
            <param-name>ignorePaths</param-name>
            <!-- Paths should match
                 * SyndicationFilter <url-pattern>
                 * SyndicationServlet <url-pattern>
                 * com.gitblit.Constants.SYNDICATION_PATH
                 * GitFilter <url-pattern>
                 * GitServlet <url-pattern>
                 * com.gitblit.Constants.GIT_PATH
                 * ZipServlet <url-pattern>
                 * com.gitblit.Constants.ZIP_PATH -->
            <param-value>git/,feed/,zip/</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>wicketFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
src/com/gitblit/AccessRestrictionFilter.java
@@ -16,6 +16,7 @@
package com.gitblit;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.Principal;
import java.text.MessageFormat;
import java.util.Enumeration;
@@ -32,6 +33,7 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jgit.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -114,7 +116,8 @@
            if (authorization != null && authorization.startsWith(BASIC)) {
                // Authorization: Basic base64credentials
                String base64Credentials = authorization.substring(BASIC.length()).trim();
                String credentials = StringUtils.decodeBase64(base64Credentials);
                String credentials = new String(Base64.decode(base64Credentials),
                        Charset.forName("UTF-8"));
                if (GitBlit.isDebugMode()) {
                    logger.info(MessageFormat.format("AUTH: {0} ({1})", authorization, credentials));
                }
@@ -131,7 +134,8 @@
                            // authenticated request permitted.
                            // pass processing to the restricted servlet.
                            newSession(accessRequest, httpResponse);
                            logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE + ") authenticated");
                            logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE
                                    + ") authenticated");
                            chain.doFilter(accessRequest, httpResponse);
                            return;
                        }
@@ -163,7 +167,8 @@
        }
        if (GitBlit.isDebugMode()) {
            logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE + ") unauthenticated");
            logger.info("ARF: " + fullUrl + " (" + HttpServletResponse.SC_CONTINUE
                    + ") unauthenticated");
        }
        // unauthenticated request permitted.
        // pass processing to the restricted servlet.
@@ -202,19 +207,19 @@
    @Override
    public void destroy() {
    }
    /**
     * Wraps a standard HttpServletRequest and overrides user principal methods.
     */
    public static class AccessRestrictionRequest extends ServletRequestWrapper {
        private UserModel user;
        public AccessRestrictionRequest(HttpServletRequest req) {
            super(req);
            user = new UserModel("anonymous");
        }
        void setUser(UserModel user) {
            this.user = user;
        }
src/com/gitblit/Build.java
@@ -312,10 +312,10 @@
                "c7adc475ca40c288c93054e0f4fe58f3a98c0cb5");
        public static final MavenObject JETTY = new MavenObject("Jetty",
                "org/eclipse/jetty/aggregate", "jetty-all", "7.4.1.v20110513", 1500000, 1000000,
                4100000, "1e2de9ed25a7c6ae38717d5ffdc7cfcd6be4bd46",
                "7b6279d16ce8f663537d9faf55ea353e748dbbaa",
                "fa06212e751296f1a7abc15c843b135bf49a112b");
                "org/eclipse/jetty/aggregate", "jetty-webapp", "7.4.2.v20110526", 1000000, 680000,
                2720000, "56331143afa22d24d9faba96e86e6371b0686c7c",
                "9f38230fd589e29c8be0fc3c80fb51c5093c2e1e",
                "0d48212889c25252c5c14bef62703e28215d80cc");
        public static final MavenObject SERVLET = new MavenObject("Servlet 2.5", "javax/servlet",
                "servlet-api", "2.5", 105000, 158000, 0,
@@ -363,8 +363,8 @@
                "3d32d958b2f7aa58388af5701ea3aafc433e573f",
                "c37518b67ea85af485dd61fe854137eeacc50318");
        public static final MavenObject JUNIT = new MavenObject("JUnit", "junit", "junit", "3.8.2",
                120000, 0, 0, "07e4cde26b53a9a0e3fe5b00d1dbbc7cc1d46060", "", "");
        public static final MavenObject JUNIT = new MavenObject("JUnit", "junit", "junit", "4.8.2",
                237000, 0, 0, "c94f54227b08100974c36170dcb53329435fe5ad", "", "");
        public static final MavenObject MARKDOWNPAPERS = new MavenObject("MarkdownPapers",
                "org/tautua/markdownpapers", "markdownpapers-core", "1.0.0", 87000, 58000, 278000,
src/com/gitblit/BuildWebXml.java
New file
@@ -0,0 +1,80 @@
/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
public class BuildWebXml {
    private static final String PARAMS = "<!-- PARAMS -->";
    private static final String [] STRIP_TOKENS = { "<!-- STRIP", "STRIP -->" };
    private static final String PARAM_PATTERN = "\n\t<context-param>\n\t\t<param-name>{0}</param-name>\n\t\t<param-value>{1}</param-value>\n\t</context-param>\n";
    public static void main(String[] args) throws Exception {
        // Read the current Gitblit properties
        // TODO extract the comments and inject them into web.xml too
        FileInputStream fis = new FileInputStream(new File("distrib/gitblit.properties"));
        Properties fileSettings = new Properties();
        fileSettings.load(fis);
        fis.close();
        List<String> keys = new ArrayList<String>(fileSettings.stringPropertyNames());
        Collections.sort(keys);
        StringBuilder parameters = new StringBuilder();
        for (String key : keys) {
            if (!skipKey(key)) {
                String value = fileSettings.getProperty(key);
                parameters.append(MessageFormat.format(PARAM_PATTERN, key, value));
            }
        }
        // Read the prototype web.xml file
        File webxml = new File("src/WEB-INF/web.xml");
        char [] buffer = new char[(int) webxml.length()];
        FileReader reader = new FileReader(webxml);
        reader.read(buffer);
        reader.close();
        String webXmlContent = new String(buffer);
        // Insert the Gitblit properties into the prototype web.xml
        for (String stripToken:STRIP_TOKENS) {
            webXmlContent = webXmlContent.replace(stripToken, "");
        }
        int idx = webXmlContent.indexOf(PARAMS);
        StringBuilder sb = new StringBuilder();
        sb.append(webXmlContent.substring(0, idx));
        sb.append(parameters.toString());
        sb.append(webXmlContent.substring(idx + PARAMS.length()));
        // Save the merged web.xml to the war build folder
        FileOutputStream os = new FileOutputStream(new File("war/WEB-INF/web.xml"), false);
        os.write(sb.toString().getBytes());
        os.close();
    }
    private static boolean skipKey(String key) {
        return key.startsWith(Keys.server._ROOT);
    }
}
src/com/gitblit/Constants.java
@@ -33,14 +33,12 @@
    public static final String PROPERTIES_FILE = "gitblit.properties";
    public static final String GIT_SERVLET_PATH = "/git/";
    public static final String GIT_PATH = "/git/";
    public static final String ZIP_SERVLET_PATH = "/zip/";
    public static final String ZIP_PATH = "/zip/";
    
    public static final String SYNDICATION_SERVLET_PATH = "/feed/";
    public static final String SYNDICATION_PATH = "/feed/";
    
    public static final String RESOURCE_PATH = "/com/gitblit/wicket/resources/";
    public static final String BORDER = "***********************************************************";
    public static enum AccessRestrictionType {
src/com/gitblit/DownloadZipServlet.java
@@ -44,7 +44,7 @@
        if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
            baseURL = baseURL.substring(0, baseURL.length() - 1);
        }
        return baseURL + Constants.ZIP_SERVLET_PATH + "?r=" + repository
        return baseURL + Constants.ZIP_PATH + "?r=" + repository
                + (path == null ? "" : ("&p=" + path))
                + (objectId == null ? "" : ("&h=" + objectId));
    }
src/com/gitblit/FileLoginService.java
@@ -53,8 +53,7 @@
            if (user.password.equalsIgnoreCase(md5)) {
                returnedUser = user;
            }
        }
        if (user.password.equals(new String(password))) {
        } else if (user.password.equals(new String(password))) {
            returnedUser = user;
        }
        return returnedUser;
src/com/gitblit/GitBlit.java
@@ -45,7 +45,7 @@
public class GitBlit implements ServletContextListener {
    private static final GitBlit GITBLIT;
    private static GitBlit gitblit;
    private final Logger logger = LoggerFactory.getLogger(GitBlit.class);
@@ -53,45 +53,48 @@
    private File repositoriesFolder;
    private boolean exportAll;
    private boolean exportAll = true;
    private ILoginService loginService;
    private IStoredSettings storedSettings;
    static {
        GITBLIT = new GitBlit();
    }
    private GitBlit() {
    public GitBlit() {
        if (gitblit == null) {
            // Singleton reference when running in standard servlet container
            gitblit = this;
        }
    }
    public static GitBlit self() {
        return GITBLIT;
        if (gitblit == null) {
            gitblit = new GitBlit();
        }
        return gitblit;
    }
    public static boolean getBoolean(String key, boolean defaultValue) {
        return GITBLIT.storedSettings.getBoolean(key, defaultValue);
        return self().storedSettings.getBoolean(key, defaultValue);
    }
    public static int getInteger(String key, int defaultValue) {
        return GITBLIT.storedSettings.getInteger(key, defaultValue);
        return self().storedSettings.getInteger(key, defaultValue);
    }
    public static String getString(String key, String defaultValue) {
        return GITBLIT.storedSettings.getString(key, defaultValue);
        return self().storedSettings.getString(key, defaultValue);
    }
    public static List<String> getStrings(String key) {
        return GITBLIT.storedSettings.getStrings(key);
        return self().storedSettings.getStrings(key);
    }
    public static List<String> getAllKeys(String startingWith) {
        return GITBLIT.storedSettings.getAllKeys(startingWith);
        return self().storedSettings.getAllKeys(startingWith);
    }
    public static boolean isDebugMode() {
        return GITBLIT.storedSettings.getBoolean(Keys.web.debugMode, false);
        return self().storedSettings.getBoolean(Keys.web.debugMode, false);
    }
    public List<String> getOtherCloneUrls(String repositoryName) {
@@ -103,6 +106,7 @@
    }
    public void setLoginService(ILoginService loginService) {
        logger.info("Setting up login service " + loginService.toString());
        this.loginService = loginService;
    }
@@ -353,9 +357,32 @@
    public void configureContext(IStoredSettings settings) {
        logger.info("Reading configuration from " + settings.toString());
        this.storedSettings = settings;
        repositoriesFolder = new File(settings.getString(Keys.git.repositoriesFolder, "repos"));
        exportAll = settings.getBoolean(Keys.git.exportAll, true);
        repositoriesFolder = new File(settings.getString(Keys.git.repositoriesFolder, "git"));
        logger.info("Git repositories folder " + repositoriesFolder.getAbsolutePath());
        repositoryResolver = new FileResolver<Void>(repositoriesFolder, exportAll);
        String realm = settings.getString(Keys.realm.realmFile, "users.properties");
        ILoginService loginService = null;
        try {
            // Check to see if this "file" is a login service class
            Class<?> realmClass = Class.forName(realm);
            if (ILoginService.class.isAssignableFrom(realmClass)) {
                loginService = (ILoginService) realmClass.newInstance();
            }
        } catch (Throwable t) {
            // Not a login service class OR other issue
            // Use default file login service
            File realmFile = new File(realm);
            if (!realmFile.exists()) {
                try {
                    realmFile.createNewFile();
                } catch (IOException x) {
                    logger.error(
                            MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmFile), x);
                }
            }
            loginService = new FileLoginService(realmFile);
        }
        setLoginService(loginService);
    }
    @Override
src/com/gitblit/GitBlitServer.java
@@ -30,10 +30,6 @@
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.PatternLayout;
import org.apache.wicket.protocol.http.ContextParamWebApplicationFactory;
import org.apache.wicket.protocol.http.WicketFilter;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
@@ -42,7 +38,6 @@
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -56,7 +51,6 @@
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebApp;
public class GitBlitServer {
@@ -121,26 +115,6 @@
     */
    private static void start(Params params) {
        FileSettings settings = params.FILESETTINGS;
        String pattern = settings.getString(Keys.server.log4jPattern,
                "%-5p %d{MM-dd HH:mm:ss.SSS}  %-20.20c{1}  %m%n");
        // allow os override of logging pattern
        String os = System.getProperty("os.name").toLowerCase();
        if (os.indexOf("windows") > -1) {
            String winPattern = settings.getString(Keys.server.log4jPattern_windows, pattern);
            if (!StringUtils.isEmpty(winPattern)) {
                pattern = winPattern;
            }
        } else if (os.indexOf("linux") > -1) {
            String linuxPattern = settings.getString(Keys.server.log4jPattern_linux, pattern);
            if (!StringUtils.isEmpty(linuxPattern)) {
                pattern = linuxPattern;
            }
        }
        PatternLayout layout = new PatternLayout(pattern);
        org.apache.log4j.Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
        rootLogger.addAppender(new ConsoleAppender(layout));
        logger = LoggerFactory.getLogger(GitBlitServer.class);
        logger.info(Constants.BORDER);
@@ -223,55 +197,23 @@
        sessionManager.setSecureCookies(params.port <= 0 && params.securePort > 0);
        rootContext.getSessionHandler().setSessionManager(sessionManager);
        // Wicket Filter
        String wicketPathSpec = "/*";
        FilterHolder wicketFilter = new FilterHolder(WicketFilter.class);
        wicketFilter.setInitParameter(ContextParamWebApplicationFactory.APP_CLASS_PARAM,
                GitBlitWebApp.class.getName());
        wicketFilter.setInitParameter(WicketFilter.FILTER_MAPPING_PARAM, wicketPathSpec);
        wicketFilter.setInitParameter(WicketFilter.IGNORE_PATHS_PARAM, "git/,feed/,zip/");
        rootContext.addFilter(wicketFilter, wicketPathSpec, FilterMapping.DEFAULT);
        // JGit Filter and Servlet
        if (settings.getBoolean(Keys.git.enableGitServlet, true)) {
            String jgitPathSpec = Constants.GIT_SERVLET_PATH + "*";
            rootContext.addFilter(GitFilter.class, jgitPathSpec, FilterMapping.DEFAULT);
            ServletHolder jGitServlet = rootContext.addServlet(GitServlet.class, jgitPathSpec);
            jGitServlet.setInitParameter("base-path", params.repositoriesFolder);
            jGitServlet.setInitParameter("export-all",
                    settings.getBoolean(Keys.git.exportAll, true) ? "1" : "0");
        }
        String jgitPathSpec = Constants.GIT_PATH + "*";
        rootContext.addFilter(GitFilter.class, jgitPathSpec, FilterMapping.DEFAULT);
        ServletHolder jGitServlet = rootContext.addServlet(GitServlet.class, jgitPathSpec);
        jGitServlet.setInitParameter("base-path", params.repositoriesFolder);
        jGitServlet.setInitParameter("export-all", "1");
        // Syndication Filter and Servlet
        String feedPathSpec = Constants.SYNDICATION_SERVLET_PATH + "*";
        rootContext.addFilter(SyndicationFilter.class, feedPathSpec, FilterMapping.DEFAULT);
        rootContext.addServlet(SyndicationServlet.class, feedPathSpec);
        // Zip Servlet
        rootContext.addServlet(DownloadZipServlet.class, Constants.ZIP_SERVLET_PATH + "*");
        // Login Service
        // Ensure there is a defined Login Service
        String realmUsers = params.realmFile;
        if (StringUtils.isEmpty(realmUsers)) {
            logger.error(MessageFormat.format("PLEASE SPECIFY {0}!!", Keys.realm.realmFile));
            return;
        }
        File realmFile = new File(realmUsers);
        if (!realmFile.exists()) {
            try {
                realmFile.createNewFile();
            } catch (IOException x) {
                logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmUsers),
                        x);
                return;
            }
        }
        logger.info("Setting up login service from " + realmUsers);
        FileLoginService loginService = new FileLoginService(realmFile);
        GitBlit.self().setLoginService(loginService);
        logger.info("Git repositories folder "
                + new File(params.repositoriesFolder).getAbsolutePath());
        // Update settings
//        settings.put(Keys.realm.realmFile, params.realmFile);
//        settings.put(Keys.git.repositoriesFolder, params.repositoriesFolder);
        // Set the server's contexts
        server.setHandler(rootContext);
src/com/gitblit/GitFilter.java
@@ -65,6 +65,10 @@
    @Override
    protected boolean canAccess(RepositoryModel repository, UserModel user, String urlRequestType) {
        if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
            // Git Servlet disabled
            return false;
        }
        if (repository.isFrozen || repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
            boolean authorizedUser = user.canAccessRepository(repository.name);
            if (urlRequestType.equals(gitReceivePack)) {
src/com/gitblit/ILoginService.java
@@ -42,4 +42,6 @@
    boolean renameRole(String oldRole, String newRole);
    boolean deleteRole(String role);
    String toString();
}
src/com/gitblit/IStoredSettings.java
@@ -27,21 +27,25 @@
public abstract class IStoredSettings {
    protected final Logger logger;
    public IStoredSettings(Class<? extends IStoredSettings> clazz) {
        logger = LoggerFactory.getLogger(clazz);
    }
    protected abstract Properties read();
    public List<String> getAllKeys(String startingWith) {
        startingWith = startingWith.toLowerCase();
        List<String> keys = new ArrayList<String>();
        Properties props = read();
        for (Object o : props.keySet()) {
            String key = o.toString();
            if (key.toLowerCase().startsWith(startingWith)) {
                keys.add(key);
        if (StringUtils.isEmpty(startingWith)) {
            keys.addAll(props.stringPropertyNames());
        } else {
            startingWith = startingWith.toLowerCase();
            for (Object o : props.keySet()) {
                String key = o.toString();
                if (key.toLowerCase().startsWith(startingWith)) {
                    keys.add(key);
                }
            }
        }
        return keys;
src/com/gitblit/SyndicationServlet.java
@@ -43,7 +43,7 @@
        }
        StringBuilder url = new StringBuilder();
        url.append(baseURL);
        url.append(Constants.SYNDICATION_SERVLET_PATH);
        url.append(Constants.SYNDICATION_PATH);
        url.append(repository);
        if (!StringUtils.isEmpty(objectId) || length > 0) {
            StringBuilder parameters = new StringBuilder("?");
src/com/gitblit/utils/JGitUtils.java
@@ -402,36 +402,30 @@
    public static List<PathChangeModel> getFilesInCommit(Repository r, RevCommit commit) {
        List<PathChangeModel> list = new ArrayList<PathChangeModel>();
        RevWalk rw = new RevWalk(r);
        TreeWalk tw = new TreeWalk(r);
        RevWalk rw = new RevWalk(r);
        try {
            if (commit == null) {
                ObjectId object = r.resolve(Constants.HEAD);
                commit = rw.parseCommit(object);
            }
            RevTree commitTree = commit.getTree();
            }
            tw.reset();
            tw.setRecursive(true);
            if (commit.getParentCount() == 0) {
                tw.addTree(commitTree);
                TreeWalk tw = new TreeWalk(r);
                tw.reset();
                tw.setRecursive(true);
                tw.addTree(commit.getTree());
                while (tw.next()) {
                    list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(), 0, tw
                            .getRawMode(0), commit.getId().getName(), ChangeType.ADD));
                }
                tw.release();
            } else {
                RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
                RevTree parentTree = parent.getTree();
                tw.addTree(parentTree);
                tw.addTree(commitTree);
                tw.setFilter(TreeFilter.ANY_DIFF);
                RawTextComparator cmp = RawTextComparator.DEFAULT;
                DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
                df.setRepository(r);
                df.setDiffComparator(cmp);
                df.setDiffComparator(RawTextComparator.DEFAULT);
                df.setDetectRenames(true);
                List<DiffEntry> diffs = df.scan(parentTree, commitTree);
                List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree());
                for (DiffEntry diff : diffs) {
                    if (diff.getChangeType().equals(ChangeType.DELETE)) {
                        list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
@@ -447,8 +441,7 @@
        } catch (Throwable t) {
            LOGGER.error("failed to determine files in commit!", t);
        } finally {
            rw.dispose();
            tw.release();
            rw.dispose();
        }
        return list;
    }
src/com/gitblit/utils/StringUtils.java
@@ -16,15 +16,11 @@
package com.gitblit.utils;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.PatternSyntaxException;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jgit.util.Base64;
public class StringUtils {
@@ -152,9 +148,10 @@
            md.update(string.getBytes("iso-8859-1"));
            byte[] digest = md.digest();
            return toHex(digest);
        } catch (Exception e) {
            Log.warn(e);
            return null;
        } catch (UnsupportedEncodingException u) {
            throw new RuntimeException(u);
        } catch (NoSuchAlgorithmException t) {
            throw new RuntimeException(t);
        }
    }
@@ -168,11 +165,7 @@
        }
        return sb.toString();
    }
    public static String decodeBase64(String base64) {
        return new String(Base64.decode(base64), Charset.forName("UTF-8"));
    }
    public static String getRootPath(String path) {
        if (path.indexOf('/') > -1) {
            return path.substring(0, path.lastIndexOf('/'));
src/com/gitblit/utils/SyndicationUtils.java
@@ -48,7 +48,7 @@
        feed.setDescription(description);
        SyndImageImpl image = new SyndImageImpl();
        image.setTitle(Constants.NAME);
        image.setUrl(hostUrl + Constants.RESOURCE_PATH + "gitblt_25.png");
        image.setUrl(hostUrl + "/gitblt_25.png");
        image.setLink(hostUrl);
        feed.setImage(image);
src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -66,7 +66,7 @@
gb.missingUsername = Missing Username
gb.edit = edit
gb.searchTypeTooltip = Select Search Type
gb.searchTooltip = Search Git:Blit
gb.searchTooltip = Search Gitblit
gb.delete = delete
gb.docs = docs
gb.accessRestriction = access restriction
@@ -86,7 +86,7 @@
gb.useTicketsDescription = distributed Ticgit issues
gb.useDocsDescription = enumerates Markdown documentation in repository
gb.showRemoteBranchesDescription = show remote branches
gb.canAdminDescription = can administer Git:Blit server
gb.canAdminDescription = can administer Gitblit server
gb.permittedUsers = permitted users
gb.isFrozen = is frozen
gb.isFrozenDescription = deny push operations
src/com/gitblit/wicket/WicketUtils.java
@@ -169,7 +169,7 @@
    }
    public static ContextImage newImage(String wicketId, String file, String tooltip) {
        ContextImage img = new ContextImage(wicketId, com.gitblit.Constants.RESOURCE_PATH + file);
        ContextImage img = new ContextImage(wicketId, file);
        if (!StringUtils.isEmpty(tooltip)) {
            setHtmlTooltip(img, tooltip);
        }
@@ -177,7 +177,7 @@
    }
    public static ContextRelativeResource getResource(String file) {
        return new ContextRelativeResource(com.gitblit.Constants.RESOURCE_PATH + file);
        return new ContextRelativeResource(file);
    }
    public static String getHostURL(Request request) {
src/com/gitblit/wicket/pages/BasePage.html
@@ -4,25 +4,21 @@
      xml:lang="en"  
      lang="en"> 
    <!-- Head with Wicket-controlled resources in this package -->
    <!-- Head -->
    <wicket:head>
           <title wicket:id="title">[page title]</title>
           <wicket:link>
               <link rel="stylesheet" type="text/css" href="/com/gitblit/wicket/resources/gitblit.css"/>
               <link rel="shortcut icon" href="/com/gitblit/wicket/resources/gitblt-favicon.png" type="image/png" />
           </wicket:link>
        <link rel="stylesheet" type="text/css" href="gitblit.css"/>
        <link rel="icon" href="gitblt-favicon.png" type="image/png" />
    </wicket:head>
    <body>
        <!-- page header -->
        <div class="page_header">
            <a title="gitblit homepage" href="http://gitblit.com/">
                <wicket:link>
                    <img src="/com/gitblit/wicket/resources/gitblt_25.png" width="79" height="25" alt="gitblit" class="logo"/>
                </wicket:link>
                <img src="gitblt_25.png" width="79" height="25" alt="gitblit" class="logo"/>
            </a>
            <span>
                <a href="/"><span wicket:id="siteName">[site name]</span></a> / <span wicket:id="repositoryName">[repository name]</span> <span wicket:id="pageName">[page name]</span>
                <span wicket:id="siteName">[site name]</span> / <span wicket:id="repositoryName">[repository name]</span> <span wicket:id="pageName">[page name]</span>
            </span>    
        </div>
src/com/gitblit/wicket/pages/BasePage.java
@@ -63,7 +63,7 @@
        if (siteName == null || siteName.trim().length() == 0) {
            siteName = Constants.NAME;
        }
        add(new Label("siteName", siteName));
        add(new LinkPanel("siteName", null, siteName, RepositoriesPage.class, null));
        add(new LinkPanel("repositoryName", null, repositoryName, SummaryPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new Label("pageName", pageName));
@@ -122,6 +122,10 @@
        HttpServletRequest req = servletWebRequest.getHttpServletRequest();
        return req.getServerName();
    }
    public void warn(String message, Throwable t) {
        logger.warn(message, t);
    }
    public void error(String message, boolean redirect) {
        logger.error(message);
src/com/gitblit/wicket/pages/DocsPage.java
@@ -64,7 +64,8 @@
                        .newPathParameter(repositoryName, entry.commitId, entry.path)));
                item.add(new BookmarkablePageLink<Void>("raw", RawPage.class, WicketUtils
                        .newPathParameter(repositoryName, entry.commitId, entry.path)));
                item.add(new BookmarkablePageLink<Void>("blame", BlobPage.class).setEnabled(false));
                item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class,
                        WicketUtils.newPathParameter(repositoryName, entry.commitId, entry.path)));
                item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class, WicketUtils
                        .newPathParameter(repositoryName, entry.commitId, entry.path)));
                WicketUtils.setAlternatingBackground(item, counter);
src/com/gitblit/wicket/pages/LoginPage.html
@@ -7,18 +7,14 @@
    <!-- Head with Wicket-controlled resources in this package -->
    <wicket:head>
           <title wicket:id="title">[page title]</title>
           <wicket:link>
               <link rel="stylesheet" type="text/css" href="/com/gitblit/wicket/resources/gitblit.css"/>
               <link rel="shortcut icon" href="/com/gitblit/wicket/resources/gitblt-favicon.png" type="image/png" />
           </wicket:link>
        <link rel="stylesheet" type="text/css" href="gitblit.css"/>
        <link rel="shortcut icon" href="gitblt-favicon.png" type="image/png" />
    </wicket:head>
    
    <body onload="document.getElementById('username').focus();">
        <div>
            <div style="padding-top: 10px;text-align:center;">
                <wicket:link>
                    <img src="/com/gitblit/wicket/resources/gitblt_25.png" alt="Git:Blit"/><br/>
                </wicket:link>
                <img src="gitblt_25.png" alt="Gitblit"/><br/>
                <div style="padding-top:30px;font-weight:bold;" wicket:id="name">[name]</div>
            </div>
src/com/gitblit/wicket/pages/MarkdownPage.html
@@ -6,16 +6,14 @@
      
<!-- contribute markdown css to the page header -->
<wicket:head>
  <wicket:link>
       <link href="/com/gitblit/wicket/resources/markdown.css" type="text/css" rel="stylesheet" />
  </wicket:link>
    <link href="markdown.css" type="text/css" rel="stylesheet" />
</wicket:head>
<body>
<wicket:extend>
        <!-- markdown nav links -->    
        <div class="page_nav2">
            <span wicket:id="blameLink">[blame link]</span> | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="rawLink"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a>
            <a wicket:id="blameLink"><wicket:message key="gb.blame"></wicket:message></a>  | <a wicket:id="historyLink"><wicket:message key="gb.history"></wicket:message></a> | <a wicket:id="rawLink"><wicket:message key="gb.raw"></wicket:message></a> | <a wicket:id="headLink"><wicket:message key="gb.head"></wicket:message></a>
        </div>    
    
        <!--  markdown content -->
src/com/gitblit/wicket/pages/MarkdownPage.java
@@ -39,7 +39,8 @@
        RevCommit commit = JGitUtils.getCommit(r, objectId);
        // markdown page links
        add(new Label("blameLink", getString("gb.blame")));
        add(new BookmarkablePageLink<Void>("blameLink", BlamePage.class,
                WicketUtils.newPathParameter(repositoryName, objectId, markdownPath)));
        add(new BookmarkablePageLink<Void>("historyLink", HistoryPage.class,
                WicketUtils.newPathParameter(repositoryName, objectId, markdownPath)));
        add(new BookmarkablePageLink<Void>("rawLink", RawPage.class, WicketUtils.newPathParameter(
src/com/gitblit/wicket/pages/RepositoriesPage.html
@@ -4,9 +4,7 @@
      xml:lang="en"  
      lang="en"> 
<wicket:head>
  <wicket:link>
       <link href="/com/gitblit/wicket/resources/markdown.css" type="text/css" rel="stylesheet" />
  </wicket:link>
       <link href="markdown.css" type="text/css" rel="stylesheet" />
</wicket:head>
<body>
src/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -86,7 +86,7 @@
                        message = MarkdownUtils.transformMarkdown(reader);
                    } catch (Throwable t) {
                        message = "Failed to read " + file;
                        error(message, t, false);
                        warn(message, t);
                    }
                } else {
                    message = messageSource + " is not a valid file.";
src/com/gitblit/wicket/pages/RepositoryPage.html
@@ -19,7 +19,7 @@
            <!-- page nav links -->
            <div class="page_nav">
                <a style="text-decoration: none;" wicket:id="syndication">
                    <img style="border:0px;vertical-align:middle;" src="/com/gitblit/wicket/resources/feed_16x16.png"></img>
                    <img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img>
                </a>                
                <a wicket:id="summary"><wicket:message key="gb.summary"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a> | <a wicket:id="branches"><wicket:message key="gb.branches"></wicket:message></a> | <a wicket:id="tags"><wicket:message key="gb.tags"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> <span wicket:id="extra"><span wicket:id="extraSeparator"></span><span wicket:id="extraLink"></span></span>
            </div>
src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -40,8 +40,6 @@
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
@@ -65,20 +63,19 @@
    private RepositoryModel m;
    private final Logger logger = LoggerFactory.getLogger(RepositoryPage.class);
    private final Map<String, String> knownPages = new HashMap<String, String>() {
    private final Map<String, PageRegistration> registeredPages = new HashMap<String, PageRegistration>() {
        private static final long serialVersionUID = 1L;
        {
            put("summary", "gb.summary");
            put("log", "gb.log");
            put("branches", "gb.branches");
            put("tags", "gb.tags");
            put("tree", "gb.tree");
            put("tickets", "gb.tickets");
            put("edit", "gb.edit");
            put("summary", new PageRegistration("gb.summary", SummaryPage.class));
            put("log", new PageRegistration("gb.log", LogPage.class));
            put("branches", new PageRegistration("gb.branches", BranchesPage.class));
            put("tags", new PageRegistration("gb.tags", TagsPage.class));
            put("tree", new PageRegistration("gb.tree", TreePage.class));
            put("tickets", new PageRegistration("gb.tickets", TicketsPage.class));
            put("edit", new PageRegistration("gb.edit", EditRepositoryPage.class));
            put("docs", new PageRegistration("gb.docs", DocsPage.class));
        }
    };
@@ -95,26 +92,17 @@
        RepositoryModel model = getRepositoryModel();
        // standard page links
        add(new BookmarkablePageLink<Void>("summary", SummaryPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("log", LogPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("branches", BranchesPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("tags", TagsPage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        add(new BookmarkablePageLink<Void>("tree", TreePage.class,
                WicketUtils.newRepositoryParameter(repositoryName)));
        addRegisteredPageLink("summary");
        addRegisteredPageLink("log");
        addRegisteredPageLink("branches");
        addRegisteredPageLink("tags");
        addRegisteredPageLink("tree");
        // per-repository extra page links
        List<String> extraPageLinks = new ArrayList<String>();
        // Conditionally add tickets link
        if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) {
            extraPageLinks.add("tickets");
        }
        // Conditionally add docs link
        if (model.useDocs) {
            extraPageLinks.add("docs");
        }
@@ -135,26 +123,19 @@
            extraPageLinks.add("edit");
        }
        final String pageName = getPageName();
        final String pageWicketId = getLinkWicketId(pageName);
        ListDataProvider<String> extrasDp = new ListDataProvider<String>(extraPageLinks);
        DataView<String> extrasView = new DataView<String>("extra", extrasDp) {
            private static final long serialVersionUID = 1L;
            public void populateItem(final Item<String> item) {
                String extra = item.getModelObject();
                if (extra.equals("tickets")) {
                    item.add(new Label("extraSeparator", " | "));
                    item.add(new LinkPanel("extraLink", null, getString("gb.tickets"),
                            TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName)));
                } else if (extra.equals("docs")) {
                    item.add(new Label("extraSeparator", " | "));
                    item.add(new LinkPanel("extraLink", null, getString("gb.docs"), DocsPage.class,
                            WicketUtils.newRepositoryParameter(repositoryName)));
                } else if (extra.equals("edit")) {
                    item.add(new Label("extraSeparator", " | "));
                    item.add(new LinkPanel("extraLink", null, getString("gb.edit"),
                            EditRepositoryPage.class, WicketUtils
                                    .newRepositoryParameter(repositoryName)));
                }
                PageRegistration pageReg = registeredPages.get(extra);
                item.add(new Label("extraSeparator", " | "));
                item.add(new LinkPanel("extraLink", null, getString(pageReg.translationKey),
                        pageReg.pageClass, WicketUtils.newRepositoryParameter(repositoryName))
                        .setEnabled(!extra.equals(pageWicketId)));
            }
        };
        add(extrasView);
@@ -163,7 +144,7 @@
                .getRelativePathPrefixToContextRoot(), repositoryName, null, 0)));
        // disable current page
        disablePageLink(getPageName());
        disableRegisteredPageLink(pageName);
        // add floating search form
        SearchForm searchForm = new SearchForm("searchForm", repositoryName);
@@ -174,18 +155,31 @@
        setStatelessHint(true);
    }
    public void disablePageLink(String pageName) {
        for (String wicketId : knownPages.keySet()) {
            String key = knownPages.get(wicketId);
    public String getLinkWicketId(String pageName) {
        for (String wicketId : registeredPages.keySet()) {
            String key = registeredPages.get(wicketId).translationKey;
            String linkName = getString(key);
            if (linkName.equals(pageName)) {
                Component c = get(wicketId);
                if (c != null) {
                    c.setEnabled(false);
                }
                break;
                return wicketId;
            }
        }
        return null;
    }
    public void disableRegisteredPageLink(String pageName) {
        String wicketId = getLinkWicketId(pageName);
        if (!StringUtils.isEmpty(wicketId)) {
            Component c = get(wicketId);
            if (c != null) {
                c.setEnabled(false);
            }
        }
    }
    private void addRegisteredPageLink(String key) {
        PageRegistration pageReg = registeredPages.get(key);
        add(new BookmarkablePageLink<Void>(key, pageReg.pageClass,
                WicketUtils.newRepositoryParameter(repositoryName)));
    }
    protected void addSyndicationDiscoveryLink() {
@@ -339,6 +333,16 @@
        return WicketUtils.newPathParameter(repositoryName, objectId, path);
    }
    private static class PageRegistration {
        final String translationKey;
        final Class<? extends BasePage> pageClass;
        PageRegistration(String translationKey, Class<? extends BasePage> pageClass) {
            this.translationKey = translationKey;
            this.pageClass = pageClass;
        }
    }
    private static class SearchForm extends StatelessForm<Void> {
        private static final long serialVersionUID = 1L;
src/com/gitblit/wicket/pages/SummaryPage.html
@@ -5,9 +5,7 @@
      lang="en"> 
<wicket:head>
  <wicket:link>
       <link href="/com/gitblit/wicket/resources/markdown.css" type="text/css" rel="stylesheet" />
  </wicket:link>
      <link href="markdown.css" type="text/css" rel="stylesheet" />
</wicket:head>
<body>
src/com/gitblit/wicket/pages/SummaryPage.java
@@ -122,7 +122,7 @@
            }
            StringBuilder sb = new StringBuilder();
            sb.append(WicketUtils.getHostURL(getRequestCycle().getRequest()));                    
            sb.append(Constants.GIT_SERVLET_PATH);
            sb.append(Constants.GIT_PATH);
            sb.append(repositoryName);
            repositoryUrls.add(sb.toString());
        } else {
src/com/gitblit/wicket/panels/RepositoriesPanel.html
@@ -21,9 +21,7 @@
    <wicket:fragment wicket:id="adminLinks">
        <!-- page nav links -->    
        <div class="admin_nav">
            <wicket:link>
                   <img style="vertical-align: top;" src="/com/gitblit/wicket/resources/add_16x16.png"/>
              </wicket:link>
            <img style="vertical-align: top;" src="add_16x16.png"/>
            <a wicket:id="newRepository">
                <wicket:message key="gb.newRepository"></wicket:message>
            </a>
@@ -41,9 +39,7 @@
    <wicket:fragment wicket:id="flatRepositoryHeader">
        <tr>
            <th class="left" wicket:id="orderByRepository">
                <wicket:link>
                       <img style="vertical-align: top; border: 1px solid #888;" src="/com/gitblit/wicket/resources/gitweb-favicon.png"/>
                  </wicket:link>
                <img style="vertical-align: top; border: 1px solid #888;" src="gitweb-favicon.png"/>
                <wicket:message key="gb.repository">Repository</wicket:message>
            </th>
            <th wicket:id="orderByDescription"><wicket:message key="gb.description">Description</wicket:message></th>
@@ -57,9 +53,7 @@
    <wicket:fragment wicket:id="groupRepositoryHeader">
        <tr>
            <th class="left">
                <wicket:link>
                       <img style="vertical-align: top; border: 1px solid #888;" src="/com/gitblit/wicket/resources/gitweb-favicon.png"/>
                  </wicket:link>
                <img style="vertical-align: top; border: 1px solid #888;" src="gitweb-favicon.png"/>
                <wicket:message key="gb.repository">Repository</wicket:message>
            </th>
            <th><wicket:message key="gb.description">Description</wicket:message></th>
@@ -83,7 +77,7 @@
        <td class="rightAlign">
            <span wicket:id="repositoryLinks"></span>
            <a style="text-decoration: none;" wicket:id="syndication">
                <img style="border:0px;vertical-align:middle;" src="/com/gitblit/wicket/resources/feed_16x16.png"></img>
                <img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img>
            </a>
        </td>                
    </wicket:fragment>
src/com/gitblit/wicket/panels/SearchPanel.html
@@ -8,8 +8,10 @@
<wicket:panel>
    <!-- header -->    
    <div class="header" wicket:id="header">[search header]</div>
    <div wicket:id="commitHeader">[search header]</div>
    <!-- header -->
    <div style="margin-top:10px;font-weight:bold;" class="header"><wicket:message key="gb.search"></wicket:message>: <span wicket:id="searchString">[search string]</span> (<span wicket:id="searchType">[search type]</span>)</div>
    <table class="pretty">
        <tbody>
               <tr wicket:id="commit">
src/com/gitblit/wicket/panels/SearchPanel.java
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
@@ -72,9 +73,10 @@
        hasMore = commits.size() >= itemsPerPage;
        // header
        add(new LinkPanel("header", "title", commit == null ? "" : commit.getShortMessage(),
                CommitPage.class, WicketUtils.newObjectParameter(repositoryName,
                        commit == null ? "" : commit.getName())));
        add(new CommitHeaderPanel("commitHeader", repositoryName, commit));
        add(new Label("searchString", value));
        add(new Label("searchType", searchType.toString()));
        ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
        DataView<RevCommit> searchView = new DataView<RevCommit>("commit", dp) {
src/com/gitblit/wicket/panels/UsersPanel.html
@@ -12,9 +12,7 @@
        <table class="repositories">
        <tr>
            <th class="left">
                <wicket:link>
                       <img style="vertical-align: top; border: 1px solid #888; background-color: white;" src="/com/gitblit/wicket/resources/user_16x16.png"/>
                  </wicket:link>
                <img style="vertical-align: top; border: 1px solid #888; background-color: white;" src="user_16x16.png"/>
                <wicket:message key="gb.username">[username]</wicket:message>
            </th>
            <th class="right"></th>
@@ -30,9 +28,7 @@
    <wicket:fragment wicket:id="adminLinks">
        <!-- page nav links -->    
        <div class="admin_nav">
            <wicket:link>
                   <img style="vertical-align: top;" src="/com/gitblit/wicket/resources/add_16x16.png"/>
              </wicket:link>
            <img style="vertical-align: top;" src="add_16x16.png"/>
            <a wicket:id="newUser">
                <wicket:message key="gb.newUser"></wicket:message>
            </a>
src/com/gitblit/wicket/resources/gitblt-favicon.png
Binary files differ
src/log4j.properties
@@ -1,12 +1,66 @@
log4j.debug=false
#------------------------------------------------------------------------------
#
#  The following properties set the logging levels and log appender.  The
#  log4j.rootCategory variable defines the default log level and one or more
#  appenders.  For the console, use 'S'.  For the daily rolling file, use 'R'.
#  For an HTML formatted log, use 'H'.
#
#  To override the default (rootCategory) log level, define a property of the
#  form (see below for available values):
#
#        log4j.logger. =
#
#    Available logger names:
#      TODO
#
#    Possible Log Levels:
#      FATAL, ERROR, WARN, INFO, DEBUG
#
#------------------------------------------------------------------------------
log4j.rootCategory=INFO, S
log4j.rootLogger=INFO
log4j.logger.org=INFO
log4j.logger.com=INFO
log4j.logger.net=INFO
#log4j.rootLogger=INFO
#log4j.logger.org=INFO
#log4j.logger.com=INFO
#log4j.logger.net=INFO
log4j.logger.com.gitblit=DEBUG
#log4j.logger.com.gitblit=DEBUG
log4j.logger.org.apache.wicket=INFO
log4j.logger.org.apache.wicket.RequestListenerInterface=WARN
log4j.logger.org.apache.wicket.protocol.http.HttpSessionStore=WARN
#------------------------------------------------------------------------------
#
#  The following properties configure the console (stdout) appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.S = org.apache.log4j.ConsoleAppender
log4j.appender.S.layout = org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern = %-5p %m%n
#------------------------------------------------------------------------------
#
#  The following properties configure the Daily Rolling File appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File = logs/gitblit.log
log4j.appender.R.Append = true
log4j.appender.R.DatePattern = '.'yyy-MM-dd
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
#------------------------------------------------------------------------------
#
#  The following properties configure the Rolling File appender in HTML.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.H = org.apache.log4j.RollingFileAppender
log4j.appender.H.File = logs/gitblit.html
log4j.appender.H.MaxFileSize = 100KB
log4j.appender.H.Append = false
log4j.appender.H.layout = org.apache.log4j.HTMLLayout