123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949 |
- package com.gitblit.utils;
-
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.nio.charset.Charset;
- import java.text.DateFormat;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- 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.Set;
- import java.util.concurrent.atomic.AtomicInteger;
-
- import org.eclipse.jgit.api.Git;
- import org.eclipse.jgit.diff.DiffEntry;
- import org.eclipse.jgit.diff.DiffEntry.ChangeType;
- import org.eclipse.jgit.diff.DiffFormatter;
- import org.eclipse.jgit.diff.RawTextComparator;
- import org.eclipse.jgit.errors.ConfigInvalidException;
- 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;
- import org.eclipse.jgit.lib.ObjectLoader;
- import org.eclipse.jgit.lib.PersonIdent;
- import org.eclipse.jgit.lib.Ref;
- import org.eclipse.jgit.lib.Repository;
- import org.eclipse.jgit.lib.StoredConfig;
- import org.eclipse.jgit.revwalk.RevBlob;
- import org.eclipse.jgit.revwalk.RevCommit;
- import org.eclipse.jgit.revwalk.RevObject;
- import org.eclipse.jgit.revwalk.RevSort;
- import org.eclipse.jgit.revwalk.RevTree;
- import org.eclipse.jgit.revwalk.RevWalk;
- import org.eclipse.jgit.revwalk.filter.RevFilter;
- import org.eclipse.jgit.treewalk.TreeWalk;
- import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
- import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
- import org.eclipse.jgit.treewalk.filter.PathFilter;
- import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
- import org.eclipse.jgit.treewalk.filter.PathSuffixFilter;
- import org.eclipse.jgit.treewalk.filter.TreeFilter;
- import org.eclipse.jgit.util.io.DisabledOutputStream;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import com.gitblit.wicket.models.Metric;
- import com.gitblit.wicket.models.PathModel;
- import com.gitblit.wicket.models.PathModel.PathChangeModel;
- import com.gitblit.wicket.models.RefModel;
- import com.gitblit.wicket.models.TicketModel;
- import com.gitblit.wicket.models.TicketModel.Comment;
-
- public class JGitUtils {
-
- /** Prefix for notes refs */
- public static final String R_NOTES = "refs/notes/";
-
- /** Standard notes ref */
- public static final String R_NOTES_COMMITS = R_NOTES + "commits";
-
- private final static Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class);
-
- public static Repository createRepository(File repositoriesFolder, String name, boolean bare) {
- Git git = Git.init().setDirectory(new File(repositoriesFolder, name)).setBare(bare).call();
- return git.getRepository();
- }
-
- public static List<String> getRepositoryList(File repositoriesFolder, boolean exportAll, boolean readNested) {
- List<String> list = new ArrayList<String>();
- list.addAll(getNestedRepositories(repositoriesFolder, repositoriesFolder, exportAll, readNested));
- Collections.sort(list);
- return list;
- }
-
- public static List<String> getNestedRepositories(File repositoriesFolder, File folder, boolean exportAll, boolean readNested) {
- String basefile = repositoriesFolder.getAbsolutePath();
- List<String> list = new ArrayList<String>();
- for (File file : folder.listFiles()) {
- if (file.isDirectory() && !file.getName().equalsIgnoreCase(Constants.DOT_GIT)) {
- // if this is a git repository add it to the list
- //
- // first look for standard folder/.git structure
- File gitFolder = new File(file, Constants.DOT_GIT);
- boolean isGitRepository = gitFolder.exists() && gitFolder.isDirectory();
-
- // then look for folder.git/HEAD
- if (!isGitRepository) {
- if (file.getName().endsWith(Constants.DOT_GIT_EXT) && new File(file, Constants.HEAD).exists()) {
- gitFolder = file;
- isGitRepository = true;
- }
- }
- boolean exportRepository = isGitRepository && (exportAll || new File(gitFolder, "git-daemon-export-ok").exists());
-
- if (exportRepository) {
- // determine repository name relative to repositories folder
- String filename = file.getAbsolutePath();
- String repo = filename.substring(basefile.length()).replace('\\', '/');
- if (repo.charAt(0) == '/') {
- repo = repo.substring(1);
- }
- list.add(repo);
- }
-
- // look for nested repositories
- if (readNested) {
- list.addAll(getNestedRepositories(repositoriesFolder, file, exportAll, readNested));
- }
- }
- }
- return list;
- }
-
- public static RevCommit getFirstCommit(Repository r, String branch) {
- if (StringUtils.isEmpty(branch)) {
- branch = Constants.HEAD;
- }
- try {
- RevWalk walk = new RevWalk(r);
- walk.sort(RevSort.REVERSE);
- RevCommit head = walk.parseCommit(r.resolve(branch));
- walk.markStart(head);
- RevCommit commit = walk.next();
- walk.dispose();
- return commit;
- } catch (Throwable t) {
- LOGGER.error("Failed to determine first commit", t);
- }
- return null;
- }
-
- public static Date getFirstChange(Repository r, String branch) {
- try {
- RevCommit commit = getFirstCommit(r, branch);
- if (commit == null) {
- // fresh repository
- return new Date(r.getDirectory().lastModified());
- }
- return getCommitDate(commit);
- } catch (Throwable t) {
- LOGGER.error("Failed to determine first change", t);
- }
- return null;
- }
-
- public static Date getLastChange(Repository r) {
- RevCommit commit = getCommit(r, Constants.HEAD);
- if (commit == null) {
- // fresh repository
- return new Date(r.getDirectory().lastModified());
- }
- return getCommitDate(commit);
- }
-
- public static RevCommit getCommit(Repository r, String objectId) {
- RevCommit commit = null;
- try {
- if (objectId == null || objectId.trim().length() == 0) {
- objectId = Constants.HEAD;
- }
- ObjectId object = r.resolve(objectId);
- RevWalk walk = new RevWalk(r);
- RevCommit rev = walk.parseCommit(object);
- commit = rev;
- walk.dispose();
- } catch (Throwable t) {
- LOGGER.error("Failed to determine last change", t);
- }
- 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 (AnyObjectId id : allRefs.keySet()) {
- List<String> list = new ArrayList<String>();
- for (Ref setRef : allRefs.get(id)) {
- String name = setRef.getName();
- list.add(name);
- }
- refs.put(id.toObjectId(), list);
- }
- return refs;
- }
-
- public static Map<ObjectId, List<String>> getRefs(Repository r, String baseRef) {
- Map<ObjectId, List<String>> refs = new HashMap<ObjectId, List<String>>();
- Map<AnyObjectId, Set<Ref>> allRefs = r.getAllRefsByPeeledObjectId();
- for (AnyObjectId id : allRefs.keySet()) {
- List<String> list = new ArrayList<String>();
- for (Ref setRef : allRefs.get(id)) {
- String name = setRef.getName();
- if (name.startsWith(baseRef)) {
- list.add(name);
- }
- }
- refs.put(id.toObjectId(), list);
- }
- 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 RevObject getRevObject(Repository r, final RevTree tree, final String path) {
- RevObject ro = null;
- RevWalk rw = new RevWalk(r);
- TreeWalk tw = new TreeWalk(r);
- tw.setFilter(PathFilterGroup.createFromStrings(Collections.singleton(path)));
- try {
- tw.reset(tree);
- while (tw.next()) {
- if (tw.isSubtree() && !path.equals(tw.getPathString())) {
- tw.enterSubtree();
- continue;
- }
- ObjectId entid = tw.getObjectId(0);
- FileMode entmode = tw.getFileMode(0);
- ro = rw.lookupAny(entid, entmode.getObjectType());
- rw.parseBody(ro);
- }
- } catch (Throwable t) {
- LOGGER.error("Can't find " + path + " in tree " + tree.name(), t);
- } finally {
- if (rw != null) {
- rw.dispose();
- }
- }
- return ro;
- }
-
- public static byte[] getRawContent(Repository r, RevBlob blob) {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- try {
- ObjectLoader ldr = r.open(blob.getId(), Constants.OBJ_BLOB);
- byte[] tmp = new byte[1024];
- InputStream in = ldr.openStream();
- int n;
- while ((n = in.read(tmp)) > 0) {
- os.write(tmp, 0, n);
- }
- in.close();
- } catch (Throwable t) {
- LOGGER.error("Failed to read raw content", t);
- }
- return os.toByteArray();
- }
-
- public static String getRawContentAsString(Repository r, RevBlob blob) {
- byte [] content = getRawContent(r, blob);
- return new String(content, Charset.forName("UTF-8"));
- }
-
- public static String getRawContentAsString(Repository r, RevCommit commit, String blobPath) {
- RevObject obj = getRevObject(r, commit.getTree(), blobPath);
- byte [] content = getRawContent(r, (RevBlob) obj);
- return new String(content, Charset.forName("UTF-8"));
- }
-
- public static List<PathModel> getFilesInPath(Repository r, String basePath, String objectId) {
- RevCommit commit = getCommit(r, objectId);
- return getFilesInPath(r, basePath, commit);
- }
-
- public static List<PathModel> getFilesInPath(Repository r, String basePath, RevCommit commit) {
- List<PathModel> list = new ArrayList<PathModel>();
- if (commit == null) {
- return list;
- }
- final TreeWalk walk = new TreeWalk(r);
- try {
- walk.addTree(commit.getTree());
- if (basePath != null && basePath.length() > 0) {
- PathFilter f = PathFilter.create(basePath);
- walk.setFilter(f);
- walk.setRecursive(false);
- boolean foundFolder = false;
- while (walk.next()) {
- if (!foundFolder && walk.isSubtree()) {
- walk.enterSubtree();
- }
- if (walk.getPathString().equals(basePath)) {
- foundFolder = true;
- continue;
- }
- if (foundFolder) {
- list.add(getPathModel(walk, basePath, commit));
- }
- }
- } else {
- walk.setRecursive(false);
- while (walk.next()) {
- list.add(getPathModel(walk, null, commit));
- }
- }
- } catch (IOException e) {
- LOGGER.error("Failed to get files for commit " + commit.getName(), e);
- } finally {
- walk.release();
- }
- Collections.sort(list);
- return list;
- }
-
- public static List<PathChangeModel> getFilesInCommit(Repository r, String commitId) {
- RevCommit commit = getCommit(r, commitId);
- return getFilesInCommit(r, commit);
- }
-
- public static List<PathChangeModel> getFilesInCommit(Repository r, RevCommit commit) {
- List<PathChangeModel> list = new ArrayList<PathChangeModel>();
- try {
- final RevWalk rw = new RevWalk(r);
- RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
- RevTree parentTree = parent.getTree();
- RevTree commitTree = commit.getTree();
-
- final TreeWalk walk = new TreeWalk(r);
- walk.reset();
- walk.setRecursive(true);
- walk.addTree(parentTree);
- walk.addTree(commitTree);
- walk.setFilter(TreeFilter.ANY_DIFF);
-
- RawTextComparator cmp = RawTextComparator.DEFAULT;
- DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE);
- df.setRepository(r);
- df.setDiffComparator(cmp);
- df.setDetectRenames(true);
- List<DiffEntry> diffs = df.scan(parentTree, commitTree);
- for (DiffEntry diff : diffs) {
- if (diff.getChangeType().equals(ChangeType.DELETE)) {
- list.add(new PathChangeModel(diff.getOldPath(), diff.getOldPath(), 0, diff.getNewMode().getBits(), commit.getId().getName(), diff.getChangeType()));
- } else {
- list.add(new PathChangeModel(diff.getNewPath(), diff.getNewPath(), 0, diff.getNewMode().getBits(), commit.getId().getName(), diff.getChangeType()));
- }
- }
- } catch (Throwable t) {
- LOGGER.error("failed to determine files in commit!", t);
- }
- return list;
- }
-
- public static List<PathModel> getDocuments(Repository r, List<String> extensions) {
- List<PathModel> list = new ArrayList<PathModel>();
- RevCommit commit = getCommit(r, Constants.HEAD);
- final TreeWalk walk = new TreeWalk(r);
- try {
- walk.addTree(commit.getTree());
- if (extensions != null && extensions.size() > 0) {
- Collection<TreeFilter> suffixFilters = new ArrayList<TreeFilter>();
- for (String extension:extensions) {
- if (extension.charAt(0) == '.') {
- suffixFilters.add(PathSuffixFilter.create(extension));
- } else {
- // escape the . since this is a regexp filter
- suffixFilters.add(PathSuffixFilter.create("\\." + extension));
- }
- }
- TreeFilter filter = OrTreeFilter.create(suffixFilters);
- walk.setFilter(filter);
- walk.setRecursive(true);
- while (walk.next()) {
- list.add(getPathModel(walk, null, commit));
- }
- } else {
- while (walk.next()) {
- list.add(getPathModel(walk, null, commit));
- }
- }
- } catch (IOException e) {
- LOGGER.error("Failed to get files for commit " + commit.getName(), e);
- } finally {
- walk.release();
- }
- Collections.sort(list);
- return list;
- }
-
- public static Map<ChangeType, AtomicInteger> getChangedPathsStats(List<PathChangeModel> paths) {
- Map<ChangeType, AtomicInteger> stats = new HashMap<ChangeType, AtomicInteger>();
- for (PathChangeModel path : paths) {
- if (!stats.containsKey(path.changeType)) {
- stats.put(path.changeType, new AtomicInteger(0));
- }
- stats.get(path.changeType).incrementAndGet();
- }
- return stats;
- }
-
- public static enum DiffOutputType {
- PLAIN, GITWEB, GITBLIT;
-
- public static DiffOutputType forName(String name) {
- for (DiffOutputType type : values()) {
- if (type.name().equalsIgnoreCase(name)) {
- return type;
- }
- }
- return null;
- }
- }
-
- public static String getCommitDiff(Repository r, RevCommit commit, DiffOutputType outputType) {
- return getCommitDiff(r, null, commit, null, outputType);
- }
-
- public static String getCommitDiff(Repository r, RevCommit commit, String path, DiffOutputType outputType) {
- return getCommitDiff(r, null, commit, path, outputType);
- }
-
- public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, DiffOutputType outputType) {
- return getCommitDiff(r, baseCommit, commit, null, outputType);
- }
-
- public static String getCommitDiff(Repository r, RevCommit baseCommit, RevCommit commit, String path, DiffOutputType outputType) {
- try {
- RevTree baseTree;
- if (baseCommit == null) {
- final RevWalk rw = new RevWalk(r);
- RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
- rw.dispose();
- baseTree = parent.getTree();
- } else {
- baseTree = baseCommit.getTree();
- }
-
- RevTree commitTree = commit.getTree();
-
- final TreeWalk walk = new TreeWalk(r);
- walk.reset();
- walk.setRecursive(true);
- walk.addTree(baseTree);
- walk.addTree(commitTree);
- walk.setFilter(TreeFilter.ANY_DIFF);
-
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- RawTextComparator cmp = RawTextComparator.DEFAULT;
- DiffFormatter df;
- switch (outputType) {
- case GITWEB:
- df = new GitWebDiffFormatter(os);
- break;
- case GITBLIT:
- df = new GitBlitDiffFormatter(os);
- break;
- case PLAIN:
- default:
- df = new DiffFormatter(os);
- break;
- }
- df.setRepository(r);
- df.setDiffComparator(cmp);
- df.setDetectRenames(true);
- List<DiffEntry> diffs = df.scan(baseTree, commitTree);
- if (path != null && path.length() > 0) {
- for (DiffEntry diff : diffs) {
- if (diff.getNewPath().equalsIgnoreCase(path)) {
- df.format(diff);
- break;
- }
- }
- } else {
- df.format(diffs);
- }
- String diff;
- if (df instanceof GitWebDiffFormatter) {
- // workaround for complex private methods in DiffFormatter
- diff = ((GitWebDiffFormatter) df).getHtml();
- } else {
- diff = os.toString();
- }
- df.flush();
- return diff;
- } catch (Throwable t) {
- LOGGER.error("failed to generate commit diff!", t);
- }
- return null;
- }
-
- public static String getCommitPatch(Repository r, RevCommit commit) {
- return getCommitPatch(r, commit);
- }
-
- public static String getCommitPatch(Repository r, RevCommit commit, String path) {
- return getCommitPatch(r, null, commit, path);
- }
-
- public static String getCommitPatch(Repository r, RevCommit baseCommit, RevCommit commit, String path) {
- try {
- RevTree baseTree;
- if (baseCommit == null) {
- final RevWalk rw = new RevWalk(r);
- RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
- baseTree = parent.getTree();
- } else {
- baseTree = baseCommit.getTree();
- }
- RevTree commitTree = commit.getTree();
-
- final TreeWalk walk = new TreeWalk(r);
- walk.reset();
- walk.setRecursive(true);
- walk.addTree(baseTree);
- walk.addTree(commitTree);
- walk.setFilter(TreeFilter.ANY_DIFF);
-
- final ByteArrayOutputStream os = new ByteArrayOutputStream();
- RawTextComparator cmp = RawTextComparator.DEFAULT;
- PatchFormatter df = new PatchFormatter(os);
- df.setRepository(r);
- df.setDiffComparator(cmp);
- df.setDetectRenames(true);
- List<DiffEntry> diffs = df.scan(baseTree, commitTree);
- if (path != null && path.length() > 0) {
- for (DiffEntry diff : diffs) {
- if (diff.getNewPath().equalsIgnoreCase(path)) {
- df.format(diff);
- break;
- }
- }
- } else {
- df.format(diffs);
- }
- String diff = df.getPatch(commit);
- df.flush();
- return diff;
- } catch (Throwable t) {
- LOGGER.error("failed to generate commit diff!", t);
- }
- return null;
- }
-
- private static PathModel getPathModel(TreeWalk walk, String basePath, RevCommit commit) {
- String name;
- long size = 0;
- if (basePath == null) {
- name = walk.getPathString();
- } else {
- try {
- name = walk.getPathString().substring(basePath.length() + 1);
- } catch (Throwable t) {
- name = walk.getPathString();
- }
- }
- try {
- if (!walk.isSubtree()) {
- size = walk.getObjectReader().getObjectSize(walk.getObjectId(0), Constants.OBJ_BLOB);
- }
- } catch (Throwable t) {
- LOGGER.error("Failed to retrieve blob size", t);
- }
- return new PathModel(name, walk.getPathString(), size, walk.getFileMode(0).getBits(), commit.getName());
- }
-
- public static String getPermissionsFromMode(int mode) {
- if (FileMode.TREE.equals(mode)) {
- return "drwxr-xr-x";
- } else if (FileMode.REGULAR_FILE.equals(mode)) {
- return "-rw-r--r--";
- } 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";
- } else if (FileMode.MISSING.equals(mode)) {
- // FIXME missing permissions
- return "missing";
- }
- return "" + mode;
- }
-
- public static boolean isTreeFromMode(int mode) {
- return FileMode.TREE.equals(mode);
- }
-
- public static List<RevCommit> getRevLog(Repository r, int maxCount) {
- return getRevLog(r, Constants.HEAD, 0, maxCount);
- }
-
- public static List<RevCommit> getRevLog(Repository r, String objectId, int offset, int maxCount) {
- return getRevLog(r, objectId, null, offset, maxCount);
- }
-
- public static List<RevCommit> getRevLog(Repository r, String objectId, String path, int offset, int maxCount) {
- List<RevCommit> list = new ArrayList<RevCommit>();
- try {
- if (objectId == null || objectId.trim().length() == 0) {
- objectId = Constants.HEAD;
- }
- RevWalk walk = new RevWalk(r);
- ObjectId object = r.resolve(objectId);
- walk.markStart(walk.parseCommit(object));
- if (!StringUtils.isEmpty(path)) {
- TreeFilter filter = AndTreeFilter.create(PathFilterGroup.createFromStrings(Collections.singleton(path)), TreeFilter.ANY_DIFF);
- walk.setTreeFilter(filter);
- }
- Iterable<RevCommit> revlog = walk;
- if (offset > 0) {
- int count = 0;
- for (RevCommit rev : revlog) {
- count++;
- if (count > offset) {
- list.add(rev);
- if (maxCount > 0 && list.size() == maxCount) {
- break;
- }
- }
- }
- } else {
- for (RevCommit rev : revlog) {
- list.add(rev);
- if (maxCount > 0 && list.size() == maxCount) {
- break;
- }
- }
- }
- walk.dispose();
- } catch (Throwable t) {
- LOGGER.error("Failed to determine last change", t);
- }
- return list;
- }
-
- public static enum SearchType {
- AUTHOR, COMMITTER, COMMIT;
-
- public static SearchType forName(String name) {
- for (SearchType type : values()) {
- if (type.name().equalsIgnoreCase(name)) {
- return type;
- }
- }
- return null;
- }
-
- public String toString() {
- return name().toLowerCase();
- }
- }
-
- public static List<RevCommit> searchRevlogs(Repository r, String objectId, String value, final SearchType type, int offset, int maxCount) {
- final String lcValue = value.toLowerCase();
- List<RevCommit> list = new ArrayList<RevCommit>();
- try {
- if (objectId == null || objectId.trim().length() == 0) {
- objectId = Constants.HEAD;
- }
- RevWalk walk = new RevWalk(r);
- walk.setRevFilter(new RevFilter() {
-
- @Override
- public RevFilter clone() {
- return this;
- }
-
- @Override
- public boolean include(RevWalk walker, RevCommit commit) throws StopWalkException, MissingObjectException, IncorrectObjectTypeException, IOException {
- switch (type) {
- case AUTHOR:
- return (commit.getAuthorIdent().getName().toLowerCase().indexOf(lcValue) > -1) || (commit.getAuthorIdent().getEmailAddress().toLowerCase().indexOf(lcValue) > -1);
- case COMMITTER:
- return (commit.getCommitterIdent().getName().toLowerCase().indexOf(lcValue) > -1) || (commit.getCommitterIdent().getEmailAddress().toLowerCase().indexOf(lcValue) > -1);
- case COMMIT:
- return commit.getFullMessage().toLowerCase().indexOf(lcValue) > -1;
- }
- return false;
- }
-
- });
- ObjectId object = r.resolve(objectId);
- walk.markStart(walk.parseCommit(object));
- Iterable<RevCommit> revlog = walk;
- if (offset > 0) {
- int count = 0;
- for (RevCommit rev : revlog) {
- count++;
- if (count > offset) {
- list.add(rev);
- if (maxCount > 0 && list.size() == maxCount) {
- break;
- }
- }
- }
- } else {
- for (RevCommit rev : revlog) {
- list.add(rev);
- if (maxCount > 0 && list.size() == maxCount) {
- break;
- }
- }
- }
- walk.dispose();
- } catch (Throwable t) {
- LOGGER.error("Failed to determine last change", t);
- }
- return list;
- }
-
- public static List<RefModel> getTags(Repository r, int maxCount) {
- return getRefs(r, Constants.R_TAGS, maxCount);
- }
-
- public static List<RefModel> getLocalBranches(Repository r, int maxCount) {
- return getRefs(r, Constants.R_HEADS, maxCount);
- }
-
- public static List<RefModel> getRemoteBranches(Repository r, int maxCount) {
- return getRefs(r, Constants.R_REMOTES, maxCount);
- }
-
- public static List<RefModel> getRefs(Repository r, String refs, int maxCount) {
- List<RefModel> list = new ArrayList<RefModel>();
- try {
- Map<String, Ref> map = r.getRefDatabase().getRefs(refs);
- for (String name : map.keySet()) {
- Ref ref = map.get(name);
- RevCommit commit = getCommit(r, ref.getObjectId().getName());
- list.add(new RefModel(name, ref, commit));
- }
- Collections.sort(list);
- Collections.reverse(list);
- if (maxCount > 0 && list.size() > maxCount) {
- list = new ArrayList<RefModel>(list.subList(0, maxCount));
- }
- } catch (IOException e) {
- LOGGER.error("Failed to retrieve " + refs, e);
- }
- return list;
- }
-
- public static Ref getRef(Repository r, String id) {
- try {
- Map<String, Ref> map = r.getRefDatabase().getRefs(id);
- for (String name : map.keySet()) {
- return map.get(name);
- }
- } catch (IOException e) {
- LOGGER.error("Failed to retrieve ref " + id, e);
- }
- return null;
- }
-
- public static Date getCommitDate(RevCommit commit) {
- return new Date(commit.getCommitTime() * 1000l);
- }
-
- public static String getDisplayName(PersonIdent person) {
- final StringBuilder r = new StringBuilder();
- r.append(person.getName());
- r.append(" <");
- r.append(person.getEmailAddress());
- r.append(">");
- return r.toString();
- }
-
- public static StoredConfig readConfig(Repository r) {
- StoredConfig c = r.getConfig();
- if (c != null) {
- try {
- c.load();
- } catch (ConfigInvalidException cex) {
- LOGGER.error("Repository configuration is invalid!", cex);
- } catch (IOException cex) {
- LOGGER.error("Could not open repository configuration!", cex);
- }
- return c;
- }
- return null;
- }
-
- public static List<Metric> getDateMetrics(Repository r) {
- final List<RefModel> tags = getTags(r, -1);
- final Map<ObjectId, RefModel> tagMap = new HashMap<ObjectId, RefModel>();
- for (RefModel tag : tags) {
- tagMap.put(tag.getCommitId(), tag);
- }
- Metric total = new Metric("TOTAL");
- final Map<String, Metric> metricMap = new HashMap<String, Metric>();
- try {
- RevWalk walk = new RevWalk(r);
- ObjectId object = r.resolve(Constants.HEAD);
-
- RevCommit firstCommit = getFirstCommit(r, Constants.HEAD);
- RevCommit lastCommit = walk.parseCommit(object);
- int diffDays = (lastCommit.getCommitTime() - firstCommit.getCommitTime()) / (60 * 60 * 24);
- total.duration = diffDays;
- DateFormat df;
- if (diffDays <= 90) {
- // Days
- df = new SimpleDateFormat("yyyy-MM-dd");
- } else if (diffDays > 90 && diffDays < 365) {
- // Weeks
- df = new SimpleDateFormat("yyyy-MM (w)");
- } else {
- // Months
- df = new SimpleDateFormat("yyyy-MM");
- }
- walk.markStart(lastCommit);
-
- Iterable<RevCommit> revlog = walk;
- for (RevCommit rev : revlog) {
- Date d = getCommitDate(rev);
- String p = df.format(d);
- if (!metricMap.containsKey(p))
- metricMap.put(p, new Metric(p));
- Metric m = metricMap.get(p);
- m.count++;
- total.count++;
- if (tagMap.containsKey(rev.getId())) {
- m.tag++;
- total.tag++;
- }
- }
- } catch (Throwable t) {
- LOGGER.error("Failed to mine log history for metrics", t);
- }
- List<String> keys = new ArrayList<String>(metricMap.keySet());
- Collections.sort(keys);
- List<Metric> metrics = new ArrayList<Metric>();
- for (String key : keys) {
- metrics.add(metricMap.get(key));
- }
- metrics.add(0, total);
- return metrics;
- }
-
- public static RefModel getTicketsBranch(Repository r) {
- RefModel ticgitBranch = null;
- try {
- // search for ticgit branch in local heads
- for (RefModel ref : getLocalBranches(r, -1)) {
- if (ref.getDisplayName().endsWith("ticgit")) {
- ticgitBranch = ref;
- break;
- }
- }
-
- // search for ticgit branch in remote heads
- if (ticgitBranch == null) {
- for (RefModel ref : getRemoteBranches(r, -1)) {
- if (ref.getDisplayName().endsWith("ticgit")) {
- ticgitBranch = ref;
- break;
- }
- }
- }
- } catch (Throwable t) {
- LOGGER.error("Failed to find ticgit branch!", t);
- }
- return ticgitBranch;
- }
-
- public static List<TicketModel> getTickets(Repository r) {
- RefModel ticgitBranch = getTicketsBranch(r);
- List<PathModel> paths = getFilesInPath(r, null, ticgitBranch.getCommit());
- List<TicketModel> tickets = new ArrayList<TicketModel>();
- for (PathModel ticketFolder : paths) {
- if (ticketFolder.isTree()) {
- try {
- TicketModel t = new TicketModel(ticketFolder.name);
- readTicketContents(r, ticgitBranch, t);
- tickets.add(t);
- } catch (Throwable t) {
- LOGGER.error("Failed to get a ticket!", t);
- }
- }
- }
- Collections.sort(tickets);
- Collections.reverse(tickets);
- return tickets;
- }
-
- public static TicketModel getTicket(Repository r, String ticketFolder) {
- RefModel ticketsBranch = getTicketsBranch(r);
- if (ticketsBranch != null) {
- try {
- TicketModel ticket = new TicketModel(ticketFolder);
- readTicketContents(r, ticketsBranch, ticket);
- return ticket;
- } catch (Throwable t) {
- LOGGER.error("Failed to get ticket " + ticketFolder, t);
- }
- }
- return null;
- }
-
- private static void readTicketContents(Repository r, RefModel ticketsBranch, TicketModel ticket) {
- List<PathModel> ticketFiles = getFilesInPath(r, ticket.name, ticketsBranch.getCommit());
- for (PathModel file : ticketFiles) {
- String content = getRawContentAsString(r, ticketsBranch.getCommit(), file.path).trim();
- if (file.name.equals("TICKET_ID")) {
- ticket.id = content;
- } else if (file.name.equals("TITLE")) {
- ticket.title = content;
- } else {
- String[] chunks = file.name.split("_");
- if (chunks[0].equals("ASSIGNED")) {
- ticket.handler = content;
- } else if (chunks[0].equals("COMMENT")) {
- try {
- Comment c = new Comment(file.name, content);
- ticket.comments.add(c);
- } catch (ParseException e) {
- e.printStackTrace();
- }
- } else if (chunks[0].equals("TAG")) {
- if (content.startsWith("TAG_")) {
- ticket.tags.add(content.substring(4));
- } else {
- ticket.tags.add(content);
- }
- } else if (chunks[0].equals("STATE")) {
- ticket.state = content;
- }
- }
- }
- Collections.sort(ticket.comments);
- }
-
- public static String getTicketContent(Repository r, String filePath) {
- RefModel ticketsBranch = getTicketsBranch(r);
- if (ticketsBranch != null) {
- return getRawContentAsString(r, ticketsBranch.getCommit(), filePath);
- }
- return "";
- }
- }
|