diff options
author | James Moger <james.moger@gitblit.com> | 2014-05-27 18:13:30 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-06-03 10:34:50 -0400 |
commit | 0047fbba99b804d268a66ed7504a568596de6168 (patch) | |
tree | 4940877475bddebe41d25b9cdced960eb5a107c2 | |
parent | e1bcda8c6245035c96bf44ee09d61fa5a52bcafc (diff) | |
download | gitblit-0047fbba99b804d268a66ed7504a568596de6168.tar.gz gitblit-0047fbba99b804d268a66ed7504a568596de6168.zip |
Simplified repository creation with a NewRepositoryPage
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | build.xml | 6 | ||||
-rw-r--r-- | releases.moxie | 2 | ||||
-rw-r--r-- | src/main/distrib/data/gitblit.properties | 5 | ||||
m--------- | src/main/distrib/data/gitignore | 0 | ||||
-rw-r--r-- | src/main/java/com/gitblit/Constants.java | 8 | ||||
-rw-r--r-- | src/main/java/com/gitblit/servlet/GitblitContext.java | 16 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/GitBlitWebApp.java | 10 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | 17 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java | 16 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html | 98 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java | 493 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/RootPage.java | 2 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/UserPage.java | 4 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java | 3 | ||||
-rw-r--r-- | src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java | 5 |
16 files changed, 673 insertions, 15 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..01eaa2c8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/main/distrib/data/gitignore"] + path = src/main/distrib/data/gitignore + url = https://github.com/github/gitignore.git @@ -919,6 +919,12 @@ <include name="subgit.groovy" />
</fileset>
</copy>
+ <mkdir dir="@{toDir}/gitignore" />
+ <copy todir="@{toDir}/gitignore">
+ <fileset dir="${project.distrib.dir}/data/gitignore">
+ <include name="*.gitignore" />
+ </fileset>
+ </copy>
</sequential>
</macrodef>
diff --git a/releases.moxie b/releases.moxie index 4332238d..5aa207fa 100644 --- a/releases.moxie +++ b/releases.moxie @@ -36,6 +36,7 @@ r24: { - Add FORK_REPOSITORY RPC request type (issue-371, pr-161, ticket-65) - Add object type (ot) parameter for RSS queries to retrieve tag details (pr-165, ticket-66) - Add setting to allow STARTTLS without requiring SMTPS (pr-183) + - Simplified repository creation, offer simple README generation, and insertion of a pre-defined .gitignore file (ticket-76) - Added an extension point for monitoring onStartup and onShutdown (ticket-79) - Tag server-side merges when incremental push tags are enabled (issue-432, ticket-85) - Add setting to control default thread pool size for miscellaneous background tasks (ticket-92) @@ -55,6 +56,7 @@ r24: { - { name: 'web.allowDeletingNonEmptyRepositories', defaultValue: 'true' } - { name: 'mail.starttls', defaultValue: 'false' } - { name: 'execution.defaultThreadPoolSize', defaultValue: '1' } + - { name: 'git.gitignoreFolder', defaultValue: '${baseFolder}/gitignore' } } # diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties index 6f55a3eb..d5623cd5 100644 --- a/src/main/distrib/data/gitblit.properties +++ b/src/main/distrib/data/gitblit.properties @@ -271,6 +271,11 @@ git.defaultIncrementalPushTagPrefix = r # SINCE 1.4.0
git.createRepositoriesShared = false
+# Directory for gitignore templates used during repository creation.
+#
+# SINCE 1.6.0
+git.gitignoreFolder = ${baseFolder}/gitignore
+
# Enable JGit-based garbage collection. (!!EXPERIMENTAL!!)
#
# USE AT YOUR OWN RISK!
diff --git a/src/main/distrib/data/gitignore b/src/main/distrib/data/gitignore new file mode 160000 +Subproject 097db81c08b138dea7cb031eb18eeb16afe44bd diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 95eb944a..3e307537 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -122,6 +122,14 @@ public class Constants { public static final String R_TICKETS_PATCHSETS = "refs/tickets/";
+ public static final String R_MASTER = "refs/heads/master";
+
+ public static final String MASTER = "master";
+
+ public static final String R_DEVELOP = "refs/heads/develop";
+
+ public static final String DEVELOP = "develop";
+
public static String getVersion() {
String v = Constants.class.getPackage().getImplementationVersion();
if (v == null) {
diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index 110e553c..50f22d5a 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -372,6 +372,22 @@ public class GitblitContext extends DaggerContext { } } + // Copy the included gitignore files to the configured gitignore folder + String gitignorePath = webxmlSettings.getString(Keys.git.gitignoreFolder, "gitignore"); + File localGitignores = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, base, gitignorePath); + if (!localGitignores.exists()) { + File warGitignores = new File(contextFolder, "/WEB-INF/data/gitignore"); + if (!warGitignores.equals(localGitignores)) { + try { + com.gitblit.utils.FileUtils.copy(localGitignores, warGitignores.listFiles()); + } catch (IOException e) { + logger.error(MessageFormat.format( + "Failed to copy included .gitignore files from {0} to {1}", + warGitignores, localGitignores)); + } + } + } + // merge the WebXmlSettings into the runtime settings (for backwards-compatibilty) runtimeSettings.merge(webxmlSettings); diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 7291d039..f63ff3d9 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -57,6 +57,7 @@ import com.gitblit.wicket.pages.ComparePage; import com.gitblit.wicket.pages.DocPage; import com.gitblit.wicket.pages.DocsPage; import com.gitblit.wicket.pages.EditMilestonePage; +import com.gitblit.wicket.pages.EditRepositoryPage; import com.gitblit.wicket.pages.EditTicketPage; import com.gitblit.wicket.pages.ExportTicketPage; import com.gitblit.wicket.pages.FederationRegistrationPage; @@ -71,6 +72,7 @@ import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.MyDashboardPage; import com.gitblit.wicket.pages.MyTicketsPage; import com.gitblit.wicket.pages.NewMilestonePage; +import com.gitblit.wicket.pages.NewRepositoryPage; import com.gitblit.wicket.pages.NewTicketPage; import com.gitblit.wicket.pages.OverviewPage; import com.gitblit.wicket.pages.PatchPage; @@ -92,6 +94,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { private final Class<? extends WebPage> homePageClass = MyDashboardPage.class; + private final Class<? extends WebPage> newRepositoryPageClass = NewRepositoryPage.class; + private final Map<String, CacheControl> cacheablePages = new HashMap<String, CacheControl>(); private final IStoredSettings settings; @@ -207,6 +211,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { mount("/proposal", ReviewProposalPage.class, "t"); mount("/registration", FederationRegistrationPage.class, "u", "n"); + mount("/new", NewRepositoryPage.class); + mount("/edit", EditRepositoryPage.class, "r"); mount("/activity", ActivityPage.class, "r", "h"); mount("/lucene", LuceneSearchPage.class); mount("/project", ProjectPage.class, "p"); @@ -262,6 +268,10 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { return homePageClass; } + public Class<? extends WebPage> getNewRepositoryPage() { + return newRepositoryPageClass; + } + /* (non-Javadoc) * @see com.gitblit.wicket.Webapp#isCacheablePage(java.lang.String) */ diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index 12430ade..ac589558 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -685,4 +685,19 @@ gb.closedMilestones = closed milestones gb.administration = administration gb.plugins = plugins gb.extensions = extensions - +gb.anonymous = Anonymous +gb.anonymousRepoDescription = Anyone can see, clone, and push to this repository. +gb.public = Public +gb.publicRepoDescription = Anyone can see and clone this repository. You choose who can push. +gb.protected = Protected +gb.protectedRepoDescription = Anyone can see this repository. You choose who can clone and push. +gb.private = Private +gb.privateRepoDescription = You choose who can see, clone, and push to this repository. +gb.initialCommit = Initial Commit +gb.initialCommitDescription = This will allow you to <code>git clone</code> this repository immediately. Skip this step if you have already run <code>git init</code> locally. +gb.initWithReadme = Include a README +gb.initWithReadmeDescription = This will generate a simple README document for your repository. +gb.initWithGitignore = Include a .gitignore file +gb.initWithGitignoreDescription = This will insert a config file that instructs your Git clients to ignore files or directories that match defined patterns. +gb.initWithGitflow = Include a .gitflow file +gb.initWithGitflowDescription = This will generate a config file which guides Git clients in setting up Gitflow branches.
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java index 412c0ecc..c18cd514 100644 --- a/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -429,11 +429,7 @@ public class EditRepositoryPage extends RootSubPage { return;
}
setRedirect(false);
- if (isCreate) {
- setResponsePage(RepositoriesPage.class);
- } else {
- setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
- }
+ setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
}
};
@@ -632,7 +628,15 @@ public class EditRepositoryPage extends RootSubPage { if (canDelete) {
if (app().repositories().deleteRepositoryModel(latestModel)) {
info(MessageFormat.format(getString("gb.repositoryDeleted"), latestModel));
- setResponsePage(RepositoriesPage.class);
+ if (latestModel.isPersonalRepository()) {
+ // redirect to user's profile page
+ String prefix = app().settings().getString(Keys.git.userRepositoryPrefix, "~");
+ String username = latestModel.projectPath.substring(prefix.length());
+ setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(username));
+ } else {
+ // redirect to server repositories page
+ setResponsePage(RepositoriesPage.class);
+ }
} else {
error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), latestModel));
}
diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html new file mode 100644 index 00000000..e9f12027 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.html @@ -0,0 +1,98 @@ +<!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:extend>
+<body onload="document.getElementById('name').focus();">
+ <form style="padding-top:5px;" wicket:id="editForm">
+<div class="row">
+ <div class="span12">
+
+ <table class="plain">
+ <tbody class="settings">
+ <tr>
+ <th><wicket:message key="gb.project"></wicket:message></th>
+ <td></td>
+ <th><wicket:message key="gb.name"></wicket:message></th>
+ </tr>
+ <tr>
+ <td><select class="span2" wicket:id="projectPath" /></td>
+ <td style="font-size:24px;color:#ccc;">/</td>
+ <td class="edit"><input class="span3" type="text" wicket:id="name" id="name" /> <span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div>
+ <b><wicket:message key="gb.description"></wicket:message></b><br/>
+ <input class="span6" type="text" wicket:id="description" />
+ </div>
+
+ <hr/>
+
+ <span wicket:id="permissionsGroup">
+ <div wicket:id="permissions">
+ <div style="display: inline-block;vertical-align: top;">
+ <input type="radio" wicket:id="radio" />
+ <img wicket:id="image"></img>
+ </div>
+ <div style="display: inline-block;vertical-align: top;">
+ <b><span wicket:id="name"></span></b><br/>
+ <span wicket:id="description"></span>
+ </div>
+ </div>
+ </span>
+
+ <hr/>
+
+ <h4><wicket:message key="gb.initialCommit"></wicket:message></h4>
+ <div>
+ <p><wicket:message key="gb.initialCommitDescription"></wicket:message></p>
+ </div>
+
+ <div style="clear:both;padding-top:10px;">
+ <div style="display: inline-block;vertical-align: top;">
+ <input type="checkbox" wicket:id="addReadme" />
+ </div>
+ <div style="display: inline-block;">
+ <b><wicket:message key="gb.initWithReadme"></wicket:message></b><br/>
+ <p><wicket:message key="gb.initWithReadmeDescription"></wicket:message></p>
+ </div>
+ </div>
+
+ <div style="clear:both;padding-top:10px;display:none;">
+ <!-- future GitFlow -->
+ <div style="display: inline-block;vertical-align: top;">
+ <input type="checkbox" wicket:id="addGitflow" />
+ </div>
+ <div style="display: inline-block;">
+ <b><wicket:message key="gb.initWithGitflow"></wicket:message></b>
+ <p><wicket:message key="gb.initWithGitflowDescription"></wicket:message></p>
+ </div>
+ </div>
+
+ <div style="clear:both;padding-top:10px;">
+ <div style="display: inline-block;vertical-align: top;">
+ <input type="checkbox" wicket:id="addGitignore" />
+ </div>
+ <div style="display:inline-block;">
+ <b><wicket:message key="gb.initWithGitignore"></wicket:message></b><br/>
+ <p><wicket:message key="gb.initWithGitignoreDescription"></wicket:message></p>
+ <p style="padding-top:5px;"><select class="span2" wicket:id="gitignore" /></p>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="row">
+<div class="span12">
+ <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Create" wicket:message="value:gb.create" wicket:id="create" /></div>
+</div>
+</div>
+
+</form>
+</body>
+</wicket:extend>
+</html>
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java new file mode 100644 index 00000000..b0cc3e95 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -0,0 +1,493 @@ +/*
+ * Copyright 2014 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.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.CheckBox;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.Radio;
+import org.apache.wicket.markup.html.form.RadioGroup;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheBuilder;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import com.gitblit.Constants;
+import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
+import com.gitblit.GitBlitException;
+import com.gitblit.Keys;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
+import com.gitblit.utils.ArrayUtils;
+import com.gitblit.utils.FileUtils;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.WicketUtils;
+
+public class NewRepositoryPage extends RootSubPage {
+
+ private final RepositoryModel repositoryModel;
+ private RadioGroup<Permission> permissionGroup;
+ private IModel<Boolean> addReadmeModel;
+ private Model<String> gitignoreModel;
+ private IModel<Boolean> addGitflowModel;
+ private IModel<Boolean> addGitignoreModel;
+
+ public NewRepositoryPage() {
+ // create constructor
+ super();
+ repositoryModel = new RepositoryModel();
+
+ setupPage(getString("gb.newRepository"), "");
+
+ setStatelessHint(false);
+ setOutputMarkupId(true);
+ }
+
+ @Override
+ protected boolean requiresPageMap() {
+ return true;
+ }
+
+ @Override
+ protected Class<? extends BasePage> getRootNavPageClass() {
+ return RepositoriesPage.class;
+ }
+
+ @Override
+ protected void onInitialize() {
+ super.onInitialize();
+
+ CompoundPropertyModel<RepositoryModel> rModel = new CompoundPropertyModel<>(repositoryModel);
+ Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", rModel) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void onSubmit() {
+
+ // confirm a repository name was entered
+ if (StringUtils.isEmpty(repositoryModel.name)) {
+ error(getString("gb.pleaseSetRepositoryName"));
+ return;
+ }
+
+ String project = repositoryModel.projectPath;
+ String fullName = (project + "/" + repositoryModel.name).trim();
+ fullName = fullName.replace('\\', '/');
+ fullName = fullName.replace("//", "/");
+ if (fullName.charAt(0) == '/') {
+ fullName = fullName.substring(1);
+ }
+ if (fullName.endsWith("/")) {
+ fullName = fullName.substring(0, fullName.length() - 1);
+ }
+
+ try {
+ if (fullName.contains("../")) {
+ error(getString("gb.illegalRelativeSlash"));
+ return;
+ }
+ if (fullName.contains("/../")) {
+ error(getString("gb.illegalRelativeSlash"));
+ return;
+ }
+
+ // confirm valid characters in repository name
+ Character c = StringUtils.findInvalidCharacter(fullName);
+ if (c != null) {
+ error(MessageFormat.format(getString("gb.illegalCharacterRepositoryName"),
+ c));
+ return;
+ }
+
+ repositoryModel.name = fullName;
+ repositoryModel.projectPath = null;
+
+ Permission permisison = permissionGroup.getModelObject();
+ repositoryModel.accessRestriction = permisison.type;
+ repositoryModel.authorizationControl = AuthorizationControl.NAMED;
+
+ repositoryModel.owners = new ArrayList<String>();
+ repositoryModel.owners.add(GitBlitWebSession.get().getUsername());
+
+ // setup branch defaults
+ boolean useGitFlow = addGitflowModel.getObject();
+
+ repositoryModel.HEAD = Constants.R_MASTER;
+ repositoryModel.mergeTo = Constants.MASTER;
+ if (useGitFlow) {
+ // tickets normally merge to develop unless they are hotfixes
+ repositoryModel.mergeTo = Constants.DEVELOP;
+ }
+
+ repositoryModel.allowForks = app().settings().getBoolean(Keys.web.allowForking, true);
+
+ // optionally generate an initial commit
+ boolean addReadme = addReadmeModel.getObject();
+ String gitignore = null;
+ boolean addGitignore = addGitignoreModel.getObject();
+ if (addGitignore) {
+ gitignore = gitignoreModel.getObject();
+ if (StringUtils.isEmpty(gitignore)) {
+ throw new GitBlitException("Please select a .gitignore file");
+ }
+ }
+
+ // init the repository
+ app().gitblit().updateRepositoryModel(repositoryModel.name, repositoryModel, true);
+
+ // optionally create an initial commit
+ initialCommit(repositoryModel, addReadme, gitignore, useGitFlow);
+
+ } catch (GitBlitException e) {
+ error(e.getMessage());
+
+ // restore project and name fields on error condition
+ repositoryModel.projectPath = StringUtils.getFirstPathElement(fullName);
+ if (!StringUtils.isEmpty(repositoryModel.projectPath)) {
+ repositoryModel.name = fullName.substring(repositoryModel.projectPath.length() + 1);
+ }
+ return;
+ }
+ setRedirect(true);
+ setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(fullName));
+ }
+ };
+
+ GitBlitWebSession session = GitBlitWebSession.get();
+ UserModel user = session.getUser();
+
+ // build project list for repository destination
+ String defaultProject = null;
+ List<String> projects = new ArrayList<String>();
+
+ if (user.canAdmin()) {
+ String main = app().settings().getString(Keys.web.repositoryRootGroupName, "main");
+ projects.add(main);
+ defaultProject = main;
+ }
+
+ if (user.canCreate()) {
+ projects.add(user.getPersonalPath());
+ if (defaultProject == null) {
+ // only prefer personal namespace if default is not already set
+ defaultProject = user.getPersonalPath();
+ }
+ }
+
+ repositoryModel.projectPath = defaultProject;
+
+ // do not let the browser pre-populate these fields
+ form.add(new SimpleAttributeModifier("autocomplete", "off"));
+
+ form.add(new DropDownChoice<String>("projectPath", projects));
+ form.add(new TextField<String>("name"));
+ form.add(new TextField<String>("description"));
+
+ Permission anonymousPermission = new Permission(getString("gb.anonymous"), getString("gb.anonymousRepoDescription"), "blank.png", AccessRestrictionType.NONE);
+ Permission publicPermission = new Permission(getString("gb.public"), getString("gb.publicRepoDescription"), "lock_go_16x16.png", AccessRestrictionType.PUSH);
+ Permission protectedPermission = new Permission(getString("gb.protected"), getString("gb.protectedRepoDescription"), "lock_pull_16x16.png", AccessRestrictionType.CLONE);
+ Permission privatePermission = new Permission(getString("gb.private"), getString("gb.privateRepoDescription"), "shield_16x16.png", AccessRestrictionType.VIEW);
+
+ List<Permission> permissions = new ArrayList<Permission>();
+ if (app().settings().getBoolean(Keys.git.allowAnonymousPushes, false)) {
+ permissions.add(anonymousPermission);
+ }
+ permissions.add(publicPermission);
+ permissions.add(protectedPermission);
+ permissions.add(privatePermission);
+
+ // determine default permission selection
+ AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName(
+ app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name()));
+ if (AccessRestrictionType.NONE == defaultRestriction) {
+ defaultRestriction = AccessRestrictionType.PUSH;
+ }
+
+ Permission defaultPermission = publicPermission;
+ for (Permission permission : permissions) {
+ if (permission.type == defaultRestriction) {
+ defaultPermission = permission;
+ }
+ }
+
+ permissionGroup = new RadioGroup<>("permissionsGroup", new Model<Permission>(defaultPermission));
+ form.add(permissionGroup);
+
+ ListView<Permission> permissionsList = new ListView<Permission>("permissions", permissions) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void populateItem(ListItem<Permission> item) {
+ Permission p = item.getModelObject();
+ item.add(new Radio<Permission>("radio", item.getModel()));
+ item.add(WicketUtils.newImage("image", p.image));
+ item.add(new Label("name", p.name));
+ item.add(new Label("description", p.description));
+ }
+ };
+ permissionGroup.add(permissionsList);
+
+ //
+ // initial commit options
+ //
+
+ // add README
+ addReadmeModel = Model.of(false);
+ form.add(new CheckBox("addReadme", addReadmeModel));
+
+ // add .gitignore
+ File gitignoreDir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
+ File [] files = gitignoreDir.listFiles();
+ if (files == null) {
+ files = new File[0];
+ }
+ List<String> gitignores = new ArrayList<String>();
+ for (File file : files) {
+ if (file.isFile() && file.getName().endsWith(".gitignore")) {
+ gitignores.add(StringUtils.stripFileExtension(file.getName()));
+ }
+ }
+ Collections.sort(gitignores);
+ gitignoreModel = Model.of("");
+ final DropDownChoice<String> gitignoreChoice = new DropDownChoice<String>("gitignore", gitignoreModel, gitignores);
+ gitignoreChoice.setOutputMarkupId(true);
+ form.add(gitignoreChoice.setEnabled(false));
+
+ addGitignoreModel = Model.of(false);
+ final CheckBox gitignoreCheckbox = new CheckBox("addGitignore", addGitignoreModel);
+ form.add(gitignoreCheckbox);
+
+ gitignoreCheckbox.add(new AjaxFormComponentUpdatingBehavior("onchange") {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void onUpdate(AjaxRequestTarget target) {
+ gitignoreChoice.setEnabled(addGitignoreModel.getObject());
+ target.addComponent(gitignoreChoice);
+ }
+ });
+
+ // TODO add .gitflow
+ addGitflowModel = Model.of(false);
+ form.add(new CheckBox("addGitflow", addGitflowModel));
+
+ form.add(new Button("create"));
+
+ add(form);
+ }
+
+ /**
+ * Prepare the initial commit for the repository.
+ *
+ * @param repository
+ * @param addReadme
+ * @param gitignore
+ * @param addGitFlow
+ * @return true if an initial commit was created
+ */
+ protected boolean initialCommit(RepositoryModel repository, boolean addReadme, String gitignore,
+ boolean addGitFlow) {
+ boolean initialCommit = addReadme || !StringUtils.isEmpty(gitignore) || addGitFlow;
+ if (!initialCommit) {
+ return false;
+ }
+
+ // build an initial commit
+ boolean success = false;
+ Repository db = app().repositories().getRepository(repositoryModel.name);
+ ObjectInserter odi = db.newObjectInserter();
+ try {
+
+ UserModel user = GitBlitWebSession.get().getUser();
+ PersonIdent author = new PersonIdent(user.getDisplayName(), user.emailAddress);
+
+ DirCache newIndex = DirCache.newInCore();
+ DirCacheBuilder indexBuilder = newIndex.builder();
+
+ if (addReadme) {
+ // insert a README
+ String title = StringUtils.stripDotGit(StringUtils.getLastPathElement(repositoryModel.name));
+ String description = repositoryModel.description == null ? "" : repositoryModel.description;
+ String readme = String.format("## %s\n\n%s\n\n", title, description);
+ byte [] bytes = readme.getBytes(Constants.ENCODING);
+
+ DirCacheEntry entry = new DirCacheEntry("README.md");
+ entry.setLength(bytes.length);
+ entry.setLastModified(System.currentTimeMillis());
+ entry.setFileMode(FileMode.REGULAR_FILE);
+ entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
+
+ indexBuilder.add(entry);
+ }
+
+ if (!StringUtils.isEmpty(gitignore)) {
+ // insert a .gitignore file
+ File dir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
+ File file = new File(dir, gitignore + ".gitignore");
+ if (file.exists() && file.length() > 0) {
+ byte [] bytes = FileUtils.readContent(file);
+ if (!ArrayUtils.isEmpty(bytes)) {
+ DirCacheEntry entry = new DirCacheEntry(".gitignore");
+ entry.setLength(bytes.length);
+ entry.setLastModified(System.currentTimeMillis());
+ entry.setFileMode(FileMode.REGULAR_FILE);
+ entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
+
+ indexBuilder.add(entry);
+ }
+ }
+ }
+
+ if (addGitFlow) {
+ // insert a .gitflow file
+ Config config = new Config();
+ config.setString("gitflow", null, "masterBranch", Constants.MASTER);
+ config.setString("gitflow", null, "developBranch", Constants.DEVELOP);
+ config.setString("gitflow", null, "featureBranchPrefix", "feature/");
+ config.setString("gitflow", null, "releaseBranchPrefix", "release/");
+ config.setString("gitflow", null, "hotfixBranchPrefix", "hotfix/");
+ config.setString("gitflow", null, "supportBranchPrefix", "support/");
+ config.setString("gitflow", null, "versionTagPrefix", "");
+
+ byte [] bytes = config.toText().getBytes(Constants.ENCODING);
+
+ DirCacheEntry entry = new DirCacheEntry(".gitflow");
+ entry.setLength(bytes.length);
+ entry.setLastModified(System.currentTimeMillis());
+ entry.setFileMode(FileMode.REGULAR_FILE);
+ entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));
+
+ indexBuilder.add(entry);
+ }
+
+ indexBuilder.finish();
+
+ if (newIndex.getEntryCount() == 0) {
+ // nothing to commit
+ return false;
+ }
+
+ ObjectId treeId = newIndex.writeTree(odi);
+
+ // Create a commit object
+ CommitBuilder commit = new CommitBuilder();
+ commit.setAuthor(author);
+ commit.setCommitter(author);
+ commit.setEncoding(Constants.ENCODING);
+ commit.setMessage("Initial commit");
+ commit.setTreeId(treeId);
+
+ // Insert the commit into the repository
+ ObjectId commitId = odi.insert(commit);
+ odi.flush();
+
+ // set the branch refs
+ RevWalk revWalk = new RevWalk(db);
+ try {
+ // set the master branch
+ RevCommit revCommit = revWalk.parseCommit(commitId);
+ RefUpdate masterRef = db.updateRef(Constants.R_MASTER);
+ masterRef.setNewObjectId(commitId);
+ masterRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
+ Result masterRC = masterRef.update();
+ switch (masterRC) {
+ case NEW:
+ success = true;
+ break;
+ default:
+ success = false;
+ }
+
+ if (addGitFlow) {
+ // set the develop branch for git-flow
+ RefUpdate developRef = db.updateRef(Constants.R_DEVELOP);
+ developRef.setNewObjectId(commitId);
+ developRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
+ Result developRC = developRef.update();
+ switch (developRC) {
+ case NEW:
+ success = true;
+ break;
+ default:
+ success = false;
+ }
+ }
+ } finally {
+ revWalk.release();
+ }
+ } catch (UnsupportedEncodingException e) {
+ logger().error(null, e);
+ } catch (IOException e) {
+ logger().error(null, e);
+ } finally {
+ odi.release();
+ db.close();
+ }
+ return success;
+ }
+
+ private static class Permission implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ final String name;
+ final String description;
+ final String image;
+ final AccessRestrictionType type;
+
+ Permission(String name, String description, String img, AccessRestrictionType type) {
+ this.name = name;
+ this.description = description;
+ this.image = img;
+ this.type = type;
+ }
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java index a2f3a497..b1c3639d 100644 --- a/src/main/java/com/gitblit/wicket/pages/RootPage.java +++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java @@ -607,7 +607,7 @@ public abstract class RootPage extends BasePage { List<MenuItem> standardItems = new ArrayList<MenuItem>(); standardItems.add(new MenuDivider()); if (user.canAdmin() || user.canCreate()) { - standardItems.add(new PageLinkMenuItem("gb.newRepository", EditRepositoryPage.class)); + standardItems.add(new PageLinkMenuItem("gb.newRepository", app().getNewRepositoryPage())); } standardItems.add(new PageLinkMenuItem("gb.myProfile", UserPage.class, WicketUtils.newUsernameParameter(user.username))); diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java index 6cb791eb..29b49b33 100644 --- a/src/main/java/com/gitblit/wicket/pages/UserPage.java +++ b/src/main/java/com/gitblit/wicket/pages/UserPage.java @@ -30,8 +30,8 @@ import org.eclipse.jgit.lib.PersonIdent; import com.gitblit.Keys;
import com.gitblit.models.Menu.ParameterMenuItem;
-import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
import com.gitblit.models.NavLink;
+import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
@@ -95,7 +95,7 @@ public class UserPage extends RootPage { UserModel sessionUser = GitBlitWebSession.get().getUser();
if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) {
// user can create personal repositories
- add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
} else {
add(new Label("newRepository").setVisible(false));
}
diff --git a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java index 45b0bab1..4433b043 100644 --- a/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java +++ b/src/main/java/com/gitblit/wicket/panels/FilterableRepositoryList.java @@ -33,7 +33,6 @@ import com.gitblit.utils.StringUtils; import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.freemarker.FreemarkerPanel;
import com.gitblit.wicket.ng.NgController;
-import com.gitblit.wicket.pages.EditRepositoryPage;
/**
* A client-side filterable rich repository list which uses Freemarker, Wicket,
@@ -98,7 +97,7 @@ public class FilterableRepositoryList extends BasePanel { }
if (allowCreate) {
- panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class));
+ panel.add(new LinkPanel(ngList + "Button", "btn btn-mini", getString("gb.newRepository"), app().getNewRepositoryPage()));
} else {
panel.add(new Label(ngList + "Button").setVisible(false));
}
diff --git a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java index dd208e23..8573e1a6 100644 --- a/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/RepositoriesPanel.java @@ -51,7 +51,6 @@ import com.gitblit.utils.StringUtils; 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.ProjectPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.SummaryPage;
@@ -87,12 +86,12 @@ public class RepositoriesPanel extends BasePanel { setResponsePage(RepositoriesPage.class);
}
}.setVisible(app().settings().getBoolean(Keys.git.cacheRepositoryList, true)));
- managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
add(managementLinks);
} else if (showManagement && user != null && user.canCreate()) {
// user can create personal repositories
managementLinks = new Fragment("managementPanel", "personalLinks", this);
- managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ managementLinks.add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
add(managementLinks);
} else {
// user has no management permissions
|