View Javadoc

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.io.IOException;
29  import java.util.Collection;
30  import java.util.List;
31  import java.util.Map;
32  
33  import com.aragost.javahg.Changeset;
34  import com.aragost.javahg.Repository;
35  import com.aragost.javahg.commands.flags.AnnotateCommandFlags;
36  import com.aragost.javahg.internals.HgInputStream;
37  import com.google.common.collect.Lists;
38  import com.google.common.collect.Maps;
39  import com.google.common.collect.Sets;
40  
41  /**
42   * Command class for executing <tt>hg annotate</tt>. Set flags from
43   * {@link AnnotateCommandFlags} and see the {@link #execute} method
44   * for how to run the command.
45   */
46  public class AnnotateCommand extends AnnotateCommandFlags {
47  
48      /**
49       * @param repository
50       *            the repository associated with this command.
51       */
52      public AnnotateCommand(Repository repository) {
53          super(repository);
54          cmdAppend("--number");
55      }
56  
57      /**
58       * Execute <tt>hg annotate</tt> for the specified file.
59       * <p>
60       * On the command line, Mercurial can annotate more than one file,
61       * JavaHg can only annotate one file for each call (but the
62       * overhead is negligible to make multiple calls).
63       * 
64       * @param file
65       * @return list of annotated lines.
66       * @throws IOException
67       */
68      public List<AnnotateLine> execute(String file) throws IOException {
69          Repository repo = getRepository();
70          List<Integer> revisions = Lists.newArrayList();
71          List<String> lines = Lists.newArrayList();
72          HgInputStream stream = launchStream(file);
73          while (stream.peek() != -1) {
74              revisions.add(stream.revisionUpTo(':'));
75              stream.skip(1);
76              lines.add(stream.textUpTo('\n'));
77          }
78          Map<Integer, Changeset> revNumMap = createRevNumMap(repo, revisions);
79          int size = lines.size();
80          List<AnnotateLine> result = Lists.newArrayListWithCapacity(size);
81          for (int i = 0 ; i < size; i ++) {
82              Changeset changeset = revNumMap.get(revisions.get(i));
83              result.add(new AnnotateLine(changeset, lines.get(i)));
84          }
85          return result;
86      }
87  
88      /**
89       * Create a map mapping revision numbers to Changesets
90       * 
91       * @param repo
92       * @param revisions
93       * @return
94       */
95      private Map<Integer, Changeset> createRevNumMap(Repository repo, List<Integer> revisions) {
96          Collection<Integer> uniqRevs = Sets.newHashSet(revisions);
97          String[] revs = new String[uniqRevs.size()];
98          int index = 0;
99          for (Integer rev : uniqRevs) {
100             revs[index++] = String.valueOf(rev);
101         }
102         LogCommand logCmd = LogCommand.on(repo).rev(revs);
103         Map<Integer, Changeset> revNumMap = Maps.newHashMap();
104         for (Changeset cs : logCmd.execute()) {
105             revNumMap.put(cs.getRevision(), cs);
106         }
107         return revNumMap;
108     }
109 
110 }