diff options
author | James Moger <james.moger@gitblit.com> | 2014-06-03 08:38:55 -0600 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2014-06-03 08:38:55 -0600 |
commit | 42972d830611fa4b1aa2c2c49c824a15e1987597 (patch) | |
tree | 8f3edf5322c852ab9b85f62fbd5b7ff7b15c4399 /src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java | |
parent | e1bcda8c6245035c96bf44ee09d61fa5a52bcafc (diff) | |
parent | b79824366fe4814e6912fa38f6da7939b6f27124 (diff) | |
download | gitblit-42972d830611fa4b1aa2c2c49c824a15e1987597.tar.gz gitblit-42972d830611fa4b1aa2c2c49c824a15e1987597.zip |
Merged #76 "Simplify repository creation with a new page"
Diffstat (limited to 'src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java')
-rw-r--r-- | src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java | 373 |
1 files changed, 373 insertions, 0 deletions
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..bc2c68cc --- /dev/null +++ b/src/main/java/com/gitblit/wicket/pages/NewRepositoryPage.java @@ -0,0 +1,373 @@ +/*
+ * 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.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.wicket.behavior.SimpleAttributeModifier;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+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;
+import com.gitblit.wicket.panels.AccessPolicyPanel;
+import com.gitblit.wicket.panels.CheckboxOption;
+import com.gitblit.wicket.panels.ConditionalChoiceOption;
+import com.gitblit.wicket.panels.RepositoryNamePanel;
+
+public class NewRepositoryPage extends RootSubPage {
+
+ private final RepositoryModel repositoryModel;
+ private IModel<Boolean> addReadmeModel;
+ private Model<String> gitignoreModel;
+ private IModel<Boolean> addGitflowModel;
+ private IModel<Boolean> addGitignoreModel;
+ private AccessPolicyPanel accessPolicyPanel;
+ private RepositoryNamePanel namePanel;
+
+ 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() {
+ try {
+ if (!namePanel.updateModel(repositoryModel)) {
+ return;
+ }
+ accessPolicyPanel.updateModel(repositoryModel);
+
+ 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(getString("gb.pleaseSelectGitIgnore"));
+ }
+ }
+
+ // 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());
+ namePanel.resetModel(repositoryModel);
+ return;
+ }
+ setRedirect(true);
+ setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
+ }
+ };
+
+ // do not let the browser pre-populate these fields
+ form.add(new SimpleAttributeModifier("autocomplete", "off"));
+
+ namePanel = new RepositoryNamePanel("namePanel", repositoryModel);
+ form.add(namePanel);
+
+ // prepare the default access controls
+ AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName(
+ app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name()));
+ if (AccessRestrictionType.NONE == defaultRestriction) {
+ defaultRestriction = AccessRestrictionType.PUSH;
+ }
+ AuthorizationControl defaultControl = AuthorizationControl.fromName(
+ app().settings().getString(Keys.git.defaultAuthorizationControl, AuthorizationControl.NAMED.name()));
+
+ if (AuthorizationControl.AUTHENTICATED == defaultControl) {
+ defaultRestriction = AccessRestrictionType.PUSH;
+ }
+
+ repositoryModel.authorizationControl = defaultControl;
+ repositoryModel.accessRestriction = defaultRestriction;
+
+ accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel);
+ form.add(accessPolicyPanel);
+
+ //
+ // initial commit options
+ //
+
+ // add README
+ addReadmeModel = Model.of(false);
+ form.add(new CheckboxOption("addReadme",
+ getString("gb.initWithReadme"),
+ getString("gb.initWithReadmeDescription"),
+ 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("");
+ addGitignoreModel = Model.of(false);
+ form.add(new ConditionalChoiceOption<String>("addGitIgnore",
+ getString("gb.initWithGitignore"),
+ getString("gb.initWithGitignoreDescription"),
+ addGitignoreModel,
+ gitignoreModel,
+ gitignores));
+
+ // TODO consider gitflow at creation (ticket-55)
+ addGitflowModel = Model.of(false);
+ form.add(new CheckboxOption("addGitFlow",
+ "Include a .gitflow file",
+ "This will generate a config file which guides Git clients in setting up Gitflow branches.",
+ addGitflowModel).setVisible(false));
+
+ 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;
+ }
+}
|