<commit_before>/*
 * Copyright 2000-2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.updater;

import com.intellij.updater.Utils.OpenByteArrayOutputStream;
import ie.wombat.jbdiff.JBDiff;
import ie.wombat.jbdiff.JBPatch;

import java.io.*;
import java.util.zip.ZipOutputStream;

public abstract class BaseUpdateAction extends PatchAction {
  private final String mySource;
  private final boolean myIsMove;

  public BaseUpdateAction(Patch patch, String path, String source, long checksum, boolean move) {
    super(patch, path, checksum);
    myIsMove = move;
    mySource = source;
  }

  public BaseUpdateAction(Patch patch, DataInputStream in) throws IOException {
    super(patch, in);
    mySource = in.readUTF();
    myIsMove = in.readBoolean();
  }

  @Override
  public void write(DataOutputStream out) throws IOException {
    super.write(out);
    out.writeUTF(mySource);
    out.writeBoolean(myIsMove);
  }

  protected File getSource(File toDir) {
    return new File(toDir, mySource);
  }

  public String getSourcePath() {
    return mySource;
  }

  public boolean isMove() {
    return myIsMove;
  }

  @Override
  protected boolean doShouldApply(File toDir) {
    // if the file is optional in may not exist
    return getSource(toDir).exists();
  }

  @Override
  public void buildPatchFile(File olderDir, File newerDir, ZipOutputStream patchOutput) throws IOException {
    doBuildPatchFile(getSource(olderDir), getFile(newerDir), patchOutput);
  }

  @Override
  public ValidationResult validate(File toDir) throws IOException {
    File fromFile = getSource(toDir);
    ValidationResult result = doValidateAccess(fromFile, ValidationResult.Action.UPDATE);
    if (result != null) return result;
    if (!mySource.isEmpty()) {
      result = doValidateAccess(getFile(toDir), ValidationResult.Action.UPDATE);
      if (result != null) return result;
    }
    return doValidateNotChanged(fromFile, ValidationResult.Kind.ERROR, ValidationResult.Action.UPDATE);
  }

  @Override
  protected void doBackup(File toFile, File backupFile) throws IOException {
    Utils.mirror(toFile, backupFile);
  }

  protected void replaceUpdated(File from, File dest) throws IOException {
    // on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
    if (dest.exists() && !dest.delete()) throw new IOException("Cannot delete file " + dest);
    Utils.copy(from, dest);
  }

  @Override
  protected void doRevert(File toFile, File backupFile) throws IOException {
    if (!toFile.exists() || isModified(toFile)) {
      Utils.mirror(backupFile, toFile);
    }
  }

  protected void writeDiff(File olderFile, File newerFile, OutputStream patchOutput) throws IOException {
    try (BufferedInputStream olderFileIn = new BufferedInputStream(Utils.newFileInputStream(olderFile, myPatch.isNormalized()));
         BufferedInputStream newerFileIn = new BufferedInputStream(new FileInputStream(newerFile))) {
      writeDiff(olderFileIn, newerFileIn, patchOutput);
    }
  }

  protected void writeDiff(InputStream olderFileIn, InputStream newerFileIn, OutputStream patchOutput) throws IOException {
    Runner.logger().info("writing diff");
    ByteArrayOutputStream diffOutput = new OpenByteArrayOutputStream();
    byte[] newerFileBuffer = JBDiff.bsdiff(olderFileIn, newerFileIn, diffOutput);
    diffOutput.close();

    if (!isCritical() && diffOutput.size() < newerFileBuffer.length) {
      patchOutput.write(1);
      diffOutput.writeTo(patchOutput);
    }
    else {
      patchOutput.write(0);
      Utils.writeBytes(newerFileBuffer, newerFileBuffer.length, patchOutput);
    }
  }

  protected void applyDiff(InputStream patchInput, InputStream oldFileIn, OutputStream toFileOut) throws IOException {
    if (patchInput.read() == 1) {
      JBPatch.bspatch(oldFileIn, toFileOut, patchInput);
    }
    else {
      Utils.copyStream(patchInput, toFileOut);
    }
  }

  @Override
  public String toString() {
    String moveInfo = "";
    if (!mySource.equals(getPath())) {
      moveInfo = "[" + (myIsMove ? "= " : "~ ") + mySource + "]";
    }<commit_msg>Cleanup (patch content type constants)<commit_after>/*
 * Copyright 2000-2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.updater;

import com.intellij.updater.Utils.OpenByteArrayOutputStream;
import ie.wombat.jbdiff.JBDiff;
import ie.wombat.jbdiff.JBPatch;

import java.io.*;
import java.util.zip.ZipOutputStream;

public abstract class BaseUpdateAction extends PatchAction {
  private static final byte RAW = 0;
  private static final byte COMPRESSED = 1;

  private final String mySource;
  private final boolean myIsMove;

  public BaseUpdateAction(Patch patch, String path, String source, long checksum, boolean move) {
    super(patch, path, checksum);
    myIsMove = move;
    mySource = source;
  }

  public BaseUpdateAction(Patch patch, DataInputStream in) throws IOException {
    super(patch, in);
    mySource = in.readUTF();
    myIsMove = in.readBoolean();
  }

  @Override
  public void write(DataOutputStream out) throws IOException {
    super.write(out);
    out.writeUTF(mySource);
    out.writeBoolean(myIsMove);
  }

  protected File getSource(File toDir) {
    return new File(toDir, mySource);
  }

  public String getSourcePath() {
    return mySource;
  }

  public boolean isMove() {
    return myIsMove;
  }

  @Override
  protected boolean doShouldApply(File toDir) {
    // if the file is optional in may not exist
    return getSource(toDir).exists();
  }

  @Override
  public void buildPatchFile(File olderDir, File newerDir, ZipOutputStream patchOutput) throws IOException {
    doBuildPatchFile(getSource(olderDir), getFile(newerDir), patchOutput);
  }

  @Override
  public ValidationResult validate(File toDir) throws IOException {
    File fromFile = getSource(toDir);
    ValidationResult result = doValidateAccess(fromFile, ValidationResult.Action.UPDATE);
    if (result != null) return result;
    if (!mySource.isEmpty()) {
      result = doValidateAccess(getFile(toDir), ValidationResult.Action.UPDATE);
      if (result != null) return result;
    }
    return doValidateNotChanged(fromFile, ValidationResult.Kind.ERROR, ValidationResult.Action.UPDATE);
  }

  @Override
  protected void doBackup(File toFile, File backupFile) throws IOException {
    Utils.mirror(toFile, backupFile);
  }

  protected void replaceUpdated(File from, File dest) throws IOException {
    // on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
    if (dest.exists() && !dest.delete()) throw new IOException("Cannot delete file " + dest);
    Utils.copy(from, dest);
  }

  @Override
  protected void doRevert(File toFile, File backupFile) throws IOException {
    if (!toFile.exists() || isModified(toFile)) {
      Utils.mirror(backupFile, toFile);
    }
  }

  protected void writeDiff(File olderFile, File newerFile, OutputStream patchOutput) throws IOException {
    try (BufferedInputStream olderFileIn = new BufferedInputStream(Utils.newFileInputStream(olderFile, myPatch.isNormalized()));
         BufferedInputStream newerFileIn = new BufferedInputStream(new FileInputStream(newerFile))) {
      writeDiff(olderFileIn, newerFileIn, patchOutput);
    }
  }

  protected void writeDiff(InputStream olderFileIn, InputStream newerFileIn, OutputStream patchOutput) throws IOException {
    Runner.logger().info("writing diff");
    ByteArrayOutputStream diffOutput = new OpenByteArrayOutputStream();
    byte[] newerFileBuffer = JBDiff.bsdiff(olderFileIn, newerFileIn, diffOutput);
    diffOutput.close();

    if (!isCritical() && diffOutput.size() < newerFileBuffer.length) {
      patchOutput.write(COMPRESSED);
      diffOutput.writeTo(patchOutput);
    }
    else {
      patchOutput.write(RAW);
      Utils.writeBytes(newerFileBuffer, newerFileBuffer.length, patchOutput);
    }
  }

  protected void applyDiff(InputStream patchInput, InputStream oldFileIn, OutputStream toFileOut) throws IOException {
    int type = patchInput.read();
    if (type == COMPRESSED) {
      JBPatch.bspatch(oldFileIn, toFileOut, patchInput);
    }
    else if (type == RAW) {
      Utils.copyStream(patchInput, toFileOut);
    }
    else {
      throw new IOException("Corrupted patch");
    }
  }

  @Override
  public String toString() {
    String moveInfo = "";
    if (!mySource.equals(getPath())) {
      moveInfo = "[" + (myIsMove ? "= " : "~ ") + mySource + "]";
    }
{'fraction_non_alphanumeric': 0.09734974958263773, 'fraction_numerical': 0.0030258764607679466, 'mean_word_length': 4.031496062992126, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3015150', 'n_tokens_mistral': 2766, 'n_tokens_neox': 2681, 'n_words': 795}