1.1 --- a/mercurial.remote/src/org/netbeans/modules/mercurial/remote/ui/update/ResolveConflictsExecutor.java Mon Nov 04 14:34:07 2019 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,607 +0,0 @@
1.4 -/*
1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 - *
1.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
1.8 - *
1.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
1.10 - * Other names may be trademarks of their respective owners.
1.11 - *
1.12 - * The contents of this file are subject to the terms of either the GNU
1.13 - * General Public License Version 2 only ("GPL") or the Common
1.14 - * Development and Distribution License("CDDL") (collectively, the
1.15 - * "License"). You may not use this file except in compliance with the
1.16 - * License. You can obtain a copy of the License at
1.17 - * http://www.netbeans.org/cddl-gplv2.html
1.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.19 - * specific language governing permissions and limitations under the
1.20 - * License. When distributing the software, include this License Header
1.21 - * Notice in each file and include the License file at
1.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
1.23 - * particular file as subject to the "Classpath" exception as provided
1.24 - * by Oracle in the GPL Version 2 section of the License file that
1.25 - * accompanied this code. If applicable, add the following below the
1.26 - * License Header, with the fields enclosed by brackets [] replaced by
1.27 - * your own identifying information:
1.28 - * "Portions Copyrighted [year] [name of copyright owner]"
1.29 - *
1.30 - * Contributor(s):
1.31 - *
1.32 - * The Original Software is NetBeans. The Initial Developer of the Original
1.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
1.34 - * Microsystems, Inc. All Rights Reserved.
1.35 - *
1.36 - * If you wish your version of this file to be governed by only the CDDL
1.37 - * or only the GPL Version 2, indicate your decision by adding
1.38 - * "[Contributor] elects to include this software in this distribution
1.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
1.40 - * single choice of license, a recipient has the option to distribute
1.41 - * your version of this file under either the CDDL, the GPL Version 2 or
1.42 - * to extend the choice of license to its licensees as provided above.
1.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
1.44 - * Version 2 license, then the option applies only if the new code is
1.45 - * made subject to such option by the copyright holder.
1.46 - */
1.47 -
1.48 -package org.netbeans.modules.mercurial.remote.ui.update;
1.49 -
1.50 -import java.awt.Component;
1.51 -import java.awt.EventQueue;
1.52 -import java.io.BufferedReader;
1.53 -import java.io.BufferedWriter;
1.54 -import java.io.File;
1.55 -import java.io.FilterWriter;
1.56 -import java.io.IOException;
1.57 -import java.io.InputStreamReader;
1.58 -import java.io.OutputStreamWriter;
1.59 -import java.io.Reader;
1.60 -import java.io.Writer;
1.61 -import java.nio.charset.Charset;
1.62 -import java.nio.file.Files;
1.63 -import java.util.ArrayList;
1.64 -import java.util.Iterator;
1.65 -import java.util.List;
1.66 -import java.util.Set;
1.67 -import java.util.logging.Level;
1.68 -import javax.swing.SwingUtilities;
1.69 -import org.netbeans.api.diff.Difference;
1.70 -import org.netbeans.api.diff.StreamSource;
1.71 -import org.netbeans.api.queries.FileEncodingQuery;
1.72 -import org.netbeans.modules.mercurial.remote.HgException;
1.73 -import org.netbeans.modules.mercurial.remote.HgProgressSupport;
1.74 -import org.netbeans.modules.mercurial.remote.Mercurial;
1.75 -import org.netbeans.modules.mercurial.remote.ui.branch.HgBranch;
1.76 -import org.netbeans.modules.mercurial.remote.ui.log.HgLogMessage;
1.77 -import org.netbeans.modules.mercurial.remote.util.HgCommand;
1.78 -import org.netbeans.modules.remotefs.versioning.api.VCSFileProxySupport;
1.79 -import org.netbeans.modules.versioning.core.api.VCSFileProxy;
1.80 -import org.netbeans.spi.diff.MergeVisualizer;
1.81 -import org.openide.filesystems.FileAlreadyLockedException;
1.82 -import org.openide.filesystems.FileLock;
1.83 -import org.openide.filesystems.FileObject;
1.84 -import org.openide.filesystems.FileUtil;
1.85 -import org.openide.util.Lookup;
1.86 -import org.openide.windows.TopComponent;
1.87 -
1.88 -/**
1.89 - * Shows basic conflict resolver UI.
1.90 - *
1.91 - * This class is copy&pasted from javacvs
1.92 - *
1.93 - *
1.94 - */
1.95 -public class ResolveConflictsExecutor extends HgProgressSupport {
1.96 -
1.97 - private static final String TMP_PREFIX = "merge"; // NOI18N
1.98 - private static final String ORIG_SUFFIX = ".orig."; // NOI18N
1.99 - private static final String LOCAL = "local"; //NOI18N
1.100 -
1.101 - static final String CHANGE_LEFT = "<<<<<<< "; // NOI18N
1.102 - static final String CHANGE_RIGHT = ">>>>>>> "; // NOI18N
1.103 - static final String CHANGE_DELIMETER = "======="; // NOI18N
1.104 - static final String CHANGE_BASE_DELIMETER = "|||||||"; // NOI18N
1.105 -
1.106 - private String leftFileRevision = null;
1.107 - private String rightFileRevision = null;
1.108 -
1.109 - private final VCSFileProxy file;
1.110 -
1.111 - public ResolveConflictsExecutor(VCSFileProxy file) {
1.112 - super();
1.113 - this.file = file;
1.114 - }
1.115 -
1.116 - public void exec() {
1.117 - MergeVisualizer merge = (MergeVisualizer) Lookup.getDefault().lookup(MergeVisualizer.class);
1.118 - if (merge == null) {
1.119 - throw new IllegalStateException("No Merge engine found."); // NOI18N
1.120 - }
1.121 -
1.122 - try {
1.123 - FileObject fo = file.toFileObject();
1.124 - if(fo == null) {
1.125 - Mercurial.LOG.warning("can't resolve conflicts for null fileobject : " + file + ", exists: " + file.exists());
1.126 - return;
1.127 - }
1.128 - FileLock lock = fo.lock();
1.129 - boolean mergeViewerDisplayed = false;
1.130 - try {
1.131 - mergeViewerDisplayed = handleMergeFor(file, fo, lock, merge);
1.132 - } finally {
1.133 - if (!mergeViewerDisplayed) {
1.134 - lock.releaseLock();
1.135 - }
1.136 - }
1.137 - } catch (FileAlreadyLockedException e) {
1.138 - SwingUtilities.invokeLater(new Runnable() {
1.139 - @Override
1.140 - public void run() {
1.141 - Set components = TopComponent.getRegistry().getOpened();
1.142 - for (Iterator i = components.iterator(); i.hasNext();) {
1.143 - TopComponent tc = (TopComponent) i.next();
1.144 - if (tc.getClientProperty(ResolveConflictsExecutor.class.getName()) != null) {
1.145 - tc.requestActive();
1.146 - }
1.147 - }
1.148 - }
1.149 - });
1.150 - } catch (IOException ioex) {
1.151 - org.openide.ErrorManager.getDefault().notify(ioex);
1.152 - }
1.153 - }
1.154 -
1.155 - private boolean handleMergeFor(final VCSFileProxy file, FileObject fo, FileLock lock,
1.156 - final MergeVisualizer merge) throws IOException {
1.157 - String mimeType = (fo == null) ? "text/plain" : fo.getMIMEType(); // NOI18N
1.158 - String ext = (fo == null) ? "" : "." + fo.getExt(); //NOI18N
1.159 - File f1 = FileUtil.normalizeFile(File.createTempFile(TMP_PREFIX, ext));
1.160 - File f2 = FileUtil.normalizeFile(File.createTempFile(TMP_PREFIX, ext));
1.161 - File f3 = FileUtil.normalizeFile(File.createTempFile(TMP_PREFIX, ext));
1.162 - f1.deleteOnExit();
1.163 - f2.deleteOnExit();
1.164 - f3.deleteOnExit();
1.165 -
1.166 - Charset encoding = FileEncodingQuery.getEncoding(fo);
1.167 - final Difference[] diffs = copyParts(true, file, f1, true, encoding);
1.168 - if (diffs.length == 0) {
1.169 - ConflictResolvedAction.resolved(file); // remove conflict status
1.170 - return false;
1.171 - }
1.172 -
1.173 - copyParts(false, file, f2, false, encoding);
1.174 - //GraphicalMergeVisualizer merge = new GraphicalMergeVisualizer();
1.175 - String originalLeftFileRevision = leftFileRevision;
1.176 - String originalRightFileRevision = rightFileRevision;
1.177 - if (leftFileRevision != null) {
1.178 - leftFileRevision = leftFileRevision.trim();
1.179 - }
1.180 - if (rightFileRevision != null) {
1.181 - rightFileRevision = rightFileRevision.trim();
1.182 - }
1.183 - List<HgLogMessage> parentRevisions = null;
1.184 - if (LOCAL.equals(leftFileRevision)) {
1.185 - try {
1.186 - parentRevisions = HgCommand.getParents(Mercurial.getInstance().getRepositoryRoot(file), file, null);
1.187 - } catch (HgException ex) {
1.188 - Mercurial.LOG.log(Level.INFO, null, ex);
1.189 - }
1.190 - if (parentRevisions != null && parentRevisions.size() > 1) {
1.191 - leftFileRevision = formatRevision(parentRevisions.get(0));
1.192 - rightFileRevision = formatRevision(parentRevisions.get(1));
1.193 - }
1.194 - }
1.195 - if (leftFileRevision == null || leftFileRevision.equals(file.getPath() + ORIG_SUFFIX)
1.196 - || leftFileRevision.equals(LOCAL)){
1.197 - leftFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleWorkingFile"); // NOI18N
1.198 - }
1.199 - if (rightFileRevision == null || rightFileRevision.equals(file.getPath() + ORIG_SUFFIX)) {
1.200 - rightFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleWorkingFile"); // NOI18N
1.201 - }
1.202 -
1.203 - final StreamSource s1;
1.204 - final StreamSource s2;
1.205 - VCSFileProxySupport.associateEncoding(VCSFileProxy.createFileProxy(f1), encoding);
1.206 - VCSFileProxySupport.associateEncoding(VCSFileProxy.createFileProxy(f2), encoding);
1.207 - s1 = StreamSource.createSource(file.getName(), leftFileRevision, mimeType, f1);
1.208 - s2 = StreamSource.createSource(file.getName(), rightFileRevision, mimeType, f2);
1.209 - final StreamSource result = new MergeResultWriterInfo(f1, f2, f3, file, mimeType,
1.210 - originalLeftFileRevision,
1.211 - originalRightFileRevision,
1.212 - fo, lock, encoding);
1.213 - EventQueue.invokeLater(new Runnable() {
1.214 - @Override
1.215 - public void run() {
1.216 - try {
1.217 - Component c = merge.createView(diffs, s1, s2, result);
1.218 - if (c instanceof TopComponent) {
1.219 - ((TopComponent) c).putClientProperty(ResolveConflictsExecutor.class.getName(), Boolean.TRUE);
1.220 - }
1.221 - } catch (IOException ioex) {
1.222 - org.openide.ErrorManager.getDefault().notify(ioex);
1.223 - }
1.224 - }
1.225 - });
1.226 - return true;
1.227 - }
1.228 -
1.229 - /**
1.230 - * Copy the file and conflict parts into another file.
1.231 - */
1.232 - private Difference[] copyParts(boolean generateDiffs, VCSFileProxy source,
1.233 - File dest, boolean leftPart, Charset charset) throws IOException {
1.234 - BufferedReader r = new BufferedReader(new InputStreamReader(source.getInputStream(false), charset));
1.235 - BufferedWriter w = Files.newBufferedWriter(dest.toPath(), charset);
1.236 - ArrayList<Difference> diffList = null;
1.237 - if (generateDiffs) {
1.238 - diffList = new ArrayList<>();
1.239 - }
1.240 - try {
1.241 - String line;
1.242 - boolean isChangeLeft = false;
1.243 - boolean isChangeRight = false;
1.244 - boolean isChangeBase = false;
1.245 - int f1l1 = 0, f1l2 = 0, f2l1 = 0, f2l2 = 0;
1.246 - StringBuilder text1 = new StringBuilder();
1.247 - StringBuilder text2 = new StringBuilder();
1.248 - int i = 1, j = 1;
1.249 - while ((line = r.readLine()) != null) {
1.250 - // As the Graphical Merge Visualizer does not support 3 way diff,
1.251 - // remove the base diff itself.
1.252 - // Only show the diffs of the two heads against the base
1.253 - if (line.startsWith(CHANGE_BASE_DELIMETER)) {
1.254 - isChangeBase = true;
1.255 - continue;
1.256 - }
1.257 - if (isChangeBase && line.startsWith(CHANGE_DELIMETER)) {
1.258 - isChangeBase = false;
1.259 - } else if (isChangeBase) {
1.260 - continue;
1.261 - }
1.262 - if (line.startsWith(CHANGE_LEFT)) {
1.263 - if (generateDiffs) {
1.264 - if (leftFileRevision == null) {
1.265 - leftFileRevision = line.substring(CHANGE_LEFT.length());
1.266 - }
1.267 - if (isChangeLeft) {
1.268 - f1l2 = i - 1;
1.269 - diffList.add((f1l1 > f1l2) ? new Difference(Difference.ADD,
1.270 - f1l1 - 1, 0, f2l1, f2l2,
1.271 - text1.toString(),
1.272 - text2.toString()) :
1.273 - (f2l1 > f2l2) ? new Difference(Difference.DELETE,
1.274 - f1l1, f1l2, f2l1 - 1, 0,
1.275 - text1.toString(),
1.276 - text2.toString())
1.277 - : new Difference(Difference.CHANGE,
1.278 - f1l1, f1l2, f2l1, f2l2,
1.279 - text1.toString(),
1.280 - text2.toString()));
1.281 - f1l1 = f1l2 = f2l1 = f2l2 = 0;
1.282 - text1.delete(0, text1.length());
1.283 - text2.delete(0, text2.length());
1.284 - } else {
1.285 - f1l1 = i;
1.286 - }
1.287 - }
1.288 - isChangeLeft = !isChangeLeft;
1.289 - continue;
1.290 - } else if (line.startsWith(CHANGE_RIGHT)) {
1.291 - if (generateDiffs) {
1.292 - if (rightFileRevision == null) {
1.293 - rightFileRevision = line.substring(CHANGE_RIGHT.length());
1.294 - }
1.295 - if (isChangeRight) {
1.296 - f2l2 = j - 1;
1.297 - diffList.add((f1l1 > f1l2) ? new Difference(Difference.ADD,
1.298 - f1l1 - 1, 0, f2l1, f2l2,
1.299 - text1.toString(),
1.300 - text2.toString()) :
1.301 - (f2l1 > f2l2) ? new Difference(Difference.DELETE,
1.302 - f1l1, f1l2, f2l1 - 1, 0,
1.303 - text1.toString(),
1.304 - text2.toString())
1.305 - : new Difference(Difference.CHANGE,
1.306 - f1l1, f1l2, f2l1, f2l2,
1.307 - text1.toString(),
1.308 - text2.toString()));
1.309 - /*
1.310 - diffList.add(new Difference((f1l1 > f1l2) ? Difference.ADD :
1.311 - (f2l1 > f2l2) ? Difference.DELETE :
1.312 - Difference.CHANGE,
1.313 - f1l1, f1l2, f2l1, f2l2));
1.314 - */
1.315 - f1l1 = f1l2 = f2l1 = f2l2 = 0;
1.316 - text1.delete(0, text1.length());
1.317 - text2.delete(0, text2.length());
1.318 - } else {
1.319 - f2l1 = j;
1.320 - }
1.321 - }
1.322 - isChangeRight = !isChangeRight;
1.323 - continue;
1.324 - } else if (isChangeRight && line.indexOf(CHANGE_RIGHT) != -1) {
1.325 - String lineText = line.substring(0, line.lastIndexOf(CHANGE_RIGHT));
1.326 - if (generateDiffs) {
1.327 - if (rightFileRevision == null) {
1.328 - rightFileRevision = line.substring(line.lastIndexOf(CHANGE_RIGHT) + CHANGE_RIGHT.length());
1.329 - }
1.330 - text2.append(lineText);
1.331 - f2l2 = j;
1.332 - diffList.add((f1l1 > f1l2) ? new Difference(Difference.ADD,
1.333 - f1l1 - 1, 0, f2l1, f2l2,
1.334 - text1.toString(),
1.335 - text2.toString()) :
1.336 - (f2l1 > f2l2) ? new Difference(Difference.DELETE,
1.337 - f1l1, f1l2, f2l1 - 1, 0,
1.338 - text1.toString(),
1.339 - text2.toString())
1.340 - : new Difference(Difference.CHANGE,
1.341 - f1l1, f1l2, f2l1, f2l2,
1.342 - text1.toString(),
1.343 - text2.toString()));
1.344 - f1l1 = f1l2 = f2l1 = f2l2 = 0;
1.345 - text1.delete(0, text1.length());
1.346 - text2.delete(0, text2.length());
1.347 - }
1.348 - if (!leftPart) {
1.349 - w.write(lineText);
1.350 - w.newLine();
1.351 - }
1.352 - isChangeRight = !isChangeRight;
1.353 - continue;
1.354 - } else if (line.equals(CHANGE_DELIMETER)) {
1.355 - if (isChangeLeft) {
1.356 - isChangeLeft = false;
1.357 - isChangeRight = true;
1.358 - f1l2 = i - 1;
1.359 - f2l1 = j;
1.360 - continue;
1.361 - } else if (isChangeRight) {
1.362 - isChangeRight = false;
1.363 - isChangeLeft = true;
1.364 - f2l2 = j - 1;
1.365 - f1l1 = i;
1.366 - continue;
1.367 - }
1.368 - } else if (line.endsWith(CHANGE_DELIMETER) && !line.endsWith(CHANGE_DELIMETER + CHANGE_DELIMETER.charAt(0))) {
1.369 - String lineText = line.substring(0, line.length() - CHANGE_DELIMETER.length()) + "\n"; // NOI18N
1.370 - if (isChangeLeft) {
1.371 - text1.append(lineText);
1.372 - if (leftPart) {
1.373 - w.write(lineText);
1.374 - w.newLine();
1.375 - }
1.376 - isChangeLeft = false;
1.377 - isChangeRight = true;
1.378 - f1l2 = i;
1.379 - f2l1 = j;
1.380 - } else if (isChangeRight) {
1.381 - text2.append(lineText);
1.382 - if (!leftPart) {
1.383 - w.write(lineText);
1.384 - w.newLine();
1.385 - }
1.386 - isChangeRight = false;
1.387 - isChangeLeft = true;
1.388 - f2l2 = j;
1.389 - f1l1 = i;
1.390 - }
1.391 - continue;
1.392 - }
1.393 - if (!isChangeLeft && !isChangeRight || leftPart == isChangeLeft) {
1.394 - w.write(line);
1.395 - w.newLine();
1.396 - }
1.397 - if (isChangeLeft) {
1.398 - text1.append(line + "\n"); // NOI18N
1.399 - }
1.400 - if (isChangeRight) {
1.401 - text2.append(line + "\n"); // NOI18N
1.402 - }
1.403 - if (generateDiffs) {
1.404 - if (isChangeLeft) {
1.405 - i++;
1.406 - } else if (isChangeRight) {
1.407 - j++;
1.408 - } else {
1.409 - i++;
1.410 - j++;
1.411 - }
1.412 - }
1.413 - }
1.414 - } finally {
1.415 - try {
1.416 - r.close();
1.417 - } finally {
1.418 - w.close();
1.419 - }
1.420 - }
1.421 - if (generateDiffs) {
1.422 - return diffList.toArray(new Difference[diffList.size()]);
1.423 - } else {
1.424 - return null;
1.425 - }
1.426 - }
1.427 -
1.428 - @Override
1.429 - public void perform() {
1.430 - exec();
1.431 - }
1.432 -
1.433 - @Override
1.434 - public void run() {
1.435 - throw new RuntimeException("Not implemented"); // NOI18N
1.436 - }
1.437 -
1.438 - private static final int MAX_LEN = 40;
1.439 - private static String formatRevision (HgLogMessage revision) {
1.440 - StringBuilder sb = new StringBuilder(100);
1.441 - String branch = revision.getBranches().length == 0 ? HgBranch.DEFAULT_NAME : revision.getBranches()[0];
1.442 - sb.append(revision.getRevisionNumber()).append(" (").append(branch).append(") "); //NOI18N
1.443 - sb.append(revision.getShortMessage());
1.444 - if (sb.length() > MAX_LEN) {
1.445 - sb.delete(MAX_LEN, sb.length());
1.446 - }
1.447 - return sb.toString();
1.448 - }
1.449 -
1.450 -
1.451 - private static class MergeResultWriterInfo extends StreamSource {
1.452 -
1.453 - private final File tempf1, tempf2, tempf3;
1.454 - private final VCSFileProxy outputFile;
1.455 - private VCSFileProxy fileToRepairEntriesOf;
1.456 - private final String mimeType;
1.457 - private final String leftFileRevision;
1.458 - private final String rightFileRevision;
1.459 - private FileObject fo;
1.460 - private FileLock lock;
1.461 - private final Charset encoding;
1.462 -
1.463 - public MergeResultWriterInfo(File tempf1, File tempf2, File tempf3,
1.464 - VCSFileProxy outputFile, String mimeType,
1.465 - String leftFileRevision, String rightFileRevision,
1.466 - FileObject fo, FileLock lock, Charset encoding) {
1.467 - this.tempf1 = tempf1;
1.468 - this.tempf2 = tempf2;
1.469 - this.tempf3 = tempf3;
1.470 - this.outputFile = outputFile;
1.471 - this.mimeType = mimeType;
1.472 - this.leftFileRevision = leftFileRevision;
1.473 - this.rightFileRevision = rightFileRevision;
1.474 - this.fo = fo;
1.475 - this.lock = lock;
1.476 - if (encoding == null) {
1.477 - encoding = FileEncodingQuery.getEncoding(FileUtil.toFileObject(tempf1));
1.478 - }
1.479 - this.encoding = encoding;
1.480 - }
1.481 -
1.482 - @Override
1.483 - public String getName() {
1.484 - return outputFile.getName();
1.485 - }
1.486 -
1.487 - @Override
1.488 - public String getTitle() {
1.489 - return org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Merge.titleResult"); // NOI18N
1.490 - }
1.491 -
1.492 - @Override
1.493 - public String getMIMEType() {
1.494 - return mimeType;
1.495 - }
1.496 -
1.497 - @Override
1.498 - public Reader createReader() throws IOException {
1.499 - throw new IOException("No reader of merge result"); // NOI18N
1.500 - }
1.501 -
1.502 - /**
1.503 - * Create a writer, that writes to the source.
1.504 - * @param conflicts The list of conflicts remaining in the source.
1.505 - * Can be <code>null</code> if there are no conflicts.
1.506 - * @return The writer or <code>null</code>, when no writer can be created.
1.507 - */
1.508 - @Override
1.509 - public Writer createWriter(Difference[] conflicts) throws IOException {
1.510 - Writer w;
1.511 - if (fo != null) {
1.512 - w = new OutputStreamWriter(fo.getOutputStream(lock), encoding);
1.513 - } else {
1.514 - w = new OutputStreamWriter(VCSFileProxySupport.getOutputStream(outputFile), encoding);
1.515 - }
1.516 - if (conflicts == null || conflicts.length == 0) {
1.517 - fileToRepairEntriesOf = outputFile;
1.518 - return w;
1.519 - } else {
1.520 - return new MergeConflictFileWriter(w, fo, conflicts,
1.521 - leftFileRevision, rightFileRevision);
1.522 - }
1.523 - }
1.524 -
1.525 - /**
1.526 - * This method is called when the visual merging process is finished.
1.527 - * All possible writting processes are finished before this method is called.
1.528 - */
1.529 - @Override
1.530 - public void close() {
1.531 - tempf1.delete();
1.532 - tempf2.delete();
1.533 - tempf3.delete();
1.534 - if (lock != null) {
1.535 - lock.releaseLock();
1.536 - lock = null;
1.537 - }
1.538 - fo = null;
1.539 - if (fileToRepairEntriesOf != null) {
1.540 - repairEntries(fileToRepairEntriesOf);
1.541 - fileToRepairEntriesOf = null;
1.542 - }
1.543 - }
1.544 -
1.545 - private void repairEntries(VCSFileProxy file) {
1.546 - ConflictResolvedAction.resolved(file); // remove conflict status
1.547 - }
1.548 - }
1.549 -
1.550 - private static class MergeConflictFileWriter extends FilterWriter {
1.551 -
1.552 - private final Difference[] conflicts;
1.553 - private int lineNumber;
1.554 - private int currentConflict;
1.555 - private final String leftName;
1.556 - private final String rightName;
1.557 - private final FileObject fo;
1.558 -
1.559 - public MergeConflictFileWriter(Writer delegate, FileObject fo,
1.560 - Difference[] conflicts, String leftName,
1.561 - String rightName) throws IOException {
1.562 - super(delegate);
1.563 - this.conflicts = conflicts;
1.564 - this.leftName = leftName;
1.565 - this.rightName = rightName;
1.566 - this.lineNumber = 1;
1.567 - this.currentConflict = 0;
1.568 - if (lineNumber == conflicts[currentConflict].getFirstStart()) {
1.569 - writeConflict(conflicts[currentConflict]);
1.570 - currentConflict++;
1.571 - }
1.572 - this.fo = fo;
1.573 - }
1.574 -
1.575 - @Override
1.576 - public void write(String str) throws IOException {
1.577 - super.write(str);
1.578 - lineNumber += numChars('\n', str);
1.579 - if (currentConflict < conflicts.length && lineNumber >= conflicts[currentConflict].getFirstStart()) {
1.580 - writeConflict(conflicts[currentConflict]);
1.581 - currentConflict++;
1.582 - }
1.583 - }
1.584 -
1.585 - private void writeConflict(Difference conflict) throws IOException {
1.586 - super.write(CHANGE_LEFT + leftName + "\n"); // NOI18N
1.587 - super.write(conflict.getFirstText());
1.588 - super.write(CHANGE_DELIMETER + "\n"); // NOI18N
1.589 - super.write(conflict.getSecondText());
1.590 - super.write(CHANGE_RIGHT + rightName + "\n"); // NOI18N
1.591 - }
1.592 -
1.593 - private static int numChars(char c, String str) {
1.594 - int n = 0;
1.595 - for (int pos = str.indexOf(c); pos >= 0 && pos < str.length(); pos = str.indexOf(c, pos + 1)) {
1.596 - n++;
1.597 - }
1.598 - return n;
1.599 - }
1.600 -
1.601 - @Override
1.602 - public void close() throws IOException {
1.603 - super.close();
1.604 - if (fo != null) {
1.605 - fo.refresh(true);
1.606 - }
1.607 - }
1.608 - }
1.609 -}
1.610 -
2.1 --- a/subversion.remote/src/org/netbeans/modules/subversion/remote/ui/update/ResolveConflictsExecutor.java Mon Nov 04 14:34:07 2019 +0100
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,566 +0,0 @@
2.4 -/*
2.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 - *
2.7 - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
2.8 - *
2.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 - * Other names may be trademarks of their respective owners.
2.11 - *
2.12 - * The contents of this file are subject to the terms of either the GNU
2.13 - * General Public License Version 2 only ("GPL") or the Common
2.14 - * Development and Distribution License("CDDL") (collectively, the
2.15 - * "License"). You may not use this file except in compliance with the
2.16 - * License. You can obtain a copy of the License at
2.17 - * http://www.netbeans.org/cddl-gplv2.html
2.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 - * specific language governing permissions and limitations under the
2.20 - * License. When distributing the software, include this License Header
2.21 - * Notice in each file and include the License file at
2.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 - * particular file as subject to the "Classpath" exception as provided
2.24 - * by Oracle in the GPL Version 2 section of the License file that
2.25 - * accompanied this code. If applicable, add the following below the
2.26 - * License Header, with the fields enclosed by brackets [] replaced by
2.27 - * your own identifying information:
2.28 - * "Portions Copyrighted [year] [name of copyright owner]"
2.29 - *
2.30 - * Contributor(s):
2.31 - *
2.32 - * The Original Software is NetBeans. The Initial Developer of the Original
2.33 - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
2.34 - * Microsystems, Inc. All Rights Reserved.
2.35 - *
2.36 - * If you wish your version of this file to be governed by only the CDDL
2.37 - * or only the GPL Version 2, indicate your decision by adding
2.38 - * "[Contributor] elects to include this software in this distribution
2.39 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.40 - * single choice of license, a recipient has the option to distribute
2.41 - * your version of this file under either the CDDL, the GPL Version 2 or
2.42 - * to extend the choice of license to its licensees as provided above.
2.43 - * However, if you add GPL Version 2 code and therefore, elected the GPL
2.44 - * Version 2 license, then the option applies only if the new code is
2.45 - * made subject to such option by the copyright holder.
2.46 - */
2.47 -
2.48 -package org.netbeans.modules.subversion.remote.ui.update;
2.49 -
2.50 -import java.util.*;
2.51 -import java.awt.*;
2.52 -import java.io.BufferedReader;
2.53 -import java.io.BufferedWriter;
2.54 -import java.io.FilterWriter;
2.55 -import java.io.IOException;
2.56 -import java.io.InputStreamReader;
2.57 -import java.io.OutputStreamWriter;
2.58 -import java.io.Reader;
2.59 -import java.io.Writer;
2.60 -import java.nio.charset.Charset;
2.61 -import java.util.logging.Level;
2.62 -import javax.swing.*;
2.63 -import org.netbeans.spi.diff.*;
2.64 -
2.65 -import org.openide.util.*;
2.66 -import org.openide.windows.TopComponent;
2.67 -import org.openide.filesystems.*;
2.68 -
2.69 -import org.netbeans.api.diff.*;
2.70 -import org.netbeans.api.queries.FileEncodingQuery;
2.71 -import org.netbeans.modules.subversion.remote.Subversion;
2.72 -import org.netbeans.modules.subversion.remote.api.SVNClientException;
2.73 -import org.netbeans.modules.subversion.remote.client.SvnClientExceptionHandler;
2.74 -import org.netbeans.modules.subversion.remote.client.SvnProgressSupport;
2.75 -import org.netbeans.modules.subversion.remote.ui.commit.ConflictResolvedAction;
2.76 -import org.netbeans.modules.subversion.remote.util.Context;
2.77 -import org.netbeans.modules.remotefs.versioning.api.VCSFileProxySupport;
2.78 -import org.netbeans.modules.versioning.core.api.VCSFileProxy;
2.79 -
2.80 -/**
2.81 - * Shows basic conflict resolver UI.
2.82 - *
2.83 - * This class is copy&pasted from javacvs
2.84 - *
2.85 - */
2.86 -public class ResolveConflictsExecutor extends SvnProgressSupport {
2.87 -
2.88 - private static final String TMP_PREFIX = "merge"; // NOI18N
2.89 -
2.90 - static final String CHANGE_LEFT = "<<<<<<< "; // NOI18N
2.91 - static final String CHANGE_RIGHT = ">>>>>>> "; // NOI18N
2.92 - static final String CHANGE_DELIMETER = "======="; // NOI18N
2.93 -
2.94 - static final String LOCAL_FILE_SUFFIX = ".mine"; // NOI18N
2.95 - static final String WORKING_FILE_SUFFIX = ".working"; // NOI18N
2.96 -
2.97 - private String leftFileRevision = null;
2.98 - private String rightFileRevision = null;
2.99 -
2.100 - private final VCSFileProxy file;
2.101 - private static final String NESTED_CONFLICT = "NESTED_CONFLICT"; //NOI18N
2.102 -
2.103 - public ResolveConflictsExecutor(VCSFileProxy file) {
2.104 - super(VCSFileProxySupport.getFileSystem(file));
2.105 - this.file = file;
2.106 - }
2.107 -
2.108 - public void exec() {
2.109 - assert SwingUtilities.isEventDispatchThread();
2.110 - MergeVisualizer merge = Lookup.getDefault().lookup(MergeVisualizer.class);
2.111 - if (merge == null) {
2.112 - throw new IllegalStateException("No Merge engine found."); // NOI18N
2.113 - }
2.114 -
2.115 - try {
2.116 - FileObject fo = file.toFileObject();
2.117 - if(fo == null) {
2.118 - Subversion.LOG.log(Level.WARNING, "can''t resolve conflicts for null fileobject : {0}, exists: {1}", new Object[]{file, file.exists()});
2.119 - return;
2.120 - }
2.121 - FileLock lock = fo.lock();
2.122 - boolean mergeWriterCreated = false;
2.123 - try {
2.124 - mergeWriterCreated = handleMergeFor(file, fo, lock, merge);
2.125 - } finally {
2.126 - if(!mergeWriterCreated && lock != null) {
2.127 - lock.releaseLock();
2.128 - }
2.129 - }
2.130 - } catch (FileAlreadyLockedException e) {
2.131 - SwingUtilities.invokeLater(new Runnable() {
2.132 - @Override
2.133 - public void run() {
2.134 - Set components = TopComponent.getRegistry().getOpened();
2.135 - for (Iterator i = components.iterator(); i.hasNext();) {
2.136 - TopComponent tc = (TopComponent) i.next();
2.137 - if (tc.getClientProperty(ResolveConflictsExecutor.class.getName()) != null) {
2.138 - tc.requestActive();
2.139 - }
2.140 - }
2.141 - }
2.142 - });
2.143 - } catch (IOException ioex) {
2.144 - if (NESTED_CONFLICT.equals(ioex.getMessage())) {
2.145 - JOptionPane.showMessageDialog(null, NbBundle.getMessage(ResolveConflictsExecutor.class, "MSG_NestedConflicts"),
2.146 - NbBundle.getMessage(ResolveConflictsExecutor.class, "MSG_NestedConflicts_Title"),
2.147 - JOptionPane.WARNING_MESSAGE);
2.148 - VCSFileProxySupport.openFile(file);
2.149 - } else {
2.150 - Subversion.LOG.log(Level.SEVERE, null, ioex);
2.151 - }
2.152 - }
2.153 - }
2.154 -
2.155 - private boolean handleMergeFor(final VCSFileProxy file, FileObject fo, FileLock lock,
2.156 - final MergeVisualizer merge) throws IOException {
2.157 - String mimeType = fo.getMIMEType();
2.158 - String ext = "."+fo.getExt(); // NOI18N
2.159 -
2.160 - VCSFileProxy f1 = VCSFileProxySupport.createTempFile(file, TMP_PREFIX, ext, true);
2.161 - VCSFileProxy f2 = VCSFileProxySupport.createTempFile(file, TMP_PREFIX, ext, true);
2.162 - VCSFileProxy f3 = VCSFileProxySupport.createTempFile(file, TMP_PREFIX, ext, true);
2.163 -
2.164 - Charset encoding = FileEncodingQuery.getEncoding(fo);
2.165 - final Difference[] diffs = copyParts(true, file, f1, true, encoding);
2.166 - if (diffs.length == 0) {
2.167 - try {
2.168 - ConflictResolvedAction.perform(file); // remove conflict status
2.169 - } catch (SVNClientException ex) {
2.170 - // XXX consolidate with the progresssuport
2.171 - SvnClientExceptionHandler.notifyException(new Context(file), ex, true, true);
2.172 - } finally {
2.173 - if (lock != null) {
2.174 - lock.releaseLock();
2.175 - }
2.176 - }
2.177 - return false;
2.178 - }
2.179 -
2.180 - copyParts(false, file, f2, false, encoding);
2.181 - //GraphicalMergeVisualizer merge = new GraphicalMergeVisualizer();
2.182 - String originalLeftFileRevision = leftFileRevision;
2.183 - String originalRightFileRevision = rightFileRevision;
2.184 - if (leftFileRevision != null) {
2.185 - leftFileRevision = leftFileRevision.trim();
2.186 - }
2.187 - if (rightFileRevision != null) {
2.188 - rightFileRevision = rightFileRevision.trim();
2.189 - }
2.190 - if (leftFileRevision == null || leftFileRevision.equals(LOCAL_FILE_SUFFIX) || leftFileRevision.equals(WORKING_FILE_SUFFIX)) { // NOI18N
2.191 - leftFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleWorkingFile"); // NOI18N
2.192 - } else {
2.193 - leftFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleRevision", leftFileRevision); // NOI18N
2.194 - }
2.195 - if (rightFileRevision == null || rightFileRevision.equals(LOCAL_FILE_SUFFIX) || rightFileRevision.equals(WORKING_FILE_SUFFIX)) { // NOI18N
2.196 - rightFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleWorkingFile"); // NOI18N
2.197 - } else {
2.198 - rightFileRevision = org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Diff.titleRevision", rightFileRevision); // NOI18N
2.199 - }
2.200 -
2.201 - final StreamSource s1;
2.202 - final StreamSource s2;
2.203 - VCSFileProxySupport.associateEncoding(file, f1);
2.204 - VCSFileProxySupport.associateEncoding(file, f2);
2.205 - s1 = StreamSource.createSource(file.getName(), leftFileRevision, mimeType, new BufferedReader(new InputStreamReader(f1.getInputStream(false), encoding)));
2.206 - s2 = StreamSource.createSource(file.getName(), rightFileRevision, mimeType, new BufferedReader(new InputStreamReader(f2.getInputStream(false), encoding)));
2.207 - final StreamSource result = new MergeResultWriterInfo(f1, f2, f3, file, mimeType,
2.208 - originalLeftFileRevision,
2.209 - originalRightFileRevision,
2.210 - fo, lock, encoding);
2.211 -
2.212 - try {
2.213 - Component c = merge.createView(diffs, s1, s2, result);
2.214 - if (c instanceof TopComponent) {
2.215 - ((TopComponent) c).putClientProperty(ResolveConflictsExecutor.class.getName(), Boolean.TRUE);
2.216 - }
2.217 - } catch (IOException ioex) {
2.218 - Subversion.LOG.log(Level.SEVERE, null, ioex);
2.219 - }
2.220 - return true;
2.221 - }
2.222 -
2.223 - /**
2.224 - * Copy the file and conflict parts into another file.
2.225 - */
2.226 - private Difference[] copyParts(boolean generateDiffs, VCSFileProxy source,
2.227 - VCSFileProxy dest, boolean leftPart, Charset charset) throws IOException {
2.228 - BufferedReader r = new BufferedReader(new InputStreamReader(source.getInputStream(false), charset));
2.229 - BufferedWriter w = new BufferedWriter(new OutputStreamWriter(VCSFileProxySupport.getOutputStream(dest), charset));
2.230 - ArrayList<Difference> diffList = null;
2.231 - if (generateDiffs) {
2.232 - diffList = new ArrayList<>();
2.233 - }
2.234 - try {
2.235 - String line;
2.236 - boolean isChangeLeft = false;
2.237 - boolean isChangeRight = false;
2.238 - int f1l1 = 0, f1l2 = 0, f2l1 = 0, f2l2 = 0;
2.239 - StringBuilder text1 = new StringBuilder();
2.240 - StringBuilder text2 = new StringBuilder();
2.241 - int i = 1, j = 1;
2.242 - while ((line = r.readLine()) != null) {
2.243 - int pos;
2.244 - if (line.startsWith(CHANGE_LEFT)) {
2.245 - if (isChangeLeft || isChangeRight) {
2.246 - // nested conflicts are not supported
2.247 - throw new IOException(NESTED_CONFLICT);
2.248 - }
2.249 - if (generateDiffs) {
2.250 - if (leftFileRevision == null) {
2.251 - leftFileRevision = line.substring(CHANGE_LEFT.length());
2.252 - }
2.253 - f1l1 = i;
2.254 - }
2.255 - isChangeLeft = !isChangeLeft;
2.256 - continue;
2.257 - } else if (line.startsWith(CHANGE_RIGHT)) {
2.258 - if (generateDiffs) {
2.259 - if (rightFileRevision == null) {
2.260 - rightFileRevision = line.substring(CHANGE_RIGHT.length());
2.261 - }
2.262 - if (isChangeRight) {
2.263 - f2l2 = j - 1;
2.264 - diffList.add((f1l1 > f1l2) ? new Difference(Difference.ADD,
2.265 - f1l1 - 1, 0, f2l1, f2l2,
2.266 - text1.toString(),
2.267 - text2.toString()) :
2.268 - (f2l1 > f2l2) ? new Difference(Difference.DELETE,
2.269 - f1l1, f1l2, f2l1 - 1, 0,
2.270 - text1.toString(),
2.271 - text2.toString())
2.272 - : new Difference(Difference.CHANGE,
2.273 - f1l1, f1l2, f2l1, f2l2,
2.274 - text1.toString(),
2.275 - text2.toString()));
2.276 - /*
2.277 - diffList.add(new Difference((f1l1 > f1l2) ? Difference.ADD :
2.278 - (f2l1 > f2l2) ? Difference.DELETE :
2.279 - Difference.CHANGE,
2.280 - f1l1, f1l2, f2l1, f2l2));
2.281 - */
2.282 - f1l1 = f1l2 = f2l1 = f2l2 = 0;
2.283 - text1.delete(0, text1.length());
2.284 - text2.delete(0, text2.length());
2.285 - } else {
2.286 - f2l1 = j;
2.287 - }
2.288 - }
2.289 - isChangeRight = !isChangeRight;
2.290 - continue;
2.291 - } else if (isChangeRight && line.indexOf(CHANGE_RIGHT) != -1) {
2.292 - String lineText = line.substring(0, line.lastIndexOf(CHANGE_RIGHT));
2.293 - if (generateDiffs) {
2.294 - if (rightFileRevision == null) {
2.295 - rightFileRevision = line.substring(line.lastIndexOf(CHANGE_RIGHT) + CHANGE_RIGHT.length());
2.296 - }
2.297 - text2.append(lineText);
2.298 - f2l2 = j;
2.299 - diffList.add((f1l1 > f1l2) ? new Difference(Difference.ADD,
2.300 - f1l1 - 1, 0, f2l1, f2l2,
2.301 - text1.toString(),
2.302 - text2.toString()) :
2.303 - (f2l1 > f2l2) ? new Difference(Difference.DELETE,
2.304 - f1l1, f1l2, f2l1 - 1, 0,
2.305 - text1.toString(),
2.306 - text2.toString())
2.307 - : new Difference(Difference.CHANGE,
2.308 - f1l1, f1l2, f2l1, f2l2,
2.309 - text1.toString(),
2.310 - text2.toString()));
2.311 - f1l1 = f1l2 = f2l1 = f2l2 = 0;
2.312 - text1.delete(0, text1.length());
2.313 - text2.delete(0, text2.length());
2.314 - }
2.315 - if (!leftPart) {
2.316 - w.write(lineText);
2.317 - w.newLine();
2.318 - }
2.319 - isChangeRight = !isChangeRight;
2.320 - continue;
2.321 - } else if (line.equals(CHANGE_DELIMETER)) {
2.322 - if (isChangeLeft) {
2.323 - isChangeLeft = false;
2.324 - isChangeRight = true;
2.325 - f1l2 = i - 1;
2.326 - f2l1 = j;
2.327 - continue;
2.328 - } else if (isChangeRight) {
2.329 - isChangeRight = false;
2.330 - isChangeLeft = true;
2.331 - f2l2 = j - 1;
2.332 - f1l1 = i;
2.333 - continue;
2.334 - }
2.335 - } else if (line.endsWith(CHANGE_DELIMETER) && !line.endsWith(CHANGE_DELIMETER + CHANGE_DELIMETER.charAt(0))) {
2.336 - String lineText = line.substring(0, line.length() - CHANGE_DELIMETER.length()) + "\n"; // NOI18N
2.337 - if (isChangeLeft) {
2.338 - text1.append(lineText);
2.339 - if (leftPart) {
2.340 - w.write(lineText);
2.341 - w.newLine();
2.342 - }
2.343 - isChangeLeft = false;
2.344 - isChangeRight = true;
2.345 - f1l2 = i;
2.346 - f2l1 = j;
2.347 - } else if (isChangeRight) {
2.348 - text2.append(lineText);
2.349 - if (!leftPart) {
2.350 - w.write(lineText);
2.351 - w.newLine();
2.352 - }
2.353 - isChangeRight = false;
2.354 - isChangeLeft = true;
2.355 - f2l2 = j;
2.356 - f1l1 = i;
2.357 - }
2.358 - continue;
2.359 - }
2.360 - if (!isChangeLeft && !isChangeRight || leftPart == isChangeLeft) {
2.361 - w.write(line);
2.362 - w.newLine();
2.363 - }
2.364 - if (isChangeLeft) {
2.365 - text1.append(line).append("\n"); // NOI18N
2.366 - }
2.367 - if (isChangeRight) {
2.368 - text2.append(line).append("\n"); // NOI18N
2.369 - }
2.370 - if (generateDiffs) {
2.371 - if (isChangeLeft) {
2.372 - i++;
2.373 - } else if (isChangeRight) {
2.374 - j++;
2.375 - } else {
2.376 - i++;
2.377 - j++;
2.378 - }
2.379 - }
2.380 - }
2.381 - } finally {
2.382 - try {
2.383 - r.close();
2.384 - } finally {
2.385 - w.close();
2.386 - }
2.387 - }
2.388 - if (generateDiffs) {
2.389 - return diffList.toArray(new Difference[diffList.size()]);
2.390 - } else {
2.391 - return null;
2.392 - }
2.393 - }
2.394 -
2.395 - @Override
2.396 - public void perform() {
2.397 - exec();
2.398 - }
2.399 -
2.400 - @Override
2.401 - public void run() {
2.402 - throw new RuntimeException("Not implemented"); // NOI18N
2.403 - }
2.404 -
2.405 -
2.406 - private static class MergeResultWriterInfo extends StreamSource {
2.407 -
2.408 - private final VCSFileProxy tempf1, tempf2, tempf3, outputFile;
2.409 - private VCSFileProxy fileToRepairEntriesOf;
2.410 - private final String mimeType;
2.411 - private final String leftFileRevision;
2.412 - private final String rightFileRevision;
2.413 - private FileObject fo;
2.414 - private FileLock lock;
2.415 - private final Charset encoding;
2.416 -
2.417 - public MergeResultWriterInfo(VCSFileProxy tempf1, VCSFileProxy tempf2, VCSFileProxy tempf3,
2.418 - VCSFileProxy outputFile, String mimeType,
2.419 - String leftFileRevision, String rightFileRevision,
2.420 - FileObject fo, FileLock lock, Charset encoding) {
2.421 - this.tempf1 = tempf1;
2.422 - this.tempf2 = tempf2;
2.423 - this.tempf3 = tempf3;
2.424 - this.outputFile = outputFile;
2.425 - this.mimeType = mimeType;
2.426 - this.leftFileRevision = leftFileRevision;
2.427 - this.rightFileRevision = rightFileRevision;
2.428 - this.fo = fo;
2.429 - this.lock = lock;
2.430 - if (encoding == null) {
2.431 - encoding = FileEncodingQuery.getEncoding(tempf1.toFileObject());
2.432 - }
2.433 - this.encoding = encoding;
2.434 - }
2.435 -
2.436 - @Override
2.437 - public String getName() {
2.438 - return outputFile.getName();
2.439 - }
2.440 -
2.441 - @Override
2.442 - public String getTitle() {
2.443 - return org.openide.util.NbBundle.getMessage(ResolveConflictsExecutor.class, "Merge.titleResult"); // NOI18N
2.444 - }
2.445 -
2.446 - @Override
2.447 - public String getMIMEType() {
2.448 - return mimeType;
2.449 - }
2.450 -
2.451 - @Override
2.452 - public Reader createReader() throws IOException {
2.453 - throw new IOException("No reader of merge result"); // NOI18N
2.454 - }
2.455 -
2.456 - /**
2.457 - * Create a writer, that writes to the source.
2.458 - * @param conflicts The list of conflicts remaining in the source.
2.459 - * Can be <code>null</code> if there are no conflicts.
2.460 - * @return The writer or <code>null</code>, when no writer can be created.
2.461 - */
2.462 - @Override
2.463 - public Writer createWriter(Difference[] conflicts) throws IOException {
2.464 - Writer w;
2.465 - if (fo != null) {
2.466 - w = new OutputStreamWriter(fo.getOutputStream(lock), encoding);
2.467 - } else {
2.468 - w = new OutputStreamWriter(VCSFileProxySupport.getOutputStream(outputFile), encoding);
2.469 - }
2.470 - if (conflicts == null || conflicts.length == 0) {
2.471 - fileToRepairEntriesOf = outputFile;
2.472 - return w;
2.473 - } else {
2.474 - return new MergeConflictFileWriter(w, fo, conflicts,
2.475 - leftFileRevision, rightFileRevision);
2.476 - }
2.477 - }
2.478 -
2.479 - /**
2.480 - * This method is called when the visual merging process is finished.
2.481 - * All possible writting processes are finished before this method is called.
2.482 - */
2.483 - @Override
2.484 - public void close() {
2.485 - VCSFileProxySupport.delete(tempf1);
2.486 - VCSFileProxySupport.delete(tempf2);
2.487 - VCSFileProxySupport.delete(tempf3);
2.488 - if (lock != null) {
2.489 - lock.releaseLock();
2.490 - lock = null;
2.491 - }
2.492 - fo = null;
2.493 - if (fileToRepairEntriesOf != null) {
2.494 - repairEntries(fileToRepairEntriesOf);
2.495 - fileToRepairEntriesOf = null;
2.496 - }
2.497 - }
2.498 -
2.499 - private void repairEntries(VCSFileProxy file) {
2.500 - try {
2.501 - ConflictResolvedAction.perform(file);
2.502 - } catch (SVNClientException ex) {
2.503 - // XXX consolidate with the progresssuport
2.504 - SvnClientExceptionHandler.notifyException(new Context(file), ex, true, true);
2.505 - }
2.506 - }
2.507 - }
2.508 -
2.509 - private static class MergeConflictFileWriter extends FilterWriter {
2.510 -
2.511 - private final Difference[] conflicts;
2.512 - private int lineNumber;
2.513 - private int currentConflict;
2.514 - private final String leftName;
2.515 - private final String rightName;
2.516 - private final FileObject fo;
2.517 -
2.518 - public MergeConflictFileWriter(Writer delegate, FileObject fo,
2.519 - Difference[] conflicts, String leftName,
2.520 - String rightName) throws IOException {
2.521 - super(delegate);
2.522 - this.conflicts = conflicts;
2.523 - this.leftName = leftName;
2.524 - this.rightName = rightName;
2.525 - this.lineNumber = 1;
2.526 - this.currentConflict = 0;
2.527 - if (lineNumber == conflicts[currentConflict].getFirstStart()) {
2.528 - writeConflict(conflicts[currentConflict]);
2.529 - currentConflict++;
2.530 - }
2.531 - this.fo = fo;
2.532 - }
2.533 -
2.534 - @Override
2.535 - public void write(String str) throws IOException {
2.536 - super.write(str);
2.537 - lineNumber += numChars('\n', str);
2.538 - if (currentConflict < conflicts.length && lineNumber >= conflicts[currentConflict].getFirstStart()) {
2.539 - writeConflict(conflicts[currentConflict]);
2.540 - currentConflict++;
2.541 - }
2.542 - }
2.543 -
2.544 - private void writeConflict(Difference conflict) throws IOException {
2.545 - super.write(CHANGE_LEFT + leftName + "\n"); // NOI18N
2.546 - super.write(conflict.getFirstText());
2.547 - super.write(CHANGE_DELIMETER + "\n"); // NOI18N
2.548 - super.write(conflict.getSecondText());
2.549 - super.write(CHANGE_RIGHT + rightName + "\n"); // NOI18N
2.550 - }
2.551 -
2.552 - private static int numChars(char c, String str) {
2.553 - int n = 0;
2.554 - for (int pos = str.indexOf(c); pos >= 0 && pos < str.length(); pos = str.indexOf(c, pos + 1)) {
2.555 - n++;
2.556 - }
2.557 - return n;
2.558 - }
2.559 -
2.560 - @Override
2.561 - public void close() throws IOException {
2.562 - super.close();
2.563 - if (fo != null) {
2.564 - fo.refresh(true);
2.565 - }
2.566 - }
2.567 - }
2.568 -}
2.569 -