public @Nullable CommitT convert(@NotNull String line) {

    // we need to get all attributes, include empty trailing strings, so use non-positive limit as second argument
    List<String> attributes = StringUtil.split(line, HgChangesetUtil.ITEM_SEPARATOR, true, false);
    int numAttributes = attributes.size();
    if (numAttributes <= AUTHOR_INDEX) {
      LOG.info("Hg Log Command was cancelled or failed");
      return null;
    }
    try {
      String revisionString = attributes.get(REVISION_INDEX);
      String changeset = attributes.get(CHANGESET_INDEX);
      String parentsString = attributes.get(PARENTS_INDEX);

      SmartList<HgRevisionNumber> parents = parseParentRevisions(parentsString, revisionString);
      String unixTimeStamp = ContainerUtil.getFirstItem(StringUtil.split(attributes.get(DATE_INDEX), " "));
      if (unixTimeStamp == null) {
        LOG.warn("Error parsing date in line " + line);
        return null;
      }
      Date revisionDate = new Date(Long.parseLong(unixTimeStamp.trim()) * 1000);
      Couple<String> authorAndEmail = HgUtil.parseUserNameAndEmail(attributes.get(AUTHOR_INDEX));
      return convertDetails(revisionString, changeset, parents, revisionDate, authorAndEmail.first, authorAndEmail.second, attributes);
    }
    catch (NumberFormatException e) {
      LOG.warn("Error parsing rev in line " + line);
      return null;
    }
  }
public @Nullable CommitT convert(@NotNull String line)