001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.provider.hg.command.diff; 020 021import java.io.File; 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.maven.scm.ScmFile; 028import org.apache.maven.scm.ScmFileStatus; 029import org.apache.maven.scm.provider.hg.command.HgConsumer; 030 031/** 032 * @author <a href="mailto:thurner.rupert@ymono.net">thurner rupert</a> 033 * @author Olivier Lamy 034 * 035 */ 036public class HgDiffConsumer extends HgConsumer { 037 038 // private static final String MODIFIED_FILE_TOKEN = "=== modified file "; 039 040 private static final String INDEX_TOKEN = "diff -r "; 041 042 private static final String FILE_SEPARATOR_TOKEN = "==="; 043 044 private static final String START_REVISION_TOKEN = "---"; 045 046 private static final String END_REVISION_TOKEN = "+++"; 047 048 private static final String ADDED_LINE_TOKEN = "+"; 049 050 private static final String REMOVED_LINE_TOKEN = "-"; 051 052 private static final String UNCHANGED_LINE_TOKEN = " "; 053 054 private static final String CHANGE_SEPARATOR_TOKEN = "@@"; 055 056 private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file"; 057 058 private static final int HASH_ID_LEN = 12; 059 060 private String currentFile; 061 062 private StringBuilder currentDifference; 063 064 private final List<ScmFile> changedFiles = new ArrayList<>(); 065 066 private final Map<String, CharSequence> differences = new HashMap<>(); 067 068 private final StringBuilder patch = new StringBuilder(); 069 070 @SuppressWarnings("unused") 071 private final File workingDirectory; 072 073 public HgDiffConsumer(File workingDirectory) { 074 this.workingDirectory = workingDirectory; 075 } 076 077 // ---------------------------------------------------------------------- 078 // StreamConsumer Implementation 079 // ---------------------------------------------------------------------- 080 081 /** {@inheritDoc} */ 082 public void consumeLine(String line) { 083 if (line.startsWith(INDEX_TOKEN)) { 084 // start a new file 085 currentFile = line.substring(INDEX_TOKEN.length() + HASH_ID_LEN + 1); 086 087 changedFiles.add(new ScmFile(currentFile, ScmFileStatus.MODIFIED)); 088 089 currentDifference = new StringBuilder(); 090 091 differences.put(currentFile, currentDifference); 092 093 patch.append(line).append("\n"); 094 095 return; 096 } 097 098 if (currentFile == null) { 099 if (logger.isWarnEnabled()) { 100 logger.warn("Unparseable line: '" + line + "'"); 101 } 102 patch.append(line).append("\n"); 103 return; 104 } 105 106 if (line.startsWith(FILE_SEPARATOR_TOKEN)) { 107 // skip 108 patch.append(line).append("\n"); 109 } else if (line.startsWith(START_REVISION_TOKEN)) { 110 // skip, though could parse to verify filename, start revision 111 patch.append(line).append("\n"); 112 } else if (line.startsWith(END_REVISION_TOKEN)) { 113 // skip, though could parse to verify filename, end revision 114 patch.append(line).append("\n"); 115 } else if (line.startsWith(ADDED_LINE_TOKEN) 116 || line.startsWith(REMOVED_LINE_TOKEN) 117 || line.startsWith(UNCHANGED_LINE_TOKEN) 118 || line.startsWith(CHANGE_SEPARATOR_TOKEN) 119 || line.equals(NO_NEWLINE_TOKEN)) { 120 // add to buffer 121 currentDifference.append(line).append("\n"); 122 patch.append(line).append("\n"); 123 } else { 124 // TODO: handle property differences 125 126 if (logger.isWarnEnabled()) { 127 logger.warn("Unparseable line: '" + line + "'"); 128 } 129 patch.append(line).append("\n"); 130 // skip to next file 131 currentFile = null; 132 currentDifference = null; 133 } 134 } 135 136 public List<ScmFile> getChangedFiles() { 137 return changedFiles; 138 } 139 140 public Map<String, CharSequence> getDifferences() { 141 return differences; 142 } 143 144 public String getPatch() { 145 return patch.toString(); 146 } 147}