From 7efca20047167f90e118ef1296deacd862f6ede4 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 03 Oct 2012 17:11:27 -0400
Subject: [PATCH] Fix broken project links
---
src/com/gitblit/GitBlit.java | 177 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 145 insertions(+), 32 deletions(-)
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 699bbac..6348964 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/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;
@@ -81,6 +82,7 @@
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
+import com.gitblit.models.ForkModel;
import com.gitblit.models.Metric;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
@@ -1268,6 +1270,9 @@
Constants.CONFIG_GITBLIT, null, "federationSets")));
model.isFederated = getConfig(config, "isFederated", false);
model.origin = config.getString("remote", "origin", "url");
+ if (model.origin != null) {
+ model.origin = model.origin.replace('\\', '/');
+ }
model.preReceiveScripts = new ArrayList<String>(Arrays.asList(config.getStringList(
Constants.CONFIG_GITBLIT, null, "preReceiveScript")));
model.postReceiveScripts = new ArrayList<String>(Arrays.asList(config.getStringList(
@@ -1324,6 +1329,113 @@
}
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 fork network for a repository by traversing up the fork graph
+ * to discover the root and then down through all children of the root node.
+ *
+ * @param repository
+ * @return a ForkModel
+ */
+ public ForkModel getForkNetwork(String repository) {
+ if (settings.getBoolean(Keys.git.cacheRepositoryList, true)) {
+ // find the root
+ RepositoryModel model = repositoryListCache.get(repository);
+ while (model.originRepository != null) {
+ model = repositoryListCache.get(model.originRepository);
+ }
+ ForkModel root = getForkModel(model.name);
+ return root;
+ }
+ return null;
+ }
+
+ private ForkModel getForkModel(String repository) {
+ RepositoryModel model = repositoryListCache.get(repository);
+ ForkModel fork = new ForkModel(model);
+ if (!ArrayUtils.isEmpty(model.forks)) {
+ for (String aFork : model.forks) {
+ ForkModel fm = getForkModel(aFork);
+ fork.forks.add(fm);
+ }
+ }
+ return fork;
}
/**
@@ -2528,44 +2640,45 @@
*
* @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;
}
}
--
Gitblit v1.9.1