Skip to content

Commit 5c241e6

Browse files
committed
handle tags with multiple spaces
1 parent dc41655 commit 5c241e6

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/history/MercurialRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,11 @@ protected void buildTagList(File directory, CommandTimeoutType cmdType) {
635635
ensureCommand(CMD_PROPERTY_KEY, CMD_FALLBACK);
636636
argv.add(RepoCommand);
637637
argv.add("tags");
638+
argv.add("--template");
639+
// Use '|' as a revision separator rather than ':' to avoid collision with the commonly used
640+
// separator within the revision string (which is not used in the 'hg tags' output but better
641+
// safe than sorry).
642+
argv.add("{rev}|{tag}\\n");
638643

639644
Executor executor = new Executor(argv, directory,
640645
RuntimeEnvironment.getInstance().getCommandTimeout(cmdType));

opengrok-indexer/src/main/java/org/opengrok/indexer/history/MercurialTagParser.java

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.IOException;
2727
import java.io.InputStream;
2828
import java.io.InputStreamReader;
29+
import java.util.NavigableSet;
2930
import java.util.TreeSet;
3031
import java.util.logging.Level;
3132
import java.util.logging.Logger;
@@ -49,7 +50,7 @@ public class MercurialTagParser implements Executor.StreamHandler {
4950
*
5051
* @return entries a set of tag entries
5152
*/
52-
public TreeSet<TagEntry> getEntries() {
53+
public NavigableSet<TagEntry> getEntries() {
5354
return entries;
5455
}
5556

@@ -59,35 +60,23 @@ public void processStream(InputStream input) throws IOException {
5960
try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) {
6061
String line;
6162
while ((line = in.readLine()) != null) {
62-
String[] parts = line.split(" *");
63+
String[] parts = line.split("\\|");
6364
if (parts.length < 2) {
6465
LOGGER.log(Level.WARNING,
6566
"Failed to parse tag list: {0}",
6667
"Tag line contains more than 2 columns: " + line);
6768
entries = null;
6869
break;
6970
}
70-
// Grrr, how to parse tags with spaces inside?
71-
// This solution will lose multiple spaces ;-/
72-
String tag = parts[0];
73-
for (int i = 1; i < parts.length - 1; ++i) {
74-
tag = tag.concat(" ");
75-
tag = tag.concat(parts[i]);
76-
}
71+
String rev = parts[0];
72+
String tag = parts[1];
73+
7774
// The implicit 'tip' tag only causes confusion so ignore it.
7875
if (tag.contentEquals("tip")) {
7976
continue;
8077
}
81-
String[] revParts = parts[parts.length - 1].split(":");
82-
if (revParts.length != 2) {
83-
LOGGER.log(Level.WARNING,
84-
"Failed to parse tag list: {0}",
85-
"Mercurial revision parsing error: "
86-
+ parts[parts.length - 1]);
87-
entries = null;
88-
break;
89-
}
90-
TagEntry tagEntry = new MercurialTagEntry(Integer.parseInt(revParts[0]), tag);
78+
79+
TagEntry tagEntry = new MercurialTagEntry(Integer.parseInt(rev), tag);
9180
// Reverse the order of the list.
9281
entries.add(tagEntry);
9382
}

opengrok-indexer/src/main/java/org/opengrok/indexer/history/TagEntry.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ protected TagEntry(Date date, String tags) {
8383
this.tags = tags;
8484
}
8585

86+
public int getRevision() {
87+
return revision;
88+
}
89+
8690
public String getTags() {
8791
return this.tags;
8892
}

opengrok-indexer/src/test/java/org/opengrok/indexer/history/MercurialRepositoryTest.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,17 +481,24 @@ void testBuildTagListOneMore() throws Exception {
481481
Path repositoryRootPath = Files.createDirectory(Path.of(RuntimeEnvironment.getInstance().getSourceRootPath(),
482482
"addedTagTest"));
483483
File repositoryRoot = repositoryRootPath.toFile();
484+
// Clone the internal repository because it will be modified.
485+
// This avoids interference with other tests in this class.
484486
runHgCommand(this.repositoryRoot, "clone", this.repositoryRoot.toString(), repositoryRootPath.toString());
485487
MercurialRepository hgRepo = (MercurialRepository) RepositoryFactory.getRepository(repositoryRoot);
486488
assertNotNull(hgRepo);
487-
runHgCommand(repositoryRoot, "tag", "foo");
489+
// Using double space on purpose to test the parsing of tags.
490+
final String newTagName = "foo bar";
491+
runHgCommand(repositoryRoot, "tag", newTagName);
488492
hgRepo.buildTagList(new File(hgRepo.getDirectoryName()), CommandTimeoutType.INDEXER);
489493
var tags = hgRepo.getTagList();
490494
assertNotNull(tags);
491495
assertEquals(2, tags.size());
492-
Set<TagEntry> expectedTags = Set.of(new MercurialTagEntry(7, "start_of_novel"),
493-
new MercurialTagEntry(9, "foo"));
494-
assertEquals(expectedTags, tags);
496+
// TagEntry has special semantics for comparing/equality which does not compare the tags at all,
497+
// so using assertEquals() on two sets of TagEntry objects would not help.
498+
// Instead, check the tags separately.
499+
assertEquals(List.of(7, 9), tags.stream().map(TagEntry::getRevision).collect(Collectors.toList()));
500+
List<String> expectedTags = List.of("start_of_novel", newTagName);
501+
assertEquals(expectedTags, tags.stream().map(TagEntry::getTags).collect(Collectors.toList()));
495502
IOUtils.removeRecursive(repositoryRootPath);
496503
}
497504
}

0 commit comments

Comments
 (0)