Mercurial > hg > mercurial
view mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/LogCommand.java @ 345:607091bd8ccd
Merge branch Eluru-6.5.x
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Tue, 10 Jan 2012 13:08:37 +0400 |
parents | 6667765025c6 ec375e18374f |
children | 4a49a0baf30b |
line wrap: on
line source
/* * Copyright 2000-2011 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.buildServer.buildTriggers.vcs.mercurial.command; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.openapi.util.JDOMUtil; import jetbrains.buildServer.ExecResult; import jetbrains.buildServer.vcs.VcsException; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class LogCommand extends VcsRootCommand { private final static String ZERO_PARENT_ID = "0000000000000000000000000000000000000000"; private static final String DATE_FORMAT = "EEE MMM d HH:mm:ss yyyy Z"; private String myFromId; private String myToId; private Integer myLimit = null; private String myBranchName; private boolean myCalculateParents = true; private String myRevsets; private final File myTemplate; public LogCommand(@NotNull Settings settings, @NotNull File workingDir, @NotNull final File template) { super(settings, workingDir); myTemplate = template; myBranchName = settings.getBranchName(); } public void setFromRevId(String id) { myFromId = id; } public void setToRevId(String id) { myToId = id; } public void setLimit(final int limit) { myLimit = limit; } public void showCommitsFromAllBranches() { myBranchName = null; } public void setCalculateParents(boolean doCalculate) { myCalculateParents = doCalculate; } public void setRevsets(String revsets) { myRevsets = revsets; } public List<ChangeSet> execute() throws VcsException { GeneralCommandLine cli = createCommandLine(); cli.addParameter("log"); cli.addParameter("-v"); cli.addParameter("--style=" + myTemplate.getAbsolutePath()); if (myBranchName != null) { cli.addParameter("-b"); cli.addParameter(getSettings().getBranchName()); } cli.addParameter("-r"); if (myRevsets != null) { cli.addParameter(myRevsets); } else { String from = myFromId != null ? myFromId : "0"; String to = myToId != null ? myToId : "tip"; cli.addParameter(from + ":" + to); } if (myLimit != null) { cli.addParameter("--limit"); cli.addParameter(myLimit.toString()); } ExecResult res = runCommand(cli); try { List<ChangeSet> changes = parseChangeSetsXml(res.getStdout()); if (myCalculateParents) assignTrivialParents(changes); return changes; } catch (Exception e) { throw new VcsException("Error while parsing log output:\n" + res.getStdout(), e); } } private List<ChangeSet> parseChangeSetsXml(@NotNull final String xml) throws JDOMException, IOException, ParseException { if ("".equals(xml)) return Collections.emptyList(); Document doc = loadDocument(xml); Element log = doc.getRootElement(); return parseLog(log); } private Document loadDocument(@NotNull final String xml) throws IOException, JDOMException { String validXml = makeValidXml(xml); return JDOMUtil.loadDocument(validXml); } private String makeValidXml(@NotNull final String xml) { String trimmed = xml.trim(); if (trimmed.endsWith("</log>")) return xml; else return xml + "</log>"; } private List<ChangeSet> parseLog(@NotNull final Element logElement) throws ParseException { List<ChangeSet> result = new ArrayList<ChangeSet>(); for (Object o : logElement.getChildren("logentry")) { Element entry = (Element) o; result.add(parseLogEntry(entry)); } return result; } private ChangeSet parseLogEntry(@NotNull final Element logEntry) throws ParseException { ChangeSet cset = new ChangeSet(getRevision(logEntry), getId(logEntry)); addParents(cset, logEntry); cset.setUser(getAuthor(logEntry)); cset.setDescription(getDescription(logEntry)); cset.setTimestamp(getDate(logEntry)); cset.setModifiedFiles(getModifiedFiles(logEntry)); return cset; } private int getRevision(@NotNull final Element logEntry) { return Integer.parseInt(logEntry.getAttribute("revision").getValue()); } private String getId(@NotNull final Element logEntry) { return logEntry.getAttribute("shortnode").getValue(); } private void addParents(@NotNull final ChangeSet cset, @NotNull final Element logEntry) { List parents = logEntry.getChildren("parent"); for (Object p : parents) { Element parent = (Element) p; ChangeSetRevision parentCset = getParent(parent); cset.addParent(parentCset); } } private ChangeSetRevision getParent(@NotNull final Element parent) { return new ChangeSetRevision(getRevision(parent), getId(parent)); } private String getAuthor(@NotNull final Element logEntry) { Element author = logEntry.getChild("author"); return author.getAttribute("original").getValue(); } private String getDescription(@NotNull final Element logEntry) { Element msg = logEntry.getChild("msg"); return msg.getText(); } private Date getDate(@NotNull final Element logEntry) throws ParseException { Element date = logEntry.getChild("date"); return new SimpleDateFormat(DATE_FORMAT, Locale.ENGLISH).parse(date.getText()); } private List<ModifiedFile> getModifiedFiles(@NotNull final Element logEntry) { List<ModifiedFile> result = new ArrayList<ModifiedFile>(); Element paths = logEntry.getChild("paths"); for (Object o : paths.getChildren("path")) { Element path = (Element) o; result.add(getModifiedFile(path)); } return result; } private ModifiedFile getModifiedFile(@NotNull final Element path) { String filePath = path.getText(); ModifiedFile.Status status = getStatus(path); return new ModifiedFile(status, filePath); } private ModifiedFile.Status getStatus(@NotNull final Element path) { String action = path.getAttribute("action").getValue(); if (action.equals("A")) { return ModifiedFile.Status.ADDED; } else if (action.equals("M")) { return ModifiedFile.Status.MODIFIED; } else if (action.equals("R")) { return ModifiedFile.Status.REMOVED; } else { return ModifiedFile.Status.UNKNOWN; } } private void assignTrivialParents(final @NotNull List<ChangeSet> csets) throws VcsException { for (ChangeSet cset : csets) { if (cset.getParents().isEmpty()) { int parentRevNumber = cset.getRevNumber() - 1; String parentId = getIdOf(parentRevNumber); cset.addParent(new ChangeSetRevision(parentRevNumber, parentId)); } } } private String getIdOf(int revNumber) throws VcsException { if (revNumber < 0) return ZERO_PARENT_ID; IdentifyCommand identify = new IdentifyCommand(getSettings(), getWorkDirectory()); identify.setInLocalRepository(true); identify.setRevisionNumber(revNumber); return identify.execute(); } }