From 8daefa09d99774639a355c0dfa2b989fa1007f5f Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 11 Oct 2012 17:11:18 -0400
Subject: [PATCH] Created static repository close functions for unit testing and fixed Windows sharing violations
---
src/com/gitblit/utils/JGitUtils.java | 515 ++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 363 insertions(+), 152 deletions(-)
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java
index 05c0852..231b935 100644
--- a/src/com/gitblit/utils/JGitUtils.java
+++ b/src/com/gitblit/utils/JGitUtils.java
@@ -20,25 +20,23 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.ResetCommand;
-import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.DiffFormatter;
@@ -47,6 +45,7 @@
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.StopWalkException;
+import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
@@ -59,7 +58,6 @@
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
-import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.lib.TreeFormatter;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -89,6 +87,7 @@
import com.gitblit.models.PathModel;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
+import com.gitblit.models.SubmoduleModel;
/**
* Collection of static methods for retrieving information from a repository.
@@ -211,11 +210,10 @@
if (credentialsProvider != null) {
clone.setCredentialsProvider(credentialsProvider);
}
- clone.call();
+ Repository repository = clone.call().getRepository();
+
// Now we have to fetch because CloneCommand doesn't fetch
// refs/notes nor does it allow manual RefSpec.
- File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED);
- FileRepository repository = new FileRepository(gitDir);
result.createdRepository = true;
result.fetchResult = fetchRepository(credentialsProvider, repository);
repository.close();
@@ -254,27 +252,6 @@
}
/**
- * Reset HEAD to the latest remote tracking commit.
- *
- * @param repository
- * @param remoteRef
- * the remote tracking reference (e.g. origin/master)
- * @return Ref
- * @throws Exception
- */
- public static Ref resetHEAD(Repository repository, String remoteRef) throws Exception {
- if (!remoteRef.startsWith(Constants.R_REMOTES)) {
- remoteRef = Constants.R_REMOTES + remoteRef;
- }
- Git git = new Git(repository);
- ResetCommand reset = git.reset();
- reset.setMode(ResetType.SOFT);
- reset.setRef(remoteRef);
- Ref result = reset.call();
- return result;
- }
-
- /**
* Creates a bare repository.
*
* @param repositoriesFolder
@@ -282,29 +259,43 @@
* @return Repository
*/
public static Repository createRepository(File repositoriesFolder, String name) {
- Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();
- return git.getRepository();
+ try {
+ Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call();
+ return git.getRepository();
+ } catch (GitAPIException e) {
+ throw new RuntimeException(e);
+ }
}
/**
* Returns a list of repository names in the specified folder.
*
* @param repositoriesFolder
- * @param exportAll
- * if true, all repositories are listed. If false only the
- * repositories with a "git-daemon-export-ok" file are included
+ * @param onlyBare
+ * if true, only bare repositories repositories are listed. If
+ * false all repositories are included.
* @param searchSubfolders
* recurse into subfolders to find grouped repositories
+ * @param depth
+ * optional recursion depth, -1 = infinite recursion
+ * @param exclusions
+ * list of regex exclusions for matching to folder names
* @return list of repository names
*/
- public static List<String> getRepositoryList(File repositoriesFolder, boolean exportAll,
- boolean searchSubfolders) {
+ public static List<String> getRepositoryList(File repositoriesFolder, boolean onlyBare,
+ boolean searchSubfolders, int depth, List<String> exclusions) {
List<String> list = new ArrayList<String>();
if (repositoriesFolder == null || !repositoriesFolder.exists()) {
return list;
}
+ List<Pattern> patterns = new ArrayList<Pattern>();
+ if (!ArrayUtils.isEmpty(exclusions)) {
+ for (String regex : exclusions) {
+ patterns.add(Pattern.compile(regex));
+ }
+ }
list.addAll(getRepositoryList(repositoriesFolder.getAbsolutePath(), repositoriesFolder,
- exportAll, searchSubfolders));
+ onlyBare, searchSubfolders, depth, patterns));
StringUtils.sortRepositorynames(list);
return list;
}
@@ -316,33 +307,60 @@
* basePath is stripped from the repository name as repositories
* are relative to this path
* @param searchFolder
- * @param exportAll
- * if true all repositories are listed. If false only the
- * repositories with a "git-daemon-export-ok" file are included
+ * @param onlyBare
+ * if true only bare repositories will be listed. if false all
+ * repositories are included.
* @param searchSubfolders
* recurse into subfolders to find grouped repositories
+ * @param depth
+ * recursion depth, -1 = infinite recursion
+ * @param patterns
+ * list of regex patterns for matching to folder names
* @return
*/
private static List<String> getRepositoryList(String basePath, File searchFolder,
- boolean exportAll, boolean searchSubfolders) {
+ boolean onlyBare, boolean searchSubfolders, int depth, List<Pattern> patterns) {
+ File baseFile = new File(basePath);
List<String> list = new ArrayList<String>();
+ if (depth == 0) {
+ return list;
+ }
+
+ int nextDepth = (depth == -1) ? -1 : depth - 1;
for (File file : searchFolder.listFiles()) {
if (file.isDirectory()) {
+ boolean exclude = false;
+ for (Pattern pattern : patterns) {
+ String path = FileUtils.getRelativePath(baseFile, file).replace('\\', '/');
+ if (pattern.matcher(path).matches()) {
+ LOGGER.debug(MessageFormat.format("excluding {0} because of rule {1}", path, pattern.pattern()));
+ exclude = true;
+ break;
+ }
+ }
+ if (exclude) {
+ // skip to next file
+ continue;
+ }
+
File gitDir = FileKey.resolve(new File(searchFolder, file.getName()), FS.DETECTED);
if (gitDir != null) {
- boolean exportRepository = exportAll
- || new File(gitDir, "git-daemon-export-ok").exists();
-
- if (!exportRepository) {
+ if (onlyBare && gitDir.getName().equals(".git")) {
continue;
}
- // determine repository name relative to base path
- String repository = StringUtils.getRelativePath(basePath,
- file.getAbsolutePath());
- list.add(repository);
- } else if (searchSubfolders) {
+ if (gitDir.equals(file) || gitDir.getParentFile().equals(file)) {
+ // determine repository name relative to base path
+ String repository = FileUtils.getRelativePath(baseFile, file);
+ list.add(repository);
+ } else if (searchSubfolders && file.canRead()) {
+ // look for repositories in subfolders
+ list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
+ nextDepth, patterns));
+ }
+ } else if (searchSubfolders && file.canRead()) {
// look for repositories in subfolders
- list.addAll(getRepositoryList(basePath, file, exportAll, searchSubfolders));
+ list.addAll(getRepositoryList(basePath, file, onlyBare, searchSubfolders,
+ nextDepth, patterns));
}
}
}
@@ -427,11 +445,9 @@
* last modified date of the repository folder is returned.
*
* @param repository
- * @param branch
- * if unspecified, all branches are checked.
* @return
*/
- public static Date getLastChange(Repository repository, String branch) {
+ public static Date getLastChange(Repository repository) {
if (!hasCommits(repository)) {
// null repository
if (repository == null) {
@@ -440,26 +456,21 @@
// fresh repository
return new Date(repository.getDirectory().lastModified());
}
- if (StringUtils.isEmpty(branch)) {
- List<RefModel> branchModels = getLocalBranches(repository, true, -1);
- if (branchModels.size() > 0) {
- // find most recent branch update
- Date lastChange = new Date(0);
- for (RefModel branchModel : branchModels) {
- if (branchModel.getDate().after(lastChange)) {
- lastChange = branchModel.getDate();
- }
- }
- return lastChange;
- } else {
- // try to find head
- branch = Constants.HEAD;
- }
- }
- // lookup specified branch
- RevCommit commit = getCommit(repository, branch);
- return getCommitDate(commit);
+ List<RefModel> branchModels = getLocalBranches(repository, true, -1);
+ if (branchModels.size() > 0) {
+ // find most recent branch update
+ Date lastChange = new Date(0);
+ for (RefModel branchModel : branchModels) {
+ if (branchModel.getDate().after(lastChange)) {
+ lastChange = branchModel.getDate();
+ }
+ }
+ return lastChange;
+ }
+
+ // default to the repository folder modification date
+ return new Date(repository.getDirectory().lastModified());
}
/**
@@ -548,18 +559,20 @@
}
ObjectId entid = tw.getObjectId(0);
FileMode entmode = tw.getFileMode(0);
- RevObject ro = rw.lookupAny(entid, entmode.getObjectType());
- rw.parseBody(ro);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- ObjectLoader ldr = repository.open(ro.getId(), Constants.OBJ_BLOB);
- byte[] tmp = new byte[4096];
- InputStream in = ldr.openStream();
- int n;
- while ((n = in.read(tmp)) > 0) {
- os.write(tmp, 0, n);
+ if (entmode != FileMode.GITLINK) {
+ RevObject ro = rw.lookupAny(entid, entmode.getObjectType());
+ rw.parseBody(ro);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ObjectLoader ldr = repository.open(ro.getId(), Constants.OBJ_BLOB);
+ byte[] tmp = new byte[4096];
+ InputStream in = ldr.openStream();
+ int n;
+ while ((n = in.read(tmp)) > 0) {
+ os.write(tmp, 0, n);
+ }
+ in.close();
+ content = os.toByteArray();
}
- in.close();
- content = os.toByteArray();
}
} catch (Throwable t) {
error(t, repository, "{0} can't find {1} in tree {2}", path, tree.name());
@@ -577,14 +590,15 @@
* @param tree
* if null, the RevTree from HEAD is assumed.
* @param blobPath
+ * @param charsets optional
* @return UTF-8 string content
*/
- public static String getStringContent(Repository repository, RevTree tree, String blobPath) {
+ public static String getStringContent(Repository repository, RevTree tree, String blobPath, String... charsets) {
byte[] content = getByteContent(repository, tree, blobPath);
if (content == null) {
return null;
}
- return new String(content, Charset.forName(Constants.CHARACTER_ENCODING));
+ return StringUtils.decodeString(content, charsets);
}
/**
@@ -623,14 +637,15 @@
*
* @param repository
* @param objectId
+ * @param charsets optional
* @return UTF-8 string content
*/
- public static String getStringContent(Repository repository, String objectId) {
+ public static String getStringContent(Repository repository, String objectId, String... charsets) {
byte[] content = getByteContent(repository, objectId);
if (content == null) {
return null;
}
- return new String(content, Charset.forName(Constants.CHARACTER_ENCODING));
+ return StringUtils.decodeString(content, charsets);
}
/**
@@ -717,7 +732,8 @@
tw.addTree(commit.getTree());
while (tw.next()) {
list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(), 0, tw
- .getRawMode(0), commit.getId().getName(), ChangeType.ADD));
+ .getRawMode(0), tw.getObjectId(0).getName(), commit.getId().getName(),
+ ChangeType.ADD));
}
tw.release();
} else {
@@ -728,13 +744,22 @@
df.setDetectRenames(true);
List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree());
for (DiffEntry diff : diffs) {
+ String objectId = null;
+ if (FileMode.GITLINK.equals(diff.getNewMode())) {
+ objectId = diff.getNewId().name();
+ }
+
if (diff.getChangeType().equals(ChangeType.DELETE)) {
list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff
- .getNewMode().getBits(), commit.getId().getName(), diff
+ .getNewMode().getBits(), objectId, commit.getId().getName(), diff
+ .getChangeType()));
+ } else if (diff.getChangeType().equals(ChangeType.RENAME)) {
+ list.add(new PathChangeModel(diff.getOldPath(), diff.getNewPath(), 0, diff
+ .getNewMode().getBits(), objectId, commit.getId().getName(), diff
.getChangeType()));
} else {
list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff
- .getNewMode().getBits(), commit.getId().getName(), diff
+ .getNewMode().getBits(), objectId, commit.getId().getName(), diff
.getChangeType()));
}
}
@@ -748,25 +773,40 @@
}
/**
- * Returns the list of files in the repository that match one of the
- * specified extensions. This is a CASE-SENSITIVE search. If the repository
- * does not exist or is empty, an empty list is returned.
+ * Returns the list of files in the repository on the default branch that
+ * match one of the specified extensions. This is a CASE-SENSITIVE search.
+ * If the repository does not exist or is empty, an empty list is returned.
*
* @param repository
* @param extensions
* @return list of files in repository with a matching extension
*/
public static List<PathModel> getDocuments(Repository repository, List<String> extensions) {
+ return getDocuments(repository, extensions, null);
+ }
+
+ /**
+ * Returns the list of files in the repository in the specified commit that
+ * match one of the specified extensions. This is a CASE-SENSITIVE search.
+ * If the repository does not exist or is empty, an empty list is returned.
+ *
+ * @param repository
+ * @param extensions
+ * @param objectId
+ * @return list of files in repository with a matching extension
+ */
+ public static List<PathModel> getDocuments(Repository repository, List<String> extensions,
+ String objectId) {
List<PathModel> list = new ArrayList<PathModel>();
if (!hasCommits(repository)) {
return list;
}
- RevCommit commit = getCommit(repository, null);
+ RevCommit commit = getCommit(repository, objectId);
final TreeWalk tw = new TreeWalk(repository);
try {
tw.addTree(commit.getTree());
if (extensions != null && extensions.size() > 0) {
- Collection<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
+ List<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
for (String extension : extensions) {
if (extension.charAt(0) == '.') {
suffixFilters.add(PathSuffixFilter.create("\\" + extension));
@@ -775,7 +815,12 @@
suffixFilters.add(PathSuffixFilter.create("\\." + extension));
}
}
- TreeFilter filter = OrTreeFilter.create(suffixFilters);
+ TreeFilter filter;
+ if (suffixFilters.size() == 1) {
+ filter = suffixFilters.get(0);
+ } else {
+ filter = OrTreeFilter.create(suffixFilters);
+ }
tw.setFilter(filter);
tw.setRecursive(true);
}
@@ -807,15 +852,16 @@
} else {
name = tw.getPathString().substring(basePath.length() + 1);
}
+ ObjectId objectId = tw.getObjectId(0);
try {
- if (!tw.isSubtree()) {
- size = tw.getObjectReader().getObjectSize(tw.getObjectId(0), Constants.OBJ_BLOB);
+ if (!tw.isSubtree() && (tw.getFileMode(0) != FileMode.GITLINK)) {
+ size = tw.getObjectReader().getObjectSize(objectId, Constants.OBJ_BLOB);
}
} catch (Throwable t) {
error(t, null, "failed to retrieve blob size for " + tw.getPathString());
}
return new PathModel(name, tw.getPathString(), size, tw.getFileMode(0).getBits(),
- commit.getName());
+ objectId.getName(), commit.getName());
}
/**
@@ -832,13 +878,10 @@
} else if (FileMode.EXECUTABLE_FILE.equals(mode)) {
return "-rwxr-xr-x";
} else if (FileMode.SYMLINK.equals(mode)) {
- // FIXME symlink permissions
return "symlink";
} else if (FileMode.GITLINK.equals(mode)) {
- // FIXME gitlink permissions
- return "gitlink";
+ return "submodule";
}
- // FIXME missing permissions
return "missing";
}
@@ -945,6 +988,9 @@
branchObject = getDefaultBranch(repository);
} else {
branchObject = repository.resolve(objectId);
+ }
+ if (branchObject == null) {
+ return list;
}
RevWalk rw = new RevWalk(repository);
@@ -1156,63 +1202,163 @@
}
/**
- * Returns the default HEAD for a repository. Normally returns the ref HEAD points to, but if HEAD points to nothing
- * it returns null.
+ * Returns the target of the symbolic HEAD reference for a repository.
+ * Normally returns a branch reference name, but when HEAD is detached,
+ * the commit is matched against the known tags. The most recent matching
+ * tag ref name will be returned if it references the HEAD commit. If
+ * no match is found, the SHA1 is returned.
*
* @param repository
- * @return the refmodel for HEAD or null
+ * @return the ref name or the SHA1 for a detached HEAD
*/
- public static RefModel getDefaultHead(Repository repository) {
- RefModel ref = null;
+ public static String getHEADRef(Repository repository) {
+ String target = null;
try {
- Ref head = repository.getRef(Constants.HEAD);
- if (head != null) {
- Ref target = head.getTarget();
- RevWalk rw = new RevWalk(repository);
- ObjectId targetId = target.getObjectId();
- if (targetId != null) {
- RevObject object = rw.parseAny(targetId);
- ref = new RefModel(target.getName(), target, object);
+ target = repository.getFullBranch();
+ if (!target.startsWith(Constants.R_HEADS)) {
+ // refers to an actual commit, probably a tag
+ // find latest tag that matches the commit, if any
+ List<RefModel> tagModels = getTags(repository, true, -1);
+ if (tagModels.size() > 0) {
+ RefModel tag = null;
+ Date lastDate = new Date(0);
+ for (RefModel tagModel : tagModels) {
+ if (tagModel.getReferencedObjectId().getName().equals(target) &&
+ tagModel.getDate().after(lastDate)) {
+ tag = tagModel;
+ lastDate = tag.getDate();
+ }
+ }
+ target = tag.getName();
}
- rw.dispose();
}
} catch (Throwable t) {
- LOGGER.error("Failed to get default head!", t);
+ error(t, repository, "{0} failed to get symbolic HEAD target");
}
- return ref;
+ return target;
}
-
+
/**
- * Sets the default HEAD symbolic ref for a repository.
+ * Sets the symbolic ref HEAD to the specified target ref. The
+ * HEAD will be detached if the target ref is not a branch.
*
* @param repository
- * @param ref
+ * @param targetRef
+ * @return true if successful
*/
- public static void setDefaultHead(Repository repository, Ref ref) {
+ public static boolean setHEADtoRef(Repository repository, String targetRef) {
try {
- boolean detach = !ref.getName().startsWith(Constants.R_HEADS); // detach if not a branch
+ // detach HEAD if target ref is not a branch
+ boolean detach = !targetRef.startsWith(Constants.R_HEADS);
RefUpdate.Result result;
RefUpdate head = repository.updateRef(Constants.HEAD, detach);
if (detach) { // Tag
- RevCommit commit = getCommit(repository, ref.getObjectId().getName());
+ RevCommit commit = getCommit(repository, targetRef);
head.setNewObjectId(commit.getId());
result = head.forceUpdate();
} else {
- result = head.link(ref.getName());
+ result = head.link(targetRef);
}
switch (result) {
case NEW:
case FORCED:
case NO_CHANGE:
case FAST_FORWARD:
- break;
+ return true;
default:
- LOGGER.error(MessageFormat.format("{0} failed to set default head to {1} ({2})",
- repository.getDirectory().getAbsolutePath(), ref.getName(), result));
+ LOGGER.error(MessageFormat.format("{0} HEAD update to {1} returned result {2}",
+ repository.getDirectory().getAbsolutePath(), targetRef, result));
}
} catch (Throwable t) {
- error(t, repository, "{0} failed to set default head to {1}", ref.getName());
+ error(t, repository, "{0} failed to set HEAD to {1}", targetRef);
}
+ return false;
+ }
+
+ /**
+ * Sets the local branch ref to point to the specified commit id.
+ *
+ * @param repository
+ * @param branch
+ * @param commitId
+ * @return true if successful
+ */
+ public static boolean setBranchRef(Repository repository, String branch, String commitId) {
+ String branchName = branch;
+ if (!branchName.startsWith(Constants.R_HEADS)) {
+ branchName = Constants.R_HEADS + branch;
+ }
+
+ try {
+ RefUpdate refUpdate = repository.updateRef(branchName, false);
+ refUpdate.setNewObjectId(ObjectId.fromString(commitId));
+ RefUpdate.Result result = refUpdate.forceUpdate();
+
+ switch (result) {
+ case NEW:
+ case FORCED:
+ case NO_CHANGE:
+ case FAST_FORWARD:
+ return true;
+ default:
+ LOGGER.error(MessageFormat.format("{0} {1} update to {2} returned result {3}",
+ repository.getDirectory().getAbsolutePath(), branchName, commitId, result));
+ }
+ } catch (Throwable t) {
+ error(t, repository, "{0} failed to set {1} to {2}", branchName, commitId);
+ }
+ return false;
+ }
+
+ /**
+ * Deletes the specified branch ref.
+ *
+ * @param repository
+ * @param branch
+ * @return true if successful
+ */
+ public static boolean deleteBranchRef(Repository repository, String branch) {
+ String branchName = branch;
+ if (!branchName.startsWith(Constants.R_HEADS)) {
+ branchName = Constants.R_HEADS + branch;
+ }
+
+ try {
+ RefUpdate refUpdate = repository.updateRef(branchName, false);
+ refUpdate.setForceUpdate(true);
+ RefUpdate.Result result = refUpdate.delete();
+ switch (result) {
+ case NEW:
+ case FORCED:
+ case NO_CHANGE:
+ case FAST_FORWARD:
+ return true;
+ default:
+ LOGGER.error(MessageFormat.format("{0} failed to delete to {1} returned result {2}",
+ repository.getDirectory().getAbsolutePath(), branchName, result));
+ }
+ } catch (Throwable t) {
+ error(t, repository, "{0} failed to delete {1}", branchName);
+ }
+ return false;
+ }
+
+ /**
+ * Get the full branch and tag ref names for any potential HEAD targets.
+ *
+ * @param repository
+ * @return a list of ref names
+ */
+ public static List<String> getAvailableHeadTargets(Repository repository) {
+ List<String> targets = new ArrayList<String>();
+ for (RefModel branchModel : JGitUtils.getLocalBranches(repository, true, -1)) {
+ targets.add(branchModel.getName());
+ }
+
+ for (RefModel tagModel : JGitUtils.getTags(repository, true, -1)) {
+ targets.add(tagModel.getName());
+ }
+ return targets;
}
/**
@@ -1222,9 +1368,23 @@
* @return all refs grouped by their referenced object id
*/
public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository) {
+ return getAllRefs(repository, true);
+ }
+
+ /**
+ * Returns all refs grouped by their associated object id.
+ *
+ * @param repository
+ * @param includeRemoteRefs
+ * @return all refs grouped by their referenced object id
+ */
+ public static Map<ObjectId, List<RefModel>> getAllRefs(Repository repository, boolean includeRemoteRefs) {
List<RefModel> list = getRefs(repository, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1);
Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>();
for (RefModel ref : list) {
+ if (!includeRemoteRefs && ref.getName().startsWith(Constants.R_REMOTES)) {
+ continue;
+ }
ObjectId objectid = ref.getReferencedObjectId();
if (!refs.containsKey(objectid)) {
refs.put(objectid, new ArrayList<RefModel>());
@@ -1391,6 +1551,62 @@
}
return branch;
}
+
+ /**
+ * Returns the list of submodules for this repository.
+ *
+ * @param repository
+ * @param commit
+ * @return list of submodules
+ */
+ public static List<SubmoduleModel> getSubmodules(Repository repository, String commitId) {
+ RevCommit commit = getCommit(repository, commitId);
+ return getSubmodules(repository, commit.getTree());
+ }
+
+ /**
+ * Returns the list of submodules for this repository.
+ *
+ * @param repository
+ * @param commit
+ * @return list of submodules
+ */
+ public static List<SubmoduleModel> getSubmodules(Repository repository, RevTree tree) {
+ List<SubmoduleModel> list = new ArrayList<SubmoduleModel>();
+ byte [] blob = getByteContent(repository, tree, ".gitmodules");
+ if (blob == null) {
+ return list;
+ }
+ try {
+ BlobBasedConfig config = new BlobBasedConfig(repository.getConfig(), blob);
+ for (String module : config.getSubsections("submodule")) {
+ String path = config.getString("submodule", module, "path");
+ String url = config.getString("submodule", module, "url");
+ list.add(new SubmoduleModel(module, path, url));
+ }
+ } catch (ConfigInvalidException e) {
+ LOGGER.error("Failed to load .gitmodules file for " + repository.getDirectory(), e);
+ }
+ return list;
+ }
+
+ /**
+ * Returns the submodule definition for the specified path at the specified
+ * commit. If no module is defined for the path, null is returned.
+ *
+ * @param repository
+ * @param commit
+ * @param path
+ * @return a submodule definition or null if there is no submodule
+ */
+ public static SubmoduleModel getSubmoduleModel(Repository repository, String commitId, String path) {
+ for (SubmoduleModel model : getSubmodules(repository, commitId)) {
+ if (model.path.equals(path)) {
+ return model;
+ }
+ }
+ return null;
+ }
/**
* Returns the list of notes entered about the commit from the refs/notes
@@ -1409,10 +1625,23 @@
List<RefModel> noteBranches = getNoteBranches(repository, true, -1);
for (RefModel notesRef : noteBranches) {
RevTree notesTree = JGitUtils.getCommit(repository, notesRef.getName()).getTree();
+ // flat notes list
+ String notePath = commit.getName();
+ String text = getStringContent(repository, notesTree, notePath);
+ if (!StringUtils.isEmpty(text)) {
+ List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
+ RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
+ .size() - 1));
+ GitNote gitNote = new GitNote(noteRef, text);
+ list.add(gitNote);
+ continue;
+ }
+
+ // folder structure
StringBuilder sb = new StringBuilder(commit.getName());
sb.insert(2, '/');
- String notePath = sb.toString();
- String text = getStringContent(repository, notesTree, notePath);
+ notePath = sb.toString();
+ text = getStringContent(repository, notesTree, notePath);
if (!StringUtils.isEmpty(text)) {
List<RevCommit> history = getRevLog(repository, notesRef.getName(), notePath, 0, -1);
RefModel noteRef = new RefModel(notesRef.displayName, null, history.get(history
@@ -1449,7 +1678,7 @@
// Create a tree object to reference from a commit
TreeFormatter tree = new TreeFormatter();
- tree.append("NEWBRANCH", FileMode.REGULAR_FILE, blobId);
+ tree.append(".branch", FileMode.REGULAR_FILE, blobId);
ObjectId treeId = odi.insert(tree);
// Create a commit object
@@ -1493,24 +1722,6 @@
error(t, repository, "Failed to create orphan branch {1} in repository {0}", branchName);
}
return success;
- }
-
- /**
- * Returns a StoredConfig object for the repository.
- *
- * @param repository
- * @return the StoredConfig of the repository
- */
- public static StoredConfig readConfig(Repository repository) {
- StoredConfig c = repository.getConfig();
- try {
- c.load();
- } catch (ConfigInvalidException cex) {
- error(cex, repository, "{0} configuration is invalid!");
- } catch (IOException cex) {
- error(cex, repository, "Could not open configuration for {0}!");
- }
- return c;
}
/**
--
Gitblit v1.9.1