2 * Copyright 2000-2014 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 import com.intellij.openapi.components.ServiceManager;
19 import com.intellij.openapi.util.Condition;
20 import com.intellij.openapi.util.text.StringUtil;
21 import com.intellij.openapi.vcs.VcsException;
22 import com.intellij.openapi.vfs.VirtualFile;
23 import com.intellij.util.ArrayUtil;
24 import com.intellij.util.CollectConsumer;
25 import com.intellij.util.Consumer;
26 import com.intellij.util.Function;
27 import com.intellij.util.containers.ContainerUtil;
28 import com.intellij.vcs.log.*;
29 import com.intellij.vcs.log.data.VcsLogBranchFilterImpl;
30 import com.intellij.vcs.log.impl.*;
31 import com.intellij.vcs.log.impl.VcsLogUserFilterImpl;
32 import com.intellij.vcsUtil.VcsFileUtil;
33 import git4idea.test.GitSingleRepoTest;
34 import git4idea.test.GitTestUtil;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
38 import java.io.IOException;
39 import java.util.Collections;
40 import java.util.List;
43 import static git4idea.test.GitExecutor.*;
44 import static java.util.Collections.singleton;
46 public class GitLogProviderTest extends GitSingleRepoTest {
48 private GitLogProvider myLogProvider;
49 private VcsLogObjectsFactory myObjectsFactory;
51 public void setUp() throws Exception {
53 myLogProvider = GitTestUtil.findGitLogProvider(myProject);
54 myObjectsFactory = ServiceManager.getService(myProject, VcsLogObjectsFactory.class);
57 public void tearDown() throws Exception {
61 public void test_init_with_tagged_branch() throws VcsException {
63 List<VcsCommitMetadata> expectedLogWithoutTaggedBranch = log();
66 VcsLogProvider.DetailedLogData block = myLogProvider.readFirstBlock(myProjectRoot,new RequirementsImpl(1000, false, Collections.<VcsRef>emptySet()));
67 assertOrderedEquals(block.getCommits(), expectedLogWithoutTaggedBranch);
70 public void test_refresh_with_new_tagged_branch() throws VcsException {
72 Set<VcsRef> prevRefs = GitTestUtil.readAllRefs(myProjectRoot, myObjectsFactory);
75 List<VcsCommitMetadata> expectedLog = log();
76 VcsLogProvider.DetailedLogData block = myLogProvider.readFirstBlock(myProjectRoot, new RequirementsImpl(1000, true, prevRefs));
77 assertSameElements(block.getCommits(), expectedLog);
80 public void test_refresh_when_new_tag_moved() throws VcsException {
82 Set<VcsRef> prevRefs = GitTestUtil.readAllRefs(myProjectRoot, myObjectsFactory);
85 List<VcsCommitMetadata> expectedLog = log();
86 Set<VcsRef> refs = GitTestUtil.readAllRefs(myProjectRoot, myObjectsFactory);
87 VcsLogProvider.DetailedLogData block = myLogProvider.readFirstBlock(myProjectRoot, new RequirementsImpl(1000, true, prevRefs));
88 assertSameElements(block.getCommits(), expectedLog);
89 assertSameElements(block.getRefs(), refs);
92 public void test_new_tag_on_old_commit() throws VcsException {
94 Set<VcsRef> prevRefs = GitTestUtil.readAllRefs(myProjectRoot, myObjectsFactory);
95 List<VcsCommitMetadata> log = log();
96 String firstCommit = log.get(log.size() - 1).getId().asString();
97 git("tag NEW_TAG " + firstCommit);
99 Set<VcsRef> refs = GitTestUtil.readAllRefs(myProjectRoot, myObjectsFactory);
100 VcsLogProvider.DetailedLogData block = myLogProvider.readFirstBlock(myProjectRoot, new RequirementsImpl(1000, true, prevRefs));
101 assertSameElements(block.getRefs(), refs);
104 public void test_all_log_with_tagged_branch() throws VcsException {
105 prepareSomeHistory();
106 createTaggedBranch();
107 List<VcsCommitMetadata> expectedLog = log();
108 List<TimedVcsCommit> collector = ContainerUtil.newArrayList();
109 //noinspection unchecked
110 myLogProvider.readAllHashes(myProjectRoot, new CollectConsumer<>(collector));
111 assertOrderedEquals(expectedLog, collector);
114 public void test_get_current_user() throws Exception {
115 VcsUser user = myLogProvider.getCurrentUser(myProjectRoot);
116 assertNotNull("User is not defined", user);
117 VcsUser expected = getDefaultUser();
118 assertEquals("User name is incorrect", expected.getName(), user.getName());
119 assertEquals("User email is incorrect", expected.getEmail(), user.getEmail());
122 public void test_dont_report_origin_HEAD() throws Exception {
123 prepareSomeHistory();
124 git("update-ref refs/remotes/origin/HEAD master");
126 VcsLogProvider.DetailedLogData block = myLogProvider.readFirstBlock(myProjectRoot,
127 new RequirementsImpl(1000, false, Collections.<VcsRef>emptySet()));
128 assertFalse("origin/HEAD should be ignored", ContainerUtil.exists(block.getRefs(), new Condition<VcsRef>() {
130 public boolean value(VcsRef ref) {
131 return ref.getName().equals("origin/HEAD");
136 public void test_support_equally_named_branch_and_tag() throws Exception {
137 prepareSomeHistory();
141 VcsLogProvider.DetailedLogData data = myLogProvider.readFirstBlock(myProjectRoot,
142 new RequirementsImpl(1000, true, Collections.<VcsRef>emptySet()));
143 List<VcsCommitMetadata> expectedLog = log();
144 assertOrderedEquals(data.getCommits(), expectedLog);
145 assertTrue(ContainerUtil.exists(data.getRefs(), new Condition<VcsRef>() {
147 public boolean value(VcsRef ref) {
148 return ref.getName().equals("build") && ref.getType() == GitRefManager.LOCAL_BRANCH;
151 assertTrue(ContainerUtil.exists(data.getRefs(), new Condition<VcsRef>() {
153 public boolean value(VcsRef ref) {
154 return ref.getName().equals("build") && ref.getType() == GitRefManager.TAG;
159 public void test_filter_by_branch() throws Exception {
160 List<String> hashes = generateHistoryForFilters(true);
161 VcsLogBranchFilter branchFilter = VcsLogBranchFilterImpl.fromBranch("feature");
162 List<String> actualHashes = getFilteredHashes(branchFilter, null);
163 assertEquals(hashes, actualHashes);
166 public void test_filter_by_branch_and_user() throws Exception {
167 List<String> hashes = generateHistoryForFilters(false);
168 VcsLogBranchFilter branchFilter = VcsLogBranchFilterImpl.fromBranch("feature");
169 VcsLogUserFilter userFilter = new VcsLogUserFilterImpl(singleton(GitTestUtil.USER_NAME), Collections.<VirtualFile, VcsUser>emptyMap(),
170 Collections.<VcsUser>emptySet());
171 List<String> actualHashes = getFilteredHashes(branchFilter, userFilter);
172 assertEquals(hashes, actualHashes);
175 public void test_short_details() throws Exception {
176 prepareLongHistory(VcsFileUtil.FILE_PATH_LIMIT * 2 / 40);
177 List<VcsCommitMetadata> log = log();
179 final List<String> hashes = ContainerUtil.newArrayList();
180 myLogProvider.readAllHashes(myProjectRoot, new Consumer<TimedVcsCommit>() {
182 public void consume(TimedVcsCommit timedVcsCommit) {
183 hashes.add(timedVcsCommit.getId().asString());
187 List<? extends VcsShortCommitDetails> shortDetails = myLogProvider.readShortDetails(myProjectRoot, hashes);
189 Function<VcsShortCommitDetails, String> shortDetailsToString = getShortDetailsToString();
190 assertOrderedEquals(ContainerUtil.map(shortDetails, shortDetailsToString), ContainerUtil.map(log, shortDetailsToString));
193 public void test_full_details() throws Exception {
194 prepareLongHistory(VcsFileUtil.FILE_PATH_LIMIT * 2 / 40);
195 List<VcsCommitMetadata> log = log();
197 final List<String> hashes = ContainerUtil.newArrayList();
198 myLogProvider.readAllHashes(myProjectRoot, new Consumer<TimedVcsCommit>() {
200 public void consume(TimedVcsCommit timedVcsCommit) {
201 hashes.add(timedVcsCommit.getId().asString());
205 List<? extends VcsFullCommitDetails> fullDetails = myLogProvider.readFullDetails(myProjectRoot, hashes);
207 // we do not check for changes here
208 final Function<VcsShortCommitDetails, String> shortDetailsToString = getShortDetailsToString();
209 Function<VcsCommitMetadata, String> metadataToString = new Function<VcsCommitMetadata, String>() {
211 public String fun(VcsCommitMetadata details) {
212 return shortDetailsToString.fun(details) + "\n" + details.getFullMessage();
215 assertOrderedEquals(ContainerUtil.map(fullDetails, metadataToString), ContainerUtil.map(log, metadataToString));
219 private Function<VcsShortCommitDetails, String> getShortDetailsToString() {
220 return new Function<VcsShortCommitDetails, String>() {
222 public String fun(VcsShortCommitDetails details) {
225 result += details.getId().toShortString() + "\n";
226 result += details.getAuthorTime() + "\n";
227 result += details.getAuthor() + "\n";
228 result += details.getCommitTime() + "\n";
229 result += details.getCommitter() + "\n";
230 result += details.getSubject();
238 * Generates some history with two branches: master and feature, and made by two users.
239 * Returns hashes of this history filtered by the given parameters:
240 * @param takeAllUsers if true, don't filter by users, otherwise filter by default user.
242 private List<String> generateHistoryForFilters(boolean takeAllUsers) {
243 List<String> hashes = ContainerUtil.newArrayList();
246 GitTestUtil.setupUsername("bob.smith", "bob.smith@example.com");
248 String commitByBob = tac("file.txt");
249 hashes.add(commitByBob);
251 GitTestUtil.setupDefaultUsername();
253 hashes.add(tac("file1.txt"));
254 git("checkout -b feature");
255 String commitOnlyInFeature = tac("file2.txt");
256 hashes.add(commitOnlyInFeature);
257 git("checkout master");
258 String commitOnlyInMaster = tac("master.txt");
260 Collections.reverse(hashes);
266 private List<String> getFilteredHashes(@Nullable VcsLogBranchFilter branchFilter,
267 @Nullable VcsLogUserFilter userFilter) throws VcsException {
268 VcsLogFilterCollectionImpl filters = new VcsLogFilterCollectionImpl(branchFilter, userFilter, null, null, null, null, null);
269 List<TimedVcsCommit> commits = myLogProvider.getCommitsMatchingFilter(myProjectRoot, filters, -1);
270 return ContainerUtil.map(commits, new Function<TimedVcsCommit, String>() {
272 public String fun(TimedVcsCommit commit) {
273 return commit.getId().asString();
278 private static void prepareSomeHistory() {
284 private static void prepareLongHistory(int size) throws IOException {
285 for (int i = 0; i < size; i++) {
286 String file = "a" + (i % 10) + ".txt";
296 private static void createTaggedBranch() {
297 String hash = last();
302 git("reset --hard " + hash);
306 private static VcsUser getDefaultUser() {
307 return new VcsUserImpl(GitTestUtil.USER_NAME, GitTestUtil.USER_EMAIL);
311 private List<VcsCommitMetadata> log() {
312 String output = git("log --all --date-order --full-history --sparse --pretty='%H|%P|%ct|%s|%B'");
313 final VcsUser defaultUser = getDefaultUser();
314 final Function<String, Hash> TO_HASH = new Function<String, Hash>() {
316 public Hash fun(String s) {
317 return HashImpl.build(s);
320 return ContainerUtil.map(StringUtil.splitByLines(output), new Function<String, VcsCommitMetadata>() {
322 public VcsCommitMetadata fun(String record) {
323 String[] items = ArrayUtil.toStringArray(StringUtil.split(record, "|", true, false));
324 long time = Long.valueOf(items[2]) * 1000;
325 return new VcsCommitMetadataImpl(TO_HASH.fun(items[0]), ContainerUtil.map(items[1].split(" "), TO_HASH), time,
326 myProjectRoot, items[3], defaultUser, items[4], defaultUser, time);