src/com/gitblit/GitBlit.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/models/UserModel.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/wicket/pages/ForksPage.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/wicket/pages/RepositoryPage.java | ●●●●● patch | view | raw | blame | history |
src/com/gitblit/GitBlit.java
@@ -32,6 +32,7 @@ import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -1327,6 +1328,81 @@ } /** * Determines if the specified user has a fork of the specified origin * repository. * * @param username * @param origin * @return true the if the user has a fork */ public boolean hasFork(String username, String origin) { return getFork(username, origin) != null; } /** * Gets the name of a user's fork of the specified origin * repository. * * @param username * @param origin * @return the name of the user's fork, null otherwise */ public String getFork(String username, String origin) { String userProject = "~" + username.toLowerCase(); if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) { String userPath = userProject + "/"; // collect all origin nodes in fork network Set<String> roots = new HashSet<String>(); roots.add(origin); RepositoryModel originModel = repositoryListCache.get(origin); while (originModel != null) { if (!ArrayUtils.isEmpty(originModel.forks)) { for (String fork : originModel.forks) { if (!fork.startsWith(userPath)) { roots.add(fork); } } } if (originModel.originRepository != null) { roots.add(originModel.originRepository); originModel = repositoryListCache.get(originModel.originRepository); } else { // break originModel = null; } } for (String repository : repositoryListCache.keySet()) { if (repository.toLowerCase().startsWith(userPath)) { RepositoryModel model = repositoryListCache.get(repository); if (!StringUtils.isEmpty(model.originRepository)) { if (roots.contains(model.originRepository)) { // user has a fork in this graph return model.name; } } } } } else { // not caching ProjectModel project = getProjectModel(userProject); for (String repository : project.repositories) { if (repository.toLowerCase().startsWith(userProject)) { RepositoryModel model = repositoryListCache.get(repository); if (model.originRepository.equalsIgnoreCase(origin)) { // user has a fork return model.name; } } } } // user does not have a fork return null; } /** * Returns the size in bytes of the repository. Gitblit caches the * repository sizes to reduce the performance penalty of recursive * calculation. The cache is updated if the repository has been changed src/com/gitblit/models/UserModel.java
@@ -86,6 +86,16 @@ return false; } public boolean canViewRepository(RepositoryModel repository) { if (canAdmin) { return true; } if (repository.accessRestriction.atLeast(AccessRestrictionType.VIEW)) { return canAccessRepository(repository); } return true; } public boolean canForkRepository(RepositoryModel repository) { if (canAdmin) { return true; src/com/gitblit/wicket/pages/ForksPage.java
@@ -42,26 +42,32 @@ public ForksPage(PageParameters params) { super(params); UserModel user = GitBlitWebSession.get().getUser(); RepositoryModel model = getRepositoryModel(); RepositoryModel origin; RepositoryModel origin = model; List<String> list; if (ArrayUtils.isEmpty(model.forks)) { // origin repository has forks if (!StringUtils.isEmpty(model.originRepository)) { // try origin repository origin = GitBlit.self().getRepositoryModel(model.originRepository); } if (origin == null || origin.forks == null) { list = new ArrayList<String>(); } else { list = new ArrayList<String>(origin.forks); } } else { // this repository has forks origin = model; list = new ArrayList<String>(model.forks); } if (origin.isPersonalRepository()) { // personal repository UserModel user = GitBlit.self().getUserModel(origin.projectPath.substring(1)); PersonIdent ident = new PersonIdent(user.getDisplayName(), user.emailAddress); UserModel originUser = GitBlit.self().getUserModel(origin.projectPath.substring(1)); PersonIdent ident = new PersonIdent(originUser.getDisplayName(), originUser.emailAddress); add(new GravatarImage("forkSourceAvatar", ident, 20)); add(new Label("forkSourceSwatch").setVisible(false)); add(new LinkPanel("forkSourceProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username))); add(new LinkPanel("forkSourceProject", null, originUser.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(originUser.username))); } else { // standard repository add(new GravatarImage("forkSourceAvatar", new PersonIdent("", ""), 20).setVisible(false)); @@ -85,10 +91,15 @@ } String source = StringUtils.getLastPathElement(origin.name); if (user != null && user.canViewRepository(origin)) { // user can view the origin add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(origin.name))); } else { // user can not view the origin add(new Label("forkSource", StringUtils.stripDotGit(source))); } // only display user-accessible forks UserModel user = GitBlitWebSession.get().getUser(); List<RepositoryModel> forks = new ArrayList<RepositoryModel>(); for (String aFork : list) { RepositoryModel fork = GitBlit.self().getRepositoryModel(user, aFork); src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -136,21 +136,11 @@ pages.put("branches", new PageRegistration("gb.branches", BranchesPage.class, params)); pages.put("tags", new PageRegistration("gb.tags", TagsPage.class, params)); pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params)); pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params)); // conditional links Repository r = getRepository(); RepositoryModel model = getRepositoryModel(); // forks list button if (StringUtils.isEmpty(model.originRepository)) { if (!ArrayUtils.isEmpty(model.forks)) { // this origin repository has forks pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params)); } } else { // this is a fork of another repository pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params)); } // per-repository extra page links if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) { @@ -204,15 +194,29 @@ WicketUtils.newRepositoryParameter(repositoryName))); add(new Label("pageName", pageName).setRenderBodyOnly(true)); UserModel user = GitBlitWebSession.get().getUser(); // indicate origin repository RepositoryModel model = getRepositoryModel(); if (StringUtils.isEmpty(model.originRepository)) { add(new Label("originRepository").setVisible(false)); } else { RepositoryModel origin = GitBlit.self().getRepositoryModel(model.originRepository); if (origin == null) { // no origin repository add(new Label("originRepository").setVisible(false)); } else if (!user.canViewRepository(origin)) { // show origin repository without link Fragment forkFrag = new Fragment("originRepository", "originFragment", this); forkFrag.add(new Label("originRepository", StringUtils.stripDotGit(model.originRepository))); add(forkFrag); } else { // link to origin repository Fragment forkFrag = new Fragment("originRepository", "originFragment", this); forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(model.originRepository), SummaryPage.class, WicketUtils.newRepositoryParameter(model.originRepository))); add(forkFrag); } } if (getRepositoryModel().isBare) { @@ -225,32 +229,56 @@ add(wc); } if (getRepositoryModel().allowForks) { // fork controls if (user == null) { // must be logged-in to fork, hide all fork controls add(new ExternalLink("forkLink", "").setVisible(false)); add(new ExternalLink("myForkLink", "").setVisible(false)); add(new Label("forksProhibitedIndicator").setVisible(false)); } else { String fork = GitBlit.self().getFork(user.username, model.name); boolean hasFork = fork != null; boolean canFork = user.canForkRepository(model); if (hasFork || !canFork) { // user not allowed to fork or fork already exists or repo forbids forking add(new ExternalLink("forkLink", "").setVisible(false)); if (user.canFork && !model.allowForks) { // show forks prohibited indicator Fragment wc = new Fragment("forksProhibitedIndicator", "forksProhibitedFragment", this); Label lbl = new Label("forksProhibited", getString("gb.forksProhibited")); WicketUtils.setHtmlTooltip(lbl, getString("gb.forksProhibitedWarning")); wc.add(lbl); add(wc); } else { // can not fork, no need for forks prohibited indicator add(new Label("forksProhibitedIndicator").setVisible(false)); } UserModel user = GitBlitWebSession.get().getUser(); // fork button if (user != null) { final String clonedRepo = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(model.name))); boolean hasClone = GitBlit.self().hasRepository(clonedRepo) && !getRepositoryModel().name.equals(clonedRepo); if (user.canForkRepository(model) && !hasClone) { if (hasFork && !fork.equals(model.name)) { // user has fork, view my fork link String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(fork)).toString(); add(new ExternalLink("myForkLink", url)); } else { // no fork, hide view my fork link add(new ExternalLink("myForkLink", "").setVisible(false)); } } else if (canFork) { // 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(clonedRepo)); throw new RedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(asFork)); } else { error(MessageFormat.format(getString("gb.repositoryForkFailed"), model)); } @@ -259,23 +287,7 @@ forkLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( getString("gb.forkRepository"), getRepositoryModel()))); add(forkLink); } else { // user not allowed to fork or fork already exists or repo forbids forking add(new ExternalLink("forkLink", "").setVisible(false)); } if (hasClone) { // user has clone String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(clonedRepo)).toString(); add(new ExternalLink("myForkLink", url)); } else { // user does not have clone add(new ExternalLink("myForkLink", "").setVisible(false)); } } else { // server prohibits forking add(new ExternalLink("forkLink", "").setVisible(false)); add(new ExternalLink("myForkLink", "").setVisible(false)); } super.setupPage(repositoryName, pageName);