James Moger
2012-10-02 1f52c8b5f123b97fc631465479bc2855c12b9ee3
Moved the fork mechanism from a javascript link to a separate page
3 files added
8 files modified
222 ■■■■ changed files
resources/git-black.png patch | view | raw | blame | history
src/com/gitblit/GitBlit.java 17 ●●●● patch | view | raw | blame | history
src/com/gitblit/models/RepositoryModel.java 3 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebApp.properties 5 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/GitBlitWebSession.java 12 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/ForkPage.html 40 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/ForkPage.java 107 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/pages/RepositoryPage.java 30 ●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/ProjectRepositoryPanel.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/wicket/panels/RepositoriesPanel.java 4 ●●●● patch | view | raw | blame | history
resources/git-black.png
src/com/gitblit/GitBlit.java
@@ -2637,14 +2637,19 @@
     * 
     * @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);
        try {
            // clone the repository
        try {
            JGitUtils.cloneRepository(repositoriesFolder, cloneName, fromUrl, true, null);
        } catch (Exception e) {
            throw new GitBlitException(e);
        }
            
            // create a Gitblit repository model for the clone
            RepositoryModel cloneModel = repository.cloneAs(cloneName);
@@ -2671,10 +2676,6 @@
            
            // add this clone to the cached model
            addToCachedRepositoryList(cloneModel.name, cloneModel);
            return true;
        } catch (Exception e) {
            logger.error("failed to fork", e);
        }
        return false;
        return cloneModel;
    }
}
src/com/gitblit/models/RepositoryModel.java
@@ -145,7 +145,10 @@
    
    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;
src/com/gitblit/wicket/GitBlitWebApp.java
@@ -34,6 +34,7 @@
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;
@@ -120,6 +121,7 @@
        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) {
src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -323,7 +323,7 @@
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
@@ -334,3 +334,6 @@
gb.forksProhibited = forks prohibited
gb.forksProhibitedWarning = this repository forbids 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
src/com/gitblit/wicket/GitBlitWebSession.java
@@ -17,6 +17,7 @@
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
@@ -42,8 +43,11 @@
    
    private String requestUrl;
    
    private AtomicBoolean isForking;
    public GitBlitWebSession(Request request) {
        super(request);
        isForking = new AtomicBoolean();
    }
    public void invalidate() {
@@ -135,6 +139,14 @@
        return msg;
    }
    public boolean isForking() {
        return isForking.get();
    }
    public void isForking(boolean val) {
        isForking.set(val);
    }
    public static GitBlitWebSession get() {
        return (GitBlitWebSession) Session.get();
    }
src/com/gitblit/wicket/pages/ForkPage.html
New file
@@ -0,0 +1,40 @@
<!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>
src/com/gitblit/wicket/pages/ForkPage.java
New file
@@ -0,0 +1,107 @@
/*
 * 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);
            }
        }
    }
}
src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -28,12 +28,10 @@
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;
@@ -62,7 +60,6 @@
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;
@@ -172,6 +169,10 @@
        return pages;
    }
    protected boolean allowForkControls() {
        return true;
    }
    @Override
    protected void setupPage(String repositoryName, String pageName) {
        String projectName = StringUtils.getFirstPathElement(repositoryName);
@@ -230,7 +231,7 @@
        }
        // 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));
@@ -268,25 +269,8 @@
                // 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));
            }
        }
        
src/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
@@ -22,7 +22,6 @@
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;
@@ -153,7 +152,6 @@
                    @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)));
src/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -305,11 +305,11 @@
                        @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));