update-freshmeat.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/usr/bin/php
  2. <?php
  3. chdir(dirname(__FILE__));
  4. require_once 'common.php';
  5. assertCli();
  6. /**
  7. * @file
  8. * Updates Freshmeat's HTML Purifier with the latest information via XML RPC.
  9. */
  10. class XmlRpc_Freshmeat
  11. {
  12. const URL = 'http://freshmeat.net/xmlrpc/';
  13. public $chatty = false;
  14. public $encodeOptions = array(
  15. 'encoding' => 'utf-8',
  16. );
  17. /**
  18. * This array defines shortcut method signatures for dealing with simple
  19. * XML RPC methods. More complex ones (publish_release) should use the named parameter
  20. * syntax.
  21. */
  22. public $signatures = array(
  23. 'login' => array('username', 'password'),
  24. 'fetch_branch_list' => array('project_name'),
  25. 'fetch_release' => array('project_name', 'branch_name', 'version'),
  26. 'withdraw_release' => array('project_name', 'branch_name', 'version'),
  27. );
  28. protected $sid = null;
  29. /**
  30. * @param $username Username to login with
  31. * @param $password Password to login with
  32. */
  33. public function __construct($username = null, $password = null) {
  34. if ($username && $password) {
  35. $this->login($username, $password);
  36. }
  37. }
  38. /**
  39. * Performs a raw XML RPC call to self::URL
  40. */
  41. protected function call($method, $params) {
  42. $request = xmlrpc_encode_request($method, $params, $this->encodeOptions);
  43. $ch = curl_init();
  44. curl_setopt($ch, CURLOPT_URL, self::URL);
  45. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  46. curl_setopt($ch, CURLOPT_TIMEOUT, 1);
  47. curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  48. 'Content-type: text/xml',
  49. 'Content-length: ' . strlen($request)
  50. ));
  51. curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
  52. $data = curl_exec($ch);
  53. if ($errno = curl_errno($ch)) {
  54. throw new Exception("Curl error [$errno]: " . curl_error($ch));
  55. } else {
  56. curl_close($ch);
  57. return xmlrpc_decode($data);
  58. }
  59. }
  60. /**
  61. * Performs an XML RPC call to Freshmeat.
  62. * @param $name Name of method to call, can be methodName or method_name
  63. * @param $args Arguments of call, in form array('key1', 'val1', 'key2' ...)
  64. */
  65. public function __call($name, $args) {
  66. $method = $this->camelToUnderscore($name);
  67. $params = array();
  68. if ($this->sid) $params['SID'] = $this->sid;
  69. if (isset($this->signatures[$method])) {
  70. for ($i = 0, $c = count($this->signatures[$method]); $i < $c; $i++) {
  71. $params[$this->signatures[$method][$i]] = $args[$i];
  72. }
  73. } else {
  74. for ($i = 0, $c = count($args); $i + 1 < $c; $i += 2) {
  75. $params[$args[$i]] = $args[$i + 1];
  76. }
  77. }
  78. $result = $this->call($method, $params);
  79. switch ($method) {
  80. case 'login':
  81. $this->sid = $result['SID'];
  82. break;
  83. case 'logout':
  84. $this->sid = null;
  85. break;
  86. }
  87. if ($this->chatty) print_r($result);
  88. return $result;
  89. }
  90. /**
  91. * Munge methodName to method_name
  92. */
  93. private function camelToUnderscore($name) {
  94. $method = '';
  95. for ($i = 0, $c = strlen($name); $i < $c; $i++) {
  96. $v = $name[$i];
  97. if (ctype_lower($v)) $method .= $v;
  98. else $method .= '_' . strtolower($v);
  99. }
  100. return $method;
  101. }
  102. /**
  103. * Automatically logout at end of scope
  104. */
  105. public function __destruct() {
  106. if ($this->sid) $this->logout();
  107. }
  108. }
  109. $rpc = new XmlRpc_Freshmeat($argv[1], $argv[2]);
  110. $rpc->chatty = true;
  111. $project = 'htmlpurifier';
  112. $branch = 'Default';
  113. $version = file_get_contents('../VERSION');
  114. $result = $rpc->fetchRelease($project, $branch, $version);
  115. if (!isset($result['faultCode'])) {
  116. echo "Freshmeat release already exists.\n";
  117. exit(0);
  118. }
  119. $changes = strtr(file_get_contents('../WHATSNEW'), array("\r" => '', "\n" => ' '));
  120. $focus = (int) trim(file_get_contents('../FOCUS'));
  121. if (strlen($changes) > 600) {
  122. echo "WHATSNEW entry is too long.\n";
  123. exit(1);
  124. }
  125. $rpc->publishRelease(
  126. 'project_name', $project,
  127. 'branch_name', $branch,
  128. 'version', $version,
  129. 'changes', $changes,
  130. 'release_focus', $focus,
  131. 'url_tgz', "http://htmlpurifier.org/releases/htmlpurifier-$version.tar.gz",
  132. 'url_zip', "http://htmlpurifier.org/releases/htmlpurifier-$version.zip",
  133. 'url_changelog', "http://htmlpurifier.org/svnroot/htmlpurifier/tags/$version/NEWS"
  134. );
  135. // vim: et sw=4 sts=4