Mercurial > hg > mercurial
view mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/command/CommitsAndMountPointsParser.java @ 919:16ad8d51b001
fix non-ascii characters support in commandline arguments
author | eugene.petrenko@jetbrains.com |
---|---|
date | Mon, 19 Jan 2015 18:30:08 +0100 |
parents | fba173530aa6 |
children | 7bf4d943d5bb |
line wrap: on
line source
/* * Copyright 2000-2014 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 jetbrains.buildServer.util.FileUtil; import org.apache.commons.codec.binary.Base64; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; /** * Created 09.01.14 17:10 * * @author Eugene Petrenko (eugene.petrenko@jetbrains.com) */ public class CommitsAndMountPointsParser { public static void parseFileLog(@NotNull final File dump, @NotNull final ContentsConsumer consumer) throws IOException { final BufferedReader st = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(dump)), "utf-8")); try { final Decoder fileDecoder = new Decoder(5); String line; while((line = st.readLine()) != null) { if (!line.startsWith("$$@@@@ ")) continue; final String[] items = line.split(" "); if (items.length != 1 + 2) continue; final String commitId = items[1]; final String content = fileDecoder.decode(items[2]); consumer.onCommit(commitId, content == null ? "" : content); } } finally { FileUtil.close(st); } } public interface ContentsConsumer { void onCommit( @NotNull String fileNodeId, @NotNull String content); } public interface CommitsConsumer { void onCommit( @NotNull String commitNum, @NotNull String commitId, @NotNull String[] parents, @NotNull String branch, @NotNull String[] tags, @NotNull String author, @NotNull String message, @NotNull Date timestamp, @Nullable String hgsubNodeId, @Nullable String hgsubstateNodeId); } public static void parseCommits(@NotNull final File dump, @NotNull final CommitsConsumer consumer) throws IOException { final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'Z'HH:mm:ss'T'Z", Locale.ENGLISH); final Decoder branchDecoder = new Decoder(250); final Decoder tagsDecoder = new Decoder(250); final Decoder authorDecoder = new Decoder(200); final Decoder messageDecoder = new Decoder(210); final BufferedReader st = new BufferedReader(new InputStreamReader(new BufferedInputStream(new FileInputStream(dump)), "utf-8")); try { String line; while((line = st.readLine()) != null) { if (!line.startsWith("$$@@@@ ")) continue; final Iterator<String> items = Arrays.asList(line.split(" ")).iterator(); items.next(); //$$@@@@ try { final String commitNum = items.next(); final String commitId = items.next(); final String[] parents = new String[Integer.parseInt(items.next())]; for (int i = 0; i < parents.length; i++) { parents[i] = items.next(); } final String branch = branchDecoder.decode(items.next()); final String[] tags = new String[Integer.parseInt(items.next())]; for (int i = 0; i < tags.length; i++) { tags[i] = tagsDecoder.decode(items.next()); } final String author = authorDecoder.decode(items.next()); final String message = messageDecoder.decode(items.next()); final Date time = parseTime(dateFormat, items.next()); final String hgsub = textOrNull(items.next()); final String hgsubstate = textOrNull(items.next()); consumer.onCommit( commitNum, commitId, parents, branch, tags, author == null ? "" : author, message == null ? "" : message, time, hgsub, hgsubstate); } catch (NoSuchElementException e) { //NOP } } } finally{ FileUtil.close(st); } } @NotNull private static Date parseTime(@NotNull final SimpleDateFormat dateFormat, @NotNull final String time) { try { return dateFormat.parse(time); } catch (ParseException e) { throw new RuntimeException("Failed to parse datetime: " + time + ". " + e, e); } } @Nullable private static String textOrNull(@NotNull final String text) { if (text.equals("=====")) return null; return text; } private static class Decoder { private final Map<String, String> myCache; public Decoder(final int SZ) { myCache = new LinkedHashMap<String, String>(SZ, 0.9f) { @Override protected boolean removeEldestEntry(Map.Entry<String, String> eldest) { return size() > SZ; } }; } public String decode(@NotNull final String base64) throws UnsupportedEncodingException { if (textOrNull(base64) == null) return null; final String result = myCache.get(base64); if (result != null) return result; final String value = new String(Base64.decodeBase64(base64), "utf-8"); //noinspection RedundantStringConstructorCall myCache.put(new String(base64), value); return value; } } }