private function exitIfError(\Result\Result $result) { if ($result->isErr()) { echo sprintf("ERROR: %s\n", $result->getErr()); exit(1); } }
public static function fromFile($path) { if (!is_file($path)) { return \Result\Result::err('file not found'); } return self::fromString(file_get_contents($path)); }
public static function find($cwd) { $path = $cwd; while (dirname($path) !== $path) { if (is_file($path . '/whippet.json')) { return \Result\Result::ok(new self($path)); } $path = dirname($path); } return \Result\Result::err('whippet.json not found'); }
public function testMigrate() { $dir = $this->getDir(); file_put_contents($dir . '/plugins', implode("\n", ['source = "git@git.dxw.net:wordpress-plugins/"', 'twitget=', 'acf-options-page=', 'new-members-only=', 'wordpress-importer=', 'page-links-to=', 'akismet=', 'acf-repeater=', 'advanced-custom-fields=', 'theme-my-login='******'breadcrumb-navxt=', 'contact-form-7=', 'wp-realtime-sitemap=', 'tinymce-advanced=', 'relevanssi-premium=', 'jw-player-plugin-for-wordpress=', 'gravityforms=', 'unconfirmed=', 'oauth2-server = ,git@git.dxw.net:dxw-wp-plugins/oauth2-server', 'network-approve-users = v1.1.1,git@git.dxw.net:dxw-wp-plugins/network-approve-users'])); $whippetJson = $this->getWhippetJsonExpectSavePath($dir . '/whippet.json'); $this->addFactoryNewInstance('\\Dxw\\Whippet\\Files\\WhippetJson', ['src' => ['plugins' => 'git@git.dxw.net:wordpress-plugins/'], 'plugins' => [['name' => 'twitget'], ['name' => 'acf-options-page'], ['name' => 'new-members-only'], ['name' => 'wordpress-importer'], ['name' => 'page-links-to'], ['name' => 'akismet'], ['name' => 'acf-repeater'], ['name' => 'advanced-custom-fields'], ['name' => 'theme-my-login'], ['name' => 'breadcrumb-navxt'], ['name' => 'contact-form-7'], ['name' => 'wp-realtime-sitemap'], ['name' => 'tinymce-advanced'], ['name' => 'relevanssi-premium'], ['name' => 'jw-player-plugin-for-wordpress'], ['name' => 'gravityforms'], ['name' => 'unconfirmed'], ['name' => 'oauth2-server', 'src' => 'git@git.dxw.net:dxw-wp-plugins/oauth2-server'], ['name' => 'network-approve-users', 'ref' => 'v1.1.1', 'src' => 'git@git.dxw.net:dxw-wp-plugins/network-approve-users']]], $whippetJson); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@git.dxw.net:wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@git.dxw.net:wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); $migration = new \Dxw\Whippet\Dependencies\Migration($this->getFactory(), $this->getProjectDirectory($dir)); ob_start(); $result = $migration->migrate(); $output = ob_get_clean(); $this->assertFalse($result->isErr()); $this->assertEquals('', $output); }
private function installDependency($type, $dep) { $path = $this->dir . '/wp-content/' . $type . '/' . $dep['name']; $git = $this->factory->newInstance('\\Dxw\\Whippet\\Git\\Git', $path); if (!$git->is_repo()) { echo sprintf("[Adding %s/%s]\n", $type, $dep['name']); $result = $git->clone_repo($dep['src']); if ($result === false) { return \Result\Result::err('could not clone repository'); } } else { echo sprintf("[Checking %s/%s]\n", $type, $dep['name']); } $result = $git->checkout($dep['revision']); if ($result === false) { return \Result\Result::err('could not checkout revision'); } return \Result\Result::ok(); }
public function install($internal = false) { $this->deprecationNotice($internal); $this->whippet_init(); $this->load_plugins_manifest(); $this->load_plugins_lock(); if (count(get_object_vars($this->plugins_manifest)) == 0) { echo "The plugin manifest file is empty\n"; } // // If there is no lock file: // // 1. Install everything from the manifest // 2. Update the lockfile // if (!$this->plugins_lock_file) { foreach ($this->plugins_manifest as $dir => $plugin) { $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); // Is the repo there already? if (!$git->is_repo()) { echo "[Adding {$dir}] "; // We don't have the repo. Clone it. if (!$git->clone_repo($plugin->repository)) { echo "Aborting...\n"; die; } } // Make sure repo is up to date. echo "[Checking {$dir}] "; if (!$git->checkout($plugin->revision)) { echo "Aborting...\n"; die; } $git->checkout($git->current_commit()); if (!$git->submodule_update()) { echo "Aborting...\n"; die; } } } else { // // If there is a lock file: // // 1. Compare the lockfile to the manifest. Delete any plugins that have been removed. // 2. Check that the installed plugins are on the lockfile commit. Checkout the correct commit if not. // 3. Compare the lockfile to the manifest. Clone any plugins that have been added. // 4. Update the lockfile with the new list of commits. // // 1. Compare the lockfile to the manifest. Delete any plugins that have been removed. // // Make sure every entry in the lockfile also appears in the manifest $plugins_to_delete = array_keys((array) $this->plugins_locked); foreach ($this->plugins_locked as $lock_dir => $lock_plugin) { foreach ($this->plugins_manifest as $manifest_dir => $manifest_plugin) { if ($lock_dir == $manifest_dir) { unset($plugins_to_delete[array_search($lock_dir, $plugins_to_delete)]); } } } // Delete the ones that don't: $gitignore = new \Dxw\Whippet\Git\Gitignore($this->project_dir); $ignores = $gitignore->get_ignores(); foreach ($plugins_to_delete as $dir) { echo "[Removing {$dir}]\n"; $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); $git->delete_repo(); // remove from ignores: $plugin_dir = "/wp-content/plugins/{$dir}\n"; if (($index = array_search($plugin_dir, $ignores)) !== false) { unset($ignores[$index]); } // Remove from the lockfile unset($this->plugins_locked->{$dir}); } $gitignore->save_ignores($ignores); // // 2. Check that the installed plugins are on the lockfile commit. Checkout the correct commit if not. // foreach ($this->plugins_locked as $dir => $plugin) { $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); if (!$git->is_repo()) { // The repo has gone missing. Let's add it back. echo "[Adding {$dir}] "; $git->clone_repo($plugin->repository); } if ($this->plugins_manifest->{$dir}->repository != $plugin->repository) { // The remote has changed. Zap the plugin and add it again. $git->delete_repo(); // The repo should be re-added below when we add new plugins continue; } // Check out a new revision, or if no new revision, check the existing one out again (in case of naughty changes) if ($this->plugins_manifest->{$dir}->revision == $plugin->revision) { echo "[Checking {$dir}] "; $git->checkout($plugin->commit); } else { echo "[Updating {$dir}] "; $git->checkout($this->plugins_manifest->{$dir}->revision); } if (!$git->submodule_update()) { echo "Aborting...\n"; die; } } // // 3. Compare the lockfile to the manifest. Clone any plugins that have been added. // // Make sure every entry in the lockfile also appears in the manifest $plugins_to_clone = array_keys((array) $this->plugins_manifest); foreach ($this->plugins_manifest as $manifest_dir => $manifest_plugin) { foreach ($this->plugins_locked as $lock_dir => $lock_plugin) { if ($lock_dir == $manifest_dir && $manifest_plugin->repository == $lock_plugin->repository) { unset($plugins_to_clone[array_search($manifest_dir, $plugins_to_clone)]); } } } foreach ($plugins_to_clone as $dir) { $plugin = $this->plugins_manifest->{$dir}; echo "[Adding {$dir}] "; $git = new \Dxw\Whippet\Git\Git("{$this->plugin_dir}/{$dir}"); // Is the repo there already? if (!$git->is_repo()) { // We don't have the repo. Clone it. if (!$git->clone_repo($plugin->repository)) { echo "Aborting...\n"; die; } } // Make sure repo is up to date. if (!$git->checkout($plugin->revision)) { echo "Aborting...\n"; die; } if (!$git->submodule_update()) { echo "Aborting...\n"; die; } } } // // Update the lockfile // $this->update_plugins_lock(); // // Make sure that Whippet-managed plugins are gitignored // $gitignore = new \Dxw\Whippet\Git\Gitignore($this->project_dir); $ignores = $gitignore->get_ignores(); foreach ($this->plugins_locked as $dir => $plugin) { $plugin_dir = "/wp-content/plugins/{$dir}\n"; if (array_search($plugin_dir, $ignores) === false) { $ignores[] = $plugin_dir; } } $gitignore->save_ignores($ignores); echo "Completed successfully\n"; return \Result\Result::ok(); }
public function testUpdateWithBrokenJson() { $dir = $this->getDir(); $whippetJson = $this->getWhippetJson(['src' => ['plugins' => 'git@git.dxw.net:wordpress-plugins/'], 'themes' => [['name' => 'my-theme', 'ref' => 'v1.4']], 'plugins' => [['name' => 'my-plugin', 'ref' => 'v1.6']]]); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetJson', 'fromFile', $dir . '/whippet.json', \Result\Result::ok($whippetJson)); file_put_contents($dir . '/whippet.json', 'foobar'); $gitignore = $this->getGitignore([], ["/wp-content/themes/my-theme\n", "/wp-content/plugins/my-plugin\n"], false, false); $this->addFactoryNewInstance('\\Dxw\\Whippet\\Git\\Gitignore', $dir, $gitignore); $whippetLock = $this->getWhippetLockWritable([], sha1('foobar'), null, []); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir . '/whippet.lock', \Result\Result::ok($whippetLock)); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@git.dxw.net:wordpress-themes/my-theme', 'v1.4', \Result\Result::ok('27ba906')); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', 'git@git.dxw.net:wordpress-plugins/my-plugin', 'v1.6', \Result\Result::ok('d961c3d')); $dependencies = new \Dxw\Whippet\Dependencies\Updater($this->getFactory(), $this->getProjectDirectory($dir)); ob_start(); $result = $dependencies->update(); $output = ob_get_clean(); $this->assertTrue($result->isErr()); $this->assertEquals('missing sources', $result->getErr()); $this->assertEquals("[Updating themes/my-theme]\n", $output); }
public static function ls_remote($repo, $ref) { exec(sprintf('git ls-remote %s %s', escapeshellarg($repo), escapeshellarg($ref)), $output, $return); if ($return !== 0) { return \Result\Result::err('git error'); } if (count($output) === 0) { return \Result\Result::err('ref not found'); } return \Result\Result::ok(explode("\t", $output[0])[0]); }
public function testInstallBlankLockfile() { $dir = $this->getDir(); file_put_contents($dir . '/whippet.json', 'foobar'); file_put_contents($dir . '/whippet.lock', 'foobar'); $whippetLock = $this->getWhippetLock(sha1('foobar'), ['themes' => [], 'plugins' => []]); $this->addFactoryCallStatic('\\Dxw\\Whippet\\Files\\WhippetLock', 'fromFile', $dir . '/whippet.lock', \Result\Result::ok($whippetLock)); $dependencies = new \Dxw\Whippet\Dependencies\Installer($this->getFactory(), $this->getProjectDirectory($dir)); ob_start(); $result = $dependencies->install(); $output = ob_get_clean(); $this->assertFalse($result->isErr()); $this->assertEquals("whippet.lock contains nothing to install\n", $output); }
<?php use Result\Result as R; require __DIR__ . "/vendor/autoload.php"; $divide = function ($a, $b) { if ($b === 0 || $b === 0.0) { return R::err("division_by_zero"); } return R::ok($a / $b); }; $calculateSomething = function ($a, $b, $c) use($divide) { $errMapper = function ($err) { return "calculation_error"; }; // $x now has a value of expression ($a / $b) // meaning Result returned from divide was already unwrapped for you $x = (yield $divide($a, $b)); // you can also remap errors if it's needed $x = (yield $divide($x, $c)->remapErr($errMapper)); (yield R::ok($x + 42)); }; $res = R::reduce($calculateSomething(1, 2, 3)); var_dump($res); $res = R::reduce($calculateSomething(1, 0, 1)); var_dump($res); $res = R::reduce($calculateSomething(1, 2, 0)); var_dump($res); // the error was remapped, now it will be "calculation_error"
public function testRemapErr() { $ok = Result::ok("asd"); $this->assertSame($ok, $ok->remapErr(function ($er) { return "err"; })); $err = Result::err("fooerr"); $mapped = $err->remapErr(function ($er) { return ["bar"]; }); $this->assertSame("fooerr", $err->getErr()); $this->assertSame(["bar"], $mapped->getErr()); }
private function addDependencyToLockfile($type, array $dep) { if (isset($dep['src'])) { $src = $dep['src']; } else { $sources = $this->jsonFile->getSources(); if (!isset($sources[$type])) { return \Result\Result::err('missing sources'); } $src = $sources[$type] . $dep['name']; } $ref = 'master'; if (isset($dep['ref'])) { $ref = $dep['ref']; } $commitResult = $this->factory->callStatic('\\Dxw\\Whippet\\Git\\Git', 'ls_remote', $src, $ref); if ($commitResult->isErr()) { return \Result\Result::err(sprintf('git command failed: %s', $commitResult->getErr())); } $this->lockFile->addDependency($type, $dep['name'], $src, $commitResult->unwrap()); return \Result\Result::ok(); }
private function parsePluginsFile($raw_file) { // Check for #-comments $lines = explode("\n", $raw_file); foreach ($lines as $line) { if (preg_match('/^\\s*#/', $line)) { return \Result\Result::err('Comments beginning with # are not permitted'); } } $plugins = parse_ini_string($raw_file); if (!is_array($plugins)) { return \Result\Result::err('Unable to parse Plugins file'); } // Got plugins - turn names to sources $source = $append = ''; $plugins_manifest = new \stdClass(); foreach ($plugins as $plugin => $data) { // // Special lines // if ($plugin == 'source') { if (empty($data)) { return \Result\Result::err("Source is empty. It should just specify a repo root:\n\n source = 'git@git.dxw.net:wordpress-plugins/'\n\nWhippet will attempt to find a source for your plugins by appending the plugin name to this URL."); } $source = $data; continue; } if ($plugin == 'append') { $append = $data; continue; } $repository = $revision = ''; // // Everything else should be a plugin // // First see if there is data. if (!empty($data)) { // Format: LABEL[, REPO] if (strpos($data, ',') !== false) { list($revision, $repository) = explode(',', $data); } else { $revision = $data; } } // if (empty($repository)) { // $repository = "{$source}{$plugin}{$append}"; // } if (empty($revision)) { $revision = 'master'; } // We should now have repo and revision $plugins_manifest->{$plugin} = new \stdClass(); $plugins_manifest->{$plugin}->repository = $repository; $plugins_manifest->{$plugin}->revision = $revision; } return \Result\Result::ok(['source' => $source, 'plugins' => $plugins_manifest]); }