private FileAction doMerge()

in vault-vlt/src/main/java/org/apache/jackrabbit/vault/vlt/VltFile.java [662:771]


    private FileAction doMerge(VaultFile remoteFile, FileAction action)
            throws VltException {
        if (remoteFile.isDirectory()) {
            throw exception("Error while merging. remote is a directory.", null);
        }
        // abort merger if actions is already conflict
        if (action == FileAction.CONFLICTED) {
            return action;
        }
        MetaFile baseFile = getBaseFile(false);
        MetaFile tmpFile = getTmpFile();

        VltEntryInfo base = entry.base();
        VltEntryInfo work = entry.work();
        byte[] lineFeed = MimeTypes.isBinary(remoteFile.getContentType())
                ? null
                : LineOutputStream.LS_NATIVE;

        // get the remote file
        VaultFileCopy copy = null;
        boolean remoteUpdated = true;
        try {
            // first check size and last modified
            if (!base.checkModified(remoteFile)) {
                remoteUpdated = false;
            } else {
                File temp = tmpFile.openTempFile();
                copy = VaultFileCopy.copy(remoteFile, temp, lineFeed);
                // if tmp is equal to the base one, there was no update on the server
                if (copy.getMd5().equals(base.getMd5())) {
                    tmpFile.closeTempFile(tmpFile.length() >= 0);
                    remoteUpdated = false;
                } else {
                    tmpFile.closeTempFile(false);
                }
            }
        } catch (IOException e) {
            throw exception("Error while copying files.", e);
        }
        if (!remoteUpdated) {
            if (work.getMd5().equals(base.getMd5())) {
                // fix base
                base.setSize(work.getSize());
                base.setDate(work.getDate());
                return FileAction.VOID;
            } else if (remoteFile.lastModified() > 0) {
                // normal modification provided
                return action;
            }
        }

        try {
            // check if binary
            boolean remoteBT = getRemoteBinaryType(remoteFile, copy);
            boolean localBT = MimeTypes.isBinary(base.getContentType());
            if (remoteBT || localBT) {
                parent.getContext().printMessage(this, "can't merge. binary content");
                entry.conflict(file, baseFile, tmpFile);
                return FileAction.CONFLICTED;
            }

            DocumentDiff3 diff;
            // do a 3-way diff between the base, the local and the remote one.
            // we currently do not use document sources, since we don't really have
            // a label to provide (like rev. num, etc).
            try (Reader r0 = baseFile.getReader();
                 Reader r1 = tmpFile.getReader()) {
                Document baseDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(baseFile), r0, false));
                Document leftDoc = new Document(null, LineElementsFactory.create(new FileDocumentSource(file), false, Constants.ENCODING));
                Document rightDoc = new Document(null, LineElementsFactory.create(new MetaFileDocSource(tmpFile), r1, false));
                diff = baseDoc.diff3(leftDoc, rightDoc);
            }

            // save the diff output
            try (Writer out = new OutputStreamWriter(FileUtils.openOutputStream(file), Constants.ENCODING)) {
                diff.write(new DiffWriter(out), false);
            }

            if (diff.hasConflicts()) {
                entry.conflict(file, baseFile, tmpFile);
                action = FileAction.CONFLICTED;
            } else {
                // make the tmp file the new base
                tmpFile.moveTo(baseFile);
                base.update(baseFile, true);
                action = FileAction.MERGED;
            }

            // and update the 'work'
            // check if MD5 changes and change action accordingly
            MD5 oldMd5 = work.getMd5();
            work.update(file, true);
            if (oldMd5.equals(work.getMd5())) {
                action = FileAction.VOID;
            }
            // check if remote file provided a last modified
            if (remoteFile.lastModified() == 0) {
                if (work.getMd5().equals(base.getMd5())) {
                    base.setDate(work.getDate());
                } else {
                    base.setDate(System.currentTimeMillis());
                }
            }

        } catch (IOException e) {
            throw exception("Error during merge operation.", e);
        }

        return action;
    }