1 /*
2 * #%L
3 * JavaHg
4 * %%
5 * Copyright (C) 2011 aragost Trifork ag
6 * %%
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 * #L%
25 */
26 package com.aragost.javahg.commands;
27
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import com.aragost.javahg.Changeset;
35 import com.aragost.javahg.Repository;
36 import com.aragost.javahg.commands.flags.TagsCommandFlags;
37 import com.aragost.javahg.internals.UnexpectedCommandOutputException;
38 import com.google.common.collect.Lists;
39 import com.google.common.collect.Maps;
40
41 /**
42 * Command class for executing <tt>hg tags</tt>. Set flags from
43 * {@link TagsCommandFlags} and see the {@link #execute()} method for
44 * how to run the command.
45 */
46 public class TagsCommand extends TagsCommandFlags {
47
48 /**
49 * Tags pattern. Matching groups: 1: name 2: nodeId 3: local
50 */
51 private static final Pattern TAGS_PATTERN = Pattern.compile("^(.*) (?:[-0-9]+):([a-f0-9]+)( local)?$"); //$NON-NLS-1$
52
53 protected boolean includeTip;
54
55 public TagsCommand(Repository repository) {
56 super(repository);
57 cmdAppend("-v");
58 withDebugFlag();
59 }
60
61 /**
62 * Whether tip should be included. Default false
63 *
64 * @return this
65 */
66 public TagsCommand includeTip() {
67 this.includeTip = true;
68 return this;
69 }
70
71 /**
72 * Return a map mapping tag names to changeset with the tag.
73 * <p>
74 * The command 'hg tags' returns the pseudo tag 'tip', this is not
75 * returned here.
76 *
77 * @return map mapping tag name to changeset
78 */
79 public List<Tag> execute() {
80 List<Tag> result = Lists.newArrayList();
81 Repository repository = getRepository();
82 for (Iterator<String> iter = launchIterator(); iter.hasNext();) {
83 String line = iter.next();
84 Tag tag = fromLine(repository, line);
85 if (includeTip || !tag.getName().equals("tip")) {
86 result.add(tag);
87 }
88 }
89 return result;
90 }
91
92 /**
93 * Return alternative mapping of changeset node hash to list of
94 * tags.
95 * <p>
96 * The command 'hg tags' returns the pseudo tag 'tip', this is not
97 * returned here.
98 *
99 * @return map mapping changeset to tags at that node.
100 */
101 public Map<Changeset, List<Tag>> executeReverse() {
102 Map<Changeset, List<Tag>> result = Maps.newHashMap();
103 Repository repository = getRepository();
104 for (Iterator<String> iter = launchIterator(); iter.hasNext();) {
105 Tag tag = fromLine(repository, iter.next());
106
107 if (includeTip || !tag.getName().equals("tip")) {
108 Changeset changeset = tag.getChangeset();
109 List<Tag> tagList = result.get(changeset);
110 if (tagList == null) {
111 tagList = Lists.newArrayList();
112 result.put(changeset, tagList);
113 }
114 tagList.add(tag);
115 }
116 }
117 return result;
118 }
119
120 private Tag fromLine(Repository repository, String line) {
121 Matcher m = TAGS_PATTERN.matcher(line);
122 if (m.matches()) {
123 return new Tag(m.group(1).trim(), repository.changeset(m.group(2)),
124 m.group(3) != null);
125 }
126 throw new UnexpectedCommandOutputException(this, line);
127 }
128 }