protected function copyFile(Repo $repo, $file, $destination)
    {
        $data = $repo->getBlob($file->sha);

        if (isset($data->content)) {
            $handle = fopen($destination, 'w');

            fwrite($handle, base64_decode($data->content));

            fclose($handle);
        }
    }
    public function install(Repo $repo, $addonName, $addonPath = null, $themePath = null, $addFolder = null)
    {
        $filePath = $this->tempPath.$repo->getSha().'.zip';

        if ( ! file_exists($filePath)) {
            $handle = fopen($filePath, 'w');

            fwrite($handle, $repo->getZipball());

            fclose($handle);

            $this->unzip($filePath);
        }

        //this is how github names the zipball, usually
        $shortSha = substr($repo->getSha(), 0, 7);

        $tempDir = $repo->getUser().'-'.$repo->getRepo().'-'.$shortSha;

        $files = array();

        //the sha numbering is off, else is a somewhat messy fallback
        if (! is_dir($this->tempPath.$tempDir)) {
            $tempDir = null;

            $iterator = new \DirectoryIterator($this->tempPath);

            foreach ($iterator as $file) {
                // does it start with this user/repo combo?
                if (! $file->isDot() && $file->isDir() && preg_match('/^'.preg_quote($repo->getUser()).'-'.preg_quote($repo->getRepo()).'-/', $file->getBasename())) {
                    $tempDir = $file->getBasename();
                    break;
                }
            }
        }

        if (is_null($tempDir)) {
            throw new \Exception(sprintf('Could not find unzipped contents for %s/%s in %s', $repo->getUser(), $repo->getRepo(), $this->tempPath));
        }

        $this->tempDir = $tempDir;

        parent::install($repo, $addonName, $addonPath, $themePath, $addFolder);

        unlink($this->tempPath.$repo->getSha().'.zip');
    }
    public function install(Repo $repo, $addonName, $addonPath = null, $themePath = null, $addFolder = false)
    {
        foreach ($repo->getFiles() as $file) {
            $path = $this->thirdPartyPath;

            $destination = $file->path;

            $proceed = false;

            if ($addonPath) {
                if (strncmp($destination, $addonPath, strlen($addonPath)) === 0) {
                    $proceed = true;

                    $destination = str_replace($addonPath, '', $destination);

                    if ($addFolder) {
                        $destination = is_bool($addFolder) ? $addonName.'/'.$destination : $addFolder.'/'.$destination;
                    }
                }
            }

            if ($proceed === false && $themePath) {
                if (strncmp($destination, $themePath, strlen($themePath)) === 0) {
                    $proceed = true;

                    $destination = str_replace($themePath, '', $destination);

                    $path = $this->themePath;
                }
            }

            if (! $addonPath && $proceed === false && ! $repo->isFileIgnored($destination)) {
                $proceed = true;

                if ($addFolder) {
                    $destination = is_bool($addFolder) ? $addonName.'/'.$destination : $addFolder.'/'.$destination;
                }
            }

            if ($proceed === false) {
                continue;
            }

            if (strpos($destination, '/') !== false) {
                $path = realpath($path);

                $dirs = explode('/', $destination);

                $path .= '/';

                $destination = array_pop($dirs);

                foreach ($dirs as $dir) {
                    if (! is_dir($path.$dir)) {
                        @mkdir($path.$dir, 0777);
                    }

                    $path .= $dir.'/';
                }
            }

            $destination = $path.$destination;

            if (! is_writable($path) || (file_exists($destination) && ! is_writable($destination))) {
                throw new \Exception(sprintf('Cannot write file %s', $destination));
            }

            $this->copyFile($repo, $file, $destination);
        }
    }