package org.intellij.vcs.mks.sicommands.cli;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.vcsUtil.VcsUtil;
import org.intellij.vcs.mks.MksBundle;
import org.intellij.vcs.mks.MksCLIConfiguration;
import org.intellij.vcs.mks.MksConfiguration;
import org.intellij.vcs.mks.MksVcs;
import org.intellij.vcs.mks.model.MksMemberRevisionInfo;
import org.jetbrains.annotations.NonNls;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This command uses tabs to separate fields ...
*/
public class ViewMemberHistoryCommand extends SiCLICommand {
@NonNls
public static final String COMMAND = "viewhistory";
private static final String descriptionPattern = "(.*)";
private static final int REVISION_IDX = 1;
private static final int DATE_IDX = 2;
private static final int AUTHOR_IDX = 3;
private static final int CPID_IDX = 4;
private static final int DESCRIPTION_IDX = 5;
@NonNls
private static final String datePattern = "([^\\t+]*)";
@NonNls
public static final String wholeLinePatternString =
revisionPattern + "\\t"
+ datePattern + "\\t"
+ userPattern + "\\t"
+ changePackageIdPattern + "\\t"
+ descriptionPattern;
private List<MksMemberRevisionInfo> revisionsInfo = new ArrayList<MksMemberRevisionInfo>();
private DateFormat format;
private final String member;
public ViewMemberHistoryCommand(List<VcsException> errors, MksCLIConfiguration mksCLIConfiguration, String member) {
super(errors, mksCLIConfiguration, COMMAND,
"--fields=revision,date,author,cpid,description",
member);
setWorkingDir(new File(member).getParentFile());
this.member = member;
format = new SimpleDateFormat(mksCLIConfiguration.getDatePattern());
}
@Override
public void execute() {
try {
executeCommand();
} catch (IOException e) {
//noinspection ThrowableInstanceNeverThrown
errors.add(new VcsException(e));
return;
}
Pattern wholeLinePattern = Pattern.compile(wholeLinePatternString);
BufferedReader reader = new BufferedReader(new StringReader(commandOutput));
try {
String firstLine = reader.readLine();
if (firstLine == null || !VcsUtil.getFilePath(member).equals(VcsUtil.getFilePath(firstLine))) {
LOGGER.warn("unexpected command output " + commandOutput + ", first line is expected to be " + member);
} else {
String line;
while ((line = reader.readLine()) != null) {
Matcher matcher = wholeLinePattern.matcher(line);
try {
if (matcher.matches()) {
String rev = matcher.group(REVISION_IDX);
String date = matcher.group(DATE_IDX);
String cpid = matcher.group(CPID_IDX);
String author = matcher.group(AUTHOR_IDX);
String description = matcher.group(DESCRIPTION_IDX);
MksMemberRevisionInfo info = new MksMemberRevisionInfo();
info.setRevision(createRevision(rev));
info.setDate(parseDate(date, true));
info.setCPID(cpid);
info.setAuthor(author);
info.setDescription(description);
revisionsInfo.add(info);
} else if (line.startsWith("Member added")) {
// ignore this line
// Don't ignore the following ones
} else if (revisionsInfo.size() >= 1) {
LOGGER.debug("assuming multiline comment :" + line);
final MksMemberRevisionInfo info = revisionsInfo.get(revisionsInfo.size() - 1);
info.setDescription(info.getDescription() + "\n" + line);
} else {
//noinspection ThrowableInstanceNeverThrown
errors.add(new VcsException("ViewMemberHistory: unexpected line [" + line + "]"));
}
} catch (VcsException e) {
errors.add(e);
}
}
}
} catch (IOException e) {
//noinspection ThrowableInstanceNeverThrown
errors.add(new VcsException(e));
}
}
protected void handleErrorOutput(String errorOutput) {
if (exitValue == 128 && errorOutput.contains("is not a current or destined or pending member")) {
errors.add(new VcsException(GetRevisionInfo.NOT_A_MEMBER));
return;
} else {
super.handleErrorOutput(
errorOutput); //To change body of overridden methods use File | Settings | File Templates.
}
}
private Date parseDate(final String date, boolean updatePatternIfNeeded) throws VcsException {
try {
return format.parse(date);
} catch (ParseException e) {
if (updatePatternIfNeeded) {
final String[] patternHolder = new String[1];
Runnable runnable = new Runnable() {
public void run() {
patternHolder[0]=Messages.showInputDialog(
MksBundle.message("configuration.datepattern.incorrect.message", date,
mksCLIConfiguration.getDatePattern()),
MksBundle.message("configuration.datepattern.incorrect.title"), Messages.getErrorIcon(),
mksCLIConfiguration.getDatePattern(),
new MksConfiguration.DatePatternValidator());
}
};
MksVcs.invokeOnEventDispatchThreadAndWait(runnable);
String pattern = patternHolder[0];
if (pattern != null) {
final MksConfiguration configuration = ApplicationManager.getApplication().getComponent(MksConfiguration.class);
configuration.setDatePattern(pattern);
format = new SimpleDateFormat(configuration.getDatePattern());
}
return parseDate(date, false);
} else {
throw new VcsException(
"unknown date format for " + date + " (expected [" + mksCLIConfiguration.getDatePattern() +
"]). " +
"This may be an encoding issue, encoding used was " +
mksCLIConfiguration.getMksSiEncoding(COMMAND));
}
}
}
public List<MksMemberRevisionInfo> getRevisionsInfo() {
return revisionsInfo;
}
}