summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2012-10-01 20:45:19 -0400
committerJames Moger <james.moger@gitblit.com>2012-10-01 20:45:19 -0400
commiteb1405f736f2f98e14215774dd53eea9b9a77017 (patch)
tree0cd4d066631270ca1b70676e349f8a5f1283c956 /src
parent1e1b85270f93b3bca624c99b478f3a9a23be2395 (diff)
downloadgitblit-eb1405f736f2f98e14215774dd53eea9b9a77017.tar.gz
gitblit-eb1405f736f2f98e14215774dd53eea9b9a77017.zip
Show fork links according to user permissions. Improve fork detection.
Diffstat (limited to 'src')
-rw-r--r--src/com/gitblit/GitBlit.java76
-rw-r--r--src/com/gitblit/models/UserModel.java10
-rw-r--r--src/com/gitblit/wicket/pages/ForksPage.java31
-rw-r--r--src/com/gitblit/wicket/pages/RepositoryPage.java110
4 files changed, 168 insertions, 59 deletions
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 699bbacb..f86c66a3 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -32,6 +32,7 @@ import java.util.Collection;
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;
@@ -1325,6 +1326,81 @@ public class GitBlit implements ServletContextListener {
r.close();
return true;
}
+
+ /**
+ * 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
diff --git a/src/com/gitblit/models/UserModel.java b/src/com/gitblit/models/UserModel.java
index 0ede8787..25787a15 100644
--- a/src/com/gitblit/models/UserModel.java
+++ b/src/com/gitblit/models/UserModel.java
@@ -86,6 +86,16 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
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;
diff --git a/src/com/gitblit/wicket/pages/ForksPage.java b/src/com/gitblit/wicket/pages/ForksPage.java
index 7b8235b0..54c2c82a 100644
--- a/src/com/gitblit/wicket/pages/ForksPage.java
+++ b/src/com/gitblit/wicket/pages/ForksPage.java
@@ -42,26 +42,32 @@ public class ForksPage extends RepositoryPage {
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
- origin = GitBlit.self().getRepositoryModel(model.originRepository);
- list = new ArrayList<String>(origin.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 @@ public class ForksPage extends RepositoryPage {
}
String source = StringUtils.getLastPathElement(origin.name);
- add(new LinkPanel("forkSource", null, StringUtils.stripDotGit(source), SummaryPage.class, WicketUtils.newRepositoryParameter(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);
diff --git a/src/com/gitblit/wicket/pages/RepositoryPage.java b/src/com/gitblit/wicket/pages/RepositoryPage.java
index a85d21e1..8ca2b335 100644
--- a/src/com/gitblit/wicket/pages/RepositoryPage.java
+++ b/src/com/gitblit/wicket/pages/RepositoryPage.java
@@ -136,22 +136,12 @@ public abstract class RepositoryPage extends BasePage {
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) {
pages.put("tickets", new PageRegistration("gb.tickets", TicketsPage.class, params));
@@ -204,15 +194,29 @@ public abstract class RepositoryPage extends BasePage {
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 {
- 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);
+ 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) {
@@ -224,33 +228,57 @@ public abstract class RepositoryPage extends BasePage {
wc.add(lbl);
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 {
- 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);
- }
-
- 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) {
+ 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));
+ }
+
+ 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 @@ public abstract class RepositoryPage extends BasePage {
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);
@@ -577,4 +589,4 @@ public abstract class RepositoryPage extends BasePage {
getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
}
}
-}
+} \ No newline at end of file