/** * Get resource log * * Get the full log for the current resource up tu the current revision * * @return arbitXml */ protected function getResourceLog() { if (($log = vcsCache::get($this->path, $this->currentVersion, 'log')) === false) { // Refetch the basic logrmation, and cache it. $process = new vcsSvnCliProcess(); $process->argument('--xml'); // Fecth for specified version, if set if ($this->currentVersion !== null) { $process->argument('-r0:' . $this->currentVersion); } // Execute logr command $return = $process->argument('log')->argument(new pbsPathArgument($this->root . $this->path))->execute(); // Transform XML into object array $xmlLog = arbitXml::loadString($process->stdoutOutput); $log = array(); foreach ($xmlLog->logentry as $entry) { $log[(string) $entry['revision']] = new vcsLogEntry($entry['revision'], $entry->author, $entry->msg, strtotime($entry->date)); } uksort($log, array($this, 'compareVersions')); $last = end($log); // Cache extracted data vcsCache::cache($this->path, $this->currentVersion = (string) $last->version, 'log', $log); } return $log; }
/** * Parse XML file * * Parse the given XML into arbitXmlNode objects using the XMLReader class. * * @param string $xmlFile * @return arbitXmlNode */ protected static function parseXml($xmlFile) { $reader = new XMLReader(); // Use custom error handling to suppress warnings and errors during // parsing. $libXmlErrors = libxml_use_internal_errors(true); // Try to open configuration file, and throw parsing exception if // something fails. $errors = array(); // Just open, errors will not occure before actually reading. $reader->open($xmlFile); // Current node, processed. Start with a reference to th root node. $current = $root = new arbitXml(); // Stack of parents for the current node. We store this list, because // we do not want to store a parent node reference in the nodes, as // this breaks with var_export'ing those structures. $parents = array($root); // Start processing the XML document // // The read method may issue warning, even if // libxml_use_internal_errors was set to true. That sucks, and we need // to use the @ here... while (@$reader->read()) { switch ($reader->nodeType) { case XMLReader::ELEMENT: // A new element, which results in a new configuration node as // a child of the current node // // Get name of new element $nodeName = $reader->name; // We create a new object, so append the current node as // future parent node to the parent stack. array_push($parents, $current); // Create new child and reference node as current working // node $current = $current->{$nodeName} = new arbitXmlNode(); // After reading the elements we need to know about this // for further progressing $emptyElement = $reader->isEmptyElement; // Process elements attributes, if available if ($reader->hasAttributes) { // Read all attributes and store their values in the // current configuration node while ($reader->moveToNextAttribute()) { $current[$reader->name] = $reader->value; } } if (!$emptyElement) { // We only break for non empty elements. // // For empty elements the element may also be counted // as a closing tag, so that we want also process the // next case statement. break; } case XMLReader::END_ELEMENT: // At the end of a element set the current pointer back to its // parent // // Pop new current node from parents stack $current = array_pop($parents); break; case XMLReader::TEXT: case XMLReader::CDATA: // Text and CData node are added as node content. // // Append string, in case several text or Cdata nodes exist // in one node $current->setContent((string) $current . $reader->value); break; // Everything else can be ignored for now.. } } // Check if errors occured while reading configuration if (count($errors = libxml_get_errors())) { // Reset libxml error handling to old state libxml_use_internal_errors($libXmlErrors); libxml_clear_errors(); throw new arbitXmlParserException($xmlFile, $errors); } // Reset libxml error handling to old state libxml_use_internal_errors($libXmlErrors); return $root->skipRoot(); }
/** * Get blame information for resource * * The method should return author and revision information for each line, * describing who when last changed the current resource. The returned * array should look like: * <code> * array( * T_LINE_NUMBER => array( * 'author' => T_STRING, * 'version' => T_STRING, * ), * ... * ); * </code> * * If some file in the repository has no blame information associated, like * binary files, the method should return false. * * Optionally a version may be specified which defines a later version of * the resource for which the blame information should be returned. * * @param mixed $version * @return mixed */ public function blame($version = null) { $version = $version === null ? $this->getVersionString() : $version; if (!in_array($version, $this->getVersions(), true)) { throw new vcsNoSuchVersionException($this->path, $version); } if (($blame = vcsCache::get($this->path, $version, 'blame')) === false) { // Refetch the basic blamermation, and cache it. $process = new vcsSvnCliProcess(); $process->argument('--xml'); // Execute command $return = $process->argument('blame')->argument(new pbsPathArgument($this->root . $this->path))->execute(); $xml = arbitXml::loadString($process->stdoutOutput); // Check if blame information si available. Is absent fro binary // files. if (!$xml->target) { return false; } $blame = array(); $contents = preg_split('(\\r\\n|\\r|\\n)', $this->getVersionedContent($version)); foreach ($xml->target[0]->entry as $nr => $entry) { $blame[] = new vcsBlameStruct($contents[$nr], $entry->commit[0]['revision'], $entry->commit[0]->author, strtotime($entry->commit[0]->date)); } vcsCache::cache($this->path, $version, 'blame', $blame); } return $blame; }
/** * Convert current node into a document node * * @return arbitXml */ public function toDocument() { return arbitXml::__set_state(array('childs' => $this->childs, 'attributes' => $this->attributes, 'content' => $this->content)); }