- added: new default user service implementation: com.gitblit.ConfigUserService (users.conf) \r
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. \r
**New:** *realm.userService = users.conf*\r
-- added: Teams for specifying user-repository access\r
+- added: Teams for specifying user-repository access in bulk\r
- added: Gitblit Express bundle to get started running Gitblit on RedHat's OpenShift cloud\r
- added: optional Gravatar integration \r
**New:** *web.allowGravatar = true* \r
**New:** *web.timeFormat = HH:mm* \r
**New:** *web.datestampLongFormat = EEEE, MMMM d, yyyy* \r
- fixed: several a bugs in FileUserService related to cleaning up old repository permissions on a rename or delete\r
+- added: primitive technique for manual *copy to clipboard* of the primary repository url\r
+- 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)\r
+- 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\r
\r
\r
### Older Releases\r
gb.teamMembers = team members\r
gb.teamMemberships = team memberships\r
gb.newTeam = new team\r
-gb.permittedTeams = permitted teams
\ No newline at end of file
+gb.permittedTeams = permitted teams\r
+gb.emptyRepository = empty repository\r
+gb.repositoryUrl = repository url
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" \r
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" \r
+ xml:lang="en" \r
+ lang="en"> \r
+\r
+<wicket:head>\r
+ <link href="markdown.css" type="text/css" rel="stylesheet" />\r
+</wicket:head>\r
+\r
+<body>\r
+<wicket:extend>\r
+\r
+ <!-- markdown message -->\r
+ <div class="markdown" style="margin-top:-15px;padding-bottom:10px;">\r
+ <h2>Empty Repository</h2>\r
+ <p></p>\r
+ <span wicket:id="repository" style="font-weight: bold;">[repository]</span> is an empty repository and can not be viewed by Gitblit.\r
+ <p></p>\r
+ Please push some commits to <span wicket:id="pushurl"></span>\r
+ <p></p>\r
+ <h3>Git Command-Line Syntax</h3> \r
+ <pre wicket:id="syntax"></pre>\r
+ <p></p>\r
+ <h3>Learn Git</h3>\r
+ 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.\r
+ <p></p>\r
+ <h4>Open Source Git Clients</h4>\r
+ <ul>\r
+ <li><a href="http://git-scm.com">Git</a> - the official, command-line Git</li>\r
+ <li><a href="http://tortoisegit.googlecode.com">TortoiseGit</a> - Windows file explorer integration (requires official, command-line Git)</li>\r
+ <li><a href="http://eclipse.org/egit">Eclipse/EGit</a> - Git for the Eclipse IDE (based on JGit, like Gitblit)</li>\r
+ </ul>\r
+ <p></p>\r
+ <h4>Commercial Git Clients</h4>\r
+ <ul>\r
+ <li><a href="http://www.syntevo.com/smartgit">SmartGit</a> - Java application (requires official, command-line Git)</li>\r
+ </ul>\r
+ </div> \r
+</wicket:extend> \r
+</body>\r
+</html>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.pages;\r
+\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.wicket.PageParameters;\r
+import org.apache.wicket.markup.html.basic.Label;\r
+\r
+import com.gitblit.Constants;\r
+import com.gitblit.GitBlit;\r
+import com.gitblit.Keys;\r
+import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.panels.RepositoryUrlPanel;\r
+\r
+public class EmptyRepositoryPage extends RootPage {\r
+\r
+ public EmptyRepositoryPage(PageParameters params) {\r
+ super(params);\r
+\r
+ String repositoryName = WicketUtils.getRepositoryName(params);\r
+ setupPage(repositoryName, getString("gb.emptyRepository"));\r
+\r
+ List<String> repositoryUrls = new ArrayList<String>();\r
+\r
+ if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {\r
+ StringBuilder sb = new StringBuilder();\r
+ sb.append(WicketUtils.getGitblitURL(getRequestCycle().getRequest()));\r
+ sb.append(Constants.GIT_PATH);\r
+ sb.append(repositoryName);\r
+ repositoryUrls.add(sb.toString());\r
+ }\r
+ repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName));\r
+ \r
+ add(new Label("repository", repositoryName));\r
+ add(new RepositoryUrlPanel("pushurl", repositoryUrls.get(0)));\r
+ add(new Label("syntax", MessageFormat.format("git remote add gitblit {0}\ngit push gitblit master", repositoryUrls.get(0))));\r
+ }\r
+}\r
error(MessageFormat.format("Repository not specified for {0}!", getPageName()), true);\r
}\r
\r
+ if (!getRepositoryModel().hasCommits) {\r
+ setResponsePage(EmptyRepositoryPage.class, params);\r
+ }\r
+\r
// register the available page links for this page and user\r
registeredPages = registerPages();\r
\r
<tr><th><wicket:message key="gb.owner">[owner]</wicket:message></th><td><span wicket:id="repositoryOwner">[repository owner]</span></td></tr>\r
<tr><th><wicket:message key="gb.lastChange">[last change]</wicket:message></th><td><span wicket:id="repositoryLastChange">[repository last change]</span></td></tr>\r
<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>\r
- <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>\r
+ <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>\r
</table>\r
</div>\r
</div>\r
import com.gitblit.wicket.WicketUtils;\r
import com.gitblit.wicket.panels.BranchesPanel;\r
import com.gitblit.wicket.panels.LogPanel;\r
+import com.gitblit.wicket.panels.RepositoryUrlPanel;\r
import com.gitblit.wicket.panels.TagsPanel;\r
\r
public class SummaryPage extends RepositoryPage {\r
\r
Repository r = getRepository();\r
RepositoryModel model = getRepositoryModel();\r
+\r
List<Metric> metrics = null;\r
Metric metricsTotal = null;\r
if (!model.skipSummaryMetrics && GitBlit.getBoolean(Keys.web.generateActivityGraph, true)) {\r
add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));\r
}\r
repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName));\r
+ \r
+ String primaryUrl = repositoryUrls.remove(0);\r
+ add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl));\r
\r
- add(new Label("repositoryCloneUrl", StringUtils.flattenStrings(repositoryUrls, "<br/>"))\r
- .setEscapeModelStrings(false));\r
+ add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>"))\r
+ .setEscapeModelStrings(false));\r
\r
add(new LogPanel("commitsPanel", repositoryName, null, r, numberCommits, 0));\r
add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());\r
\r
private static final long serialVersionUID = 1L;\r
\r
- public JavascriptTextPrompt(String event, String msg) {\r
+ private String initialValue = "";\r
+ \r
+ public JavascriptTextPrompt(String event, String msg, String value) {\r
super(event, true, new Model<String>(msg));\r
+ initialValue = value;\r
}\r
\r
protected String newValue(final String currentValue, final String message) {\r
String result = "var userText = prompt('" + message + "','"\r
- + (currentValue == null ? "" : currentValue) + "'); " + "return userText; ";\r
- // String result = prefix;\r
- // if (currentValue != null) {\r
- // result = prefix + currentValue;\r
- // }\r
+ + (initialValue == null ? "" : initialValue) + "'); " + "return userText; ";\r
return result;\r
}\r
}\r
import com.gitblit.utils.TimeUtils;\r
import com.gitblit.wicket.GitBlitWebSession;\r
import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.pages.BasePage;\r
import com.gitblit.wicket.pages.EditRepositoryPage;\r
+import com.gitblit.wicket.pages.EmptyRepositoryPage;\r
import com.gitblit.wicket.pages.SummaryPage;\r
\r
public class RepositoriesPanel extends BasePanel {\r
row.add(swatch);\r
swatch.setVisible(showSwatch);\r
\r
- if (entry.hasCommits && linksActive) {\r
+ if (linksActive) {\r
+ Class<? extends BasePage> linkPage;\r
+ if (entry.hasCommits) {\r
+ // repository has content\r
+ linkPage = SummaryPage.class;\r
+ } else {\r
+ // new/empty repository OR proposed repository\r
+ linkPage = EmptyRepositoryPage.class;\r
+ }\r
+\r
PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);\r
- row.add(new LinkPanel("repositoryName", "list", repoName, SummaryPage.class, pp));\r
+ row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));\r
row.add(new LinkPanel("repositoryDescription", "list", entry.description,\r
- SummaryPage.class, pp));\r
+ linkPage, pp));\r
} else {\r
- // new/empty repository OR proposed repository\r
+ // no links like on a federation page\r
row.add(new Label("repositoryName", repoName));\r
row.add(new Label("repositoryDescription", entry.description));\r
}\r
-\r
if (entry.hasCommits) {\r
// Existing repository\r
row.add(new Label("repositorySize", entry.size).setVisible(showSize));\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" \r
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" \r
+ xml:lang="en" \r
+ lang="en"> \r
+\r
+<wicket:head>\r
+</wicket:head>\r
+\r
+<wicket:panel>\r
+ <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> \r
+</wicket:panel> \r
+</html>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.panels;\r
+\r
+import org.apache.wicket.markup.html.basic.Label;\r
+import org.apache.wicket.markup.html.image.ContextImage;\r
+\r
+import com.gitblit.wicket.WicketUtils;\r
+\r
+public class RepositoryUrlPanel extends BasePanel {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ public RepositoryUrlPanel(String wicketId, String url) {\r
+ super(wicketId);\r
+ add(new Label("repositoryUrl", url));\r
+ ContextImage img = WicketUtils.newImage("copyIcon", "clipboard_13x13.png");\r
+ WicketUtils.setHtmlTooltip(img, "Manual Copy to Clipboard");\r
+ img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", url));\r
+ add(img);\r
+ }\r
+}\r