Donation 5: ResolveConflictsExecutor.java is copied and pasted from javacvs donation_review
authorGeertjan Wielenga <geertjan@netbeans.org>
Mon, 04 Nov 2019 14:40:13 +0100
branchdonation_review
changeset 316661362cecd22c74
parent 316660 21ef2a85a12f
child 316662 42167435c72e
Donation 5: ResolveConflictsExecutor.java is copied and pasted from javacvs
mercurial.remote/src/org/netbeans/modules/mercurial/remote/ui/update/ResolveConflictsExecutor.java
subversion.remote/src/org/netbeans/modules/subversion/remote/ui/update/ResolveConflictsExecutor.java
     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 -