<commit_before>package com.zachcalvert.picturescript.export.service;

import com.zachcalvert.picturescript.export.err.StepFailedException;
import com.zachcalvert.picturescript.model.File;
import com.zachcalvert.picturescript.model.FolderBase;
import com.zachcalvert.picturescript.repository.FileRepository;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class FileDeliveryService {

  private final Logger logger = LoggerFactory.getLogger(FileDeliveryService.class);

  private ExportNotificationService exportNotificationService;

  private ConflictResolutionStrategyService conflictResolutionStrategyService;

  private FileRepository fileRepository;

  @Autowired
  public FileDeliveryService(
      ExportNotificationService exportNotificationService,
      ConflictResolutionStrategyService conflictResolutionStrategyService,
      FileRepository fileRepository) {
    this.exportNotificationService = exportNotificationService;
    this.conflictResolutionStrategyService = conflictResolutionStrategyService;
    this.fileRepository = fileRepository;
  }

  @Transactional
  public void deliverFile(boolean dryRun, String shaSum, FolderBase outputFolder, String toPath) {
    logger.debug("Request received for processing sha {} to path {}", shaSum, toPath);

    File forMove = fileRepository.findFileFileForMove(shaSum, outputFolder);
    if (forMove == null) {
      executeCopy(dryRun, shaSum, outputFolder, toPath);
    } else {
      if (forMove.getPath().equalsIgnoreCase(toPath)) {
        if (!dryRun) {
          exportNotificationService.fileSkipped(shaSum);
        }
      } else {
        executeMove(dryRun, outputFolder, toPath, forMove);
      }
    }
  }

  private void executeMove(boolean dryRun, FolderBase outputFolder, String toPath, File forMove) {
    Path from = Paths.get(forMove.getPath());
    Path movedResultTo = processFileMove(dryRun, from, toPath);
    forMove.setPath(movedResultTo.toString());
    fileRepository.save(forMove);
    if (!dryRun) {
      exportNotificationService.fileMoved(from, movedResultTo, forMove, outputFolder);
    }
  }

  private void executeCopy(boolean dryRun, String shaSum, FolderBase outputFolder, String toPath) {
    File forCopy = fileRepository.findTopBySha256AndAvailableForExportIsTrue(shaSum);
    Path from = Paths.get(forCopy.getPath());
    Path copiedResultTo = processFileCopy(dryRun, from, toPath);
    File resultingFile = new File(false, forCopy.getSha256(), copiedResultTo.toString(), forCopy.getDateCreated(), forCopy.getEarliestKnownDate(), forCopy.getExtension(), outputFolder);
    fileRepository.save(resultingFile);
    if (!dryRun) {
      exportNotificationService.fileCopied(from, copiedResultTo, forCopy, resultingFile);
    }
  }

  protected Path processFileCopy(boolean isDryRun, Path from, String targetToPath) {
    Path to = conflictResolutionStrategyService.ensureNoFilePlacementConflict(Paths.get(targetToPath));
    try {
      if (!isDryRun) {
        FileUtils.copyFile(from.toFile(), to.toFile());
        logger.info("Copy performed from {} to {}", from.toString(), to.toString());
      } else {
        logger.info("Dry run, but would perform copy from {} to {}", from.toString(), to.toString());
      }
      return to;
    } catch (IOException e) {
      logger.error("Error copying file from {} to {}", from.toString(), to.toString(), e);
      throw new StepFailedException("Copy error", e);
    }
  }

  protected Path processFileMove(boolean isDryRun, Path from, String targetToPath) {<commit_msg>Adding retain attribute<commit_after>package com.zachcalvert.picturescript.export.service;

import com.zachcalvert.picturescript.export.err.StepFailedException;
import com.zachcalvert.picturescript.model.File;
import com.zachcalvert.picturescript.model.FolderBase;
import com.zachcalvert.picturescript.repository.FileRepository;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class FileDeliveryService {

  private final Logger logger = LoggerFactory.getLogger(FileDeliveryService.class);

  private ExportNotificationService exportNotificationService;

  private ConflictResolutionStrategyService conflictResolutionStrategyService;

  private FileRepository fileRepository;

  @Autowired
  public FileDeliveryService(
      ExportNotificationService exportNotificationService,
      ConflictResolutionStrategyService conflictResolutionStrategyService,
      FileRepository fileRepository) {
    this.exportNotificationService = exportNotificationService;
    this.conflictResolutionStrategyService = conflictResolutionStrategyService;
    this.fileRepository = fileRepository;
  }

  @Transactional
  public void deliverFile(boolean dryRun, String shaSum, FolderBase outputFolder, String toPath) {
    logger.debug("Request received for processing sha {} to path {}", shaSum, toPath);

    File forMove = fileRepository.findFileFileForMove(shaSum, outputFolder);
    if (forMove == null) {
      executeCopy(dryRun, shaSum, outputFolder, toPath);
    } else {
      if (forMove.getPath().equalsIgnoreCase(toPath)) {
        if (!dryRun) {
          exportNotificationService.fileSkipped(shaSum);
        }
      } else {
        executeMove(dryRun, outputFolder, toPath, forMove);
      }
    }
  }

  private void executeMove(boolean dryRun, FolderBase outputFolder, String toPath, File forMove) {
    Path from = Paths.get(forMove.getPath());
    Path movedResultTo = processFileMove(dryRun, from, toPath);
    forMove.setPath(movedResultTo.toString());
    fileRepository.save(forMove);
    if (!dryRun) {
      exportNotificationService.fileMoved(from, movedResultTo, forMove, outputFolder);
    }
  }

  private void executeCopy(boolean dryRun, String shaSum, FolderBase outputFolder, String toPath) {
    File forCopy = fileRepository.findTopBySha256AndAvailableForExportIsTrue(shaSum);
    Path from = Paths.get(forCopy.getPath());
    Path copiedResultTo = processFileCopy(dryRun, from, toPath);
    File resultingFile = new File(false, forCopy.getSha256(), copiedResultTo.toString(), forCopy.getDateCreated(), forCopy.getEarliestKnownDate(), forCopy.getExtension(), outputFolder);
    fileRepository.save(resultingFile);
    if (!dryRun) {
      exportNotificationService.fileCopied(from, copiedResultTo, forCopy, resultingFile);
    }
  }

  protected Path processFileCopy(boolean isDryRun, Path from, String targetToPath) {
    Path to = conflictResolutionStrategyService.ensureNoFilePlacementConflict(Paths.get(targetToPath));
    try {
      if (!isDryRun) {
        FileUtils.copyFile(from.toFile(), to.toFile(), true);
        logger.info("Copy performed from {} to {}", from.toString(), to.toString());
      } else {
        logger.info("Dry run, but would perform copy from {} to {}", from.toString(), to.toString());
      }
      return to;
    } catch (IOException e) {
      logger.error("Error copying file from {} to {}", from.toString(), to.toString(), e);
      throw new StepFailedException("Copy error", e);
    }
  }

  protected Path processFileMove(boolean isDryRun, Path from, String targetToPath) {
{'fraction_non_alphanumeric': 0.09807742270719667, 'fraction_numerical': 0.0020784619381657575, 'mean_word_length': 4.78003003003003, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '2775408', 'n_tokens_mistral': 2170, 'n_tokens_neox': 2118, 'n_words': 455}