Skip to content

Commit 6dc9e9c

Browse files
committed
branch first and head commits determination improved
getTags() and getTagOnRevision() improved
1 parent ec861b3 commit 6dc9e9c

File tree

2 files changed

+122
-120
lines changed

2 files changed

+122
-120
lines changed

src/main/java/org/scm4j/vcs/svn/SVNVCS.java

Lines changed: 39 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,10 @@ private List<VCSDiffEntry> fillUnifiedDiffs(final String srcBranchName, final St
350350
}
351351

352352
protected SVNLogEntry getDirFirstCommit(final String dir) throws SVNException {
353-
final SVNLogEntry[] firstEntryHolder = new SVNLogEntry[1];
354-
repository.log(new String[] { dir }, 0 /* start from first commit */,
355-
-1 /* to the head commit */, true, true, 1 /* limit */, new ISVNLogEntryHandler() {
356-
@Override
357-
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
358-
firstEntryHolder[0] = logEntry;
359-
}
360-
});
361-
return firstEntryHolder[0];
353+
@SuppressWarnings("unchecked")
354+
Collection<SVNLogEntry> entries = repository.log(new String[] { dir }, null, 0 /* start from first commit */,
355+
-1 /* to the head commit */, true, true);
356+
return entries.iterator().next();
362357
}
363358

364359
protected SVNLogEntry getBranchFirstCommit(final String branchPath) throws Exception {
@@ -586,17 +581,21 @@ public IVCSWorkspace getWorkspace() {
586581
@Override
587582
public VCSCommit getHeadCommit(String branchName) {
588583
try {
589-
SVNLogEntry entry = revToSVNEntry(getBranchName(branchName), -1L);
590-
if (entry != null) {
591-
return svnLogEntryToVCSCommit(entry);
592-
}
593-
return null;
584+
SVNLogEntry headEntry = getDirHeadLogEntry(getBranchName(branchName));
585+
return new VCSCommit(Long.toString(headEntry.getRevision()), headEntry.getMessage(), headEntry.getAuthor());
594586
} catch (SVNException e) {
595587
throw new EVCSException(e);
596588
} catch (Exception e) {
597589
throw new RuntimeException(e);
598590
}
599591
}
592+
593+
protected SVNLogEntry getDirHeadLogEntry(String dir) throws Exception {
594+
@SuppressWarnings("unchecked")
595+
Collection<SVNLogEntry> entries = repository.log(new String[] { dir }, null, -1 /* start from head commit */,
596+
0 /* to the first commit */, true, true);
597+
return entries.iterator().next();
598+
}
600599

601600
@Override
602601
public String toString() {
@@ -645,9 +644,6 @@ public VCSTag createTag(String branchName, String tagName, String tagMessage, St
645644

646645
protected SVNLogEntry revToSVNEntry(String branchName, Long rev) throws Exception {
647646
SVNDirEntry info = repository.info(branchName, rev);
648-
if (info == null) {
649-
return null;
650-
}
651647
@SuppressWarnings("unchecked")
652648
Collection<SVNLogEntry> entries = repository.log(new String[] {branchName}, null, info.getRevision(), info.getRevision(), true, true);
653649
if (entries != null) {
@@ -659,34 +655,7 @@ protected SVNLogEntry revToSVNEntry(String branchName, Long rev) throws Exceptio
659655
@Override
660656
public List<VCSTag> getTags() {
661657
try {
662-
//List<String> entries = listEntries(TAGS_PATH);
663-
List<String> entries = new ArrayList<>();
664-
@SuppressWarnings("unchecked")
665-
Collection<SVNDirEntry> dirEntries = repository.getDir(TAGS_PATH, -1 , null , (Collection<SVNDirEntry>) null);
666-
for (SVNDirEntry dirEntry : dirEntries) {
667-
if (dirEntry.getKind() == SVNNodeKind.DIR) {
668-
entries.add(TAGS_PATH + dirEntry.getName());
669-
}
670-
}
671-
672-
List<VCSTag> res = new ArrayList<>();
673-
for (String entryStr : entries) {
674-
675-
SVNLogEntry entry = revToSVNEntry(entryStr, -1L);
676-
677-
long tagCopyFrom = 0;
678-
for (SVNLogEntryPath entryPath : getDirFirstCommit(entryStr).getChangedPaths().values()) {
679-
tagCopyFrom = entryPath.getCopyRevision();
680-
}
681-
// repository.log(new String[] { entryStr }, -1 /* start from head descending */,
682-
// 0, true, true, -1, handler);
683-
684-
SVNDirEntry copyFromEntry = repository.info("", tagCopyFrom);
685-
686-
res.add(new VCSTag(entryStr.replace(TAGS_PATH, ""), entry.getMessage(), entry.getAuthor(), new VCSCommit(Long.toString(copyFromEntry.getRevision()),
687-
copyFromEntry.getCommitMessage(), copyFromEntry.getAuthor())));
688-
}
689-
return res;
658+
return getTags(null);
690659
} catch (SVNException e) {
691660
throw new EVCSException(e);
692661
} catch (Exception e) {
@@ -718,42 +687,36 @@ public void checkout(String branchName, String targetPath, String revision) {
718687
throw new RuntimeException(e);
719688
}
720689
}
721-
722-
723-
@Override
724-
public List<VCSTag> getTagsOnRevision(String revision) {
725-
try {
726-
List<VCSTag> res = new ArrayList<>();
727-
if (repository.checkPath(TAGS_PATH , -1) == SVNNodeKind.NONE) {
728-
return res;
729-
}
730-
List<String> tagEntries = new ArrayList<>();
690+
691+
protected List<VCSTag> getTags(String onRevision) throws Exception {
692+
List<VCSTag> res = new ArrayList<>();
693+
@SuppressWarnings("unchecked")
694+
Collection<SVNDirEntry> dirEntries = repository.getDir(TAGS_PATH, -1 , null, (Collection<SVNDirEntry>) null);
695+
for (SVNDirEntry dirEntry : dirEntries) {
696+
long tagCopyFrom = 0;
731697

732-
@SuppressWarnings("unchecked")
733-
Collection<SVNDirEntry> entries = repository.getDir(TAGS_PATH, -1 , null , (Collection<SVNDirEntry>) null);
734-
for (SVNDirEntry entry : entries) {
735-
if (entry.getKind() == SVNNodeKind.DIR) {
736-
tagEntries.add(TAGS_PATH + entry.getName());
737-
}
698+
SVNLogEntry tagEntry = getDirFirstCommit(TAGS_PATH + dirEntry.getName());
699+
for (SVNLogEntryPath entryPath : tagEntry.getChangedPaths().values()) {
700+
tagCopyFrom = entryPath.getCopyRevision();
738701
}
739702

740-
for (String tagEntryStr : tagEntries) {
741-
742-
SVNLogEntry entry = revToSVNEntry(tagEntryStr, -1L);
743-
744-
long tagCopyFrom = 0;
745-
for (SVNLogEntryPath entryPath : getDirFirstCommit(tagEntryStr).getChangedPaths().values()) {
746-
tagCopyFrom = entryPath.getCopyRevision();
747-
}
748-
749-
if (tagCopyFrom == Long.parseLong(revision)) {
750-
SVNDirEntry copyFromEntry = repository.info("", tagCopyFrom);
751-
res.add(new VCSTag(tagEntryStr.replace(TAGS_PATH, ""), entry.getMessage(), entry.getAuthor(), new VCSCommit(Long.toString(copyFromEntry.getRevision()),
752-
copyFromEntry.getCommitMessage(), copyFromEntry.getAuthor())));
753-
}
703+
if (onRevision == null || tagCopyFrom == Long.parseLong(onRevision)) {
704+
SVNProperties props = repository.getRevisionProperties(tagCopyFrom, null);
705+
res.add(new VCSTag(dirEntry.getName(), tagEntry.getMessage(), tagEntry.getAuthor(), new VCSCommit(Long.toString(tagCopyFrom),
706+
props.getStringValue(SVNRevisionProperty.LOG), props.getStringValue(SVNRevisionProperty.AUTHOR))));
754707
}
755-
return res;
708+
}
709+
return res;
710+
}
711+
712+
@Override
713+
public List<VCSTag> getTagsOnRevision(String revision) {
714+
try {
715+
return getTags(revision);
756716
} catch (SVNException e) {
717+
if (e.getErrorMessage().getErrorCode().getCode() == SVN_FILE_NOT_FOUND_ERROR_CODE) {
718+
return new ArrayList<>();
719+
}
757720
throw new EVCSException(e);
758721
} catch (Exception e) {
759722
throw new RuntimeException(e);

src/test/java/org/scm4j/vcs/svn/SVNVCSTest.java

Lines changed: 83 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,35 @@
11
package org.scm4j.vcs.svn;
22

3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertNull;
6+
import static org.junit.Assert.assertTrue;
7+
import static org.junit.Assert.fail;
8+
import static org.mockito.Matchers.any;
9+
import static org.mockito.Matchers.anyBoolean;
10+
import static org.mockito.Matchers.anyLong;
11+
import static org.mockito.Matchers.anyString;
12+
import static org.mockito.Matchers.isNull;
13+
import static org.mockito.Mockito.doCallRealMethod;
14+
import static org.mockito.Mockito.doReturn;
15+
import static org.mockito.Mockito.doThrow;
16+
import static org.mockito.Mockito.mock;
17+
import static org.mockito.Mockito.reset;
18+
import static org.mockito.Mockito.spy;
19+
import static org.mockito.Mockito.verify;
20+
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.io.OutputStream;
24+
import java.lang.reflect.Field;
25+
import java.lang.reflect.InvocationTargetException;
26+
import java.lang.reflect.Method;
27+
import java.lang.reflect.Modifier;
28+
import java.util.Arrays;
29+
import java.util.Collection;
30+
import java.util.List;
31+
332
import org.junit.After;
4-
import org.junit.Ignore;
533
import org.junit.Test;
634
import org.mockito.Matchers;
735
import org.mockito.exceptions.verification.WantedButNotInvoked;
@@ -11,32 +39,25 @@
1139
import org.scm4j.vcs.api.abstracttest.VCSAbstractTest;
1240
import org.scm4j.vcs.api.exceptions.EVCSException;
1341
import org.scm4j.vcs.api.workingcopy.IVCSRepositoryWorkspace;
14-
import org.tmatesoft.svn.core.*;
42+
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
43+
import org.tmatesoft.svn.core.SVNDepth;
44+
import org.tmatesoft.svn.core.SVNDirEntry;
45+
import org.tmatesoft.svn.core.SVNErrorCode;
46+
import org.tmatesoft.svn.core.SVNErrorMessage;
47+
import org.tmatesoft.svn.core.SVNException;
48+
import org.tmatesoft.svn.core.SVNNodeKind;
49+
import org.tmatesoft.svn.core.SVNProperties;
50+
import org.tmatesoft.svn.core.SVNURL;
1551
import org.tmatesoft.svn.core.auth.ISVNProxyManager;
1652
import org.tmatesoft.svn.core.auth.SVNAuthentication;
1753
import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication;
1854
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
1955
import org.tmatesoft.svn.core.io.SVNRepository;
20-
import org.tmatesoft.svn.core.wc.*;
21-
22-
import java.io.File;
23-
import java.io.IOException;
24-
import java.io.OutputStream;
25-
import java.lang.reflect.Field;
26-
import java.lang.reflect.InvocationTargetException;
27-
import java.lang.reflect.Method;
28-
import java.lang.reflect.Modifier;
29-
import java.util.Arrays;
30-
import java.util.Collection;
31-
import java.util.List;
32-
33-
import static org.junit.Assert.*;
34-
import static org.mockito.Matchers.any;
35-
import static org.mockito.Matchers.anyBoolean;
36-
import static org.mockito.Matchers.anyLong;
37-
import static org.mockito.Matchers.anyString;
38-
import static org.mockito.Matchers.isNull;
39-
import static org.mockito.Mockito.*;
56+
import org.tmatesoft.svn.core.wc.SVNClientManager;
57+
import org.tmatesoft.svn.core.wc.SVNCommitClient;
58+
import org.tmatesoft.svn.core.wc.SVNStatusClient;
59+
import org.tmatesoft.svn.core.wc.SVNStatusType;
60+
import org.tmatesoft.svn.core.wc.SVNWCClient;
4061

4162
public class SVNVCSTest extends VCSAbstractTest {
4263

@@ -350,14 +371,21 @@ public void testGetCommitsRangeExceptions() throws Exception {
350371
public void testGetHeadCommitExceptions() throws Exception {
351372
SVNRepository mockedRepo = spy(svn.getSVNRepository());
352373
svn.setSVNRepository(mockedRepo);
353-
doThrow(testSVNException).when(mockedRepo).log(any(String[].class), anyLong(), anyLong(), anyBoolean(), anyBoolean(),
354-
any(Integer.class), any(ISVNLogEntryHandler.class));
374+
doThrow(testSVNException).when(svn).getDirHeadLogEntry(anyString());
355375
try {
356376
vcs.getHeadCommit("");
357377
fail();
358378
} catch (EVCSException e) {
359379
checkEVCSException(e);
360380
}
381+
382+
doThrow(testCommonException).when(svn).getDirHeadLogEntry(anyString());
383+
try {
384+
vcs.getHeadCommit("");
385+
fail();
386+
} catch (RuntimeException e) {
387+
checkCommonException(e);
388+
}
361389
}
362390

363391
@Test
@@ -373,30 +401,25 @@ public void testFileExistsExceptions() throws Exception {
373401
}
374402
}
375403

404+
@SuppressWarnings("unchecked")
376405
@Test
377406
public void testListEntriesSorting() throws Exception {
378407
SVNRepository mockedRepo = spy(svn.getSVNRepository());
379408
svn.setSVNRepository(mockedRepo);
380409
SVNDirEntry entry1 = new SVNDirEntry(null, null, "entry1", SVNNodeKind.DIR, 0, false, 1, null, null);
381410
SVNDirEntry entry2 = new SVNDirEntry(null, null, "entry2", SVNNodeKind.DIR, 0, false, 2, null, null);
382411

383-
doReturn(Arrays.asList(entry1, entry2)).when(mockedRepo).getDir(anyString(), anyLong(), any(SVNProperties.class),
384-
Matchers.<Collection<SVNDirEntry>>any());
412+
doReturn(Arrays.asList(entry1, entry2)).when(mockedRepo).getDir(anyString(), anyLong(), (SVNProperties) isNull(),
413+
(Collection<SVNDirEntry>) isNull());
385414

386415
List<String> entries = svn.listEntries("");
387-
assertEquals(entries.get(0), entry1.getName());
388-
assertEquals(entries.get(1), entry2.getName());
416+
assertEquals(entry1.getName(), entries.get(0));
417+
assertEquals(entry2.getName(), entries.get(1));
389418
doReturn(Arrays.asList(entry1, entry1)).when(mockedRepo).getDir(anyString(), anyLong(), any(SVNProperties.class),
390419
Matchers.<Collection<SVNDirEntry>>any());
391420
entries = svn.listEntries("");
392-
assertEquals(entries.get(0), entry1.getName());
393-
assertEquals(entries.get(1), entry1.getName());
394-
}
395-
396-
@Test
397-
public void testGetHeadCommitNull() throws Exception {
398-
doReturn(null).when(svn).revToSVNEntry(anyString(), any(Long.class));
399-
assertNull(vcs.getHeadCommit(""));
421+
assertEquals(entry1.getName(), entries.get(0));
422+
assertEquals(entry1.getName(), entries.get(1));
400423
}
401424

402425
@Test
@@ -414,12 +437,10 @@ public void testSVNVCSUtilsCreation() {
414437
}
415438

416439
@Test
417-
@Ignore
418440
public void testListEntriesNone() throws Exception {
419441
SVNRepository mockedRepo = spy(svn.getSVNRepository());
420442
svn.setSVNRepository(mockedRepo);
421443
doReturn(SVNNodeKind.NONE).when(mockedRepo).checkPath(anyString(), anyLong());
422-
assertTrue(svn.listEntries("").isEmpty());
423444
assertTrue(svn.listEntries(null).isEmpty()); // expecting no NPE
424445
}
425446

@@ -431,25 +452,43 @@ public void testGetTagsOnRevisionNoTagsDir() throws SVNException {
431452
assertTrue(vcs.getTagsOnRevision("0").isEmpty());
432453
}
433454

455+
434456
@Test
435457
public void testGetTagsOnRevisionExceptions() throws Exception {
436-
SVNRepository mockedRepo = spy(svn.getSVNRepository());
437-
svn.setSVNRepository(mockedRepo);
438458
vcs.createTag(null, TAG_NAME_1, TAG_MESSAGE_1, null);
439-
doThrow(testCommonException).when(svn).revToSVNEntry(anyString(), anyLong());
459+
doThrow(testSVNException).when(svn).getTags(anyString());
440460
try {
441461
vcs.getTagsOnRevision("");
442462
fail();
443-
} catch (RuntimeException e) {
444-
checkCommonException(e);
463+
} catch (EVCSException e) {
464+
checkEVCSException(e);
445465
}
446466

447-
doThrow(testSVNException).when(mockedRepo).checkPath(anyString(), anyLong());
467+
doThrow(testCommonException).when(svn).getTags(anyString());
448468
try {
449469
vcs.getTagsOnRevision("");
450470
fail();
471+
} catch (RuntimeException e) {
472+
checkCommonException(e);
473+
}
474+
}
475+
476+
@Test
477+
public void testGetTagsExceptions() throws Exception {
478+
doThrow(testSVNException).when(svn).getTags((String) isNull());
479+
try {
480+
vcs.getTags();
481+
fail();
451482
} catch (EVCSException e) {
452483
checkEVCSException(e);
453484
}
485+
486+
doThrow(testCommonException).when(svn).getTags((String) isNull());
487+
try {
488+
vcs.getTags();
489+
fail();
490+
} catch (RuntimeException e) {
491+
checkCommonException(e);
492+
}
454493
}
455494
}

0 commit comments

Comments
 (0)