James Moger
2011-06-09 f339f5de2ee6d354f55e14e9340bebc4611535b3
Unit testing. Documentation. Simplified settings classes.
14 files modified
545 ■■■■■ changed files
docs/00_index.mkd 23 ●●●● patch | view | raw | blame | history
src/com/gitblit/FileSettings.java 126 ●●●●● patch | view | raw | blame | history
src/com/gitblit/GitBlit.java 14 ●●●● patch | view | raw | blame | history
src/com/gitblit/IStoredSettings.java 81 ●●●● patch | view | raw | blame | history
src/com/gitblit/WebXmlSettings.java 64 ●●●● patch | view | raw | blame | history
src/com/gitblit/utils/DiffUtils.java 35 ●●●● patch | view | raw | blame | history
src/com/gitblit/utils/StringUtils.java 22 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/CommitPage.java 3 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.java 66 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/resources/gitblit.css 4 ●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/DiffUtilsTest.java 18 ●●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/GitBlitTest.java 78 ●●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/JGitUtilsTest.java 1 ●●●● patch | view | raw | blame | history
tests/com/gitblit/tests/StringUtilsTest.java 10 ●●●●● patch | view | raw | blame | history
docs/00_index.mkd
@@ -31,18 +31,17 @@
- Repository Owners may edit repositories through the web UI
- Automatically generates a self-signed certificate for https communications
- Git-notes support
- Branch metrics
- Branch metrics (uses Google Charts)
- Blame annotations view
- Dates can optionally be displayed using the browser's reported timezone
- Author and Committer email address display can be controlled
- Search commit messages, authors, and committers
- Display of Author and Committer email addresses can be disabled
- Case-insensitive searching of commit messages, authors, or committers
- Dynamic zip downloads feature
- Markdown view support
- Syntax highlighting
- Customizable regular expression handling for commit messages
- 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
- Simple repository stats and activity graph (uses Google Charts)
- Optional utility pages
    <ul class='noBullets'>
    <li>![docs](book_16x16.png) Docs page which enumerates all Markdown files within a repository</li>
@@ -50,24 +49,23 @@
    </ul>
### Limitations
- [%JGIT%][jgit] does not [garbage collect or repack](http://www.kernel.org/pub/software/scm/git/docs/git-gc.html)
- [%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
- I don't know everything there is to know about [Git][git] nor [JGit][jgit].
- Gitblit may eat your data.  Use at your own risk.
- Gitblit may have security holes.  Patches welcome.  :)
### Todo List
- Code documentation
- Unit testing
- Finish Blame (waiting for JGit 1.0.0 release)
- Clone remote repository
- Update Build.java to JGit 1.0.0, when its released
### Idea List
- Consider clone remote repository feature
- Consider [Apache Shiro](http://shiro.apache.org) for authentication
- Stronger Ticgit read-only integration
    - activity/timeline
@@ -88,7 +86,7 @@
## Architecture
![block diagram](architecture.png "Git Blit Architecture")
![block diagram](architecture.png "Gitblit Architecture")
### Bundled Dependencies
The following dependencies are bundled with the Gitblit zip distribution file.
@@ -116,6 +114,7 @@
### Other Build Dependencies
- [Fancybox image viewer](http://fancybox.net) (MIT and GPL dual-licensed)
- [JUnit](http://junit.org) (Common Public License)
- [commons-net](http://commons.apache.org/net) (Apache 2.0)
## Building from Source
[Eclipse](http://eclipse.org) is recommended for development as the project settings are preconfigured.
src/com/gitblit/FileSettings.java
@@ -18,144 +18,42 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.PatternSyntaxException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * Reads GitBlit settings file.
 * 
 */
public class FileSettings implements IStoredSettings {
    private final Logger logger = LoggerFactory.getLogger(FileSettings.class);
public class FileSettings extends IStoredSettings {
    private final File propertiesFile;
    private Properties properties = new Properties();
    private final Properties properties = new Properties();
    private long lastread;
    private volatile long lastread;
    public FileSettings(String file) {
        super(FileSettings.class);
        this.propertiesFile = new File(file);
    }
    @Override
    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().toLowerCase();
            if (key.startsWith(startingWith)) {
                keys.add(key);
            }
        }
        return keys;
    }
    @Override
    public boolean getBoolean(String name, boolean defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
                String value = props.getProperty(name);
                if (value != null && value.trim().length() > 0) {
                    return Boolean.parseBoolean(value);
                }
            } catch (Exception e) {
                logger.warn("No override setting for " + name + " using default of " + defaultValue);
            }
        }
        return defaultValue;
    }
    @Override
    public int getInteger(String name, int defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
                String value = props.getProperty(name);
                if (value != null && value.trim().length() > 0) {
                    return Integer.parseInt(value);
                }
            } catch (Exception e) {
                logger.warn("No override setting for " + name + " using default of " + defaultValue);
            }
        }
        return defaultValue;
    }
    @Override
    public String getString(String name, String defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
                String value = props.getProperty(name);
                if (value != null) {
                    return value;
                }
            } catch (Exception e) {
                logger.warn("No override setting for " + name + " using default of " + defaultValue);
            }
        }
        return defaultValue;
    }
    @Override
    public List<String> getStrings(String name) {
        return getStrings(name, " ");
    }
    @Override
    public List<String> getStringsFromValue(String value) {
        return getStringsFromValue(value, " ");
    }
    @Override
    public List<String> getStrings(String name, String separator) {
        List<String> strings = new ArrayList<String>();
        Properties props = read();
        if (props.containsKey(name)) {
            String value = props.getProperty(name);
            strings = getStringsFromValue(value, separator);
        }
        return strings;
    }
    @Override
    public List<String> getStringsFromValue(String value, String separator) {
        List<String> strings = new ArrayList<String>();
        try {
            String[] chunks = value.split(separator);
            for (String chunk : chunks) {
                chunk = chunk.trim();
                if (chunk.length() > 0) {
                    strings.add(chunk);
                }
            }
        } catch (PatternSyntaxException e) {
            logger.error("Failed to parse " + value, e);
        }
        return strings;
    }
    private synchronized Properties read() {
    protected synchronized Properties read() {
        if (propertiesFile.exists() && (propertiesFile.lastModified() > lastread)) {
            FileInputStream is = null;
            try {
                properties = new Properties();
                Properties props = new Properties();
                is = new FileInputStream(propertiesFile);
                properties.load(is);
                props.load(is);
                // load properties after we have successfully read file
                properties.clear();
                properties.putAll(props);
                lastread = propertiesFile.lastModified();
            } catch (FileNotFoundException f) {
                // IGNORE - won't happen because file.exists() check above
            } catch (Throwable t) {
                t.printStackTrace();
                logger.error("Failed to read " + propertiesFile.getName(), t);
            } finally {
                if (is != null) {
                    try {
src/com/gitblit/GitBlit.java
@@ -312,17 +312,6 @@
        return false;
    }
    public boolean renameRepository(RepositoryModel model, String newName) {
        File folder = new File(repositoriesFolder, model.name);
        if (folder.exists() && folder.isDirectory()) {
            File newFolder = new File(repositoriesFolder, newName);
            if (folder.renameTo(newFolder)) {
                return loginService.renameRole(model.name, newName);
            }
        }
        return false;
    }
    public void configureContext(IStoredSettings settings) {
        logger.info("Reading configuration from " + settings.toString());
        this.storedSettings = settings;
@@ -334,6 +323,7 @@
    @Override
    public void contextInitialized(ServletContextEvent contextEvent) {
        if (storedSettings == null) {
            // for running gitblit as a traditional webapp in a servlet container
            WebXmlSettings webxmlSettings = new WebXmlSettings(contextEvent.getServletContext());
            configureContext(webxmlSettings);
        }
@@ -341,6 +331,6 @@
    @Override
    public void contextDestroyed(ServletContextEvent contextEvent) {
        logger.info("GitBlit context destroyed by servlet container.");
        logger.info("Gitblit context destroyed by servlet container.");
    }
}
src/com/gitblit/IStoredSettings.java
@@ -15,24 +15,87 @@
 */
package com.gitblit;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public interface IStoredSettings {
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
    List<String> getAllKeys(String startingWith);
import com.gitblit.utils.StringUtils;
    boolean getBoolean(String name, boolean defaultValue);
public abstract class IStoredSettings {
    int getInteger(String name, int defaultValue);
    protected final Logger logger;
    public IStoredSettings(Class<? extends IStoredSettings> clazz) {
        logger = LoggerFactory.getLogger(clazz);
    }
    protected abstract Properties read();
    String getString(String name, String defaultValue);
    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);
            }
        }
        return keys;
    }
    List<String> getStrings(String name);
    public boolean getBoolean(String name, boolean defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            String value = props.getProperty(name);
            if (!StringUtils.isEmpty(value)) {
                return Boolean.parseBoolean(value);
            }
        }
        return defaultValue;
    }
    List<String> getStringsFromValue(String value);
    public int getInteger(String name, int defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            try {
                String value = props.getProperty(name);
                if (!StringUtils.isEmpty(value)) {
                    return Integer.parseInt(value);
                }
            } catch (NumberFormatException e) {
                logger.warn("Failed to parse integer for " + name + " using default of "
                        + defaultValue);
            }
        }
        return defaultValue;
    }
    List<String> getStrings(String name, String separator);
    public String getString(String name, String defaultValue) {
        Properties props = read();
        if (props.containsKey(name)) {
            String value = props.getProperty(name);
            if (value != null) {
                return value;
            }
        }
        return defaultValue;
    }
    List<String> getStringsFromValue(String value, String separator);
    public List<String> getStrings(String name) {
        return getStrings(name, " ");
    }
    public List<String> getStrings(String name, String separator) {
        List<String> strings = new ArrayList<String>();
        Properties props = read();
        if (props.containsKey(name)) {
            String value = props.getProperty(name);
            strings = StringUtils.getStringsFromValue(value, separator);
        }
        return strings;
    }
}
src/com/gitblit/WebXmlSettings.java
@@ -15,62 +15,28 @@
 */
package com.gitblit;
import java.util.List;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletContext;
public class WebXmlSettings implements IStoredSettings {
public class WebXmlSettings extends IStoredSettings {
    private final Properties properties = new Properties();
    public WebXmlSettings(ServletContext context) {
        super(WebXmlSettings.class);
        Enumeration<?> keys = context.getInitParameterNames();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement().toString();
            String value = context.getInitParameter(key);
            properties.put(key, value);
        }
    }
    @Override
    public List<String> getAllKeys(String startingWith) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public boolean getBoolean(String name, boolean defaultValue) {
        // TODO Auto-generated method stub
        return false;
    }
    @Override
    public int getInteger(String name, int defaultValue) {
        // TODO Auto-generated method stub
        return 0;
    }
    @Override
    public String getString(String name, String defaultValue) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStrings(String name) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStringsFromValue(String value) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStrings(String name, String separator) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public List<String> getStringsFromValue(String value, String separator) {
        // TODO Auto-generated method stub
        return null;
    protected Properties read() {
        return properties;
    }
    @Override
src/com/gitblit/utils/DiffUtils.java
@@ -25,6 +25,7 @@
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
@@ -69,6 +70,7 @@
    public static String getDiff(Repository r, RevCommit baseCommit, RevCommit commit, String path,
            DiffOutputType outputType) {
        String diff = null;
        try {
            RevTree baseTree;
            if (baseCommit == null) {
@@ -107,18 +109,17 @@
            df.setRepository(r);
            df.setDiffComparator(cmp);
            df.setDetectRenames(true);
            List<DiffEntry> diffs = df.scan(baseTree, commitTree);
            List<DiffEntry> diffEntries = df.scan(baseTree, commitTree);
            if (path != null && path.length() > 0) {
                for (DiffEntry diff : diffs) {
                    if (diff.getNewPath().equalsIgnoreCase(path)) {
                        df.format(diff);
                for (DiffEntry diffEntry : diffEntries) {
                    if (diffEntry.getNewPath().equalsIgnoreCase(path)) {
                        df.format(diffEntry);
                        break;
                    }
                }
            } else {
                df.format(diffs);
                df.format(diffEntries);
            }
            String diff;
            if (df instanceof GitWebDiffFormatter) {
                // workaround for complex private methods in DiffFormatter
                diff = ((GitWebDiffFormatter) df).getHtml();
@@ -126,15 +127,15 @@
                diff = os.toString();
            }
            df.flush();
            return diff;
        } catch (Throwable t) {
            LOGGER.error("failed to generate commit diff!", t);
        }
        return null;
        return diff;
    }
    public static String getCommitPatch(Repository r, RevCommit baseCommit, RevCommit commit,
            String path) {
        String diff = null;
        try {
            RevTree baseTree;
            if (baseCommit == null) {
@@ -159,29 +160,31 @@
            df.setRepository(r);
            df.setDiffComparator(cmp);
            df.setDetectRenames(true);
            List<DiffEntry> diffs = df.scan(baseTree, commitTree);
            List<DiffEntry> diffEntries = df.scan(baseTree, commitTree);
            if (path != null && path.length() > 0) {
                for (DiffEntry diff : diffs) {
                    if (diff.getNewPath().equalsIgnoreCase(path)) {
                        df.format(diff);
                for (DiffEntry diffEntry : diffEntries) {
                    if (diffEntry.getNewPath().equalsIgnoreCase(path)) {
                        df.format(diffEntry);
                        break;
                    }
                }
            } else {
                df.format(diffs);
                df.format(diffEntries);
            }
            String diff = df.getPatch(commit);
            diff = df.getPatch(commit);
            df.flush();
            return diff;
        } catch (Throwable t) {
            LOGGER.error("failed to generate commit diff!", t);
        }
        return null;
        return diff;
    }
    public static List<AnnotatedLine> blame(Repository r, String blobPath, String objectId) {
        List<AnnotatedLine> lines = new ArrayList<AnnotatedLine>();
        try {
            if (StringUtils.isEmpty(objectId)) {
                objectId = Constants.HEAD;
            }
            BlameCommand blameCommand = new BlameCommand(r);
            blameCommand.setFilePath(blobPath);
            blameCommand.setStartCommit(r.resolve(objectId));
src/com/gitblit/utils/StringUtils.java
@@ -18,7 +18,9 @@
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.PatternSyntaxException;
public class StringUtils {
@@ -142,4 +144,24 @@
        }
        return relativePath;
    }
    public static List<String> getStringsFromValue(String value) {
        return getStringsFromValue(value, " ");
    }
    public static List<String> getStringsFromValue(String value, String separator) {
        List<String> strings = new ArrayList<String>();
        try {
            String[] chunks = value.split(separator);
            for (String chunk : chunks) {
                chunk = chunk.trim();
                if (chunk.length() > 0) {
                    strings.add(chunk);
                }
            }
        } catch (PatternSyntaxException e) {
            throw new RuntimeException(e);
        }
        return strings;
    }
}
src/com/gitblit/wicket/pages/CommitPage.java
@@ -38,7 +38,6 @@
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.JGitUtils.SearchType;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.CommitHeaderPanel;
import com.gitblit.wicket.panels.CommitLegendPanel;
@@ -129,7 +128,7 @@
                        SearchType.AUTHOR));
                item.add(WicketUtils.createTimestampLabel("authorDate", entry.notesRef
                        .getAuthorIdent().getWhen(), getTimeZone()));
                item.add(new Label("noteContent", StringUtils.breakLinesForHtml(entry.content))
                item.add(new Label("noteContent", substituteText(entry.content))
                        .setEscapeModelStrings(false));
            }
        };
src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -227,40 +227,48 @@
    }
    protected void addFullText(String wicketId, String text, boolean substituteRegex) {
        String html = StringUtils.breakLinesForHtml(text);
        String html;
        if (substituteRegex) {
            Map<String, String> map = new HashMap<String, String>();
            // global regex keys
            if (GitBlit.getBoolean(Keys.regex.global, false)) {
                for (String key : GitBlit.getAllKeys(Keys.regex.global)) {
                    if (!key.equals(Keys.regex.global)) {
                        String subKey = key.substring(key.lastIndexOf('.') + 1);
                        map.put(subKey, GitBlit.getString(key, ""));
                    }
                }
            }
            html = substituteText(text);
        } else {
            html = StringUtils.breakLinesForHtml(text);
        }
        add(new Label(wicketId, html).setEscapeModelStrings(false));
    }
            // repository-specific regex keys
            List<String> keys = GitBlit.getAllKeys(Keys.regex._ROOT + "."
                    + repositoryName.toLowerCase());
            for (String key : keys) {
                String subKey = key.substring(key.lastIndexOf('.') + 1);
                map.put(subKey, GitBlit.getString(key, ""));
            }
            for (Entry<String, String> entry : map.entrySet()) {
                String definition = entry.getValue().trim();
                String[] chunks = definition.split("!!!");
                if (chunks.length == 2) {
                    html = html.replaceAll(chunks[0], chunks[1]);
                } else {
                    logger.warn(entry.getKey()
                            + " improperly formatted.  Use !!! to separate match from replacement: "
                            + definition);
    protected String substituteText(String text) {
        String html = StringUtils.breakLinesForHtml(text);
        Map<String, String> map = new HashMap<String, String>();
        // global regex keys
        if (GitBlit.getBoolean(Keys.regex.global, false)) {
            for (String key : GitBlit.getAllKeys(Keys.regex.global)) {
                if (!key.equals(Keys.regex.global)) {
                    String subKey = key.substring(key.lastIndexOf('.') + 1);
                    map.put(subKey, GitBlit.getString(key, ""));
                }
            }
        }
        add(new Label(wicketId, html).setEscapeModelStrings(false));
        // repository-specific regex keys
        List<String> keys = GitBlit.getAllKeys(Keys.regex._ROOT + "."
                + repositoryName.toLowerCase());
        for (String key : keys) {
            String subKey = key.substring(key.lastIndexOf('.') + 1);
            map.put(subKey, GitBlit.getString(key, ""));
        }
        for (Entry<String, String> entry : map.entrySet()) {
            String definition = entry.getValue().trim();
            String[] chunks = definition.split("!!!");
            if (chunks.length == 2) {
                html = html.replaceAll(chunks[0], chunks[1]);
            } else {
                logger.warn(entry.getKey()
                        + " improperly formatted.  Use !!! to separate match from replacement: "
                        + definition);
            }
        }
        return html;
    }
    protected abstract String getPageName();
src/com/gitblit/wicket/resources/gitblit.css
@@ -249,6 +249,10 @@
    border-width: 1px 0px 0px;
}
div.commit_message a {
    font-family: monospace;
}
div.bug_open, span.bug_open {
    padding: 2px;
    background-color: #803333;
tests/com/gitblit/tests/DiffUtilsTest.java
@@ -15,17 +15,27 @@
 */
package com.gitblit.tests;
import java.util.List;
import junit.framework.TestCase;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.models.AnnotatedLine;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.DiffUtils.DiffOutputType;
import com.gitblit.utils.JGitUtils;
public class DiffUtilsTest extends TestCase {
    public void testDiffOutputTypes() throws Exception {
        assertTrue(DiffOutputType.forName("plain").equals(DiffOutputType.PLAIN));
        assertTrue(DiffOutputType.forName("gitweb").equals(DiffOutputType.GITWEB));
        assertTrue(DiffOutputType.forName("gitblit").equals(DiffOutputType.GITBLIT));
        assertTrue(DiffOutputType.forName(null) == null);
    }
    public void testParentCommitDiff() throws Exception {
        Repository repository = GitBlitSuite.getHelloworldRepository();
        RevCommit commit = JGitUtils.getCommit(repository,
@@ -97,4 +107,12 @@
        String expected = "-        system.out.println(\"Hello World\");\n+        System.out.println(\"Hello World\"";
        assertTrue(patch.indexOf(expected) > -1);
    }
    public void testBlame() throws Exception {
        Repository repository = GitBlitSuite.getHelloworldRepository();
        List<AnnotatedLine> lines = DiffUtils.blame(repository, "java.java", "1d0c2933a4ae69c362f76797d42d6bd182d05176");
        repository.close();
        assertTrue(lines.size() > 0);
        assertTrue(lines.get(0).commitId.equals("c6d31dccf5cc75e8e46299fc62d38f60ec6d41e0"));
    }
}
tests/com/gitblit/tests/GitBlitTest.java
@@ -19,6 +19,8 @@
import junit.framework.TestCase;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.FileSettings;
import com.gitblit.GitBlit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -47,10 +49,84 @@
        assertTrue(model.toString().equals("admin"));
        assertTrue("Admin missing #admin role!", model.canAdmin);
        model.canAdmin = false;
        assertFalse("Admin should not hae #admin!", model.canAdmin);
        assertFalse("Admin should not have #admin!", model.canAdmin);
        String repository = GitBlitSuite.getHelloworldRepository().getDirectory().getName();
        assertFalse("Admin can still access repository!", model.canAccessRepository(repository));
        model.addRepository(repository);
        assertTrue("Admin can't access repository!", model.canAccessRepository(repository));
    }
    public void testAccessRestrictionTypes() throws Exception {
        assertTrue(AccessRestrictionType.PUSH.exceeds(AccessRestrictionType.NONE));
        assertTrue(AccessRestrictionType.CLONE.exceeds(AccessRestrictionType.PUSH));
        assertTrue(AccessRestrictionType.VIEW.exceeds(AccessRestrictionType.CLONE));
        assertFalse(AccessRestrictionType.NONE.exceeds(AccessRestrictionType.PUSH));
        assertFalse(AccessRestrictionType.PUSH.exceeds(AccessRestrictionType.CLONE));
        assertFalse(AccessRestrictionType.CLONE.exceeds(AccessRestrictionType.VIEW));
        assertTrue(AccessRestrictionType.PUSH.atLeast(AccessRestrictionType.NONE));
        assertTrue(AccessRestrictionType.CLONE.atLeast(AccessRestrictionType.PUSH));
        assertTrue(AccessRestrictionType.VIEW.atLeast(AccessRestrictionType.CLONE));
        assertFalse(AccessRestrictionType.NONE.atLeast(AccessRestrictionType.PUSH));
        assertFalse(AccessRestrictionType.PUSH.atLeast(AccessRestrictionType.CLONE));
        assertFalse(AccessRestrictionType.CLONE.atLeast(AccessRestrictionType.VIEW));
        assertTrue(AccessRestrictionType.PUSH.toString().equals("PUSH"));
        assertTrue(AccessRestrictionType.CLONE.toString().equals("CLONE"));
        assertTrue(AccessRestrictionType.VIEW.toString().equals("VIEW"));
        assertTrue(AccessRestrictionType.fromName("none").equals(AccessRestrictionType.NONE));
        assertTrue(AccessRestrictionType.fromName("push").equals(AccessRestrictionType.PUSH));
        assertTrue(AccessRestrictionType.fromName("clone").equals(AccessRestrictionType.CLONE));
        assertTrue(AccessRestrictionType.fromName("view").equals(AccessRestrictionType.VIEW));
    }
    public void testFileSettings() throws Exception {
        FileSettings settings = new FileSettings("distrib/gitblit.properties");
        assertTrue(settings.getBoolean("missing", true) == true);
        assertTrue(settings.getString("missing", "default").equals("default"));
        assertTrue(settings.getInteger("missing", 10) == 10);
        assertTrue(settings.getInteger("realm.realmFile", 5) == 5);
        assertTrue(settings.getBoolean("git.enableGitServlet", false) == true);
        assertTrue(settings.getString("realm.realmFile", null).equals("users.properties"));
        assertTrue(settings.getInteger("realm.minPasswordLength", 0) == 5);
        List<String> mdExtensions = settings.getStrings("web.markdownExtensions");
        assertTrue(mdExtensions.size() > 0);
        assertTrue(mdExtensions.contains("md"));
        List<String> keys = settings.getAllKeys("server");
        assertTrue(keys.size() > 0);
        assertTrue(keys.contains("server.httpsPort"));
    }
    public void testGitblitSettings() throws Exception {
        // These are already tested by above test method.
        assertTrue(GitBlit.getBoolean("missing", true) == true);
        assertTrue(GitBlit.getString("missing", "default").equals("default"));
        assertTrue(GitBlit.getInteger("missing", 10) == 10);
        assertTrue(GitBlit.getInteger("realm.realmFile", 5) == 5);
        assertTrue(GitBlit.getBoolean("git.enableGitServlet", false) == true);
        assertTrue(GitBlit.getString("realm.realmFile", null).equals("users.properties"));
        assertTrue(GitBlit.getInteger("realm.minPasswordLength", 0) == 5);
        List<String> mdExtensions = GitBlit.getStrings("web.markdownExtensions");
        assertTrue(mdExtensions.size() > 0);
        assertTrue(mdExtensions.contains("md"));
        List<String> keys = GitBlit.getAllKeys("server");
        assertTrue(keys.size() > 0);
        assertTrue(keys.contains("server.httpsPort"));
    }
    public void testAuthentication() throws Exception  {
        assertTrue(GitBlit.self().authenticate("admin", "admin".toCharArray()) != null);
    }
    public void testRepositories() throws Exception  {
        assertTrue(GitBlit.self().getRepository("missing") == null);
        assertTrue(GitBlit.self().getRepositoryModel("missing") == null);
    }
}
tests/com/gitblit/tests/JGitUtilsTest.java
@@ -122,6 +122,7 @@
            List<RefModel> list = entry.getValue();
            for (RefModel ref : list) {
                if (ref.displayName.equals("refs/tags/spearce-gpg-pub")) {
                    assertTrue(ref.toString().equals("refs/tags/spearce-gpg-pub"));
                    assertTrue(ref.getObjectId().getName()
                            .equals("8bbde7aacf771a9afb6992434f1ae413e010c6d8"));
                    assertTrue(ref.getAuthorIdent().getEmailAddress().equals("spearce@spearce.org"));
tests/com/gitblit/tests/StringUtilsTest.java
@@ -16,6 +16,7 @@
package com.gitblit.tests;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
@@ -76,4 +77,13 @@
        assertTrue(StringUtils.getRootPath(input).equals(output));
        assertTrue(StringUtils.getRootPath("repository").equals(""));
    }
    public void testStringsFromValue() throws Exception {
        List<String> strings = StringUtils.getStringsFromValue("A B C D");
        assertTrue(strings.size() == 4);
        assertTrue(strings.get(0).equals("A"));
        assertTrue(strings.get(1).equals("B"));
        assertTrue(strings.get(2).equals("C"));
        assertTrue(strings.get(3).equals("D"));
    }
}