From bc9d4a0f2266e5ac1a018f0b691c76d53479b9e5 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 29 Apr 2011 20:46:44 -0400
Subject: [PATCH] Working on error handling.

---
 src/com/gitblit/wicket/pages/RepositoriesPage.java   |   26 +++-
 src/com/gitblit/wicket/pages/PatchPage.java          |   13 +
 src/com/gitblit/wicket/pages/BlobDiffPage.java       |    4 
 src/com/gitblit/GitBlit.java                         |    4 
 src/com/gitblit/wicket/GitBlitWebApp.properties      |    3 
 src/com/gitblit/wicket/pages/CommitPage.java         |    2 
 src/com/gitblit/wicket/pages/RepositoriesPage.html   |    3 
 src/com/gitblit/wicket/pages/CommitDiffPage.java     |    2 
 src/com/gitblit/wicket/pages/EditRepositoryPage.html |    7 
 src/com/gitblit/wicket/pages/BlobPage.java           |    2 
 src/com/gitblit/Constants.java                       |    2 
 src/com/gitblit/utils/JGitUtils.java                 |  133 +++++++++++++---------
 src/com/gitblit/wicket/LoginPage.html                |    4 
 src/com/gitblit/wicket/RepositoryPage.java           |   38 ++++--
 src/com/gitblit/wicket/pages/TreePage.java           |    2 
 src/com/gitblit/wicket/GitBlitWebSession.java        |   12 ++
 src/com/gitblit/wicket/models/RepositoryModel.java   |    1 
 src/com/gitblit/wicket/RepositoryPage.html           |    2 
 src/com/gitblit/wicket/BasePage.java                 |   25 +++
 src/com/gitblit/wicket/resources/gitblit.css         |   13 +
 src/com/gitblit/wicket/BasePage.html                 |    1 
 src/com/gitblit/wicket/panels/SearchPanel.java       |    2 
 src/com/gitblit/wicket/panels/CommitHeaderPanel.java |    8 
 src/com/gitblit/wicket/GitBlitWebApp.java            |    2 
 src/com/gitblit/wicket/pages/TagPage.java            |    2 
 25 files changed, 205 insertions(+), 108 deletions(-)

diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index d5fc1a4..4ad4663 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -19,7 +19,7 @@
 	}
 
 	public static String getJGitVersion() {
-		return "JGit 0.11.3";
+		return "JGit 0.12-stable";
 	}
 
 	public static String getRunningVersion() {
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index e557c93..32ee73c 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -105,8 +105,7 @@
 			r = repositoryResolver.open(null, repositoryName);
 		} catch (RepositoryNotFoundException e) {
 			r = null;
-			logger.error("Failed to find repository " + repositoryName);
-			e.printStackTrace();
+			logger.error("GitBlit.getRepository(String) failed to find repository " + repositoryName);
 		} catch (ServiceNotEnabledException e) {
 			r = null;
 			e.printStackTrace();
@@ -128,6 +127,7 @@
 		Repository r = getRepository(repositoryName);
 		RepositoryModel model = new RepositoryModel();
 		model.name = repositoryName;
+		model.hasCommits = JGitUtils.hasCommits(r);
 		model.lastChange = JGitUtils.getLastChange(r);
 		StoredConfig config = JGitUtils.readConfig(r);
 		if (config != null) {
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java
index 70a938f..71fa20e 100644
--- a/src/com/gitblit/utils/JGitUtils.java
+++ b/src/com/gitblit/utils/JGitUtils.java
@@ -70,7 +70,7 @@
 	public static final String R_NOTES_COMMITS = R_NOTES + "commits";
 
 	private final static Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
-	
+
 	public static Repository createRepository(File repositoriesFolder, String name, boolean bare) {
 		Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call();
 		return git.getRepository();
@@ -93,11 +93,11 @@
 				// first look for standard folder/.git structure
 				File gitFolder = new File(file, Constants.DOT_GIT);
 				boolean isGitRepository = gitFolder.exists() && gitFolder.isDirectory();
-				
-				// then look for folder.git/HEAD or folder/HEAD and folder/config
+
+				// then look for folder.git/HEAD or folder/HEAD and
+				// folder/config
 				if (!isGitRepository) {
-					if ((file.getName().endsWith(Constants.DOT_GIT_EXT) && new File(file, Constants.HEAD).exists())
-							|| (new File(file, "config").exists() && new File(file, Constants.HEAD).exists())) {
+					if ((file.getName().endsWith(Constants.DOT_GIT_EXT) && new File(file, Constants.HEAD).exists()) || (new File(file, "config").exists() && new File(file, Constants.HEAD).exists())) {
 						gitFolder = file;
 						isGitRepository = true;
 					}
@@ -124,6 +124,9 @@
 	}
 
 	public static RevCommit getFirstCommit(Repository r, String branch) {
+		if (!hasCommits(r)) {
+			return null;
+		}
 		if (StringUtils.isEmpty(branch)) {
 			branch = Constants.HEAD;
 		}
@@ -146,7 +149,7 @@
 			RevCommit commit = getFirstCommit(r, branch);
 			if (commit == null) {
 				// fresh repository
-				return new Date(r.getDirectory().lastModified());			
+				return new Date(r.getDirectory().lastModified());
 			}
 			return getCommitDate(commit);
 		} catch (Throwable t) {
@@ -155,17 +158,24 @@
 		return null;
 	}
 
-	public static Date getLastChange(Repository r) {		
-		RevCommit commit = getCommit(r, Constants.HEAD);
-		if (commit == null) {
+	public static boolean hasCommits(Repository r) {
+		return new File(r.getDirectory(), Constants.R_HEADS).list().length > 0;
+	}
+
+	public static Date getLastChange(Repository r) {
+		if (!hasCommits(r)) {
 			// fresh repository
-			return new Date(r.getDirectory().lastModified());			
+			return new Date(r.getDirectory().lastModified());
 		}
+		RevCommit commit = getCommit(r, Constants.HEAD);
 		return getCommitDate(commit);
 	}
 
 	public static RevCommit getCommit(Repository r, String objectId) {
 		RevCommit commit = null;
+		if (!hasCommits(r)) {
+			return null;
+		}
 		try {
 			if (objectId == null || objectId.trim().length() == 0) {
 				objectId = Constants.HEAD;
@@ -176,7 +186,7 @@
 			commit = rev;
 			walk.dispose();
 		} catch (Throwable t) {
-			LOGGER.error("Failed to determine last change", t);
+			LOGGER.error("Failed to get commit " + objectId, t);
 		}
 		return commit;
 	}
@@ -266,13 +276,13 @@
 	}
 
 	public static String getRawContentAsString(Repository r, RevBlob blob) {
-		byte [] content = getRawContent(r, blob);
+		byte[] content = getRawContent(r, blob);
 		return new String(content, Charset.forName(Constants.CHARACTER_ENCODING));
 	}
 
 	public static String getRawContentAsString(Repository r, RevCommit commit, String blobPath) {
 		RevObject obj = getRevObject(r, commit.getTree(), blobPath);
-		byte [] content = getRawContent(r, (RevBlob) obj);
+		byte[] content = getRawContent(r, (RevBlob) obj);
 		return new String(content, Charset.forName(Constants.CHARACTER_ENCODING));
 	}
 
@@ -328,6 +338,10 @@
 
 	public static List<PathChangeModel> getFilesInCommit(Repository r, RevCommit commit) {
 		List<PathChangeModel> list = new ArrayList<PathChangeModel>();
+		if (commit == null) {
+			LOGGER.warn("getFilesInCommit for NULL commit");
+			return list;
+		}
 		try {
 			final RevWalk rw = new RevWalk(r);
 			RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
@@ -359,16 +373,16 @@
 		}
 		return list;
 	}
-	
+
 	public static List<PathModel> getDocuments(Repository r, List<String> extensions) {
 		List<PathModel> list = new ArrayList<PathModel>();
-		RevCommit commit = getCommit(r, Constants.HEAD);		
+		RevCommit commit = getCommit(r, Constants.HEAD);
 		final TreeWalk walk = new TreeWalk(r);
 		try {
 			walk.addTree(commit.getTree());
 			if (extensions != null && extensions.size() > 0) {
 				Collection<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
-				for (String extension:extensions) {
+				for (String extension : extensions) {
 					if (extension.charAt(0) == '.') {
 						suffixFilters.add(PathSuffixFilter.create(extension));
 					} else {
@@ -606,6 +620,9 @@
 
 	public static List<RevCommit> getRevLog(Repository r, String objectId, String path, int offset, int maxCount) {
 		List<RevCommit> list = new ArrayList<RevCommit>();
+		if (!hasCommits(r)) {
+			return list;
+		}
 		try {
 			if (objectId == null || objectId.trim().length() == 0) {
 				objectId = Constants.HEAD;
@@ -664,6 +681,9 @@
 	public static List<RevCommit> searchRevlogs(Repository r, String objectId, String value, final SearchType type, int offset, int maxCount) {
 		final String lcValue = value.toLowerCase();
 		List<RevCommit> list = new ArrayList<RevCommit>();
+		if (!hasCommits(r)) {
+			return list;
+		}
 		try {
 			if (objectId == null || objectId.trim().length() == 0) {
 				objectId = Constants.HEAD;
@@ -792,50 +812,53 @@
 	}
 
 	public static List<Metric> getDateMetrics(Repository r) {
-		final List<RefModel> tags = getTags(r, -1);
-		final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
-		for (RefModel tag : tags) {
-			tagMap.put(tag.getCommitId(), tag);
-		}
 		Metric total = new Metric("TOTAL");
 		final Map<String, Metric> metricMap = new HashMap<String, Metric>();
-		try {
-			RevWalk walk = new RevWalk(r);
-			ObjectId object = r.resolve(Constants.HEAD);
-
-			RevCommit firstCommit = getFirstCommit(r, Constants.HEAD);
-			RevCommit lastCommit = walk.parseCommit(object);
-			int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime()) / (60 * 60 * 24);
-			total.duration = diffDays;
-			DateFormat df;
-			if (diffDays <= 90) {
-				// Days
-				df = new SimpleDateFormat("yyyy-MM-dd");
-			} else if (diffDays > 90 && diffDays < 365) {
-				// Weeks
-				df = new SimpleDateFormat("yyyy-MM (w)");
-			} else {
-				// Months
-				df = new SimpleDateFormat("yyyy-MM");
+		
+		if (hasCommits(r)) {
+			final List<RefModel> tags = getTags(r, -1);
+			final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
+			for (RefModel tag : tags) {
+				tagMap.put(tag.getCommitId(), tag);
 			}
-			walk.markStart(lastCommit);
+			try {
+				RevWalk walk = new RevWalk(r);
+				ObjectId object = r.resolve(Constants.HEAD);
 
-			Iterable<RevCommit> revlog = walk;
-			for (RevCommit rev : revlog) {
-				Date d = getCommitDate(rev);
-				String p = df.format(d);
-				if (!metricMap.containsKey(p))
-					metricMap.put(p, new Metric(p));
-				Metric m = metricMap.get(p);
-				m.count++;
-				total.count++;
-				if (tagMap.containsKey(rev.getId())) {
-					m.tag++;
-					total.tag++;
+				RevCommit firstCommit = getFirstCommit(r, Constants.HEAD);
+				RevCommit lastCommit = walk.parseCommit(object);
+				int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime()) / (60 * 60 * 24);
+				total.duration = diffDays;
+				DateFormat df;
+				if (diffDays <= 90) {
+					// Days
+					df = new SimpleDateFormat("yyyy-MM-dd");
+				} else if (diffDays > 90 && diffDays < 365) {
+					// Weeks
+					df = new SimpleDateFormat("yyyy-MM (w)");
+				} else {
+					// Months
+					df = new SimpleDateFormat("yyyy-MM");
 				}
+				walk.markStart(lastCommit);
+
+				Iterable<RevCommit> revlog = walk;
+				for (RevCommit rev : revlog) {
+					Date d = getCommitDate(rev);
+					String p = df.format(d);
+					if (!metricMap.containsKey(p))
+						metricMap.put(p, new Metric(p));
+					Metric m = metricMap.get(p);
+					m.count++;
+					total.count++;
+					if (tagMap.containsKey(rev.getId())) {
+						m.tag++;
+						total.tag++;
+					}
+				}
+			} catch (Throwable t) {
+				LOGGER.error("Failed to mine log history for metrics", t);
 			}
-		} catch (Throwable t) {
-			LOGGER.error("Failed to mine log history for metrics", t);
 		}
 		List<String> keys = new ArrayList<String>(metricMap.keySet());
 		Collections.sort(keys);
@@ -846,7 +869,7 @@
 		metrics.add(0, total);
 		return metrics;
 	}
-	
+
 	public static RefModel getTicketsBranch(Repository r) {
 		RefModel ticgitBranch = null;
 		try {
diff --git a/src/com/gitblit/wicket/BasePage.html b/src/com/gitblit/wicket/BasePage.html
index 69183b6..0ec9e18 100644
--- a/src/com/gitblit/wicket/BasePage.html
+++ b/src/com/gitblit/wicket/BasePage.html
@@ -24,7 +24,6 @@
 			<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>	
-			<span wicket:id="feedback">[Feedback Panel]</span>
 		</div>
 
 		<!-- page content -->
diff --git a/src/com/gitblit/wicket/BasePage.java b/src/com/gitblit/wicket/BasePage.java
index 8daab44..6125f2a 100644
--- a/src/com/gitblit/wicket/BasePage.java
+++ b/src/com/gitblit/wicket/BasePage.java
@@ -5,6 +5,7 @@
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.wicket.PageParameters;
+import org.apache.wicket.RestartResponseAtInterceptPageException;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.panel.FeedbackPanel;
@@ -50,14 +51,13 @@
 		add(new FeedbackPanel("feedback"));
 
 		// footer
-		if (GitBlit.self().settings().getBoolean(Keys.web.authenticateViewPages, true)
-				|| GitBlit.self().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
+		if (GitBlit.self().settings().getBoolean(Keys.web.authenticateViewPages, true) || GitBlit.self().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
 			if (GitBlitWebSession.get().isLoggedIn()) {
 				// logout
 				add(new LinkPanel("userPanel", null, getString("gb.logout") + " " + GitBlitWebSession.get().getUser().toString(), LogoutPage.class));
 			} else {
 				// login
-				add(new LinkPanel("userPanel", null, getString("gb.login"), LoginPage.class));				
+				add(new LinkPanel("userPanel", null, getString("gb.login"), LoginPage.class));
 			}
 		} else {
 			add(new Label("userPanel", ""));
@@ -78,8 +78,23 @@
 		return req.getServerName();
 	}
 
-	public void error(String message, Throwable t) {
-		super.error(message);
+	public void error(String message, boolean redirect) {
+		logger.error(message);
+		if (redirect) {
+			GitBlitWebSession.get().cacheErrorMessage(message);
+			throw new RestartResponseAtInterceptPageException(getApplication().getHomePage());
+		} else {
+			super.error(message);
+		}
+	}
+
+	public void error(String message, Throwable t, boolean redirect) {
 		logger.error(message, t);
+		if (redirect) {
+			GitBlitWebSession.get().cacheErrorMessage(message);
+			throw new RestartResponseAtInterceptPageException(getApplication().getHomePage());
+		} else {
+			super.error(message);
+		}
 	}
 }
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.java b/src/com/gitblit/wicket/GitBlitWebApp.java
index 7410dfa..87c97a5 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.java
+++ b/src/com/gitblit/wicket/GitBlitWebApp.java
@@ -63,7 +63,7 @@
 		mount(new MixedParamUrlCodingStrategy("/commitdiff", CommitDiffPage.class, new String[] { "r", "h" }));
 		mount(new MixedParamUrlCodingStrategy("/patch", PatchPage.class, new String[] { "r", "h", "f" }));
 		mount(new MixedParamUrlCodingStrategy("/history", HistoryPage.class, new String[] { "r", "h", "f" }));
-		mount(new MixedParamUrlCodingStrategy("/search", SearchPage.class, new String[] { "r", "h", "a", "c" }));
+		mount(new MixedParamUrlCodingStrategy("/search", SearchPage.class, new String[] { }));
 
 		// setup ticket urls
 		mount(new MixedParamUrlCodingStrategy("/tickets", TicketsPage.class, new String[] { "r" }));
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 367ae3d..17bbdec 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -75,4 +75,5 @@
 gb.group = group
 gb.description = description
 gb.enableTickets = enable tickets
-gb.enableDocs = enable docs
\ No newline at end of file
+gb.enableDocs = enable docs
+gb.save = save
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/GitBlitWebSession.java b/src/com/gitblit/wicket/GitBlitWebSession.java
index 92eaff6..58ba495 100644
--- a/src/com/gitblit/wicket/GitBlitWebSession.java
+++ b/src/com/gitblit/wicket/GitBlitWebSession.java
@@ -14,6 +14,8 @@
 	protected TimeZone timezone = null;
 
 	private User user = null;
+	
+	private String errorMessage = null;
 
 	public GitBlitWebSession(Request request) {
 		super(request);
@@ -53,6 +55,16 @@
 		}
 		return timezone;
 	}
+	
+	public void cacheErrorMessage(String message) {
+		this.errorMessage = message;
+	}
+	
+	public String clearErrorMessage() {
+		String msg = errorMessage;
+		errorMessage = null;
+		return msg;
+	}
 
 	public static GitBlitWebSession get() {
 		return (GitBlitWebSession) Session.get();
diff --git a/src/com/gitblit/wicket/LoginPage.html b/src/com/gitblit/wicket/LoginPage.html
index f38e01d..71421ab 100644
--- a/src/com/gitblit/wicket/LoginPage.html
+++ b/src/com/gitblit/wicket/LoginPage.html
@@ -32,9 +32,9 @@
 					<input type="password"  wicket:id="password" value=""/>
 					<p/>
 					<input type="submit" value="Login" wicket:message="value:gb.login" />
-					<div style="background-color:#c7c7c7" wicket:id="feedback"></div>
+					<div style="padding-top:10px;" wicket:id="feedback"></div>
 				</div>
-			</form>
+			</form>					
 		</div>
 	</body>
 </html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/RepositoryPage.html b/src/com/gitblit/wicket/RepositoryPage.html
index 4b3f2e7..0e0ce47 100644
--- a/src/com/gitblit/wicket/RepositoryPage.html
+++ b/src/com/gitblit/wicket/RepositoryPage.html
@@ -21,6 +21,8 @@
 				<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>
 		</div>
+		
+		<div style="text-align:center;" wicket:id="feedback">[Feedback Panel]</div>
 	
 		<!-- page content -->
 		<wicket:child />
diff --git a/src/com/gitblit/wicket/RepositoryPage.java b/src/com/gitblit/wicket/RepositoryPage.java
index ba3ca69..1f88075 100644
--- a/src/com/gitblit/wicket/RepositoryPage.java
+++ b/src/com/gitblit/wicket/RepositoryPage.java
@@ -1,5 +1,6 @@
 package com.gitblit.wicket;
 
+import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -46,10 +47,10 @@
 public abstract class RepositoryPage extends BasePage {
 
 	protected final String repositoryName;
-	protected final String objectId;	
+	protected final String objectId;
 
 	private transient Repository r = null;
-	
+
 	private RepositoryModel m = null;
 
 	private final Logger logger = LoggerFactory.getLogger(RepositoryPage.class);
@@ -70,14 +71,17 @@
 
 	public RepositoryPage(PageParameters params) {
 		super(params);
-		if (!params.containsKey("r")) {
-			error("Repository not specified!");
-			redirectToInterceptPage(new RepositoriesPage());
-		}
 		repositoryName = WicketUtils.getRepositoryName(params);
 		objectId = WicketUtils.getObject(params);
 
+		if (StringUtils.isEmpty(repositoryName)) {
+			error(MessageFormat.format("Repository not specified for {0}!", getPageName()), true);
+		}
+
 		Repository r = getRepository();
+		if (r == null) {
+			error(MessageFormat.format("Failed to open repository {0} for {1}!", repositoryName, getPageName()), true);
+		}
 
 		// standard page links
 		add(new BookmarkablePageLink<Void>("summary", SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryName)));
@@ -86,7 +90,7 @@
 		add(new BookmarkablePageLink<Void>("tags", TagsPage.class, WicketUtils.newRepositoryParameter(repositoryName)));
 		add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils.newRepositoryParameter(repositoryName)));
 
-		// per-repository extra page links 
+		// per-repository extra page links
 		List<String> extraPageLinks = new ArrayList<String>();
 
 		// Conditionally add tickets page
@@ -115,7 +119,7 @@
 			}
 		};
 		add(extrasView);
-		
+
 		// disable current page
 		disablePageLink(getPageName());
 
@@ -123,7 +127,7 @@
 		SearchForm searchForm = new SearchForm("searchForm", repositoryName);
 		add(searchForm);
 		searchForm.setTranslatedAttributes();
-		
+
 		// set stateless page preference
 		setStatelessHint(true);
 	}
@@ -154,12 +158,20 @@
 		}
 		return r;
 	}
-	
+
 	protected RepositoryModel getRepositoryModel() {
 		if (m == null) {
 			m = GitBlit.self().getRepositoryModel(repositoryName);
 		}
 		return m;
+	}
+	
+	protected RevCommit getCommit() {
+		RevCommit commit = JGitUtils.getCommit(r, objectId);
+		if (commit == null) {
+			error(MessageFormat.format("Failed to find commit \"{0}\" in {1} for {2} page!", objectId, repositoryName, getPageName()), true);
+		}
+		return commit;
 	}
 
 	protected void addRefs(Repository r, RevCommit c) {
@@ -303,11 +315,11 @@
 			TextField<String> searchBox = new TextField<String>("searchBox", searchBoxModel);
 			add(searchBox);
 		}
-		
-		void setTranslatedAttributes() {			
+
+		void setTranslatedAttributes() {
 			WicketUtils.setHtmlTooltip(get("searchType"), getString("gb.searchTypeTooltip"));
 			WicketUtils.setHtmlTooltip(get("searchBox"), getString("gb.searchTooltip"));
-			WicketUtils.setInputPlaceholder(get("searchBox"), getString("gb.search"));			
+			WicketUtils.setInputPlaceholder(get("searchBox"), getString("gb.search"));
 		}
 
 		@Override
diff --git a/src/com/gitblit/wicket/models/RepositoryModel.java b/src/com/gitblit/wicket/models/RepositoryModel.java
index 8840f07..8efa58d 100644
--- a/src/com/gitblit/wicket/models/RepositoryModel.java
+++ b/src/com/gitblit/wicket/models/RepositoryModel.java
@@ -11,6 +11,7 @@
 	public String owner;
 	public String group;
 	public Date lastChange;
+	public boolean hasCommits;
 	public boolean useTickets;
 	public boolean useDocs;
 	public boolean useRestrictedAccess;
diff --git a/src/com/gitblit/wicket/pages/BlobDiffPage.java b/src/com/gitblit/wicket/pages/BlobDiffPage.java
index 983b3c4..4be48ec 100644
--- a/src/com/gitblit/wicket/pages/BlobDiffPage.java
+++ b/src/com/gitblit/wicket/pages/BlobDiffPage.java
@@ -25,8 +25,8 @@
 		final String baseObjectId = WicketUtils.getBaseObjectId(params);
 
 		Repository r = getRepository();
-		RevCommit commit = JGitUtils.getCommit(r, objectId);
-		
+		RevCommit commit = getCommit();
+				
 		DiffOutputType diffType = DiffOutputType.forName(GitBlit.self().settings().getString(Keys.web.diffStyle, DiffOutputType.GITBLIT.name()));
 
 		String diff;
diff --git a/src/com/gitblit/wicket/pages/BlobPage.java b/src/com/gitblit/wicket/pages/BlobPage.java
index ca2afe9..938eaab 100644
--- a/src/com/gitblit/wicket/pages/BlobPage.java
+++ b/src/com/gitblit/wicket/pages/BlobPage.java
@@ -41,7 +41,7 @@
 		
 		// standard blob view
 		Repository r = getRepository();
-		RevCommit commit = JGitUtils.getCommit(r, objectId);
+		RevCommit commit = getCommit();
 
 		// blob page links
 		add(new Label("blameLink", getString("gb.blame")));
diff --git a/src/com/gitblit/wicket/pages/CommitDiffPage.java b/src/com/gitblit/wicket/pages/CommitDiffPage.java
index eb30e08..f293c12 100644
--- a/src/com/gitblit/wicket/pages/CommitDiffPage.java
+++ b/src/com/gitblit/wicket/pages/CommitDiffPage.java
@@ -29,7 +29,7 @@
 		super(params);
 
 		Repository r = getRepository();
-		RevCommit commit = JGitUtils.getCommit(r, objectId);
+		RevCommit commit = getCommit();
 		DiffOutputType diffType = DiffOutputType.forName(GitBlit.self().settings().getString(Keys.web.diffStyle, DiffOutputType.GITBLIT.name()));
 		String diff = JGitUtils.getCommitDiff(r, commit, diffType);
 
diff --git a/src/com/gitblit/wicket/pages/CommitPage.java b/src/com/gitblit/wicket/pages/CommitPage.java
index e724ca1..5396e82 100644
--- a/src/com/gitblit/wicket/pages/CommitPage.java
+++ b/src/com/gitblit/wicket/pages/CommitPage.java
@@ -28,7 +28,7 @@
 		super(params);
 
 		Repository r = getRepository();
-		RevCommit c = JGitUtils.getCommit(r, objectId);
+		RevCommit c = getCommit();
 
 		List<String> parents = new ArrayList<String>();
 		if (c.getParentCount() > 0) {
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
index 4aebef3..6c62245 100644
--- a/src/com/gitblit/wicket/pages/EditRepositoryPage.html
+++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
@@ -8,7 +8,9 @@
 <wicket:extend>
 	<!-- Push content down to preserve header image -->
 	<div style="padding-top:20px"></div>
-	
+
+	<div style="text-align:center;" wicket:id="feedback">[Feedback Panel]</div>	
+
 	<!-- Repository Table -->
 	<form wicket:id="editForm">
 		<table class="plain">
@@ -19,10 +21,11 @@
 				<tr><th><wicket:message key="gb.group"></wicket:message></th><td class="edit"><input type="text" wicket:id="group" size="30" tabindex="4" /></td></tr>
 				<tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useTickets" tabindex="5" /> &nbsp;<i>distributed Ticgit issues</i></td></tr>
 				<tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> &nbsp;<i>enumerates repository Markdown documentation</i></td></tr>
-				<tr><td class="edit" colspan="2"><input type="submit" value="Submit" tabindex="7" /></td></tr>
+				<tr><td class="edit" colspan="2"><input type="submit" value="Save" wicket:message="value:gb.save" tabindex="7" /></td></tr>
 			</tbody>
 		</table>
 	</form>	
+
 </wicket:extend>
 </body>
 </html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/PatchPage.java b/src/com/gitblit/wicket/pages/PatchPage.java
index b7dd1a3..62431d2 100644
--- a/src/com/gitblit/wicket/pages/PatchPage.java
+++ b/src/com/gitblit/wicket/pages/PatchPage.java
@@ -9,6 +9,7 @@
 import com.gitblit.GitBlit;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.WicketUtils;
 
 public class PatchPage extends WebPage {
@@ -17,9 +18,11 @@
 		super(params);
 
 		if (!params.containsKey("r")) {
-			error("Repository not specified!");
+			GitBlitWebSession.get().cacheErrorMessage("Repository not specified!");
 			redirectToInterceptPage(new RepositoriesPage());
+			return;
 		}
+		
 		final String repositoryName = WicketUtils.getRepositoryName(params);
 		final String baseObjectId = WicketUtils.getBaseObjectId(params);
 		final String objectId = WicketUtils.getObject(params);
@@ -27,12 +30,18 @@
 
 		Repository r = GitBlit.self().getRepository(repositoryName);
 		if (r == null) {
-			error("Can not load repository " + repositoryName);
+			GitBlitWebSession.get().cacheErrorMessage("Can not load repository " + repositoryName);
 			redirectToInterceptPage(new RepositoriesPage());
 			return;
 		}
 
 		RevCommit commit = JGitUtils.getCommit(r, objectId);
+		if (commit == null) {
+			GitBlitWebSession.get().cacheErrorMessage("Commit is null");
+			redirectToInterceptPage(new RepositoriesPage());
+			return;
+		}
+		
 		String patch;
 		if (StringUtils.isEmpty(baseObjectId)) {
 			patch = JGitUtils.getCommitPatch(r, commit, blobPath);
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.html b/src/com/gitblit/wicket/pages/RepositoriesPage.html
index bb13292..09de115 100644
--- a/src/com/gitblit/wicket/pages/RepositoriesPage.html
+++ b/src/com/gitblit/wicket/pages/RepositoriesPage.html
@@ -13,6 +13,8 @@
 <wicket:extend>
 	<div wicket:id="adminPanel">[admin links]</div>
 	
+	<div style="text-align:center;padding-top:20px;" wicket:id="feedback">[Feedback Panel]</div>
+	
 	<div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div>
 		
 	<table class="repositories">
@@ -46,6 +48,7 @@
 	<wicket:fragment wicket:id="repositoryAdminLinks">
 		<span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | <a wicket:id="renameRepository"><wicket:message key="gb.rename">[rename]</wicket:message></a> | <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a></span>
 	</wicket:fragment>
+	
 </wicket:extend>
 </body>
 </html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.java b/src/com/gitblit/wicket/pages/RepositoriesPage.java
index 768cea1..2edb3e8 100644
--- a/src/com/gitblit/wicket/pages/RepositoriesPage.java
+++ b/src/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -52,6 +52,13 @@
 		adminLinks.add(new BookmarkablePageLink<Void>("newUser", RepositoriesPage.class));
 		add(adminLinks.setVisible(showAdmin));
 
+		// display an error message cached from a redirect
+		String cachedMessage = GitBlitWebSession.get().clearErrorMessage();
+		if (!StringUtils.isEmpty(cachedMessage)) {
+			error(cachedMessage);
+			System.out.println("displayed message");
+		}
+		
 		// Load the markdown welcome message
 		String messageSource = GitBlit.self().settings().getString(Keys.web.repositoriesMessage, "gitblit");
 		String message = "";
@@ -64,7 +71,7 @@
 				message = StringUtils.transformMarkdown(reader);
 			} catch (Throwable t) {
 				message = "Failed to read default welcome message!";
-				error(message, t);
+				error(message, t, false);
 			}
 		} else {
 			// Read user-supplied welcome message
@@ -76,7 +83,7 @@
 						message = StringUtils.transformMarkdown(reader);
 					} catch (Throwable t) {
 						message = "Failed to read " + file;
-						error(message, t);
+						error(message, t, false);
 					}
 				} else {
 					message = messageSource + " is not a valid file.";
@@ -97,10 +104,17 @@
 
 			public void populateItem(final Item<RepositoryModel> item) {
 				final RepositoryModel entry = item.getModelObject();
-				PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
-				item.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
-				item.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
-
+				if (entry.hasCommits) {
+					// Existing repository
+					PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
+					item.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
+					item.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
+				} else {
+					// New repository
+					item.add(new Label("repositoryName", entry.name + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
+					item.add(new Label("repositoryDescription", entry.description));					
+				}
+				
 				if (entry.useTickets) {
 					item.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png", getString("gb.tickets")));
 				} else {
diff --git a/src/com/gitblit/wicket/pages/TagPage.java b/src/com/gitblit/wicket/pages/TagPage.java
index 7448ae5..a95b967 100644
--- a/src/com/gitblit/wicket/pages/TagPage.java
+++ b/src/com/gitblit/wicket/pages/TagPage.java
@@ -19,8 +19,8 @@
 		super(params);
 
 		Repository r = getRepository();
+		RevCommit c = getCommit();
 		List<RefModel> tags = JGitUtils.getTags(r, -1);
-		RevCommit c = JGitUtils.getCommit(r, objectId);
 
 		RefModel tagRef = null;
 		// determine tag
diff --git a/src/com/gitblit/wicket/pages/TreePage.java b/src/com/gitblit/wicket/pages/TreePage.java
index 56f96d6..ea5bd53 100644
--- a/src/com/gitblit/wicket/pages/TreePage.java
+++ b/src/com/gitblit/wicket/pages/TreePage.java
@@ -30,7 +30,7 @@
 		final String path = WicketUtils.getPath(params);
 
 		Repository r = getRepository();
-		RevCommit commit = JGitUtils.getCommit(r, objectId);
+		RevCommit commit = getCommit();
 		List<PathModel> paths = JGitUtils.getFilesInPath(r, path, commit);
 
 		// tree page links
diff --git a/src/com/gitblit/wicket/panels/CommitHeaderPanel.java b/src/com/gitblit/wicket/panels/CommitHeaderPanel.java
index da72a7c..bf653ec 100644
--- a/src/com/gitblit/wicket/panels/CommitHeaderPanel.java
+++ b/src/com/gitblit/wicket/panels/CommitHeaderPanel.java
@@ -1,7 +1,5 @@
 package com.gitblit.wicket.panels;
 
-import java.util.Date;
-
 import org.apache.wicket.markup.html.basic.Label;
 import org.eclipse.jgit.revwalk.RevCommit;
 
@@ -15,9 +13,9 @@
 
 	public CommitHeaderPanel(String id, String repositoryName, RevCommit c) {
 		super(id);
-		add(new LinkPanel("shortmessage", "title", c == null ? "" : c.getShortMessage(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, c == null ? "" : c.getName())));
+		add(new LinkPanel("shortmessage", "title", c.getShortMessage(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, c.getName())));
 		add(new Label("commitid", "(" + c.getName().substring(0, 8) + ")"));		
-		add(new Label("author", c == null ? "" : c.getAuthorIdent().getName()));
-		add(WicketUtils.createDateLabel("date", c == null ? new Date(0) : c.getAuthorIdent().getWhen(), getTimeZone()));
+		add(new Label("author", c.getAuthorIdent().getName()));
+		add(WicketUtils.createDateLabel("date", c.getAuthorIdent().getWhen(), getTimeZone()));
 	}
 }
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/panels/SearchPanel.java b/src/com/gitblit/wicket/panels/SearchPanel.java
index 7a87732..38a54d9 100644
--- a/src/com/gitblit/wicket/panels/SearchPanel.java
+++ b/src/com/gitblit/wicket/panels/SearchPanel.java
@@ -55,7 +55,7 @@
 		hasMore = commits.size() >= itemsPerPage;
 
 		// header
-		add(new LinkPanel("header", "title", commit.getShortMessage(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, commit.getName())));
+		add(new LinkPanel("header", "title", commit == null ? "":commit.getShortMessage(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, commit == null ? "":commit.getName())));
 
 		ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);
 		DataView<RevCommit> searchView = new DataView<RevCommit>("commit", dp) {
diff --git a/src/com/gitblit/wicket/resources/gitblit.css b/src/com/gitblit/wicket/resources/gitblit.css
index 8317e36..3d0a1cd 100644
--- a/src/com/gitblit/wicket/resources/gitblit.css
+++ b/src/com/gitblit/wicket/resources/gitblit.css
@@ -100,6 +100,13 @@
 	padding: 0px 0px 15px 5px;
 }
 
+span.empty {
+	font-size: 0.9em;
+	font-style: italic;
+	padding-left:10px;
+	color: #008000;
+}
+
 span.link, span.link a {
 	font-family: sans-serif;
 	font-size: 11px;
@@ -633,8 +640,7 @@
 .feedbackPanelERROR {	
 	color: red;
 	list-style-image: url(bullet_error.png);
-	font-weight: bold;
-	text-align:left;
+	font-weight: bold;	
 	vertical-align: top;
 	padding:0;	
 	margin:0;	
@@ -643,8 +649,7 @@
 .feedbackPanelINFO {
 	color: green;
 	list-style: none;
-	font-weight: bold;
-	text-align:center;
+	font-weight: bold;	
 	padding:0;
 	margin:0;
 }
\ No newline at end of file

--
Gitblit v1.9.1