From 82df524570e7bf27953b14f4797ff04daf89cc3a Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 09 Dec 2011 08:50:18 -0500
Subject: [PATCH] Implemented empty repository page (issue 31)

---
 src/com/gitblit/wicket/pages/SummaryPage.html         |    2 
 src/com/gitblit/wicket/pages/EmptyRepositoryPage.html |   42 ++++++++++
 resources/clipboard_13x13.png                         |    0 
 src/com/gitblit/wicket/panels/RepositoriesPanel.java  |   20 +++-
 src/com/gitblit/wicket/pages/RepositoryPage.java      |    4 +
 src/com/gitblit/wicket/panels/BasePanel.java          |   11 +-
 resources/clipboard_16x16.png                         |    0 
 src/com/gitblit/wicket/GitBlitWebApp.properties       |    4 
 docs/04_releases.mkd                                  |    5 +
 src/com/gitblit/wicket/panels/RepositoryUrlPanel.html |   13 +++
 src/com/gitblit/wicket/pages/EmptyRepositoryPage.java |   54 +++++++++++++
 src/com/gitblit/wicket/pages/SummaryPage.java         |    9 +
 src/com/gitblit/wicket/panels/RepositoryUrlPanel.java |   35 ++++++++
 13 files changed, 183 insertions(+), 16 deletions(-)

diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index 343f794..bf70918 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -6,7 +6,7 @@
 - added: new default user service implementation: com.gitblit.ConfigUserService (users.conf)  
 This user service implementation allows for serialization and deserialization of more sophisticated Gitblit User objects and will open the door for more advanced Gitblit features. For upgrading installations, a `users.conf` file will automatically be created for you from your existing `users.properties` file on your first launch of Gitblit.  You will have to manually set *realm.userService=users.conf* to switch to the new user service.  The original `users.properties` file and it's corresponding implementation are deprecated.  
     **New:** *realm.userService = users.conf*
-- added: Teams for specifying user-repository access
+- added: Teams for specifying user-repository access in bulk
 - added: Gitblit Express bundle to get started running Gitblit on RedHat's OpenShift cloud
 - added: optional Gravatar integration  
     **New:** *web.allowGravatar = true*   
@@ -15,6 +15,9 @@
    **New:** *web.timeFormat = HH:mm*  
    **New:** *web.datestampLongFormat = EEEE, MMMM d, yyyy*  
 - fixed: several a bugs in FileUserService related to cleaning up old repository permissions on a rename or delete
+- added: primitive technique for manual *copy to clipboard* of the primary repository url
+- improved: empty repositories now link to the *empty repository* page which gives some direction to the user for the next step in using Gitblit.  This page displays the primary push/clone url of the repository and gives sample syntax for the git command-line client. (issue 31)
+- improved: unit testing framework has been migrated to JUnit4 syntax and the test suite has been redesigned to run all unit tests, including rpc, federation, and git push/clone tests
 
 
 ### Older Releases
diff --git a/resources/clipboard_13x13.png b/resources/clipboard_13x13.png
new file mode 100644
index 0000000..85f6cd7
--- /dev/null
+++ b/resources/clipboard_13x13.png
Binary files differ
diff --git a/resources/clipboard_16x16.png b/resources/clipboard_16x16.png
new file mode 100644
index 0000000..ee4bd3e
--- /dev/null
+++ b/resources/clipboard_16x16.png
Binary files differ
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 6f32168..c9afbc9 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -193,4 +193,6 @@
 gb.teamMembers = team members
 gb.teamMemberships = team memberships
 gb.newTeam = new team
-gb.permittedTeams = permitted teams
\ No newline at end of file
+gb.permittedTeams = permitted teams
+gb.emptyRepository = empty repository
+gb.repositoryUrl = repository url
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/EmptyRepositoryPage.html b/src/com/gitblit/wicket/pages/EmptyRepositoryPage.html
new file mode 100644
index 0000000..4f0b9bd
--- /dev/null
+++ b/src/com/gitblit/wicket/pages/EmptyRepositoryPage.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  
+      xml:lang="en"  
+      lang="en"> 
+
+<wicket:head>
+  	<link href="markdown.css" type="text/css" rel="stylesheet" />
+</wicket:head>
+
+<body>
+<wicket:extend>
+
+	<!-- markdown message -->
+	<div class="markdown" style="margin-top:-15px;padding-bottom:10px;">
+		<h2>Empty Repository</h2>
+		<p></p>
+		<span wicket:id="repository" style="font-weight: bold;">[repository]</span> is an empty repository and can not be viewed by Gitblit.
+		<p></p>
+		Please push some commits to <span wicket:id="pushurl"></span>
+		<p></p>
+		<h3>Git Command-Line Syntax</h3>		
+		<pre wicket:id="syntax"></pre>
+		<p></p>
+		<h3>Learn Git</h3>
+		If you are lost or don't know what to do with this information, consider reviewing the excellent <a href="http://progit.org/book" target="_blank">Pro Git</a> book for a better understanding on how to use Git.
+		<p></p>
+		<h4>Open Source Git Clients</h4>
+		<ul>
+			<li><a href="http://git-scm.com">Git</a> - the official, command-line Git</li>
+			<li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Windows file explorer integration (requires official, command-line Git)</li>
+			<li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git for the Eclipse IDE (based on JGit, like Gitblit)</li>
+		</ul>
+		<p></p>
+		<h4>Commercial Git Clients</h4>
+		<ul>
+			<li><a href="http://www.syntevo.com/smartgit">SmartGit</a> - Java application (requires official, command-line Git)</li>
+		</ul>
+	</div>	
+</wicket:extend>	
+</body>
+</html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/EmptyRepositoryPage.java b/src/com/gitblit/wicket/pages/EmptyRepositoryPage.java
new file mode 100644
index 0000000..b5f4a35
--- /dev/null
+++ b/src/com/gitblit/wicket/pages/EmptyRepositoryPage.java
@@ -0,0 +1,54 @@
+/*
+ * 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.wicket.pages;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.markup.html.basic.Label;
+
+import com.gitblit.Constants;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.panels.RepositoryUrlPanel;
+
+public class EmptyRepositoryPage extends RootPage {
+
+	public EmptyRepositoryPage(PageParameters params) {
+		super(params);
+
+		String repositoryName = WicketUtils.getRepositoryName(params);
+		setupPage(repositoryName, getString("gb.emptyRepository"));
+
+		List<String> repositoryUrls = new ArrayList<String>();
+
+		if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(WicketUtils.getGitblitURL(getRequestCycle().getRequest()));
+			sb.append(Constants.GIT_PATH);
+			sb.append(repositoryName);
+			repositoryUrls.add(sb.toString());
+		}
+		repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName));
+		
+		add(new Label("repository", repositoryName));
+		add(new RepositoryUrlPanel("pushurl", repositoryUrls.get(0)));
+		add(new Label("syntax", MessageFormat.format("git remote add gitblit {0}\ngit push gitblit master", repositoryUrls.get(0))));
+	}
+}
diff --git a/src/com/gitblit/wicket/pages/RepositoryPage.java b/src/com/gitblit/wicket/pages/RepositoryPage.java
index 4c417d9..85719f1 100644
--- a/src/com/gitblit/wicket/pages/RepositoryPage.java
+++ b/src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -73,6 +73,10 @@
 			error(MessageFormat.format("Repository not specified for {0}!", getPageName()), true);
 		}
 
+		if (!getRepositoryModel().hasCommits) {
+			setResponsePage(EmptyRepositoryPage.class, params);
+		}
+
 		// register the available page links for this page and user
 		registeredPages = registerPages();
 
diff --git a/src/com/gitblit/wicket/pages/SummaryPage.html b/src/com/gitblit/wicket/pages/SummaryPage.html
index 35ad347..132b891 100644
--- a/src/com/gitblit/wicket/pages/SummaryPage.html
+++ b/src/com/gitblit/wicket/pages/SummaryPage.html
@@ -24,7 +24,7 @@
 				<tr><th><wicket:message key="gb.owner">[owner]</wicket:message></th><td><span wicket:id="repositoryOwner">[repository owner]</span></td></tr>
 				<tr><th><wicket:message key="gb.lastChange">[last change]</wicket:message></th><td><span wicket:id="repositoryLastChange">[repository last change]</span></td></tr>
 				<tr><th><wicket:message key="gb.stats">[stats]</wicket:message></th><td><span wicket:id="branchStats">[branch stats]</span> <span class="link"><a wicket:id="metrics"><wicket:message key="gb.metrics">[metrics]</wicket:message></a></span></td></tr>
-				<tr><th valign="top"><wicket:message key="gb.url">[URL]</wicket:message></th><td><img style="vertical-align: top; padding-right:5px;" wicket:id="accessRestrictionIcon" /><span wicket:id="repositoryCloneUrl">[repository clone url]</span></td></tr>
+				<tr><th valign="middle"><wicket:message key="gb.repositoryUrl">[URL]</wicket:message></th><td><img style="vertical-align: middle;" wicket:id="accessRestrictionIcon" /><span wicket:id="repositoryCloneUrl">[repository clone url]</span><div wicket:id="otherUrls" style="margin-left:20px;"></div></td></tr>
 			</table>
 		</div>
 	</div>
diff --git a/src/com/gitblit/wicket/pages/SummaryPage.java b/src/com/gitblit/wicket/pages/SummaryPage.java
index da573d5..ed90a84 100644
--- a/src/com/gitblit/wicket/pages/SummaryPage.java
+++ b/src/com/gitblit/wicket/pages/SummaryPage.java
@@ -51,6 +51,7 @@
 import com.gitblit.wicket.WicketUtils;
 import com.gitblit.wicket.panels.BranchesPanel;
 import com.gitblit.wicket.panels.LogPanel;
+import com.gitblit.wicket.panels.RepositoryUrlPanel;
 import com.gitblit.wicket.panels.TagsPanel;
 
 public class SummaryPage extends RepositoryPage {
@@ -66,6 +67,7 @@
 
 		Repository r = getRepository();
 		RepositoryModel model = getRepositoryModel();
+
 		List<Metric> metrics = null;
 		Metric metricsTotal = null;
 		if (!model.skipSummaryMetrics && GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {
@@ -123,9 +125,12 @@
 			add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
 		}
 		repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName));
+		
+		String primaryUrl = repositoryUrls.remove(0);
+		add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl));
 
-		add(new Label("repositoryCloneUrl", StringUtils.flattenStrings(repositoryUrls, "<br/>"))
-				.setEscapeModelStrings(false));
+		add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>"))
+		.setEscapeModelStrings(false));
 
 		add(new LogPanel("commitsPanel", repositoryName, null, r, numberCommits, 0));
 		add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());
diff --git a/src/com/gitblit/wicket/panels/BasePanel.java b/src/com/gitblit/wicket/panels/BasePanel.java
index 8ea2a69..73e1399 100644
--- a/src/com/gitblit/wicket/panels/BasePanel.java
+++ b/src/com/gitblit/wicket/panels/BasePanel.java
@@ -72,17 +72,16 @@
 
 		private static final long serialVersionUID = 1L;
 
-		public JavascriptTextPrompt(String event, String msg) {
+		private String initialValue = "";
+		
+		public JavascriptTextPrompt(String event, String msg, String value) {
 			super(event, true, new Model<String>(msg));
+			initialValue = value;
 		}
 
 		protected String newValue(final String currentValue, final String message) {
 			String result = "var userText = prompt('" + message + "','"
-					+ (currentValue == null ? "" : currentValue) + "'); " + "return userText; ";
-			// String result = prefix;
-			// if (currentValue != null) {
-			// result = prefix + currentValue;
-			// }
+					+ (initialValue == null ? "" : initialValue) + "'); " + "return userText; ";
 			return result;
 		}
 	}
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
index fd5e34f..fc90316 100644
--- a/src/com/gitblit/wicket/panels/RepositoriesPanel.java
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -51,7 +51,9 @@
 import com.gitblit.utils.TimeUtils;
 import com.gitblit.wicket.GitBlitWebSession;
 import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.BasePage;
 import com.gitblit.wicket.pages.EditRepositoryPage;
+import com.gitblit.wicket.pages.EmptyRepositoryPage;
 import com.gitblit.wicket.pages.SummaryPage;
 
 public class RepositoriesPanel extends BasePanel {
@@ -160,17 +162,25 @@
 				row.add(swatch);
 				swatch.setVisible(showSwatch);
 
-				if (entry.hasCommits && linksActive) {
+				if (linksActive) {
+					Class<? extends BasePage> linkPage;
+					if (entry.hasCommits) {
+						// repository has content
+						linkPage = SummaryPage.class;
+					} else {
+						// new/empty repository OR proposed repository
+						linkPage = EmptyRepositoryPage.class;
+					}
+
 					PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
-					row.add(new LinkPanel("repositoryName", "list", repoName, SummaryPage.class, pp));
+					row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));
 					row.add(new LinkPanel("repositoryDescription", "list", entry.description,
-							SummaryPage.class, pp));
+							linkPage, pp));
 				} else {
-					// new/empty repository OR proposed repository
+					// no links like on a federation page
 					row.add(new Label("repositoryName", repoName));
 					row.add(new Label("repositoryDescription", entry.description));
 				}
-
 				if (entry.hasCommits) {
 					// Existing repository
 					row.add(new Label("repositorySize", entry.size).setVisible(showSize));
diff --git a/src/com/gitblit/wicket/panels/RepositoryUrlPanel.html b/src/com/gitblit/wicket/panels/RepositoryUrlPanel.html
new file mode 100644
index 0000000..25ba155
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/RepositoryUrlPanel.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  
+      xml:lang="en"  
+      lang="en"> 
+
+<wicket:head>
+</wicket:head>
+
+<wicket:panel>
+	<span wicket:id="repositoryUrl" style="color: blue;">[repository url]</span><span style="padding-left:5px;"><span class="btn" style="padding:0px 3px;vertical-align:middle;"><img wicket:id="copyIcon" style="padding-top:1px;"></img></span></span>	
+</wicket:panel>	
+</html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/panels/RepositoryUrlPanel.java b/src/com/gitblit/wicket/panels/RepositoryUrlPanel.java
new file mode 100644
index 0000000..bfb02f1
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/RepositoryUrlPanel.java
@@ -0,0 +1,35 @@
+/*
+ * 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.wicket.panels;
+
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.ContextImage;
+
+import com.gitblit.wicket.WicketUtils;
+
+public class RepositoryUrlPanel extends BasePanel {
+
+	private static final long serialVersionUID = 1L;
+
+	public RepositoryUrlPanel(String wicketId, String url) {
+		super(wicketId);
+		add(new Label("repositoryUrl", url));
+		ContextImage img = WicketUtils.newImage("copyIcon", "clipboard_13x13.png");
+		WicketUtils.setHtmlTooltip(img, "Manual Copy to Clipboard");
+		img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", url));
+		add(img);
+	}
+}

--
Gitblit v1.9.1