[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/diffusion/protocol/ -> DiffusionMercurialWireProtocol.php (source)

   1  <?php
   2  
   3  final class DiffusionMercurialWireProtocol {
   4  
   5    public static function getCommandArgs($command) {
   6      // We need to enumerate all of the Mercurial wire commands because the
   7      // argument encoding varies based on the command. "Why?", you might ask,
   8      // "Why would you do this?".
   9  
  10      $commands = array(
  11        'batch' => array('cmds', '*'),
  12        'between' => array('pairs'),
  13        'branchmap' => array(),
  14        'branches' => array('nodes'),
  15        'capabilities' => array(),
  16        'changegroup' => array('roots'),
  17        'changegroupsubset' => array('bases heads'),
  18        'debugwireargs' => array('one two *'),
  19        'getbundle' => array('*'),
  20        'heads' => array(),
  21        'hello' => array(),
  22        'known' => array('nodes', '*'),
  23        'listkeys' => array('namespace'),
  24        'lookup' => array('key'),
  25        'pushkey' => array('namespace', 'key', 'old', 'new'),
  26        'stream_out' => array(''),
  27        'unbundle' => array('heads'),
  28      );
  29  
  30      if (!isset($commands[$command])) {
  31        throw new Exception("Unknown Mercurial command '{$command}!");
  32      }
  33  
  34      return $commands[$command];
  35    }
  36  
  37    public static function isReadOnlyCommand($command) {
  38      $read_only = array(
  39        'between' => true,
  40        'branchmap' => true,
  41        'branches' => true,
  42        'capabilities' => true,
  43        'changegroup' => true,
  44        'changegroupsubset' => true,
  45        'debugwireargs' => true,
  46        'getbundle' => true,
  47        'heads' => true,
  48        'hello' => true,
  49        'known' => true,
  50        'listkeys' => true,
  51        'lookup' => true,
  52        'stream_out' => true,
  53      );
  54  
  55      // Notably, the write commands are "pushkey" and "unbundle". The
  56      // "batch" command is theoretically read only, but we require explicit
  57      // analysis of the actual commands.
  58  
  59      return isset($read_only[$command]);
  60    }
  61  
  62    public static function isReadOnlyBatchCommand($cmds) {
  63      if (!strlen($cmds)) {
  64        // We expect a "batch" command to always have a "cmds" string, so err
  65        // on the side of caution and throw if we don't get any data here. This
  66        // either indicates a mangled command from the client or a programming
  67        // error in our code.
  68        throw new Exception("Expected nonempty 'cmds' specification!");
  69      }
  70  
  71      // For "batch" we get a "cmds" argument like:
  72      //
  73      //   heads ;known nodes=
  74      //
  75      // We need to examine the commands (here, "heads" and "known") to make sure
  76      // they're all read-only.
  77  
  78      // NOTE: Mercurial has some code to escape semicolons, but it does not
  79      // actually function for command separation. For example, these two batch
  80      // commands will produce completely different results (the former will run
  81      // the lookup; the latter will fail with a parser error):
  82      //
  83      //  lookup key=a:xb;lookup key=z* 0
  84      //  lookup key=a:;b;lookup key=z* 0
  85      //               ^
  86      //               |
  87      //               +-- Note semicolon.
  88      //
  89      // So just split unconditionally.
  90  
  91      $cmds = explode(';', $cmds);
  92      foreach ($cmds as $sub_cmd) {
  93        $name = head(explode(' ', $sub_cmd, 2));
  94        if (!self::isReadOnlyCommand($name)) {
  95          return false;
  96        }
  97      }
  98  
  99      return true;
 100    }
 101  
 102  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1