Moved the fork mechanism from a javascript link to a separate page
3 files added
8 files modified
| | |
| | | *
|
| | | * @param repository
|
| | | * @param user
|
| | | * @return true, if successful
|
| | | * @return the repository model of the fork, if successful
|
| | | * @throws GitBlitException
|
| | | */
|
| | | public boolean fork(RepositoryModel repository, UserModel user) {
|
| | | public RepositoryModel fork(RepositoryModel repository, UserModel user) throws GitBlitException {
|
| | | String cloneName = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(repository.name)));
|
| | | String fromUrl = MessageFormat.format("file://{0}/{1}", repositoriesFolder.getAbsolutePath(), repository.name);
|
| | |
|
| | | // clone the repository
|
| | | try {
|
| | | // clone the repository
|
| | | JGitUtils.cloneRepository(repositoriesFolder, cloneName, fromUrl, true, null);
|
| | | |
| | | // create a Gitblit repository model for the clone
|
| | | RepositoryModel cloneModel = repository.cloneAs(cloneName);
|
| | | cloneModel.owner = user.username;
|
| | | updateRepositoryModel(cloneName, cloneModel, false);
|
| | | |
| | | if (AuthorizationControl.NAMED.equals(cloneModel.authorizationControl)) {
|
| | | // add the owner of the source repository to the clone's access list
|
| | | if (!StringUtils.isEmpty(repository.owner)) {
|
| | | UserModel owner = getUserModel(repository.owner);
|
| | | if (owner != null) {
|
| | | owner.repositories.add(cloneName);
|
| | | updateUserModel(owner.username, owner, false);
|
| | | }
|
| | | }
|
| | | |
| | | // inherit origin's access lists
|
| | | List<String> users = getRepositoryUsers(repository);
|
| | | setRepositoryUsers(cloneModel, users);
|
| | | |
| | | List<String> teams = getRepositoryTeams(repository);
|
| | | setRepositoryTeams(cloneModel, teams);
|
| | | }
|
| | | |
| | | // add this clone to the cached model
|
| | | addToCachedRepositoryList(cloneModel.name, cloneModel);
|
| | | return true;
|
| | | } catch (Exception e) {
|
| | | logger.error("failed to fork", e);
|
| | | throw new GitBlitException(e);
|
| | | }
|
| | | return false;
|
| | |
|
| | | // create a Gitblit repository model for the clone
|
| | | RepositoryModel cloneModel = repository.cloneAs(cloneName);
|
| | | cloneModel.owner = user.username;
|
| | | updateRepositoryModel(cloneName, cloneModel, false);
|
| | |
|
| | | if (AuthorizationControl.NAMED.equals(cloneModel.authorizationControl)) {
|
| | | // add the owner of the source repository to the clone's access list
|
| | | if (!StringUtils.isEmpty(repository.owner)) {
|
| | | UserModel owner = getUserModel(repository.owner);
|
| | | if (owner != null) {
|
| | | owner.repositories.add(cloneName);
|
| | | updateUserModel(owner.username, owner, false);
|
| | | }
|
| | | }
|
| | |
|
| | | // inherit origin's access lists
|
| | | List<String> users = getRepositoryUsers(repository);
|
| | | setRepositoryUsers(cloneModel, users);
|
| | |
|
| | | List<String> teams = getRepositoryTeams(repository);
|
| | | setRepositoryTeams(cloneModel, teams);
|
| | | }
|
| | |
|
| | | // add this clone to the cached model
|
| | | addToCachedRepositoryList(cloneModel.name, cloneModel);
|
| | | return cloneModel;
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | public RepositoryModel cloneAs(String cloneName) {
|
| | | RepositoryModel clone = new RepositoryModel();
|
| | | clone.originRepository = name;
|
| | | clone.name = cloneName;
|
| | | clone.projectPath = StringUtils.getFirstPathElement(cloneName);
|
| | | clone.isBare = true;
|
| | | clone.description = description;
|
| | | clone.accessRestriction = accessRestriction;
|
| | | clone.authorizationControl = authorizationControl;
|
| | |
| | | import com.gitblit.wicket.pages.CommitPage;
|
| | | import com.gitblit.wicket.pages.DocsPage;
|
| | | import com.gitblit.wicket.pages.FederationRegistrationPage;
|
| | | import com.gitblit.wicket.pages.ForkPage;
|
| | | import com.gitblit.wicket.pages.ForksPage;
|
| | | import com.gitblit.wicket.pages.GitSearchPage;
|
| | | import com.gitblit.wicket.pages.GravatarProfilePage;
|
| | |
| | | mount("/projects", ProjectsPage.class);
|
| | | mount("/user", UserPage.class, "user");
|
| | | mount("/forks", ForksPage.class, "r");
|
| | | mount("/fork", ForkPage.class, "r");
|
| | | }
|
| | |
|
| | | private void mount(String location, Class<? extends WebPage> clazz, String... parameters) {
|
| | |
| | | gb.forks = forks
|
| | | gb.forkRepository = fork {0}?
|
| | | gb.repositoryForked = {0} has been forked
|
| | | gb.repositoryForkFailed= failed to fork {1}
|
| | | gb.repositoryForkFailed= fork has failed
|
| | | gb.personalRepositories = personal repositories
|
| | | gb.allowForks = allow forks
|
| | | gb.allowForksDescription = allow authorized users to fork this repository
|
| | |
| | | gb.myFork = view my fork
|
| | | gb.forksProhibited = forks prohibited
|
| | | gb.forksProhibitedWarning = this repository forbids forks
|
| | | gb.noForks = {0} has no forks |
| | | gb.noForks = {0} has no forks
|
| | | gb.forkNotAuthorized = sorry, you are not authorized to fork {0}
|
| | | gb.forkInProgress = fork in progress
|
| | | gb.preparingFork = Gitblit is preparing your fork |
| | |
| | |
|
| | | import java.util.Map;
|
| | | import java.util.TimeZone;
|
| | | import java.util.concurrent.atomic.AtomicBoolean;
|
| | |
|
| | | import org.apache.wicket.Page;
|
| | | import org.apache.wicket.PageParameters;
|
| | |
| | |
|
| | | private String requestUrl;
|
| | |
|
| | | private AtomicBoolean isForking;
|
| | | |
| | | public GitBlitWebSession(Request request) {
|
| | | super(request);
|
| | | isForking = new AtomicBoolean();
|
| | | }
|
| | |
|
| | | public void invalidate() {
|
| | |
| | | errorMessage = null;
|
| | | return msg;
|
| | | }
|
| | | |
| | | public boolean isForking() {
|
| | | return isForking.get();
|
| | | }
|
| | | |
| | | public void isForking(boolean val) {
|
| | | isForking.set(val);
|
| | | }
|
| | |
|
| | | public static GitBlitWebSession get() {
|
| | | return (GitBlitWebSession) Session.get();
|
New file |
| | |
| | | <!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"> |
| | |
|
| | | <body>
|
| | | <wicket:head>
|
| | | <noscript>
|
| | | <meta http-equiv="refresh" content="5"></meta>
|
| | | </noscript>
|
| | | <script type="text/javascript"">
|
| | | function doLoad() { setTimeout( "refresh()", 5*1000 ); }
|
| | | function refresh() { window.location.reload(); }
|
| | | </script>
|
| | | </wicket:head>
|
| | | <wicket:extend>
|
| | | <!-- need to specify body.onload -->
|
| | | <body onload="doLoad()">
|
| | |
|
| | | <div class="row">
|
| | | <div class="span6 offset3">
|
| | | <div wicket:id="forkText" class="pageTitle project" style="border:0;font-weight:bold; text-align:center;">[fork text]</div>
|
| | | </div>
|
| | | <div class="span4 offset4">
|
| | | <div class="progress progress-striped active">
|
| | | <div class="bar" style="width: 100%;"></div>
|
| | | </div>
|
| | | </div>
|
| | | <div class="span6 offset3">
|
| | | <div style="opacity:0.2;">
|
| | | <center><img style="padding:10px" src="git-black.png"></img></center>
|
| | | </div>
|
| | | </div>
|
| | | </div>
|
| | | </body>
|
| | |
|
| | | </wicket:extend> |
| | | </body>
|
| | | </html> |
New file |
| | |
| | | /*
|
| | | * Copyright 2012 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 org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.slf4j.LoggerFactory;
|
| | |
|
| | | import com.gitblit.GitBlit;
|
| | | import com.gitblit.models.RepositoryModel;
|
| | | import com.gitblit.models.UserModel;
|
| | | import com.gitblit.wicket.GitBlitWebSession;
|
| | | import com.gitblit.wicket.GitblitRedirectException;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | |
|
| | | public class ForkPage extends RepositoryPage {
|
| | |
|
| | |
|
| | | public ForkPage(PageParameters params) {
|
| | | super(params);
|
| | |
|
| | | setVersioned(false);
|
| | | |
| | | GitBlitWebSession session = GitBlitWebSession.get();
|
| | |
|
| | | RepositoryModel repository = getRepositoryModel();
|
| | | UserModel user = session.getUser();
|
| | | boolean canFork = user.canForkRepository(repository);
|
| | |
|
| | | if (!canFork) {
|
| | | // redirect to the summary page if this repository is not empty
|
| | | GitBlitWebSession.get().cacheErrorMessage(
|
| | | MessageFormat.format(getString("gb.forkNotAuthorized"), repository.name));
|
| | | throw new GitblitRedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(repository.name));
|
| | | }
|
| | |
|
| | | String fork = GitBlit.self().getFork(user.username, repository.name);
|
| | | if (fork != null) {
|
| | | // redirect to user's fork
|
| | | throw new GitblitRedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(fork));
|
| | | }
|
| | |
|
| | | add(new Label("forkText", getString("gb.preparingFork")));
|
| | |
|
| | | if (!session.isForking()) {
|
| | | // prepare session
|
| | | session.isForking(true);
|
| | |
|
| | | // fork it
|
| | | ForkThread forker = new ForkThread(repository, session);
|
| | | forker.start();
|
| | | }
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected boolean allowForkControls() {
|
| | | return false;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected String getPageName() {
|
| | | return "fork";
|
| | | }
|
| | |
|
| | | /**
|
| | | * ForkThread does the work of working the repository in a background
|
| | | * thread. The completion status is tracked through a session variable and
|
| | | * monitored by this page.
|
| | | */
|
| | | private static class ForkThread extends Thread {
|
| | |
|
| | | private final RepositoryModel repository;
|
| | | private final GitBlitWebSession session;
|
| | |
|
| | | public ForkThread(RepositoryModel repository, GitBlitWebSession session) {
|
| | | this.repository = repository;
|
| | | this.session = session;
|
| | | }
|
| | |
|
| | | @Override
|
| | | public void run() {
|
| | | UserModel user = session.getUser();
|
| | | try {
|
| | | GitBlit.self().fork(repository, user);
|
| | | } catch (Exception e) {
|
| | | LoggerFactory.getLogger(ForkPage.class).error(MessageFormat.format("Failed to fork {0} for {1}", repository.name, user.username), e);
|
| | | } finally {
|
| | | session.isForking(false);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.RedirectException;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.form.DropDownChoice;
|
| | | import org.apache.wicket.markup.html.form.TextField;
|
| | | import org.apache.wicket.markup.html.link.ExternalLink;
|
| | | import org.apache.wicket.markup.html.link.Link;
|
| | | import org.apache.wicket.markup.html.panel.Fragment;
|
| | | import org.apache.wicket.model.IModel;
|
| | | import org.apache.wicket.model.Model;
|
| | |
| | | import com.gitblit.wicket.PageRegistration.OtherPageLink;
|
| | | import com.gitblit.wicket.SessionlessForm;
|
| | | import com.gitblit.wicket.WicketUtils;
|
| | | import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
|
| | | import com.gitblit.wicket.panels.LinkPanel;
|
| | | import com.gitblit.wicket.panels.NavigationPanel;
|
| | | import com.gitblit.wicket.panels.RefsPanel;
|
| | |
| | | }
|
| | | return pages;
|
| | | }
|
| | | |
| | | protected boolean allowForkControls() {
|
| | | return true;
|
| | | }
|
| | |
|
| | | @Override
|
| | | protected void setupPage(String repositoryName, String pageName) {
|
| | |
| | | }
|
| | |
|
| | | // fork controls
|
| | | if (user == null) {
|
| | | if (!allowForkControls() || user == null) {
|
| | | // must be logged-in to fork, hide all fork controls
|
| | | add(new ExternalLink("forkLink", "").setVisible(false));
|
| | | add(new ExternalLink("myForkLink", "").setVisible(false));
|
| | |
| | | // can fork and we do not have one
|
| | | add(new Label("forksProhibitedIndicator").setVisible(false));
|
| | | add(new ExternalLink("myForkLink", "").setVisible(false));
|
| | | Link<Void> forkLink = new Link<Void>("forkLink") {
|
| | |
|
| | | private static final long serialVersionUID = 1L;
|
| | |
|
| | | @Override
|
| | | public void onClick() {
|
| | | UserModel user = GitBlitWebSession.get().getUser();
|
| | | RepositoryModel model = getRepositoryModel();
|
| | | String asFork = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(model.name)));
|
| | | if (GitBlit.self().fork(model, GitBlitWebSession.get().getUser())) {
|
| | | throw new RedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(asFork));
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryForkFailed"), model));
|
| | | }
|
| | | }
|
| | | };
|
| | | forkLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
|
| | | getString("gb.forkRepository"), getRepositoryModel())));
|
| | | add(forkLink);
|
| | | String url = getRequestCycle().urlFor(ForkPage.class, WicketUtils.newRepositoryParameter(model.name)).toString();
|
| | | add(new ExternalLink("forkLink", url));
|
| | | }
|
| | | }
|
| | |
|
| | |
| | |
|
| | | import org.apache.wicket.Component;
|
| | | import org.apache.wicket.Localizer;
|
| | | import org.apache.wicket.Page;
|
| | | import org.apache.wicket.PageParameters;
|
| | | import org.apache.wicket.markup.html.basic.Label;
|
| | | import org.apache.wicket.markup.html.link.BookmarkablePageLink;
|
| | |
| | | @Override
|
| | | public void onClick() {
|
| | | if (GitBlit.self().deleteRepositoryModel(entry)) {
|
| | | info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
|
| | | // redirect to the owning page
|
| | | if (entry.isPersonalRepository()) {
|
| | | setResponsePage(getPage().getClass(), WicketUtils.newUsernameParameter(entry.projectPath.substring(1)));
|
| | |
| | | @Override
|
| | | public void onClick() {
|
| | | if (GitBlit.self().deleteRepositoryModel(entry)) {
|
| | | info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
|
| | | if (dp instanceof SortableRepositoriesProvider) {
|
| | | info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
|
| | | ((SortableRepositoriesProvider) dp).remove(entry);
|
| | | } else {
|
| | | ((RepositoriesProvider) dp).remove(entry);
|
| | | setResponsePage(getPage().getClass(), getPage().getPageParameters());
|
| | | }
|
| | | } else {
|
| | | error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry));
|