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 */ 035public class HgDiffConsumer extends HgConsumer { 036 037 // private static final String MODIFIED_FILE_TOKEN = "=== modified file "; 038 039 private static final String INDEX_TOKEN = "diff -r "; 040 041 private static final String FILE_SEPARATOR_TOKEN = "==="; 042 043 private static final String START_REVISION_TOKEN = "---"; 044 045 private static final String END_REVISION_TOKEN = "+++"; 046 047 private static final String ADDED_LINE_TOKEN = "+"; 048 049 private static final String REMOVED_LINE_TOKEN = "-"; 050 051 private static final String UNCHANGED_LINE_TOKEN = " "; 052 053 private static final String CHANGE_SEPARATOR_TOKEN = "@@"; 054 055 private static final String NO_NEWLINE_TOKEN = "\\ No newline at end of file"; 056 057 private static final int HASH_ID_LEN = 12; 058 059 private String currentFile; 060 061 private StringBuilder currentDifference; 062 063 private final List<ScmFile> changedFiles = new ArrayList<>(); 064 065 private final Map<String, CharSequence> differences = new HashMap<>(); 066 067 private final StringBuilder patch = new StringBuilder(); 068 069 @SuppressWarnings("unused") 070 private final File workingDirectory; 071 072 public HgDiffConsumer(File workingDirectory) { 073 this.workingDirectory = workingDirectory; 074 } 075 076 // ---------------------------------------------------------------------- 077 // StreamConsumer Implementation 078 // ---------------------------------------------------------------------- 079 080 /** 081 * {@inheritDoc} 082 */ 083 public void consumeLine(String line) { 084 if (line.startsWith(INDEX_TOKEN)) { 085 // start a new file 086 currentFile = line.substring(INDEX_TOKEN.length() + HASH_ID_LEN + 1); 087 088 changedFiles.add(new ScmFile(currentFile, ScmFileStatus.MODIFIED)); 089 090 currentDifference = new StringBuilder(); 091 092 differences.put(currentFile, currentDifference); 093 094 patch.append(line).append("\n"); 095 096 return; 097 } 098 099 if (currentFile == null) { 100 if (logger.isWarnEnabled()) { 101 logger.warn("Unparseable line: '" + line + "'"); 102 } 103 patch.append(line).append("\n"); 104 return; 105 } 106 107 if (line.startsWith(FILE_SEPARATOR_TOKEN)) { 108 // skip 109 patch.append(line).append("\n"); 110 } else if (line.startsWith(START_REVISION_TOKEN)) { 111 // skip, though could parse to verify filename, start revision 112 patch.append(line).append("\n"); 113 } else if (line.startsWith(END_REVISION_TOKEN)) { 114 // skip, though could parse to verify filename, end revision 115 patch.append(line).append("\n"); 116 } else if (line.startsWith(ADDED_LINE_TOKEN) 117 || line.startsWith(REMOVED_LINE_TOKEN) 118 || line.startsWith(UNCHANGED_LINE_TOKEN) 119 || line.startsWith(CHANGE_SEPARATOR_TOKEN) 120 || line.equals(NO_NEWLINE_TOKEN)) { 121 // add to buffer 122 currentDifference.append(line).append("\n"); 123 patch.append(line).append("\n"); 124 } else { 125 // TODO: handle property differences 126 127 if (logger.isWarnEnabled()) { 128 logger.warn("Unparseable line: '" + line + "'"); 129 } 130 patch.append(line).append("\n"); 131 // skip to next file 132 currentFile = null; 133 currentDifference = null; 134 } 135 } 136 137 public List<ScmFile> getChangedFiles() { 138 return changedFiles; 139 } 140 141 public Map<String, CharSequence> getDifferences() { 142 return differences; 143 } 144 145 public String getPatch() { 146 return patch.toString(); 147 } 148}