/**
  * Execute this action
  *
  * @param  string[] $args command line args
  * @return int exit code
  */
 public function perform($args)
 {
     if (empty($args)) {
         Console::$err->writeLine('*** Missing argument #1: Module name');
         return 2;
     }
     sscanf($args[0], '%[^@]@%s', $name, $version);
     $module = Module::valueOf($name);
     $cwd = new Folder('.');
     $vendor = new FileCollection(new Folder($cwd, $module->vendor));
     $versions = new FilteredIOCollectionIterator($vendor, new NameMatchesFilter('#^' . $module->name . '@.+#'));
     if (null === $version) {
         // No version given: Remove all installed modules, and the module reference
         if (!$vendor->findElement($module->name . '.json')) {
             Console::writeLine($module, ' not installed');
             return 1;
         }
         $this->removeAll($cwd, $versions);
         Console::writeLine('Removing module reference');
         $vendor->removeElement($module->name . '.json');
     } else {
         // Specific version given: Remove this version, if it's the last one, the
         // module reference, if not, select next possible one.
         if (!($coll = $vendor->findCollection($module->name . '@' . $version))) {
             Console::writeLine($module, ' not installed in version ', $version);
             return 1;
         }
         $active = $this->remove($cwd, $coll);
         if ($versions->hasNext()) {
             if ($active) {
                 $next = $versions->next();
                 $pth = new File('.' . $module->vendor . '.' . basename($next->getURI()) . '.pth');
                 $out = $pth->getOutputStream();
                 $base = strtr(substr($next->getURI(), strlen($cwd->getURI())), DIRECTORY_SEPARATOR, '/');
                 Console::writeLine('Select ', $pth);
                 foreach (new FilteredIOCollectionIterator($next, new ExtensionEqualsFilter('.pth')) as $found) {
                     $r = new StringReader($found->getInputStream());
                     while (null !== ($line = $r->readLine())) {
                         if ('' === $line || '#' === $line[0]) {
                             continue;
                         } else {
                             if ('!' === $line[0]) {
                                 $out->write('!' . $base . substr($line, 1) . "\n");
                             } else {
                                 $out->write($base . $line . "\n");
                             }
                         }
                     }
                 }
             }
         } else {
             Console::writeLine('Removing module reference');
             $vendor->removeElement($module->name . '.json');
         }
     }
     Console::writeLine('Done');
     return 0;
 }
 /**
  * Execute this action
  *
  * @param  string[] $args command line args
  * @return int exit code
  */
 public function perform($args)
 {
     $cwd = new FileCollection('.');
     $isModule = new ExtensionEqualsFilter('.json');
     // If an argument is given, search only that vendor
     if (isset($args[0])) {
         $find = $cwd->getCollection($args[0]);
     } else {
         $find = $cwd;
     }
     $total = 0;
     Console::writeLine('@', $cwd->getURI());
     foreach (new FilteredIOCollectionIterator($find, $isModule, true) as $module) {
         $result = self::$json->decodeFrom($module->getInputStream());
         Console::writeLine(new Module($result['vendor'], $result['module']), ': ', $result['info']);
         $total++;
     }
     Console::writeLine();
     Console::writeLine($total, ' module(s) installed');
     return 0;
 }
 /**
  * Execute this action
  *
  * @param  string[] $args command line args
  * @return int exit code
  */
 public function perform($args)
 {
     $cwd = new FileCollection('.');
     // Parse args
     $i = 1;
     if ('-r' === $args[0]) {
         $remote = true;
         array_shift($args);
         $i++;
     } else {
         if ('-i' === $args[0]) {
             $remote = false;
             array_shift($args);
             $i++;
             $installed = new File($args[0] . '.json');
         } else {
             $installed = new File($args[0] . '.json');
             $remote = !$installed->exists();
         }
     }
     if (empty($args)) {
         Console::$err->writeLine('*** Missing argument #', $i, ': Module name');
         return 2;
     }
     sscanf(rtrim($args[0], '/'), '%[^@]@%s', $name, $version);
     $module = Module::valueOf($name);
     // Search for module
     if ($remote) {
         Console::writeLine('@', $this->api->getBase()->getURL());
         $request = create(new RestRequest('/vendors/{vendor}/modules/{module}'))->withSegment('vendor', $module->vendor)->withSegment('module', $module->name);
         try {
             $result = $this->api->execute($request)->data();
         } catch (RestException $e) {
             Console::$err->writeLine('*** Cannot find remote module ', $module, ': ', $e->getMessage());
             return 3;
         }
         $releases = $result['releases'];
     } else {
         Console::writeLine('@', $cwd->getURI());
         try {
             $result = self::$json->decodeFrom($installed->getInputStream());
         } catch (IOException $e) {
             Console::$err->writeLine('*** Cannot find installed module ', $module, ': ', $e->getMessage());
             return 3;
         }
         $releases = $this->installedReleases($cwd, $module);
     }
     Console::writeLine(new Module($result['vendor'], $result['module']), ': ', $result['info']);
     Console::writeLine($result['link']['url']);
     uksort($releases, function ($a, $b) {
         return version_compare($a, $b, '<');
     });
     Console::writeLine('Releases: ', sizeof($releases), ', list {');
     foreach ($releases as $version => $release) {
         $s = '';
         foreach ($release as $key => $value) {
             $s .= ', ' . $key . '= ' . \xp::stringOf($value);
         }
         Console::writeLine('  ', $version, ' (', substr($s, 2), ')');
     }
     Console::writeLine('}');
     // List active releases for local queries
     if (!$remote) {
         foreach (new FilteredIOCollectionIterator($cwd, new NameMatchesFilter('#^\\.' . $module->vendor . '\\.' . $module->name . '.*\\.pth#')) as $found) {
             $r = new StringReader($found->getInputStream());
             Console::writeLine('Selected: ', basename($found->getURI()), ', class path {');
             while (null !== ($line = $r->readLine())) {
                 $resolved = realpath($cwd->getURI() . ltrim($line, '!'));
                 if (is_dir($resolved)) {
                     $cl = \lang\FileSystemClassLoader::instanceFor($resolved, false);
                 } else {
                     if (is_file($resolved)) {
                         $cl = \lang\archive\ArchiveClassLoader::instanceFor($resolved, false);
                     }
                 }
                 Console::writeLine('  ', $cl);
             }
             Console::writeLine('}');
         }
         return 0;
     }
 }
 /**
  * Finds a collection inside this collection
  *
  * @param   string name
  * @return  io.collections.IOCollection
  * @throws  io.OperationNotSupportedException
  * @throws  io.IOException
  */
 public function findCollection($name)
 {
     $qualified = $this->qualifiedName($name);
     if (!is_dir($qualified)) {
         return null;
     }
     $found = new FileCollection($qualified);
     $found->setOrigin($this);
     return $found;
 }