From 790c3829edafcb41d6eeb14301a23db22c559e96 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Fri, 01 Jul 2011 17:45:23 -0400 Subject: [PATCH] Documentation. Added upgrade info to site. Moved todos to GoogleCode. --- src/com/gitblit/utils/JGitUtils.java | 203 ++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 144 insertions(+), 59 deletions(-) diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java index fd2eaf3..1c607ca 100644 --- a/src/com/gitblit/utils/JGitUtils.java +++ b/src/com/gitblit/utils/JGitUtils.java @@ -22,6 +22,7 @@ import java.io.OutputStream; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -29,10 +30,11 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; 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.diff.DiffEntry; import org.eclipse.jgit.diff.DiffEntry.ChangeType; @@ -42,7 +44,6 @@ import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.StopWalkException; -import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; @@ -59,6 +60,9 @@ import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.storage.file.FileRepository; +import org.eclipse.jgit.transport.FetchResult; +import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.AndTreeFilter; import org.eclipse.jgit.treewalk.filter.OrTreeFilter; @@ -92,8 +96,55 @@ return r.toString().trim(); } - public static Repository createRepository(File repositoriesFolder, String name, boolean bare) { - Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call(); + public static FetchResult cloneRepository(File repositoriesFolder, String name, String fromUrl) + throws Exception { + FetchResult result = null; + if (!name.toLowerCase().endsWith(Constants.DOT_GIT_EXT)) { + name += Constants.DOT_GIT_EXT; + } + File folder = new File(repositoriesFolder, name); + if (folder.exists()) { + File gitDir = FileKey.resolve(new File(repositoriesFolder, name), FS.DETECTED); + FileRepository repository = new FileRepository(gitDir); + result = fetchRepository(repository); + repository.close(); + } else { + CloneCommand clone = new CloneCommand(); + clone.setBare(true); + clone.setCloneAllBranches(true); + clone.setURI(fromUrl); + clone.setDirectory(folder); + clone.call(); + // 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 = fetchRepository(repository); + repository.close(); + } + return result; + } + + public static FetchResult fetchRepository(Repository repository, RefSpec... refSpecs) + throws Exception { + Git git = new Git(repository); + FetchCommand fetch = git.fetch(); + List<RefSpec> specs = new ArrayList<RefSpec>(); + if (refSpecs == null || refSpecs.length == 0) { + specs.add(new RefSpec("+refs/heads/*:refs/remotes/origin/*")); + specs.add(new RefSpec("+refs/tags/*:refs/tags/*")); + specs.add(new RefSpec("+refs/notes/*:refs/notes/*")); + } else { + specs.addAll(Arrays.asList(refSpecs)); + } + fetch.setRefSpecs(specs); + FetchResult result = fetch.call(); + repository.close(); + return result; + } + + public static Repository createRepository(File repositoriesFolder, String name) { + Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(true).call(); return git.getRepository(); } @@ -212,41 +263,31 @@ return commit; } - public static Map<ObjectId, List<String>> getAllRefs(Repository r) { - Map<ObjectId, List<String>> refs = new HashMap<ObjectId, List<String>>(); - Map<AnyObjectId, Set<Ref>> allRefs = r.getAllRefsByPeeledObjectId(); - for (Entry<AnyObjectId, Set<Ref>> setRefs : allRefs.entrySet()) { - List<String> list = new ArrayList<String>(); - for (Ref setRef : setRefs.getValue()) { - String name = setRef.getName(); - list.add(name); + public static Map<ObjectId, List<RefModel>> getAllRefs(Repository r) { + List<RefModel> list = getRefs(r, org.eclipse.jgit.lib.RefDatabase.ALL, true, -1); + Map<ObjectId, List<RefModel>> refs = new HashMap<ObjectId, List<RefModel>>(); + for (RefModel ref : list) { + ObjectId objectid = ref.getReferencedObjectId(); + if (!refs.containsKey(objectid)) { + refs.put(objectid, new ArrayList<RefModel>()); } - refs.put(setRefs.getKey().toObjectId(), list); + refs.get(objectid).add(ref); } return refs; } - /** - * Lookup an entry stored in a tree, failing if not present. - * - * @param tree - * the tree to search. - * @param path - * the path to find the entry of. - * @return the parsed object entry at this path - * @throws Exception - */ - public static byte[] getRawContent(Repository r, RevCommit commit, final String path) { + public static byte[] getByteContent(Repository r, RevTree tree, final String path) { RevWalk rw = new RevWalk(r); TreeWalk tw = new TreeWalk(r); tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path))); byte[] content = null; try { - if (commit == null) { + if (tree == null) { ObjectId object = r.resolve(Constants.HEAD); - commit = rw.parseCommit(object); + RevCommit commit = rw.parseCommit(object); + tree = commit.getTree(); } - tw.reset(commit.getTree()); + tw.reset(tree); while (tw.next()) { if (tw.isSubtree() && !path.equals(tw.getPathString())) { tw.enterSubtree(); @@ -268,7 +309,7 @@ content = os.toByteArray(); } } catch (Throwable t) { - LOGGER.error("Can't find " + path + " in tree " + commit.getTree().name(), t); + LOGGER.error("Can't find " + path + " in tree " + tree.name(), t); } finally { rw.dispose(); tw.release(); @@ -276,8 +317,40 @@ return content; } - public static String getRawContentAsString(Repository r, RevCommit commit, String blobPath) { - byte[] content = getRawContent(r, commit, blobPath); + public static String getStringContent(Repository r, RevTree tree, String blobPath) { + byte[] content = getByteContent(r, tree, blobPath); + if (content == null) { + return null; + } + return new String(content, Charset.forName(Constants.CHARACTER_ENCODING)); + } + + public static byte[] getByteContent(Repository r, String objectId) { + RevWalk rw = new RevWalk(r); + byte[] content = null; + try { + RevBlob blob = rw.lookupBlob(ObjectId.fromString(objectId)); + rw.parseBody(blob); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + ObjectLoader ldr = r.open(blob.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(); + } catch (Throwable t) { + LOGGER.error("Can't find blob " + objectId, t); + } finally { + rw.dispose(); + } + return content; + } + + public static String getStringContent(Repository r, String objectId) { + byte[] content = getByteContent(r, objectId); if (content == null) { return null; } @@ -330,35 +403,29 @@ public static List<PathChangeModel> getFilesInCommit(Repository r, RevCommit commit) { List<PathChangeModel> list = new ArrayList<PathChangeModel>(); RevWalk rw = new RevWalk(r); - TreeWalk tw = new TreeWalk(r); try { if (commit == null) { ObjectId object = r.resolve(Constants.HEAD); commit = rw.parseCommit(object); } - RevTree commitTree = commit.getTree(); - tw.reset(); - tw.setRecursive(true); if (commit.getParentCount() == 0) { - tw.addTree(commitTree); + TreeWalk tw = new TreeWalk(r); + tw.reset(); + tw.setRecursive(true); + tw.addTree(commit.getTree()); while (tw.next()) { list.add(new PathChangeModel(tw.getPathString(), tw.getPathString(), 0, tw .getRawMode(0), commit.getId().getName(), ChangeType.ADD)); } + tw.release(); } else { RevCommit parent = rw.parseCommit(commit.getParent(0).getId()); - RevTree parentTree = parent.getTree(); - tw.addTree(parentTree); - tw.addTree(commitTree); - tw.setFilter(TreeFilter.ANY_DIFF); - - RawTextComparator cmp = RawTextComparator.DEFAULT; DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE); df.setRepository(r); - df.setDiffComparator(cmp); + df.setDiffComparator(RawTextComparator.DEFAULT); df.setDetectRenames(true); - List<DiffEntry> diffs = df.scan(parentTree, commitTree); + List<DiffEntry> diffs = df.scan(parent.getTree(), commit.getTree()); for (DiffEntry diff : diffs) { if (diff.getChangeType().equals(ChangeType.DELETE)) { list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff @@ -375,7 +442,6 @@ LOGGER.error("failed to determine files in commit!", t); } finally { rw.dispose(); - tw.release(); } return list; } @@ -460,6 +526,9 @@ public static List<RevCommit> getRevLog(Repository r, String objectId, String path, int offset, int maxCount) { List<RevCommit> list = new ArrayList<RevCommit>(); + if (maxCount == 0) { + return list; + } if (!hasCommits(r)) { return list; } @@ -525,6 +594,9 @@ final SearchType type, int offset, int maxCount) { final String lcValue = value.toLowerCase(); List<RevCommit> list = new ArrayList<RevCommit>(); + if (maxCount == 0) { + return list; + } if (!hasCommits(r)) { return list; } @@ -593,31 +665,40 @@ return list; } - public static List<RefModel> getTags(Repository r, int maxCount) { - return getRefs(r, Constants.R_TAGS, maxCount); + public static List<RefModel> getTags(Repository r, boolean fullName, int maxCount) { + return getRefs(r, Constants.R_TAGS, fullName, maxCount); } - public static List<RefModel> getLocalBranches(Repository r, int maxCount) { - return getRefs(r, Constants.R_HEADS, maxCount); + public static List<RefModel> getLocalBranches(Repository r, boolean fullName, int maxCount) { + return getRefs(r, Constants.R_HEADS, fullName, maxCount); } - public static List<RefModel> getRemoteBranches(Repository r, int maxCount) { - return getRefs(r, Constants.R_REMOTES, maxCount); + public static List<RefModel> getRemoteBranches(Repository r, boolean fullName, int maxCount) { + return getRefs(r, Constants.R_REMOTES, fullName, maxCount); } - public static List<RefModel> getNotes(Repository r, int maxCount) { - return getRefs(r, Constants.R_NOTES, maxCount); + public static List<RefModel> getNotesRefs(Repository r, boolean fullName, int maxCount) { + return getRefs(r, Constants.R_NOTES, fullName, maxCount); } - private static List<RefModel> getRefs(Repository r, String refs, int maxCount) { + private static List<RefModel> getRefs(Repository r, String refs, boolean fullName, int maxCount) { List<RefModel> list = new ArrayList<RefModel>(); + if (maxCount == 0) { + return list; + } try { Map<String, Ref> map = r.getRefDatabase().getRefs(refs); + RevWalk rw = new RevWalk(r); for (Entry<String, Ref> entry : map.entrySet()) { Ref ref = entry.getValue(); - RevCommit commit = getCommit(r, ref.getObjectId().getName()); - list.add(new RefModel(entry.getKey(), ref, commit)); + RevObject object = rw.parseAny(ref.getObjectId()); + String name = entry.getKey(); + if (fullName && !StringUtils.isEmpty(refs)) { + name = refs + name; + } + list.add(new RefModel(name, ref, object)); } + rw.dispose(); Collections.sort(list); Collections.reverse(list); if (maxCount > 0 && list.size() > maxCount) { @@ -631,14 +712,18 @@ public static List<GitNote> getNotesOnCommit(Repository repository, RevCommit commit) { List<GitNote> list = new ArrayList<GitNote>(); - List<RefModel> notesRefs = getNotes(repository, -1); + List<RefModel> notesRefs = getNotesRefs(repository, true, -1); for (RefModel notesRef : notesRefs) { - RevCommit notes = JGitUtils.getCommit(repository, notesRef.getName()); + RevTree notesTree = JGitUtils.getCommit(repository, notesRef.getName()).getTree(); StringBuilder sb = new StringBuilder(commit.getName()); sb.insert(2, '/'); - String text = getRawContentAsString(repository, notes, sb.toString()); + String notePath = sb.toString(); + String text = getStringContent(repository, notesTree, notePath); if (!StringUtils.isEmpty(text)) { - GitNote gitNote = new GitNote(notesRef, 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); } } -- Gitblit v1.9.1