Assembla home | Assembla project page
 

Changeset 820:8e8998989c94

Show
Ignore:
Timestamp:
08/08/08 22:52:54 (4 months ago)
Author:
Bastian Doetsch <bastian.doetsch@gmx.de>
branch:
default
Message:

Use Sax parser instead of DOM parser

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/com/vectrace/MercurialEclipse/commands/AbstractParseChangesetClient.java

    r795 r820  
    1111package com.vectrace.MercurialEclipse.commands; 
    1212 
     13import java.io.ByteArrayInputStream; 
    1314import java.io.File; 
    1415import java.io.FileOutputStream; 
     
    1617import java.io.InputStream; 
    1718import java.io.OutputStream; 
    18 import java.io.Reader; 
    19 import java.io.StringReader; 
    2019import java.util.ArrayList; 
    2120import java.util.HashMap; 
    22 import java.util.HashSet; 
    2321import java.util.List; 
    2422import java.util.Map; 
     23import java.util.Set; 
    2524import java.util.SortedSet; 
    2625import java.util.TreeSet; 
    27  
    28 import javax.xml.parsers.DocumentBuilder; 
    29 import javax.xml.parsers.DocumentBuilderFactory; 
    30 import javax.xml.parsers.ParserConfigurationException; 
    3126 
    3227import org.eclipse.core.resources.IResource; 
    3328import org.eclipse.core.runtime.IPath; 
    3429import org.eclipse.core.runtime.Path; 
    35 import org.w3c.dom.Document; 
    36 import org.w3c.dom.Element; 
    37 import org.w3c.dom.NodeList; 
     30import org.xml.sax.Attributes; 
     31import org.xml.sax.ContentHandler; 
    3832import org.xml.sax.InputSource; 
     33import org.xml.sax.Locator; 
    3934import org.xml.sax.SAXException; 
     35import org.xml.sax.XMLReader; 
     36import org.xml.sax.helpers.XMLReaderFactory; 
    4037 
    4138import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; 
     
    4643import com.vectrace.MercurialEclipse.model.FileStatus.Action; 
    4744import com.vectrace.MercurialEclipse.storage.HgRepositoryLocation; 
     45import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; 
    4846 
    4947/** 
     
    5654abstract class AbstractParseChangesetClient extends AbstractClient { 
    5755 
     56    /** 
     57     * @author bastian 
     58     *  
     59     */ 
     60    private static final class ChangesetContentHandler implements 
     61            ContentHandler { 
     62 
     63        private String br; 
     64        private String tg; 
     65        private int rv; 
     66        private String ns; 
     67        private String nl; 
     68        private String di; 
     69        private String da; 
     70        private String au; 
     71        private String pr; 
     72        private String de; 
     73        private static IResource res; 
     74        private Direction direction; 
     75        private HgRepositoryLocation repository; 
     76        private File bundleFile; 
     77        private File hgRoot; 
     78        private static Map<IPath, SortedSet<ChangeSet>> fileRevisions; 
     79        private Set<String> filesModified = new TreeSet<String>(); 
     80        private Set<String> filesAdded = new TreeSet<String>(); 
     81        private Set<String> filesRemoved = new TreeSet<String>(); 
     82        private Action action; 
     83 
     84        /** 
     85         * @param res 
     86         * @param direction 
     87         * @param repository 
     88         * @param bundleFile 
     89         * @param hgRoot 
     90         * @param fileRevisions 
     91         */ 
     92        public ChangesetContentHandler(IResource res, Direction direction, 
     93                HgRepositoryLocation repository, File bundleFile, File hgRoot, 
     94                Map<IPath, SortedSet<ChangeSet>> fileRevisions) { 
     95            ChangesetContentHandler.res = res; 
     96            this.direction = direction; 
     97            this.repository = repository; 
     98            this.bundleFile = bundleFile; 
     99            this.hgRoot = hgRoot; 
     100            ChangesetContentHandler.fileRevisions = fileRevisions; 
     101        } 
     102 
     103        private static String unescape(String string) { 
     104            return string.replaceAll("&lt;", "<").replaceAll("&gt;", ">") 
     105                    .replaceAll("&amp;", "&"); 
     106        } 
     107 
     108        /** 
     109         * Remove a leading tab on each line in the string. 
     110         *  
     111         * @param string 
     112         * @return 
     113         */ 
     114        private static String untab(String string) { 
     115            return string.replaceAll("\n\t", "\n"); 
     116        } 
     117 
     118        private static String[] splitClean(String string, String sep) { 
     119            if (string == null || string.length() == 0) { 
     120                return new String[] {}; 
     121            } 
     122            return string.split(sep); 
     123        } 
     124 
     125        public void characters(char[] ch, int start, int length) 
     126                throws SAXException { 
     127        } 
     128 
     129        public void endDocument() throws SAXException { 
     130        } 
     131 
     132        public void endElement(String uri, String localName, String name) 
     133                throws SAXException { 
     134            if (name.equals("cs")) { 
     135 
     136                ChangeSet.Builder csb = new ChangeSet.Builder(rv, nl, br, di, 
     137                        au); 
     138                csb.tag(tg); 
     139                csb.nodeShort(ns); 
     140                csb.ageDate(da); 
     141                csb.description(untab(unescape(de))); 
     142                csb.parents(splitClean(pr, " ")); 
     143 
     144                csb.hgRoot(hgRoot).bundleFile(bundleFile) 
     145                        .repository(repository).direction(direction); 
     146 
     147                csb.bundleFile(bundleFile); 
     148                csb.direction(direction); 
     149                csb.hgRoot(hgRoot); 
     150                csb.repository(repository); 
     151                 
     152                List<FileStatus> list = new ArrayList<FileStatus>(); 
     153                for (String file : filesModified) { 
     154                    list.add(new FileStatus(FileStatus.Action.MODIFIED, file)); 
     155                } 
     156                for (String file : filesAdded) { 
     157                    list.add(new FileStatus(FileStatus.Action.ADDED, file)); 
     158                } 
     159                for (String file : filesRemoved) { 
     160                    list.add(new FileStatus(FileStatus.Action.REMOVED, file)); 
     161                } 
     162                csb.changedFiles(list.toArray(new FileStatus[list.size()])); 
     163                 
     164                ChangeSet changeSet = csb.build(); 
     165 
     166                // changeset to resources & project 
     167                try { 
     168                    addChangesetToResourceMap(changeSet); 
     169                } catch (HgException e) { 
     170                    throw new SAXException(e); 
     171                } 
     172                filesModified.clear(); 
     173                filesAdded.clear(); 
     174                filesRemoved.clear(); 
     175            } 
     176        } 
     177 
     178        public void endPrefixMapping(String prefix) throws SAXException { 
     179        } 
     180 
     181        public void ignorableWhitespace(char[] ch, int start, int length) 
     182                throws SAXException { 
     183        } 
     184 
     185        public void processingInstruction(String target, String data) 
     186                throws SAXException { 
     187        } 
     188 
     189        public void setDocumentLocator(Locator locator) { 
     190        } 
     191 
     192        public void skippedEntity(String name) throws SAXException { 
     193        } 
     194 
     195        public void startDocument() throws SAXException { 
     196        } 
     197 
     198        public void startElement(String uri, String localName, String name, 
     199                Attributes atts) throws SAXException { 
     200            /* 
     201             * <br v="{branches}"/> <tg v="{tags}"/> <rv v="{rev}"/> <ns 
     202             * v="{node|short}"/> <nl v="{node}"/> <di v="{date|isodate}"/> <da 
     203             * v="{date|age}"/> <au v="{author|person}"/> <pr v="{parents}"/> 
     204             * <de v="{desc|escape|tabindent}"/> 
     205             */ 
     206            if (name.equals("br")) { 
     207                this.br = atts.getValue(0); 
     208            } else if (name.equals("tg")) { 
     209                this.tg = atts.getValue(0); 
     210            } else if (name.equals("rv")) { 
     211                this.rv = Integer.parseInt(atts.getValue(0)); 
     212            } else if (name.equals("ns")) { 
     213                this.ns = atts.getValue(0); 
     214            } else if (name.equals("nl")) { 
     215                this.nl = atts.getValue(0); 
     216            } else if (name.equals("di")) { 
     217                this.di = atts.getValue(0); 
     218            } else if (name.equals("da")) { 
     219                this.da = atts.getValue(0); 
     220            } else if (name.equals("au")) { 
     221                this.au = atts.getValue(0); 
     222            } else if (name.equals("pr")) { 
     223                this.pr = atts.getValue(0); 
     224            } else if (name.equals("de")) { 
     225                this.de = untab(unescape(atts.getValue(0))); 
     226            } else if (name.equals("fl")) { 
     227                this.action = FileStatus.Action.MODIFIED; 
     228            } else if (name.equals("fa")) { 
     229                this.action = FileStatus.Action.ADDED; 
     230            } else if (name.equals("fd")) { 
     231                this.action = FileStatus.Action.REMOVED; 
     232            } else if (name.equals("f")) { 
     233                if (this.action == Action.ADDED) { 
     234                    filesAdded.add(atts.getValue(0)); 
     235                    filesModified.remove(atts.getValue(0)); 
     236                } else if (this.action == Action.MODIFIED) { 
     237                    filesModified.add(atts.getValue(0));                     
     238                } else if (this.action == Action.REMOVED) { 
     239                    filesRemoved.add(atts.getValue(0)); 
     240                    filesModified.remove(atts.getValue(0)); 
     241                } 
     242            } 
     243        } 
     244 
     245        public void startPrefixMapping(String prefix, String uri) 
     246                throws SAXException { 
     247        } 
     248 
     249        /** 
     250         * @param proj 
     251         * @param fileRevisions 
     252         * @param cs 
     253         * @throws HgException 
     254         * @throws IOException 
     255         */ 
     256        private final static void addChangesetToResourceMap(ChangeSet cs) 
     257                throws HgException { 
     258            try { 
     259                if (cs.getChangedFiles() != null) { 
     260                    for (FileStatus file : cs.getChangedFiles()) { 
     261                        IPath hgRoot = new Path(cs.getHgRoot() 
     262                                .getCanonicalPath()); 
     263                        IPath fileRelPath = new Path(file.getPath()); 
     264                        IPath fileAbsPath = hgRoot.append(fileRelPath); 
     265 
     266                        SortedSet<ChangeSet> revs = addChangeSetRevisions(cs, 
     267                                fileAbsPath); 
     268                        fileRevisions.put(fileAbsPath, revs); 
     269 
     270                    } 
     271                } 
     272 
     273                // hg root 
     274                IPath repoPath = new Path(cs.getHgRoot().getCanonicalPath()); 
     275 
     276                SortedSet<ChangeSet> projectRevs = addChangeSetRevisions(cs, 
     277                        repoPath); 
     278 
     279                fileRevisions.put(repoPath, projectRevs); 
     280 
     281                // given path 
     282                IPath path = res.getLocation(); 
     283                SortedSet<ChangeSet> pathRevs = addChangeSetRevisions(cs, path); 
     284                fileRevisions.put(path, pathRevs); 
     285 
     286            } catch (IOException e) { 
     287                MercurialEclipsePlugin.logError(e); 
     288                throw new HgException(e.getLocalizedMessage(), e); 
     289            } 
     290        } 
     291 
     292        /** 
     293         * @param fileRevisions 
     294         * @param cs 
     295         * @param res 
     296         * @return 
     297         */ 
     298        private static SortedSet<ChangeSet> addChangeSetRevisions(ChangeSet cs, 
     299                IPath path) { 
     300            SortedSet<ChangeSet> fileRevs = fileRevisions.get(path); 
     301            if (fileRevs == null) { 
     302                fileRevs = new TreeSet<ChangeSet>(); 
     303            } 
     304            fileRevs.add(cs); 
     305            return fileRevs; 
     306        } 
     307 
     308    } 
     309 
    58310    private static final String STYLE_SRC = "/styles/log_style"; 
    59311    private static final String STYLE = "/log_style"; 
     
    61313    private static final String STYLE_WITH_FILES = "/log_style_with_files"; 
    62314    private static final String STYLE_TEMP_EXTN = ".tmpl"; 
     315 
     316    private static ContentHandler handler; 
    63317 
    64318    /** 
     
    132386     * <p> 
    133387     * Format of input is defined in the two style files in /styles and is as 
    134      * follows for each changeset. The changesets are separated by a line of '=' 
    135      * characters "^=+$". <br> 
     388     * follows for each changeset. 
    136389     *  
    137390     * <pre> 
    138391     * &lt;cs&gt; 
    139      * &lt;br&gt;b2_1_5&lt;/br&gt; 
    140      * &lt;tg&gt;&lt;/tg&gt; 
    141      * &lt;rv&gt;3624&lt;/rv&gt; 
    142      * &lt;ns&gt;209208fad980&lt;/ns&gt; 
    143      * &lt;nl&gt;209208fad980102b98ca438b79b78c64e03b6c29&lt;/nl&gt; 
    144      * &lt;di&gt;2008-04-24 05:04 +0000&lt;/di&gt; 
    145      * &lt;da&gt;4 weeks&lt;/da&gt; 
    146      * &lt;au&gt;abuckley&lt;/au&gt; 
    147      * &lt;pr&gt;3621:dc5cbf08f0d2640c334855b3ce1a38002850d65b -1:0000000000000000000000000000000000000000 &lt;/pr&gt; 
    148      * &lt;de&gt;Updated document mapping file with custom validation items 
    149      * Sent updated document mapping file and configuration files to customer&lt;/de&gt; 
    150      * &lt;fl&gt; 
    151      * &lt;f&gt;Products/overlay/config/application/documentmapping.csv&lt;/f&gt; 
    152      * &lt;/fl&gt; 
    153      * &lt;fa&gt; 
    154      * &lt;/fa&gt; 
    155      * &lt;fd&gt; 
    156      * &lt;/fd&gt; 
     392     * &lt;br v=&quot;{branches}&quot;/&gt; 
     393     * &lt;tg v=&quot;{tags}&quot;/&gt; 
     394     * &lt;rv v=&quot;{rev}&quot;/&gt; 
     395     * &lt;ns v=&quot;{node|short}&quot;/&gt; 
     396     * &lt;nl v=&quot;{node}&quot;/&gt; 
     397     * &lt;di v=&quot;{date|isodate}&quot;/&gt; 
     398     * &lt;da v=&quot;{date|age}&quot;/&gt; 
     399     * &lt;au v=&quot;{author|person}&quot;/&gt; 
     400     * &lt;pr v=&quot;{parents}&quot;/&gt; 
     401     * &lt;de v=&quot;{desc|escape|tabindent}&quot;/&gt; 
     402     * &lt;fl v=&quot;{files}&quot;/&gt; 
     403     * &lt;fa v=&quot;{file_adds}&quot;/&gt; 
     404     * &lt;fd v=&quot;{file_dels}&quot;/&gt; 
    157405     * &lt;/cs&gt; 
    158      * ================ 
    159406     * </pre> 
    160407     *  
     
    185432        } 
    186433 
    187         /* 
    188          * Would be nice to do this as a single XML document using the SAX 
    189          * parser but I haven't worked out how to get a mercurial style file to 
    190          * create a valid XML document (cannot get the closing element output) 
    191          */ 
    192         String[] changeSetStrings = input.split("\n====+\n"); 
    193         File hgRoot = HgRootClient.getHgRoot(res.getLocation().toFile()); 
    194         for (String changeSet : changeSetStrings) { 
    195             ChangeSet cs; 
    196             cs = getChangeSet(repository, 
    197                     bundleFile, 
    198                     direction, 
    199                     hgRoot,  
    200                     changeSet); 
    201  
    202             // add bundle file for being able to look into the bundle. 
    203             // cs.setRepository(repository); 
    204             // cs.setBundleFile(bundleFile); 
    205             // cs.setDirection(direction); 
    206             // cs.setHgRoot(hgRoot); 
    207  
    208             // changeset to resources & project 
    209             addChangesetToResourceMap(res.getLocation(), fileRevisions, cs); 
     434        File hgRoot = MercurialTeamProvider.getHgRoot(res); 
     435        String myInput = "<top>".concat(input).concat("</top>"); 
     436        try { 
     437            XMLReader reader = XMLReaderFactory.createXMLReader(); 
     438            reader.setContentHandler(getHandler(res, direction, repository, 
     439                    bundleFile, hgRoot, fileRevisions)); 
     440            reader.parse(new InputSource(new ByteArrayInputStream(myInput 
     441                    .getBytes()))); 
     442        } catch (Exception e) { 
     443            String nextTry = cleanControlChars(myInput); 
     444            try { 
     445                XMLReader reader = XMLReaderFactory.createXMLReader(); 
     446                reader.setContentHandler(getHandler(res, direction, repository, 
     447                        bundleFile, hgRoot, fileRevisions)); 
     448                reader.parse(new InputSource(new ByteArrayInputStream(nextTry 
     449                        .getBytes()))); 
     450            } catch (Exception e1) { 
     451                throw new HgException(e1.getLocalizedMessage(), e); 
     452            } 
    210453        } 
    211454        return fileRevisions; 
     
    213456 
    214457    /** 
    215      * @param proj 
     458     * @param hgRoot 
     459     * @param bundleFile 
     460     * @param repository 
     461     * @param direction 
     462     * @param res 
    216463     * @param fileRevisions 
    217      * @param cs 
    218      * @throws HgException 
    219      * @throws IOException 
    220      */ 
    221     protected final static void addChangesetToResourceMap(IPath path, 
    222             Map<IPath, SortedSet<ChangeSet>> fileRevisions, ChangeSet cs) 
    223             throws HgException { 
    224         try { 
    225             if (cs.getChangedFiles() != null) { 
    226                 for (FileStatus file : cs.getChangedFiles()) { 
    227                     IPath hgRoot = new Path(cs.getHgRoot().getCanonicalPath()); 
    228                     IPath fileRelPath = new Path(file.getPath()); 
    229                     IPath fileAbsPath = hgRoot.append(fileRelPath); 
    230  
    231                     SortedSet<ChangeSet> revs = addChangeSetRevisions( 
    232                             fileRevisions, cs, fileAbsPath); 
    233                     fileRevisions.put(fileAbsPath, revs); 
    234  
    235                 } 
    236             } 
    237  
    238             // hg root 
    239             IPath repoPath = new Path(cs.getHgRoot().getCanonicalPath()); 
    240  
    241             SortedSet<ChangeSet> projectRevs = addChangeSetRevisions( 
    242                     fileRevisions, cs, repoPath); 
    243  
    244             fileRevisions.put(repoPath, projectRevs); 
    245  
    246             // given path 
    247             SortedSet<ChangeSet> pathRevs = addChangeSetRevisions( 
    248                     fileRevisions, cs, path); 
    249             fileRevisions.put(path, pathRevs); 
    250  
    251         } catch (IOException e) { 
    252             MercurialEclipsePlugin.logError(e); 
    253             throw new HgException(e.getLocalizedMessage(), e); 
    254         } 
    255     } 
    256  
    257     /** 
    258      * @param fileRevisions 
    259      * @param cs 
    260      * @param res 
    261464     * @return 
    262465     */ 
    263     private static SortedSet<ChangeSet> addChangeSetRevisions( 
    264             Map<IPath, SortedSet<ChangeSet>> fileRevisions, ChangeSet cs, 
    265             IPath path) { 
    266         SortedSet<ChangeSet> fileRevs = fileRevisions.get(path); 
    267         if (fileRevs == null) { 
    268             fileRevs = new TreeSet<ChangeSet>(); 
    269         } 
    270         fileRevs.add(cs); 
    271         return fileRevs; 
     466    private static ContentHandler getHandler(IResource res, 
     467            Direction direction, HgRepositoryLocation repository, 
     468            File bundleFile, File hgRoot, 
     469            Map<IPath, SortedSet<ChangeSet>> fileRevisions) { 
     470        handler = new ChangesetContentHandler(res, direction, repository, 
     471                bundleFile, hgRoot, fileRevisions); 
     472        return handler; 
    272473    } 
    273474 
    274     private static FileStatus[] getFileStatuses(Element csn) { 
    275         HashSet<String> files = getFilesValue(csn, "fl"); 
    276         HashSet<String> adds = getFilesValue(csn, "fa"); 
    277         HashSet<String> del = getFilesValue(csn, "fd"); 
    278  
    279         files.removeAll(adds); 
    280         files.removeAll(del); 
    281  
    282         List<FileStatus> statuses = new ArrayList<FileStatus>(files.size()); 
    283         addFiles(statuses, files, Action.MODIFIED); 
    284         addFiles(statuses, adds, Action.ADDED); 
    285         addFiles(statuses, del, Action.REMOVED); 
    286  
    287         return statuses.toArray(new FileStatus[statuses.size()]); 
    288     } 
    289  
    290     private static HashSet<String> getFilesValue(Element csn, String name) { 
    291         NodeList nl = csn.getElementsByTagName(name); 
    292         if (nl.getLength() == 0) { 
    293             return new HashSet<String>(0); 
    294         } 
    295         NodeList files = ((Element) nl.item(0)).getElementsByTagName("f"); 
    296         HashSet<String> ret = new HashSet<String>(files.getLength()); 
    297         for (int i = 0; i < files.getLength(); i++) { 
    298             ret.add(files.item(i).getTextContent()); 
    299         } 
    300  
    301         return ret; 
    302     } 
    303  
    304     private static void addFiles(List<FileStatus> statuses, 
    305             HashSet<String> files, Action action) { 
    306         for (String f : files) { 
    307             statuses.add(new FileStatus(action, f)); 
    308         } 
    309     } 
    310  
    311     private static String[] splitClean(String string, String sep) { 
    312         if (string == null || string.length() == 0) { 
    313             return new String[] {}; 
    314         } 
    315         return string.split(sep); 
    316     } 
    317  
    318     private static String unescape(String string) { 
    319         return string.replaceAll("&lt;", "<").replaceAll("&gt;", ">") 
    320                 .replaceAll("&amp;", "&"); 
    321     } 
    322  
    323475    /** 
    324      * Remove a leading tab on each line in the string. 
    325      *  
    326      * @param string 
    327      * @return 
    328      */ 
    329     private static String untab(String string) { 
    330         return string.replaceAll("\n\t", "\n"); 
    331     } 
    332      
    333     /** 
    334      * Clean the string of special chars that might be invalid for the 
    335      * XML parser.  Return the cleaned string (special chars replaced by 
    336      * ordinary spaces). 
    337      *  
    338      * @param str the string to clean 
     476     * Clean the string of special chars that might be invalid for the XML 
     477     * parser. Return the cleaned string (special chars replaced by ordinary 
     478     * spaces). 
     479     *  
     480     * @param str 
     481     *            the string to clean 
    339482     * @return the cleaned string 
    340483     */ 
     
    354497        return buf.toString(); 
    355498    } 
    356  
    357     /** 
    358      * Parse a changeset as output from the log command (see 
    359      * {@link #createMercurialRevisions()}). 
    360      * @param hgRoot  
    361      * @param direction  
    362      * @param bundleFile  
    363      * @param repository  
    364      *  
    365      * @param changeSet 
    366      * @return 
    367      */ 
    368     private static ChangeSet getChangeSet(HgRepositoryLocation repository,  
    369             File bundleFile,  
    370             Direction direction,  
    371             File hgRoot,  
    372             String changeSet) throws HgException { 
    373  
    374         if (changeSet == null) { 
    375             return null; 
    376         } 
    377  
    378         String outputString = changeSet.substring(changeSet.indexOf("<cs>")); 
    379          
    380         try { 
    381             DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory 
    382                     .newInstance(); 
    383             DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 
    384             Document doc; 
    385             Reader ir = null; 
    386             try { 
    387                 ir = new StringReader(outputString); 
    388                 doc = docBuilder.parse(new InputSource(ir)); 
    389             } catch (SAXException e) { 
    390                 outputString = cleanControlChars(outputString); 
    391                 ir = new StringReader(outputString); 
    392                 doc = docBuilder.parse(new InputSource(ir)); 
    393             } finally { 
    394                 if (ir != null) { 
    395                     ir.close(); 
    396                 } 
    397             } 
    398  
    399             // normalize text representation 
    400             doc.getDocumentElement().normalize(); 
    401  
    402             NodeList csnl = doc.getElementsByTagName("cs"); 
    403             int totalCs = csnl.getLength(); 
    404             if (totalCs != 1) { 
    405                 // Something screwy going on, should have 1 and 1 only. 
    406                 throw new HgException( 
    407                         "Cannot parse changeset, bad log output?: " + changeSet); 
    408             } 
    409             Element csn = (Element) csnl.item(0); 
    410  
    411             ChangeSet.Builder csb = new ChangeSet.Builder(Integer.parseInt(getValue(csn, "rv")), 
    412                     getValue(csn, "nl"), 
    413                     getValue(csn, "br"), 
    414                     getValue(csn, "di"), 
    415                     getValue(csn, 
    416                             "au")); 
    417             csb.tag(getValue(csn, "tg")); 
    418             csb.nodeShort(getValue(csn, "ns")); 
    419             csb.ageDate(getValue(csn, "da")); 
    420             csb.description(untab(unescape(getValue(csn, "de")))); 
    421             csb.parents(splitClean(getValue(csn, "pr"), " ")); 
    422             csb.changedFiles(getFileStatuses(csn)); 
    423              
    424             csb.hgRoot(hgRoot).bundleFile(bundleFile).repository(repository).direction(direction); 
    425             return csb.build(); 
    426         } catch (ParserConfigurationException e) { 
    427             throw new HgException("Changeset parser Configuration error", e); 
    428         } catch (SAXException e) { 
    429             throw new HgException("Changeset parsing error for \"" + changeSet 
    430                     + "\"", e); 
    431         } catch (IOException e) { 
    432             throw new HgException("Error parsing changeset \"" + changeSet 
    433                     + "\"", e); 
    434         } 
    435     } 
    436  
    437     /** 
    438      * @param csn 
    439      * @return 
    440      */ 
    441     private static String getValue(Element csn, String name) { 
    442         return csn.getElementsByTagName(name).item(0).getTextContent(); 
    443     } 
    444  
    445499} 
  • styles/log_style.tmpl

    r573 r820  
    11<cs> 
    2 <br>{branches}</br
    3 <tg>{tags}</tg
    4 <rv>{rev}</rv
    5 <ns>{node|short}</ns
    6 <nl>{node}</nl
    7 <di>{date|isodate}</di
    8 <da>{date|age}</da
    9 <au>{author|person}</au
    10 <pr>{parents}</pr
    11 <de>{desc|escape|tabindent}</de
     2<br v="{branches}"/
     3<tg v="{tags}"/
     4<rv v="{rev}"/
     5<ns v="{node|short}"/
     6<nl v="{node}"/
     7<di v="{date|isodate}"/
     8<da v="{date|age}"/
     9<au v="{author|person}"/
     10<pr v="{parents}"/
     11<de v="{desc|escape|tabindent}"/
    1212</cs> 
    13 ============ 
  • styles/log_style_with_files

    r569 r820  
    11changeset = log_style_with_files.tmpl 
    22start_files = '' 
    3 file = '\n<f>{file|escape}</f>' 
     3file = '\n<f v="{file|escape}"/>' 
    44end_files = '' 
    55start_file_adds = '' 
    6 file_add = '\n<f>{file_add|escape}</f>' 
     6file_add = '\n<f v="{file_add|escape}"/>' 
    77end_file_adds = '' 
    88start_file_dels = '' 
    9 file_del = '\n<f>{file_del|escape}</f>' 
     9file_del = '\n<f v="{file_del|escape}"/>' 
    1010end_file_dels = '' 
  • styles/log_style_with_files.tmpl

    r573 r820  
    11<cs> 
    2 <br>{branches}</br> 
    3 <tg>{tags}</tg> 
    4 <rv>{rev}</rv> 
    5 <ns>{node|short}</ns> 
    6 <nl>{node}</nl> 
    7 <di>{date|isodate}</di> 
    8 <da>{date|age}</da> 
    9 <au>{author|person}</au> 
    10 <pr>{parents}</pr> 
    11 <de>{desc|escape|tabindent}</de> 
    12 <fl>{files} 
    13 </fl> 
    14 <fa>{file_adds} 
    15 </fa> 
    16 <fd>{file_dels} 
    17 </fd> 
     2<br v="{branches}"/> 
     3<tg v="{tags}"/> 
     4<rv v="{rev}"/> 
     5<ns v="{node|short}"/> 
     6<nl v="{node}"/> 
     7<di v="{date|isodate}"/> 
     8<da v="{date|age}"/> 
     9<au v="{author|person}"/> 
     10<pr v="{parents}"/> 
     11<de v="{desc|escape|tabindent}"/> 
     12<fl>{files}</fl> 
     13<fa>{file_adds}</fa> 
     14<fd>{file_dels}</fd> 
    1815</cs> 
    19 ============