diff options
Diffstat (limited to 'plugins/git4idea/src/git4idea/history/GitHistoryUtils.java')
-rw-r--r-- | plugins/git4idea/src/git4idea/history/GitHistoryUtils.java | 197 |
1 files changed, 113 insertions, 84 deletions
diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 8273c3e1abdc..f71400be2a11 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -40,12 +40,12 @@ import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.impl.HashImpl; +import com.intellij.vcs.log.impl.LogDataImpl; import com.intellij.vcs.log.util.StopWatch; import git4idea.*; import git4idea.branch.GitBranchUtil; import git4idea.commands.*; import git4idea.config.GitConfigUtil; -import git4idea.config.GitVersionSpecialty; import git4idea.history.browser.GitHeavyCommit; import git4idea.history.browser.SHAHash; import git4idea.history.browser.SymbolicRefs; @@ -53,6 +53,7 @@ import git4idea.history.browser.SymbolicRefsI; import git4idea.history.wholeTree.AbstractHash; import git4idea.history.wholeTree.CommitHashPlusParents; import git4idea.history.wholeTree.GitCommitsSequentialIndex; +import git4idea.log.GitRefManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -515,21 +516,47 @@ public class GitHistoryUtils { }); } - @NotNull - public static List<TimedVcsCommit> readCommits(@NotNull final Project project, - @NotNull VirtualFile root, - @NotNull final Consumer<VcsUser> userRegistry, - @NotNull List<String> parameters) throws VcsException { - List<TimedVcsCommit> collector = ContainerUtil.newArrayList(); - readCommits(project, root, userRegistry, parameters, new CollectConsumer<TimedVcsCommit>(collector)); - return collector; + @Nullable + public static List<VcsCommitMetadata> readLastCommits(@NotNull Project project, + @NotNull final VirtualFile root, + @NotNull String... refs) + throws VcsException { + final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); + if (factory == null) { + return null; + } + + GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); + GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, COMMIT_TIME, SUBJECT, AUTHOR_NAME, + AUTHOR_EMAIL, RAW_BODY, COMMITTER_NAME, COMMITTER_EMAIL, AUTHOR_TIME); + + h.setSilent(true); + // git show can show either -p, or --name-status, or --name-only, but we need nothing, just details => using git log --no-walk + h.addParameters("--no-walk"); + h.addParameters(parser.getPretty(), "--encoding=UTF-8"); + h.addParameters(refs); + + String output = h.run(); + List<GitLogRecord> records = parser.parse(output); + if (records.size() != refs.length) return null; + + return ContainerUtil.map(records, new Function<GitLogRecord, VcsCommitMetadata>() { + @Override + public VcsCommitMetadata fun(GitLogRecord record) { + return factory.createCommitMetadata(factory.createHash(record.getHash()), getParentHashes(factory, record), record.getCommitTime(), + root, record.getSubject(), record.getAuthorName(), record.getAuthorEmail(), + record.getFullMessage(), record.getCommitterName(), record.getCommitterEmail(), + record.getAuthorTimeStamp()); + } + }); } public static void readCommits(@NotNull final Project project, - @NotNull VirtualFile root, - @NotNull final Consumer<VcsUser> userRegistry, - @NotNull List<String> parameters, - @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException { + @NotNull final VirtualFile root, + @NotNull List<String> parameters, + @NotNull final Consumer<VcsUser> userConsumer, + @NotNull final Consumer<VcsRef> refConsumer, + @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException { final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); if (factory == null) { return; @@ -538,11 +565,12 @@ public class GitHistoryUtils { final int COMMIT_BUFFER = 1000; GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG); final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, COMMIT_TIME, - AUTHOR_NAME, AUTHOR_EMAIL); + AUTHOR_NAME, AUTHOR_EMAIL, REF_NAMES); h.setStdoutSuppressed(true); h.addParameters(parser.getPretty(), "--encoding=UTF-8"); h.addParameters("--full-history"); h.addParameters("--date-order"); + h.addParameters("--decorate=full"); h.addParameters(parameters); h.endOptions(); @@ -568,7 +596,7 @@ public class GitHistoryUtils { afterParseRemainder = line.substring(recordEnd + 1); } if (afterParseRemainder != null && records.incrementAndGet() > COMMIT_BUFFER) { // null means can't parse now - List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory); + List<TimedVcsCommit> commits = parseCommit(parser, record, userConsumer, refConsumer, factory, root); for (TimedVcsCommit commit : commits) { commitConsumer.consume(commit); } @@ -584,7 +612,7 @@ public class GitHistoryUtils { @Override public void processTerminated(int exitCode) { try { - List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory); + List<TimedVcsCommit> commits = parseCommit(parser, record, userConsumer, refConsumer, factory, root); for (TimedVcsCommit commit : commits) { commitConsumer.consume(commit); } @@ -606,9 +634,12 @@ public class GitHistoryUtils { } @NotNull - private static List<TimedVcsCommit> parseCommit(@NotNull GitLogParser parser, @NotNull StringBuilder record, + private static List<TimedVcsCommit> parseCommit(@NotNull GitLogParser parser, + @NotNull StringBuilder record, @NotNull final Consumer<VcsUser> userRegistry, - @NotNull final VcsLogObjectsFactory factory) { + @NotNull final Consumer<VcsRef> refConsumer, + @NotNull final VcsLogObjectsFactory factory, + @NotNull final VirtualFile root) { List<GitLogRecord> rec = parser.parse(record.toString()); return ContainerUtil.mapNotNull(rec, new Function<GitLogRecord, TimedVcsCommit>() { @Override @@ -616,7 +647,11 @@ public class GitHistoryUtils { if (record == null) { return null; } - TimedVcsCommit commit = convert(record, factory); + Pair<TimedVcsCommit, Collection<VcsRef>> pair = convert(record, factory, root); + TimedVcsCommit commit = pair.first; + for (VcsRef ref : pair.second) { + refConsumer.consume(ref); + } userRegistry.consume(factory.createUser(record.getAuthorName(), record.getAuthorEmail())); return commit; } @@ -624,9 +659,28 @@ public class GitHistoryUtils { } @NotNull - private static TimedVcsCommit convert(@NotNull GitLogRecord rec, @NotNull VcsLogObjectsFactory factory) { + private static Pair<TimedVcsCommit, Collection<VcsRef>> convert(@NotNull GitLogRecord rec, + @NotNull VcsLogObjectsFactory factory, + @NotNull VirtualFile root) { + Hash hash = HashImpl.build(rec.getHash()); List<Hash> parents = getParentHashes(factory, rec); - return factory.createTimedCommit(HashImpl.build(rec.getHash()), parents, rec.getCommitTime()); + TimedVcsCommit commit = factory.createTimedCommit(hash, parents, rec.getCommitTime()); + return Pair.create(commit, parseRefs(rec.getRefs(), hash, factory, root)); + } + + @NotNull + private static Collection<VcsRef> parseRefs(@NotNull Collection<String> refs, + @NotNull final Hash hash, + @NotNull final VcsLogObjectsFactory factory, + @NotNull final VirtualFile root) { + return ContainerUtil.mapNotNull(refs, new Function<String, VcsRef>() { + @Override + public VcsRef fun(String refName) { + VcsRefType type = GitRefManager.getRefType(refName); + refName = GitBranchUtil.stripRefsPrefix(refName); + return factory.createRef(hash, refName, type, root); + } + }); } @Nullable @@ -749,23 +803,28 @@ public class GitHistoryUtils { } @NotNull - public static List<VcsCommitMetadata> loadMetadata(@NotNull Project project, @NotNull final VirtualFile root, - @NotNull String... parameters) throws VcsException { - + public static VcsLogProvider.DetailedLogData loadMetadata(@NotNull final Project project, + @NotNull final VirtualFile root, + final boolean withRefs, + String... params) throws VcsException { final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); if (factory == null) { - return Collections.emptyList(); + return LogDataImpl.empty(); } - return loadDetails(project, root, false, new NullableFunction<GitLogRecord, VcsCommitMetadata>() { - @Nullable - @Override - public VcsCommitMetadata fun(GitLogRecord record) { - return factory.createCommitMetadata(factory.createHash(record.getHash()), getParentHashes(factory, record), record.getCommitTime(), - root, record.getSubject(), record.getAuthorName(), record.getAuthorEmail(), - record.getFullMessage(), record.getCommitterName(), record.getCommitterEmail(), - record.getAuthorTimeStamp()); - } - }, parameters); + final Set<VcsRef> refs = ContainerUtil.newHashSet(); + final List<VcsCommitMetadata> commits = + loadDetails(project, root, withRefs, false, new NullableFunction<GitLogRecord, VcsCommitMetadata>() { + @Nullable + @Override + public VcsCommitMetadata fun(GitLogRecord record) { + GitCommit commit = createCommit(project, root, record, factory); + if (withRefs) { + refs.addAll(parseRefs(record.getRefs(), commit.getId(), factory, root)); + } + return commit; + } + }, params); + return new LogDataImpl(refs, commits); } /** @@ -781,35 +840,39 @@ public class GitHistoryUtils { if (factory == null) { return Collections.emptyList(); } - return loadDetails(project, root, true, new NullableFunction<GitLogRecord, GitCommit>() { + return loadDetails(project, root, false, true, new NullableFunction<GitLogRecord, GitCommit>() { @Override @Nullable public GitCommit fun(GitLogRecord record) { - try { - return createCommit(project, root, record, factory); - } - catch (VcsException e) { - LOG.error(e); - return null; - } + return createCommit(project, root, record, factory); } }, parameters); } @NotNull - public static <T> List<T> loadDetails(@NotNull final Project project, @NotNull final VirtualFile root, boolean withChanges, - @NotNull NullableFunction<GitLogRecord, T> converter, String... parameters) + public static <T> List<T> loadDetails(@NotNull final Project project, + @NotNull final VirtualFile root, + boolean withRefs, + boolean withChanges, + @NotNull NullableFunction<GitLogRecord, T> converter, + String... parameters) throws VcsException { GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); GitLogParser.NameStatus status = withChanges ? GitLogParser.NameStatus.STATUS : GitLogParser.NameStatus.NONE; - GitLogParser parser = new GitLogParser(project, status, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, - AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, PARENTS, SUBJECT, BODY, RAW_BODY); + GitLogParser.GitLogOption[] options = { HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, + PARENTS, SUBJECT, BODY, RAW_BODY }; + if (withRefs) { + options = ArrayUtil.append(options, REF_NAMES); + } + GitLogParser parser = new GitLogParser(project, status, options); h.setStdoutSuppressed(true); h.addParameters(parameters); h.addParameters(parser.getPretty(), "--encoding=UTF-8"); - h.addParameters("--full-history", "--sparse"); + if (withRefs) { + h.addParameters("--decorate=full"); + } if (withChanges) { - h.addParameters("-M", "--name-status"); + h.addParameters("-M", "--name-status", "-m"); } h.endOptions(); @@ -828,7 +891,7 @@ public class GitHistoryUtils { } private static GitCommit createCommit(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLogRecord record, - @NotNull VcsLogObjectsFactory factory) throws VcsException { + @NotNull VcsLogObjectsFactory factory) { List<Hash> parents = getParentHashes(factory, record); return new GitCommit(project, HashImpl.build(record.getHash()), parents, record.getCommitTime(), root, record.getSubject(), factory.createUser(record.getAuthorName(), record.getAuthorEmail()), record.getFullMessage(), @@ -1091,40 +1154,6 @@ public class GitHistoryUtils { return rc; } - @NotNull - public static List<GitCommit> commitsDetails(@NotNull Project project, @NotNull VirtualFile root, - @NotNull final Collection<String> hashes) throws VcsException { - List<String> params = new ArrayList<String>(hashes); - GitVcs vcs = GitVcs.getInstance(project); - String noWalk = vcs != null && GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(vcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk"; - params.add(0, noWalk); - return getAllDetails(project, root, params); - } - - @NotNull - public static List<GitCommit> getAllDetails(@NotNull Project project, @NotNull VirtualFile root, - @NotNull List<String> parameters) throws VcsException { - VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); - if (factory == null) { - return Collections.emptyList(); - } - - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); - GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, - HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME, - COMMITTER_EMAIL, PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY); - h.setSilent(true); - h.addParameters("--name-status", "-M", parser.getPretty(), "--encoding=UTF-8"); - h.addParameters(parameters); - - String output = h.run(); - final List<GitCommit> rc = new ArrayList<GitCommit>(); - for (GitLogRecord record : parser.parse(output)) { - rc.add(createCommit(project, root, record, factory)); - } - return rc; - } - public static long getAuthorTime(Project project, FilePath path, final String commitsId) throws VcsException { // adjust path using change manager path = getLastCommitName(project, path); |