<commit_before><?php

namespace Robo\Task\Archive;

use Robo\Result;
use Robo\Task\BaseTask;

/**
 * Extracts an archive.
 *
 * Note that often, distributions are packaged in tar or zip archives
 * where the topmost folder may contain variable information, such as
 * the release date, or the version of the package.  This information
 * is very useful when unpacking by hand, but arbitrarily-named directories
 * are much less useful to scripts.  Therefore, by default, Extract will
 * remove the top-level directory, and instead store all extracted files
 * into the directory specified by $archivePath.
 *
 * To keep the top-level directory when extracting, use
 * `preserveTopDirectory(true)`.
 *
 * ``` php
 * <?php
 * $this->taskExtract($archivePath)
 *  ->to($destination)
 *  ->preserveTopDirectory(false) // the default
 *  ->run();
 * ?>
 * ```
 *
 * @method to(string) location to store extracted files
 */
class Extract extends BaseTask
{
    use \Robo\Common\Timer;

    protected $filename;
    protected $to;
    private $preserveTopDirectory = false;

    public function __construct($filename)
    {
        $this->filename = $filename;
    }

    public function to($to)
    {
        $this->to = $to;
        return $this;
    }

    public function preserveTopDirectory($preserve = true)
    {
        $this->preserveTopDirectory = $preserve;
        return $this;
    }

    public function run()
    {
        if (!file_exists($this->filename)) {
            $this->printTaskError("File {filename} does not exist", ['filename' => $this->filename]);

            return false;
        }
        if (!($mimetype = static::archiveType($this->filename))) {
            $this->printTaskError("Could not determine type of archive for {filename}", ['filename' => $this->filename]);

            return false;
        }

        // We will first extract to $extractLocation and then move to $this->to
        $extractLocation = static::getTmpDir();
        @mkdir($extractLocation);
        @mkdir(dirname($this->to));

        $this->startTimer();

        $this->printTaskInfo("Extracting {filename}", ['filename' => $this->filename]);
        // Perform the extraction of a zip file.
        if (($mimetype == 'application/zip') || ($mimetype == 'application/x-zip')) {
            $result = $this->extractZip($extractLocation);
        } else {
            // Otherwise we have a possibly-compressed Tar file.
            $result = $this->extractTar($extractLocation);
        }
        if ($result->wasSuccessful()) {
            $this->printTaskInfo("{filename} extracted", ['filename' => $this->filename]);
            // Now, we want to move the extracted files to $this->to. There
            // are two possibilities that we must consider:
            //
            // (1) Archived files were encapsulated in a folder with an arbitrary name
            // (2) There was no encapsulating folder, and all the files in the archive
            //     were extracted into $extractLocation
            //
            // In the case of (1), we want to move and rename the encapsulating folder
            // to $this->to.
            //
            // In the case of (2), we will just move and rename $extractLocation.
            $filesInExtractLocation = glob("$extractLocation/*");
            $hasEncapsulatingFolder = ((count($filesInExtractLocation) == 1) && is_dir($filesInExtractLocation[0]));
            if ($hasEncapsulatingFolder && !$this->preserveTopDirectory) {
                rename($filesInExtractLocation[0], $this->to);
                rmdir($extractLocation);
            } else {
                rename($extractLocation, $this->to);
            }
            if ($hasEncapsulatingFolder && !$this->preserveTopDirectory) {
                $result = $this->task('FilesystemStack')->rename($filesInExtractLocation[0], $this->to)->run();
                @rmdir($extractLocation);
            } else {
                $result = $this->task('FilesystemStack')->rename($extractLocation, $this->to)->run();
            }
        }
        $this->stopTimer();
        $result['time'] = $this->getExecutionTime();

        return $result;
    }

    protected function extractZip($extractLocation)
    {
        if (!extension_loaded('zlib')) {
            return Result::errorMissingExtension($this, 'zlib', 'zip extracting');
        }

        $zip = new \ZipArchive();
        if (($status = $zip->open($this->filename)) !== true) {
            return Result::error($this, "Could not open zip archive {$this->filename}");
        }
        if (!$zip->extractTo($extractLocation)) {<commit_msg>Remove duplicate code in Extract task, and use task('DeleteDir') to clean up after the rename.<commit_after><?php

namespace Robo\Task\Archive;

use Robo\Result;
use Robo\Task\BaseTask;

/**
 * Extracts an archive.
 *
 * Note that often, distributions are packaged in tar or zip archives
 * where the topmost folder may contain variable information, such as
 * the release date, or the version of the package.  This information
 * is very useful when unpacking by hand, but arbitrarily-named directories
 * are much less useful to scripts.  Therefore, by default, Extract will
 * remove the top-level directory, and instead store all extracted files
 * into the directory specified by $archivePath.
 *
 * To keep the top-level directory when extracting, use
 * `preserveTopDirectory(true)`.
 *
 * ``` php
 * <?php
 * $this->taskExtract($archivePath)
 *  ->to($destination)
 *  ->preserveTopDirectory(false) // the default
 *  ->run();
 * ?>
 * ```
 *
 * @method to(string) location to store extracted files
 */
class Extract extends BaseTask
{
    use \Robo\Common\Timer;

    protected $filename;
    protected $to;
    private $preserveTopDirectory = false;

    public function __construct($filename)
    {
        $this->filename = $filename;
    }

    public function to($to)
    {
        $this->to = $to;
        return $this;
    }

    public function preserveTopDirectory($preserve = true)
    {
        $this->preserveTopDirectory = $preserve;
        return $this;
    }

    public function run()
    {
        if (!file_exists($this->filename)) {
            $this->printTaskError("File {filename} does not exist", ['filename' => $this->filename]);

            return false;
        }
        if (!($mimetype = static::archiveType($this->filename))) {
            $this->printTaskError("Could not determine type of archive for {filename}", ['filename' => $this->filename]);

            return false;
        }

        // We will first extract to $extractLocation and then move to $this->to
        $extractLocation = static::getTmpDir();
        @mkdir($extractLocation);
        @mkdir(dirname($this->to));

        $this->startTimer();

        $this->printTaskInfo("Extracting {filename}", ['filename' => $this->filename]);
        // Perform the extraction of a zip file.
        if (($mimetype == 'application/zip') || ($mimetype == 'application/x-zip')) {
            $result = $this->extractZip($extractLocation);
        } else {
            // Otherwise we have a possibly-compressed Tar file.
            $result = $this->extractTar($extractLocation);
        }
        if ($result->wasSuccessful()) {
            $this->printTaskInfo("{filename} extracted", ['filename' => $this->filename]);
            // Now, we want to move the extracted files to $this->to. There
            // are two possibilities that we must consider:
            //
            // (1) Archived files were encapsulated in a folder with an arbitrary name
            // (2) There was no encapsulating folder, and all the files in the archive
            //     were extracted into $extractLocation
            //
            // In the case of (1), we want to move and rename the encapsulating folder
            // to $this->to.
            //
            // In the case of (2), we will just move and rename $extractLocation.
            $filesInExtractLocation = glob("$extractLocation/*");
            $hasEncapsulatingFolder = ((count($filesInExtractLocation) == 1) && is_dir($filesInExtractLocation[0]));
            if ($hasEncapsulatingFolder && !$this->preserveTopDirectory) {
                $result = $this->task('FilesystemStack')->rename($filesInExtractLocation[0], $this->to)->run();
                $this->task('DeleteDir', $extractLocation)->run();
            } else {
                $result = $this->task('FilesystemStack')->rename($extractLocation, $this->to)->run();
            }
        }
        $this->stopTimer();
        $result['time'] = $this->getExecutionTime();

        return $result;
    }

    protected function extractZip($extractLocation)
    {
        if (!extension_loaded('zlib')) {
            return Result::errorMissingExtension($this, 'zlib', 'zip extracting');
        }

        $zip = new \ZipArchive();
        if (($status = $zip->open($this->filename)) !== true) {
            return Result::error($this, "Could not open zip archive {$this->filename}");
        }
        if (!$zip->extractTo($extractLocation)) {
{'fraction_non_alphanumeric': 0.13438909050918288, 'fraction_numerical': 0.001649620587264929, 'mean_word_length': 2.4525436598329535, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 98, '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': '1049963', 'n_tokens_mistral': 2441, 'n_tokens_neox': 2358, 'n_words': 702}