View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.scm.provider.git.gitexe.command.info;
20  
21  import java.nio.file.Path;
22  import java.time.format.DateTimeFormatter;
23  
24  import org.apache.commons.lang3.StringUtils;
25  import org.apache.maven.scm.command.info.InfoItem;
26  import org.apache.maven.scm.util.AbstractConsumer;
27  import org.codehaus.plexus.util.cli.Arg;
28  import org.codehaus.plexus.util.cli.Commandline;
29  
30  /**
31   * Parses output of {@code git log} with a particular format and populates a {@link InfoItem}.
32   *
33   * @author Olivier Lamy
34   * @since 1.5
35   * @see <a href="https://git-scm.com/docs/git-log#_pretty_formats">Pretty Formats</a>
36   */
37  public class GitInfoConsumer extends AbstractConsumer {
38  
39      private final InfoItem infoItem;
40      private final int revisionLength;
41  
42      public GitInfoConsumer(Path path, int revisionLength) {
43          infoItem = new InfoItem();
44          infoItem.setPath(path.toString());
45          infoItem.setURL(path.toUri().toASCIIString());
46          this.revisionLength = revisionLength;
47      }
48  
49      enum LineParts {
50          HASH(0),
51          AUTHOR_NAME(3),
52          AUTHOR_EMAIL(2),
53          AUTHOR_LAST_MODIFIED(1);
54  
55          private final int index;
56  
57          LineParts(int index) {
58              this.index = index;
59          }
60  
61          public int getIndex() {
62              return index;
63          }
64      }
65  
66      /**
67       * @param line the line which is supposed to have the format as specified by {@link #getFormatArgument()}.
68       * @see org.codehaus.plexus.util.cli.StreamConsumer#consumeLine(java.lang.String)
69       */
70      public void consumeLine(String line) {
71          if (logger.isDebugEnabled()) {
72              logger.debug("consume line {}", line);
73          }
74  
75          // name must be last token as it may contain separators
76          String[] parts = line.split("\\s", 4);
77          if (parts.length != 4) {
78              throw new IllegalArgumentException(
79                      "Unexpected line: expecting 4 tokens separated by whitespace but got " + line);
80          }
81          infoItem.setLastChangedAuthor(
82                  parts[LineParts.AUTHOR_NAME.getIndex()] + " <" + parts[LineParts.AUTHOR_EMAIL.getIndex()] + ">");
83          String revision = parts[LineParts.HASH.getIndex()];
84          if (revisionLength > -1) {
85              // do not truncate below 4 characters
86              revision = StringUtils.truncate(revision, Integer.max(4, revisionLength));
87          }
88          infoItem.setRevision(revision);
89          infoItem.setLastChangedDateTime(
90                  DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(parts[LineParts.AUTHOR_LAST_MODIFIED.getIndex()]));
91      }
92  
93      public InfoItem getInfoItem() {
94          return infoItem;
95      }
96  
97      /**
98       * The format argument to use with {@code git log}
99       * @return the format argument to use {@code git log} command
100      * @see <a href="https://git-scm.com/docs/git-log#_pretty_formats">Pretty Formats</a>
101      */
102     public static Arg getFormatArgument() {
103         Commandline.Argument arg = new Commandline.Argument();
104         arg.setValue("--format=format:%H %aI %aE %aN");
105         return arg;
106     }
107 }