import java.util.Collections;\r
import java.util.Date;\r
import java.util.HashMap;\r
+import java.util.HashSet;\r
import java.util.LinkedHashMap;\r
import java.util.LinkedHashSet;\r
import java.util.List;\r
r.close();\r
return true;\r
}\r
+ \r
+ /**\r
+ * Determines if the specified user has a fork of the specified origin\r
+ * repository.\r
+ * \r
+ * @param username\r
+ * @param origin\r
+ * @return true the if the user has a fork\r
+ */\r
+ public boolean hasFork(String username, String origin) {\r
+ return getFork(username, origin) != null;\r
+ }\r
+ \r
+ /**\r
+ * Gets the name of a user's fork of the specified origin\r
+ * repository.\r
+ * \r
+ * @param username\r
+ * @param origin\r
+ * @return the name of the user's fork, null otherwise\r
+ */\r
+ public String getFork(String username, String origin) {\r
+ String userProject = "~" + username.toLowerCase();\r
+ if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {\r
+ String userPath = userProject + "/";\r
+\r
+ // collect all origin nodes in fork network\r
+ Set<String> roots = new HashSet<String>();\r
+ roots.add(origin);\r
+ RepositoryModel originModel = repositoryListCache.get(origin);\r
+ while (originModel != null) {\r
+ if (!ArrayUtils.isEmpty(originModel.forks)) {\r
+ for (String fork : originModel.forks) {\r
+ if (!fork.startsWith(userPath)) {\r
+ roots.add(fork);\r
+ }\r
+ }\r
+ }\r
+ \r
+ if (originModel.originRepository != null) {\r
+ roots.add(originModel.originRepository);\r
+ originModel = repositoryListCache.get(originModel.originRepository);\r
+ } else {\r
+ // break\r
+ originModel = null;\r
+ }\r
+ }\r
+ \r
+ for (String repository : repositoryListCache.keySet()) {\r
+ if (repository.toLowerCase().startsWith(userPath)) {\r
+ RepositoryModel model = repositoryListCache.get(repository);\r
+ if (!StringUtils.isEmpty(model.originRepository)) {\r
+ if (roots.contains(model.originRepository)) {\r
+ // user has a fork in this graph\r
+ return model.name;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ // not caching\r
+ ProjectModel project = getProjectModel(userProject);\r
+ for (String repository : project.repositories) {\r
+ if (repository.toLowerCase().startsWith(userProject)) {\r
+ RepositoryModel model = repositoryListCache.get(repository);\r
+ if (model.originRepository.equalsIgnoreCase(origin)) {\r
+ // user has a fork\r
+ return model.name;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ // user does not have a fork\r
+ return null;\r
+ }\r
\r
/**\r
* Returns the size in bytes of the repository. Gitblit caches the\r
public ForksPage(PageParameters params) {\r
super(params);\r
\r
+ UserModel user = GitBlitWebSession.get().getUser();\r
RepositoryModel model = getRepositoryModel();\r
- RepositoryModel origin;\r
+ RepositoryModel origin = model;\r
List<String> list;\r
if (ArrayUtils.isEmpty(model.forks)) {\r
- // origin repository has forks\r
- origin = GitBlit.self().getRepositoryModel(model.originRepository);\r
- list = new ArrayList<String>(origin.forks);\r
+ if (!StringUtils.isEmpty(model.originRepository)) {\r
+ // try origin repository\r
+ origin = GitBlit.self().getRepositoryModel(model.originRepository);\r
+ }\r
+ if (origin == null || origin.forks == null) {\r
+ list = new ArrayList<String>();\r
+ } else {\r
+ list = new ArrayList<String>(origin.forks);\r
+ }\r
} else {\r
// this repository has forks\r
- origin = model;\r
list = new ArrayList<String>(model.forks);\r
}\r
\r
if (origin.isPersonalRepository()) {\r
// personal repository\r
- UserModel user = GitBlit.self().getUserModel(origin.projectPath.substring(1));\r
- PersonIdent ident = new PersonIdent(user.getDisplayName(), user.emailAddress);\r
+ UserModel originUser = GitBlit.self().getUserModel(origin.projectPath.substring(1));\r
+ PersonIdent ident = new PersonIdent(originUser.getDisplayName(), originUser.emailAddress);\r
add(new GravatarImage("forkSourceAvatar", ident, 20));\r
add(new Label("forkSourceSwatch").setVisible(false));\r
- add(new LinkPanel("forkSourceProject", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(user.username)));\r
+ add(new LinkPanel("forkSourceProject", null, originUser.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(originUser.username)));\r
} else {\r
// standard repository\r
add(new GravatarImage("forkSourceAvatar", new PersonIdent("", ""), 20).setVisible(false));\r
}\r
\r
String source = StringUtils.getLastPathElement(origin.name);\r
- add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(origin.name)));\r
+ if (user != null && user.canViewRepository(origin)) {\r
+ // user can view the origin\r
+ add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(origin.name)));\r
+ } else {\r
+ // user can not view the origin\r
+ add(new Label("forkSource", StringUtils.stripDotGit(source)));\r
+ }\r
\r
// only display user-accessible forks\r
- UserModel user = GitBlitWebSession.get().getUser();\r
List<RepositoryModel> forks = new ArrayList<RepositoryModel>();\r
for (String aFork : list) {\r
RepositoryModel fork = GitBlit.self().getRepositoryModel(user, aFork);\r
pages.put("branches", new PageRegistration("gb.branches", BranchesPage.class, params));\r
pages.put("tags", new PageRegistration("gb.tags", TagsPage.class, params));\r
pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));\r
+ pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params));\r
\r
// conditional links\r
Repository r = getRepository();\r
RepositoryModel model = getRepositoryModel();\r
\r
- // forks list button\r
- if (StringUtils.isEmpty(model.originRepository)) {\r
- if (!ArrayUtils.isEmpty(model.forks)) {\r
- // this origin repository has forks\r
- pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params));\r
- }\r
- } else {\r
- // this is a fork of another repository\r
- pages.put("forks", new PageRegistration("gb.forks", ForksPage.class, params));\r
- }\r
- \r
// per-repository extra page links\r
if (model.useTickets && TicgitUtils.getTicketsBranch(r) != null) {\r
pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, params));\r
WicketUtils.newRepositoryParameter(repositoryName)));\r
add(new Label("pageName", pageName).setRenderBodyOnly(true));\r
\r
+ UserModel user = GitBlitWebSession.get().getUser();\r
+\r
// indicate origin repository\r
RepositoryModel model = getRepositoryModel();\r
if (StringUtils.isEmpty(model.originRepository)) {\r
add(new Label("originRepository").setVisible(false));\r
} else {\r
- Fragment forkFrag = new Fragment("originRepository", "originFragment", this);\r
- forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(model.originRepository), \r
- SummaryPage.class, WicketUtils.newRepositoryParameter(model.originRepository)));\r
- add(forkFrag);\r
+ RepositoryModel origin = GitBlit.self().getRepositoryModel(model.originRepository);\r
+ if (origin == null) {\r
+ // no origin repository\r
+ add(new Label("originRepository").setVisible(false));\r
+ } else if (!user.canViewRepository(origin)) {\r
+ // show origin repository without link\r
+ Fragment forkFrag = new Fragment("originRepository", "originFragment", this);\r
+ forkFrag.add(new Label("originRepository", StringUtils.stripDotGit(model.originRepository)));\r
+ add(forkFrag);\r
+ } else {\r
+ // link to origin repository\r
+ Fragment forkFrag = new Fragment("originRepository", "originFragment", this);\r
+ forkFrag.add(new LinkPanel("originRepository", null, StringUtils.stripDotGit(model.originRepository), \r
+ SummaryPage.class, WicketUtils.newRepositoryParameter(model.originRepository)));\r
+ add(forkFrag);\r
+ }\r
}\r
\r
if (getRepositoryModel().isBare) {\r
wc.add(lbl);\r
add(wc);\r
}\r
- \r
- if (getRepositoryModel().allowForks) {\r
+\r
+ // fork controls\r
+ if (user == null) {\r
+ // must be logged-in to fork, hide all fork controls\r
+ add(new ExternalLink("forkLink", "").setVisible(false));\r
+ add(new ExternalLink("myForkLink", "").setVisible(false));\r
add(new Label("forksProhibitedIndicator").setVisible(false));\r
} else {\r
- Fragment wc = new Fragment("forksProhibitedIndicator", "forksProhibitedFragment", this);\r
- Label lbl = new Label("forksProhibited", getString("gb.forksProhibited"));\r
- WicketUtils.setHtmlTooltip(lbl, getString("gb.forksProhibitedWarning"));\r
- wc.add(lbl);\r
- add(wc);\r
- }\r
- \r
- UserModel user = GitBlitWebSession.get().getUser();\r
- \r
- // fork button\r
- if (user != null) { \r
- final String clonedRepo = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(model.name)));\r
- boolean hasClone = GitBlit.self().hasRepository(clonedRepo) && !getRepositoryModel().name.equals(clonedRepo);\r
- if (user.canForkRepository(model) && !hasClone) {\r
+ String fork = GitBlit.self().getFork(user.username, model.name);\r
+ boolean hasFork = fork != null;\r
+ boolean canFork = user.canForkRepository(model);\r
+\r
+ if (hasFork || !canFork) {\r
+ // user not allowed to fork or fork already exists or repo forbids forking\r
+ add(new ExternalLink("forkLink", "").setVisible(false));\r
+ \r
+ if (user.canFork && !model.allowForks) {\r
+ // show forks prohibited indicator\r
+ Fragment wc = new Fragment("forksProhibitedIndicator", "forksProhibitedFragment", this);\r
+ Label lbl = new Label("forksProhibited", getString("gb.forksProhibited"));\r
+ WicketUtils.setHtmlTooltip(lbl, getString("gb.forksProhibitedWarning"));\r
+ wc.add(lbl);\r
+ add(wc);\r
+ } else {\r
+ // can not fork, no need for forks prohibited indicator\r
+ add(new Label("forksProhibitedIndicator").setVisible(false));\r
+ }\r
+ \r
+ if (hasFork && !fork.equals(model.name)) {\r
+ // user has fork, view my fork link\r
+ String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(fork)).toString();\r
+ add(new ExternalLink("myForkLink", url));\r
+ } else {\r
+ // no fork, hide view my fork link\r
+ add(new ExternalLink("myForkLink", "").setVisible(false));\r
+ }\r
+ } else if (canFork) {\r
+ // can fork and we do not have one\r
+ add(new Label("forksProhibitedIndicator").setVisible(false));\r
+ add(new ExternalLink("myForkLink", "").setVisible(false));\r
Link<Void> forkLink = new Link<Void>("forkLink") {\r
\r
private static final long serialVersionUID = 1L;\r
\r
@Override\r
public void onClick() {\r
+ UserModel user = GitBlitWebSession.get().getUser();\r
RepositoryModel model = getRepositoryModel();\r
+ String asFork = MessageFormat.format("~{0}/{1}.git", user.username, StringUtils.stripDotGit(StringUtils.getLastPathElement(model.name)));\r
if (GitBlit.self().fork(model, GitBlitWebSession.get().getUser())) {\r
- throw new RedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(clonedRepo));\r
+ throw new RedirectException(SummaryPage.class, WicketUtils.newRepositoryParameter(asFork));\r
} else {\r
error(MessageFormat.format(getString("gb.repositoryForkFailed"), model));\r
}\r
forkLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(\r
getString("gb.forkRepository"), getRepositoryModel())));\r
add(forkLink);\r
- } else {\r
- // user not allowed to fork or fork already exists or repo forbids forking\r
- add(new ExternalLink("forkLink", "").setVisible(false));\r
}\r
- \r
- if (hasClone) {\r
- // user has clone\r
- String url = getRequestCycle().urlFor(SummaryPage.class, WicketUtils.newRepositoryParameter(clonedRepo)).toString();\r
- add(new ExternalLink("myForkLink", url));\r
- } else {\r
- // user does not have clone\r
- add(new ExternalLink("myForkLink", "").setVisible(false));\r
- }\r
- } else {\r
- // server prohibits forking\r
- add(new ExternalLink("forkLink", "").setVisible(false));\r
- add(new ExternalLink("myForkLink", "").setVisible(false));\r
}\r
\r
super.setupPage(repositoryName, pageName);\r
getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));\r
}\r
}\r
-}\r
+}
\ No newline at end of file