home
api
develop
badge
wallpaper
rhaco.org
PHP library & setup framework
lingr
bugs
jaja
arbo
rhaco_1_x
jaja rev. 259
branches/pond/library/arbo/network/SvnLogger.php
296: google 2タイプに対応
292: 直ったかな
290: google対応
285: arboの修正に追随
265: doctestを無効にしとく
264: diffの実装
262:
259:
256: メモ
255: ソースビューに対応
254:
251: google codeの別パターンに対応
246: 全てのレイアウトが同じではない?
243: svnをマルチ対応に修正
241: 初期インポート。
type = $type; $this->url = $urlOrAccount; $this->cmd = $cmd; $this->revision = ObjectUtil::anonym(' var $id = 0; var $author = null; var $date = null; var $comment = ""; var $added = array(); var $modified = array(); var $deleted = array(); function set($id,$author,$comment,$date){ $this->id = intval($id); $this->author = StringUtil::encode(trim($author)); $this->comment = StringUtil::encode(trim($comment)); $this->date = DateUtil::format($date); } function setPath($action,$file){ $file = str_replace("\n","",StringUtil::toULD($file)); if(substr($file,0,1) == "/") $file = substr($file,1); switch (strtolower($action)){ case "A": case "added": $this->added[] = $file; break; case "M": case "modified": $this->modified[] = $file; break; case "D": case "deleted": $this->deleted[] = $file; } } '); } function TYPE_SHELL(){ return 0; } function TYPE_SOURCEFORGE(){ return 1; } function TYPE_GOOGLE(){ return 2; } /** * 指定のリビジョンを取得する * * @param integer $from * @param integer $to * @return array * */ function revision($from,$to=null,$order=true){ if(empty($to)) $to = $from; switch($this->type){ case SvnLogger::TYPE_SHELL(): $revisions = $this->_revisionShell($from,$to); break; case SvnLogger::TYPE_SOURCEFORGE(): $revisions = $this->_revisionSourceforge($from,$to); break; case SvnLogger::TYPE_GOOGLE(): $revisions = $this->_revisionGoogle($from,$to); break; } if(!$order) rsort($revisions); $this->revisions = $revisions; return $revisions; } /** * 取得したリビジョンをRSS出力する * * @param string $title * @param string $description * @param string $url * @param string $linkformat */ function toRss($title,$description,$url,$linkformat=""){ $feed = new Rss20(); $feed->setChannel($title,$description,$url); if(empty($linkformat)) $linkformat = $this->linkformat; foreach($this->revisions as $rev){ $item = new RssItem20(); $item->setPubDate($rev->date); $item->setAuthor($rev->author); $item->setDescription($rev->comment); $item->setTitle($rev->id); $item->setLink(sprintf($linkformat,$rev->id)); $feed->setItem($item); } $feed->output(); } /** * 最後のリビジョン番号を取得する * * @return integer */ function last(){ switch($this->type){ case SvnLogger::TYPE_SHELL(): return $this->_lastShell(); case SvnLogger::TYPE_SOURCEFORGE(): return $this->_lastSourceforge(); case SvnLogger::TYPE_GOOGLE(): return $this->_lastGoogle(); } return 0; } /** * 指定のファイルソースを取得する * * @param string $path * @param int $rev * @return string */ function cat($path,$rev=null){ if(substr($path,0,1) == "/") $path = substr($path,1); switch($this->type){ case SvnLogger::TYPE_SHELL(): return $this->catShell($path,$rev); case SvnLogger::TYPE_SOURCEFORGE(): return $this->_catSourceforge($path,$rev); case SvnLogger::TYPE_GOOGLE(): return $this->_catGoogle($path,$rev); } return null; } function diff($path,$revA,$revB){ if(substr($path,0,1) == "/") $path = substr($path,1); switch($this->type){ case SvnLogger::TYPE_SHELL(): return $this->_diffShell($path,$revA,$revB); case SvnLogger::TYPE_SOURCEFORGE(): return $this->_diffSourceforge($path,$revA,$revB); case SvnLogger::TYPE_GOOGLE(): return $this->_diffGoogle($path,$revA,$revB); } return null; } function _diffShell($path,$revA,$revB){ // svn diff -r 3356:3373 https://rhaco.svn.sourceforge.net/svnroot/rhaco/trunk/Rhaco.php $url = Url::parseAbsolute($this->url,$path); $info = $this->_cmd(sprintf("%s info -r %d %s",$this->cmd,$rev,$url)); if(substr_count($info,"\n") > 1){ return $this->_cmd(sprintf("%s diff -r %d:%d %s",$this->cmd,$revA,$revB,$url)); } return null; } function _diffSourceforge($path,$revA,$revB){ // http://rhaco.svn.sourceforge.net/viewvc/rhaco/trunk/Rhaco.php?r1=3356&r2=3373&diff_format=u $browser = new Browser(); $url = sprintf("http://%s.svn.sourceforge.net/viewvc/%s/%s?r1=%d&r2=%d&diff_format=u",$this->url,$this->url,$path,$revA,$revB); Logger::deep_debug($url); $src = $browser->get($url); // if($browser->status() == 404 || strrpos($src,"ViewVC Help") !== false) return null; return $src; } function _diffGoogle($path,$revA,$revB){ // http://code.google.com/p/jaja/source/diff?old=241&r=243&format=unidiff&path=/branches/pond/index.php $browser = new Browser(); $url = sprintf("http://code.google.com/p/%s/source/diff?old=%d&r=%d&format=unidiff&path=%s",$this->url,$revA,$revB,$path); Logger::deep_debug($url); $src = $browser->get($url); if($browser->status() == 404) return null; return $src; } function _catShell($path,$rev){ $url = Url::parseAbsolute($this->url,$path); $info = $this->_cmd(sprintf("%s info -r %d %s",$this->cmd,$rev,$url)); if(substr_count($info,"\n") > 1){ return $this->_cmd(sprintf("%s cat -r %d %s",$this->cmd,$rev,$url)); } return null; } function _catSourceforge($path,$rev){ $browser = new Browser(); $url = sprintf("http://%s.svn.sourceforge.net/viewvc/%s/%s?pathrev=%d",$this->url,$this->url,$path,$rev); Logger::deep_debug($url); $src = $browser->get($url); if($browser->status() == 404 || strrpos($src,"ViewVC Help") !== false) return null; return $src; } function _catGoogle($path,$rev){ $browser = new Browser(); $url = sprintf("http://%s.googlecode.com/svn-history/r%d/%s",$this->url,$rev,$path); Logger::deep_debug($url); $src = $browser->get($url); if($browser->status() == 404) return null; return $src; } function _revisionSourceforge($from,$to){ $browser = new Browser(); $result = array(); $urlformat = sprintf("http://%s.svn.sourceforge.net/viewvc/%s/?view=rev&revision=%%d",$this->url,$this->url); $this->linkformat = $urlformat; for($i=$from;$i<=$to;$i++){ $url = sprintf($urlformat,$i); Logger::deep_debug($url); if(SimpleTag::setof($tag,$browser->get($url),"body")){ $result[$i] = $this->_revision($i, $tag->f("table[1].table[0].tr[1].td.value()"), $tag->f("table[1].table[0].tr[3].td.pre.value()"), preg_replace("/^(.+?)<.+$/","\\1",$tag->f("table[1].table[0].tr[2].td.value()"))); foreach(ArrayUtil::arrays($tag->f("table[1].table[1].in(tr)")) as $tr){ $result[$i]->setPath($tr->f("td[1].a.value()"), preg_replace("/^.+>/","",$tr->f("td[0].a.value()"))); } } } return $result; } function _lastSourceforge(){ $browser = new Browser(); $url = sprintf("http://%s.svn.sourceforge.net/viewvc/%s/?view=rev",$this->url,$this->url); Logger::deep_debug($url); if(SimpleTag::setof($tag,$browser->get($url),"body")){ return (int)(preg_replace("/[^\d]/","",$tag->f("table[1].h1.value()"))); } return 0; } function _revisionGoogle($from,$to){ $browser = new Browser(); $result = array(); $urlformat = sprintf("http://code.google.com/p/%s/source/detail?r=%%d",$this->url); $this->linkformat = $urlformat; for($i=$from;$i<=$to;$i++){ $url = sprintf($urlformat,$i); Logger::deep_debug($url); if(SimpleTag::setof($tag,$browser->get($url),"body")){ $div = $tag->f("div[15].table[1].tr[0]"); if(!Variable::istype("SimpleTag",$div)) $div = $tag->f("div[13].table[1].tr[0]"); if(!Variable::istype("SimpleTag",$div)) break; $result[$i] = $this->_revision($i, trim(strip_tags($div->f("td[0].table[0].tr[0].td[0].value()"))), $div->f("td[1].pre.value()"), trim(strip_tags($div->f("td[0].table[0].tr[1].td[0].span[0].param('title')"))) ); foreach($div->f("td[1].table[0].in('tr')") as $tr){ $result[$i]->setPath($tr->f("td[1].value()"),$tr->f("td[2].a.value()")); } } } return $result; } function _lastGoogle(){ $browser = new Browser(); if(SimpleTag::setof($tag,$browser->get(sprintf("http://code.google.com/p/%s/source/list",$this->url)),"body")){ return (int)(preg_replace("/[^\d]/","",$tag->f("table[4].tr[1].td[0].a.value()"))); } return 0; } function _revisionShell($from,$to){ $src = $this->_cmd(sprintf("%s log %s --xml --verbose %s",$this->cmd,sprintf("-r %d:%d ",$from,$to),$this->url)); $result = array(); $this->linkformat = $this->url; if(SimpleTag::setof($tag,$src,"log")){ foreach($tag->getIn("logentry") as $log){ $revision = $log->param("revision"); $result[$revision] = $this->_revision($revision, $log->getInValue("author"), $log->getInValue("msg"), $log->getInValue("date")); foreach($log->getIn("paths") as $paths){ foreach($paths->getIn("path") as $path){ $result[$revision]->setPath($path->param("action"),$path->getValue()); } } } } if(($to - $from) != sizeof($result) - 1){ $last = $this->_lastShell(); if($to > $last) $to = $last; for($i=$from;$i<=$to;$i++){ if(!isset($result[$i])) $result[$i] = $this->_revision($i,null,null,null); } } return $result; } function _lastShell(){ $src = $this->_cmd(sprintf("%s info %s",$this->cmd,$this->url)); if(preg_match("/Last Changed Rev: ([\d]+)/i",$src,$match)){ return (int)$match[1]; } return 0; } function _revision($id,$author,$comment,$date){ $obj = Variable::copy($this->revision); $obj->set($id,$author,$comment,$date); return $obj; } function _cmd($cmd){ Logger::debug($cmd); ob_start(); system($cmd); return ob_get_clean(); } } ?>