<?xml version="1.0" encoding="UTF-8"?>
<leo_file>
<leo_header file_format="2" tnodes="0" max_tnode_index="16" clone_windows="0"/>
<globals body_outline_ratio="0.5">
	<global_window_position top="57" left="62" height="558" width="698"/>
	<global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences>
</preferences>
<find_panel_settings>
	<find_string></find_string>
	<change_string></change_string>
</find_panel_settings>
<vnodes>
<v t="Zoomq.20041231111725" a="E"><vh>CVSanalyser</vh>
<v t="Zoomq.20041231135046" a="EM" tnodeList="Zoomq.20041231135046"><vh>@file cvsanalyser.conf</vh></v>
<v t="Zoomq.20041231133106" tnodeList="Zoomq.20041231133106,Zoomq.20041231133106.1,Zoomq.20041231133106.2,Zoomq.20041231133106.3,Zoomq.20041231133733,Zoomq.20041231134319,Zoomq.20041231133106.4,Zoomq.20041231151106,Zoomq.20041231151106.1,Zoomq.20050104164931,Zoomq.20050104162522,Zoomq.20041231153937,Zoomq.20041231133106.5"><vh>@file cvsanalyser.py</vh>
<v t="Zoomq.20041231133106.1" a="M"><vh>&lt;&lt; cvsanalyser declarations &gt;&gt;</vh></v>
<v t="Zoomq.20041231133106.2" a="E"><vh>class CvsAnalyser</vh>
<v t="Zoomq.20041231133106.3"><vh>__init__</vh></v>
<v t="Zoomq.20041231133733" a="E"><vh>__repr__</vh></v>
<v t="Zoomq.20041231134319"><vh>chkFiles</vh></v>
<v t="Zoomq.20041231133106.4" a="E"><vh>analyseAll</vh></v>
<v t="Zoomq.20041231151106" a="E"><vh>analyseDate</vh></v>
<v t="Zoomq.20041231151106.1"><vh>analyseAct</vh></v>
<v t="Zoomq.20050104164931"><vh>analyseFile</vh></v>
<v t="Zoomq.20050104162522" a="E"><vh>viewcvsFiles</vh></v>
<v t="Zoomq.20041231153937"><vh>analyseLine</vh></v>
<v t="Zoomq.20041231133106.5"><vh>put2xml</vh></v>
</v>
</v>
<v t="Zoomq.20041231133550" a="TV"><vh>@file F:/zDevelop/zPython/@limodou/cvsdelta/cvsdelta.py</vh>
<v t="Zoomq.20041231133550.1"><vh>&lt;&lt; cvsdelta declarations &gt;&gt;</vh></v>
<v t="Zoomq.20041231133550.2"><vh>usage</vh></v>
<v t="Zoomq.20041231133550.3"><vh>main</vh></v>
<v t="Zoomq.20041231133550.4"><vh>getdate</vh></v>
<v t="Zoomq.20041231133550.5"><vh>ftp_getfile</vh></v>
<v t="Zoomq.20041231133550.6"><vh>makepath</vh></v>
<v t="Zoomq.20041231133550.7"><vh>run</vh></v>
<v t="Zoomq.20041231133550.8"><vh>analyseline</vh></v>
</v>
<v t="Zoomq.20050104171344"><vh>historystat.xsl</vh>
<v t="Zoomq.20050104171344.1" a="E"><vh>&lt;&lt;XSL head&gt;&gt;</vh></v>
<v t="Zoomq.20050104171344.2" a="E"><vh>&lt;&lt;Script&gt;&gt;</vh></v>
<v t="Zoomq.20050104171344.3" a="E"><vh>&lt;&lt;root&gt;&gt;</vh>
<v t="Zoomq.20050104171344.4" a="E"><vh>&lt;&lt;cvs&gt;&gt;</vh>
<v t="Zoomq.20050104171344.5" a="E"><vh>&lt;&lt;module&gt;&gt;</vh>
<v t="Zoomq.20050104183828"><vh>&lt;&lt;file&gt;&gt;</vh></v>
</v>
</v>
</v>
<v t="Zoomq.20050104171344.6"><vh>&lt;&lt;XSL tail&gt;&gt;</vh></v>
</v>
<v t="Zoomq.20041231111725.1" tnodeList="Zoomq.20041231111725.1,Zoomq.20041231111725.2,Zoomq.20041231111725.3,Zoomq.20041231111725.4,Zoomq.20041231111725.5,Zoomq.20041231111725.6"><vh>@file E:/ZZZ/workspace/scm/statcvs/statcvs.sh.py</vh>
<v t="Zoomq.20041231111725.2" a="M"><vh>&lt;&lt; statcvs.sh declarations &gt;&gt;</vh></v>
<v t="Zoomq.20041231111725.3" a="E"><vh>class statcvs</vh>
<v t="Zoomq.20041231111725.4"><vh>__init__</vh></v>
<v t="Zoomq.20041231111725.5"><vh>initstat</vh></v>
<v t="Zoomq.20041231111725.6"><vh>walking</vh></v>
</v>
</v>
<v t="Zoomq.20041231113947"><vh>weeklystat.xsl</vh>
<v t="Zoomq.20041231115524"><vh>&lt;&lt;XSL head&gt;&gt;</vh></v>
<v t="Zoomq.20041231115619"><vh>&lt;&lt;Script&gt;&gt;</vh></v>
<v t="Zoomq.20041231120106" a="E"><vh>&lt;&lt;root&gt;&gt;</vh>
<v t="Zoomq.20041231120306" a="E"><vh>&lt;&lt;cvs&gt;&gt;</vh>
<v t="Zoomq.20041231120349"><vh>&lt;&lt;module&gt;&gt;</vh></v>
</v>
</v>
<v t="Zoomq.20041231115524.1"><vh>&lt;&lt;XSL tail&gt;&gt;</vh></v>
</v>
<v t="Zoomq.20041231162737" a="E" tnodeList="Zoomq.20041231162737,Zoomq.20041231162737.1,Zoomq.20041231162737.2,Zoomq.20041231162737.3,Zoomq.20041231162737.4,Zoomq.20041231162737.5,Zoomq.20041231162737.6"><vh>@file weeklystat.py</vh>
<v t="Zoomq.20041231162737.1" a="M"><vh>&lt;&lt; weeklystat declarations &gt;&gt;</vh></v>
<v t="Zoomq.20041231162737.2" a="E"><vh>class WeeklyStat</vh>
<v t="Zoomq.20041231162737.3"><vh>__init__</vh></v>
<v t="Zoomq.20041231162737.4"><vh>wlkCvsCo</vh></v>
<v t="Zoomq.20041231162737.5"><vh>ckAll</vh></v>
<v t="Zoomq.20041231162737.6"><vh>put2xml</vh></v>
</v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="Zoomq.20041231111725">#$Id: CVSanalyser.leo,v 1.13 2005/01/05 07:13:36 zhouqi Exp $
针对CVS的活动进行统计，汇报
#041231 使用Leo 组织项目！</t>
<t tx="Zoomq.20041231111725.1">#@ignore
#@language python
&lt;&lt; statcvs.sh declarations &gt;&gt;
@others

if __name__ == '__main__':
    """基本运行模式
    """
    statit = statcvs()
    statit.walking()
    #os.system("echo 'check modules into ::'"+statit.snap)
    #os.system("echo 'there's modules ='"+statit.cvs.items())
    #print statit.cvs

    #print "check into:"+statit.snap
</t>
<t tx="Zoomq.20041231111725.2"># -*- coding: UTF-8 -*-

# $Id: statcvs.sh.py,v 1.6 2004/12/31 06:06:04 zhouqi Exp $

"""StatCVS-xml auto runner
    - Crontab 调用的脚本
    - 自动检出所有CVS的所有模块，
    - 并一一生成 cvs.log
    - 调用statcvs-xml-0.9.4-full.jar 自动输出分析文档！
    - 输出至 /usr/local/www/data/statcvs/ 对应目录中！
    - 运行
        -# python /usr/local/etc/statcvs.sh.py

@version: 0.1
@author: U{Zoom.Quiet&lt;mailto:Zoom.Quiet@gmail.com&gt;}
@see: U{Zoomq@mail.sina&lt;http://10.88.15.200/mailwiki/ZoomQuiet&gt;}

"""
import sys,os,string
import datetime

</t>
<t tx="Zoomq.20041231111725.3">class statcvs:
    """主类，集成所有处理
    """
	@others
</t>
<t tx="Zoomq.20041231111725.4">def __init__(self):
    """初始化参数
        - "scm"
        ,"sinaIndex"
        ,"MTA"
        ,"runmanage"
        ,"sinaIndex"
        ,"sinaInterface"
        ,"sinasys"
        ,"webmail"
    """
    self.snap = "/usr/home/statcvs/snapcvs/"
    self.statcvsjar = "/usr/home/statcvs/snapcvs/statcvs-full.jar"
    self.exp = "/usr/home/statcvs/snapcvs/pub/"
    self.checkall = "cvs -Rd /cvs/%s checkout ."
    self.cvs = ("scm"
        ,"sinaIndex"
        ,"MTA"
        ,"runmanage"
        ,"sinaIndex"
        ,"sinaInterface"
        ,"sinasys"
        ,"webmail")
</t>
<t tx="Zoomq.20041231111725.5">def initstat(self):
    """清除以前的各种分析成果！ 
        - 使用rm -Rf 系统命令       
    """        
    for key in self.cvs:
        rmall = "rm -Rf "+self.snap+key+"/*"
        print "!"+rmall
        os.system(rmall)
        rmall = "rm -Rf "+self.exp+key+"/*"
        print "!!"+rmall
        os.system(rmall)
</t>
<t tx="Zoomq.20041231111725.6">def walking(self):
    """逐一处理所有模块
    """
    self.initstat()
    #return
    os.chdir(self.snap)
    for key in self.cvs:
        # cvs check command
        os.chdir(self.snap+key)
        os.system(self.checkall%key)
        dirli = os.listdir(self.snap+key)
        print "&gt; StatCVS CVS::"+key
        for path in dirli:
            if("CVSROOT"==path or "CVS"==path):
                pass
            else:
                #print path
                #分别进行模块分析处理
                print "&gt; &gt; &gt;StatCVS module::"+key+"/"+path
                modpath = self.snap+key+"/"+path
                #os.system("cd "+self.snap+key+"/"+path)
                os.chdir(modpath)
                #041226 修正为一周内的Log
                logcvs = "cvs log -d \""+(datetime.date.today()-datetime.timedelta(7)).isoformat()+"\"\&lt; &gt; cvs.log"
                
                print "===&gt;&gt;&gt;  "+logcvs
                os.system(logcvs)
                #os.system("cvs log &gt; cvs.log")
                os.chdir(self.snap)
                # 041217 for error analyse large modules
                crtrun = "java -mx256m -jar statcvs-full.jar -output-dir pub/"+key+"/"+path+"  "+modpath+"/cvs.log"
                #print crtrun
                os.system(crtrun)
</t>
<t tx="Zoomq.20041231113947">#@ignore
@silent
@root-code weeklystat.xsl
&lt;&lt;XSL head&gt;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;!--"""
StatCVS 分析结果XML 快速XSLT模板
Zoomq::041227 使用 CSS+JS 进行点击支持

$Id: CVSanalyser.leo,v 1.13 2005/01/05 07:13:36 zhouqi Exp $
"""--&gt;
&lt;title&gt;新浪·研发·邮件-CVS周活动统计
 @ 
FreeBSD+Python+XML&lt;/title&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;

&lt;link href="sinaeye.ico" rel="shortcut icon" /&gt;
&lt;link rel="stylesheet" type="text/css" href="style.css" /&gt;

&lt;&lt;Script&gt;&gt;

&lt;/head&gt;

&lt;body  leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" &gt;

&lt;&lt;root&gt;&gt;


&lt;/body&gt;
&lt;/html&gt;
&lt;&lt;XSL tail&gt;&gt;</t>
<t tx="Zoomq.20041231115524">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:function="http://www.infopro.cn/epservernamespace"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
&gt;
&lt;xsl:template match="/"&gt;</t>
<t tx="Zoomq.20041231115524.1">&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</t>
<t tx="Zoomq.20041231115619">&lt;script language="JavaScript" &gt; 
//o=document.getElementById('xxx');o.style.display=o.style.display=='none' ? '' : 'none'
function _showDIV(divID){
    //alert(divID);
    var _obj = document.getElementById(divID);
    //alert(divID+"\n"+_obj);
    _obj.style.display = (_obj.style.display=='none')? '' : 'none';    
    return;
}
&lt;/script&gt;</t>
<t tx="Zoomq.20041231120106">&lt;xsl:for-each select="root"&gt;
&lt;xsl:for-each select="week"&gt;
&lt;h1 style="cursor : hand"&gt;
	&lt;xsl:attribute name="onclick"&gt;
	_showDIV("stat-&lt;xsl:value-of select="@date" /&gt;");
	&lt;/xsl:attribute&gt;
CVS活动周分析 截止日期&lt;xsl:value-of select="@date" /&gt;
&lt;/h1&gt;
&lt;ul&gt;
    &lt;li&gt;总更新文件数:   &lt;xsl:value-of select="@files" /&gt;
        &lt;/li&gt;
    &lt;li&gt;总提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
        &lt;/li&gt;
    &lt;li&gt;总涉及码行数:   &lt;xsl:value-of select="@lines" /&gt;
        &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="border : 1px dotted #ede;
                display : none;"&gt;
            &lt;xsl:attribute name="id"&gt;stat-&lt;xsl:value-of select="@date" /&gt;&lt;/xsl:attribute&gt;
            
    &lt;ul&gt;
    &lt;&lt;cvs&gt;&gt;
    &lt;/ul&gt;
&lt;/xsl:for-each&gt;&lt;!--week loop--&gt;
&lt;hr/&gt;

&lt;/xsl:for-each&gt;&lt;!--root--&gt;
&lt;!-- end of Page--&gt;</t>
<t tx="Zoomq.20041231120306">&lt;xsl:for-each select="cvs"&gt;
&lt;h3 style="cursor : hand"&gt;
&lt;xsl:attribute name="onclick"&gt;
_showDIV("cvs-&lt;xsl:value-of select="../@date" /&gt;-&lt;xsl:value-of select="@name" /&gt;");
//alert("cvs-&lt;xsl:value-of select="@name" /&gt;");
&lt;/xsl:attribute&gt;

&lt;xsl:value-of select="@name" /&gt; 库 中:&lt;/h3&gt;
&lt;li&gt;总更新文件数:   &lt;xsl:value-of select="@files" /&gt;
    &lt;/li&gt;
&lt;li&gt;总提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
    &lt;/li&gt;
&lt;li&gt;总涉及码行数:   &lt;xsl:value-of select="@lines" /&gt;
&lt;/li&gt;
&lt;li&gt;

    &lt;ul&gt;
    
    &lt;div style="border : 0px dotted #993300;
        display : none;
        background-color : #336699;
        color:#fff;"&gt;
        
    &lt;xsl:attribute name="id"&gt;cvs-&lt;xsl:value-of select="../@date" /&gt;-&lt;xsl:value-of select="@name" /&gt;&lt;/xsl:attribute&gt;
    &lt;&lt;module&gt;&gt;
    &lt;/div&gt;
    
    &lt;/ul&gt;
&lt;/li&gt;
&lt;/xsl:for-each&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;/li&gt;
</t>
<t tx="Zoomq.20041231120349">&lt;xsl:for-each select="module"&gt;
&lt;h5&gt;模块 &lt;xsl:value-of select="@name" /&gt; 更新细节:&lt;/h5&gt;
    &lt;li&gt;更新文件数:   &lt;xsl:value-of select="@files" /&gt;
        &lt;/li&gt;
    &lt;li&gt;提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
        &lt;/li&gt;
    &lt;li&gt;涉及码行数:   &lt;xsl:value-of select="@lines" /&gt;
    &lt;/li&gt;            
&lt;/xsl:for-each&gt;</t>
<t tx="Zoomq.20041231133106">#@ignore
#@language python
&lt;&lt; cvsanalyser declarations &gt;&gt;
@others
        

if __name__ == '__main__':
    """基本运行模式
    """
    week = CvsAnalyser()
    week.analyseAll()
    week.put2xml()</t>
<t tx="Zoomq.20041231133106.1"># -*- coding: UTF-8 -*-
"""cvsanalyser CVS History analyser
    - 直接分析CVS History 记录
    - 取得统计数据！
特别的 203 中的自动执行:
    - #su -l sinaop
    - 专门的用户中的 来维护
    - %crontab -e
    
@version: $Id: cvsanalyser.py,v 1.10 2005/01/05 07:13:36 zhouqi Exp $
@author: U{Zoom.Quiet&lt;mailto:Zoom.Quiet@gmail.com&gt;}
@see: U{cvsdelta by Limodou&lt;http://pyrecord.freezope.org/articles/doc2001082801/show&gt;}
"""
import sys,os,string
import time,datetime
from elementtree import ElementTree
from elementtree.ElementTree import Element, SubElement, tostring

import getopt
import ConfigParser

</t>
<t tx="Zoomq.20041231133106.2">class CvsAnalyser:
    """主类，集成所有处理
    """
	@others
</t>
<t tx="Zoomq.20041231133106.3">def __init__(self):
    """初始化参数
        - 通过 /var/log/cron 的据错邮件发现目录的严格性
        - 当前除了.conf 文件，要需要配置cfg 文件的读取路径!
    """    
    self.cfg = ConfigParser.ConfigParser()
    try:
        # 必须正确指定配置文件路径在此
        self.cfg.read("/home/zoomq/share/statcvs/cvsanalyser.conf")        
        #=============================
        #以下是运行脚本不需要修改
        self.cvsroot = self.cfg.get('Path','cvsroot')        
        self.cvs = self.cfg.get('Target','cvs').split()
        self.tarea = int(self.cfg.get('Target','time'))
        self.viewcvs = self.cfg.get('Target','viewcvs')
        self.xml = self.cfg.get('Target','xml')
        self.xmlhead = """&lt;?xml version='1.0' encoding='UTF-8'?&gt;
        &lt;!-- edited with elementtree (http://effbot.org/zone/element-index.htm) by Zoom.Quiet  --&gt;
        &lt;?xml-stylesheet type='text/xsl' href='historystat.xsl'?&gt;
        """
        #self.cfg.get('Target','xmlhead')
        
        self.finder = "find %s -mtime -7 -type f | wc -l | awk '{print $1}'"
    except:
        print """config files:\n cvsanalyser.conf 
        not exist or bad!!!
        please check it....and try again!
        """
        return
    self.report = {}
    self.stime = (datetime.date.today()-datetime.timedelta(self.tarea)).isoformat()
    self.etime = datetime.date.today().isoformat()
    #print self.etime
</t>
<t tx="Zoomq.20041231133106.4">def analyseAll(self):
    """逐一处理所有模块
        - 使用Python 内建结构先建立数据映射
        - self.report{}:
            - cvs 仓库名称:{}
                - commits: ; files: ;
                - mods:{}
                    - 模块名:{}
                    - commits: ; files: ;
                    - viewcvs:{} 链接到 ViewCVS 各文件的 下载，查看
    # 本地单一文件测试
        his = open("history","r")        
        hislis = his.readlines()
        print "-------------"
        print len(hislis)
        cvs="scm"
        self.report[cvs]=self.analyseDate(hislis)
        print "==============="
        #print self.report
        self.put2xml()
        return
    """
    cvsli = self.chkFiles()    
    for cvs in cvsli:
        #print hisfile
        his = open(self.cvsroot+cvs+"/CVSROOT/history","r")        
        hislis = his.readlines()
        print "-------------"
        print len(hislis)
        self.report[cvs]=self.analyseDate(hislis)
        
    #print self.report
    """成功的数据实例
    {'scm': {'files': 9, 'commits': 20
    , 'mods': {'scm': {'files': 9, 'commits': 20
    ,'viewcvs': {
        'CVSanalyser.leo': ('M', '41d50d27', 'zhouqi', 'scm/statcvs', '1.3',
 'CVSanalyser.leo')
        , 'weeklystat.py': ('M', '41d50d27', 'zhouqi', 'scm/statcvs',
 '1.4', 'weeklystat.py')
        , 'weeklystat.xsl': ('M', '41d4ec4c', 'zhouqi', 'scm/sta
tcvs', '1.3', 'weeklystat.xsl')
        , 'cvsanalyser.conf': ('M', '41d50d27', 'zhouqi',
 'scm/statcvs', '1.2', 'cvsanalyser.conf')
        , 'statcvs.sh.py': ('M', '41d4ec4c', '
zhouqi', 'scm/statcvs', '1.6', 'statcvs.sh.py')
        , 'weeklystat.xml': ('A', '41d0f6
92', 'zhouqi', 'scm/statcvs', '1.1', 'weeklystat.xml')
        , 'style.css': ('A', '41d0
f7b3', 'zhouqi', 'scm/statcvs', '1.1', 'style.css')
        , 'cvsanalyser.py': ('M', '41
d50d27', 'zhouqi', 'scm/statcvs', '1.2', 'cvsanalyser.py')
        , 'sinaeye.ico': ('A',
 '41d0f7b3', 'zhouqi', 'scm/statcvs', '1.1', 'sinaeye.ico')
        }
    }
}
}}
    """
        
        
        </t>
<t tx="Zoomq.20041231133106.5">def put2xml(self):
    """汇出数据为XML文件！
        - 使用轻型XML操作库 Elements and Element Trees
        - @see: U{Elements&lt;http://effbot.org/zone/element.htm&gt;}
    """
    re = self.report
    zday = time.strftime("%Y-%m-%d",time.localtime(time.time()))
    print zday
    ztime = time.strftime("%X",time.localtime(time.time()))
    # 必须使用系统的绝对路径！否则无法 cron 自动执行
    tree = ElementTree.parse(self.xml).getroot()
    week = tree.findall("week")
    # 先判定是否要覆盖记录
    done = 0
    for node in week:
        if(zday==node.attrib["date"]):            
            #print node.attrib["date"]
            done = 1
            tree.remove(node)
            break
    #tree.SubElement(tree, "week")
    if(1==done):        
        print "recorded xml! new upgrade it!"        
    else:
        print "need recording...will exp. as xml file" 
    neweek = Element("week")
    neweek.set("date", zday)     
    neweek.set("time", ztime)       
    statcount = {'files':0
        ,'commits':0
        }                
    for proj in re:
        #print self.report[proj]
        #print proj
        newcvs = SubElement(neweek, "cvs")            
        newcvs.set("name", proj)
        newcvs.set("files", str(re[proj]["files"])) 
        newcvs.set("commits", str(re[proj]["commits"]))
        statcount["files"]+=re[proj]["files"]
        statcount["commits"]+=re[proj]["commits"]
        for mod in re[proj]["mods"]:
            module = SubElement(newcvs, "module")
            module.set("name", mod)
            module.set("files", str(re[proj]["mods"][mod]["files"])) 
            module.set("commits", str(re[proj]["mods"][mod]["commits"]))    
            for view in re[proj]["mods"][mod]["viewcvs"]:
                file = Element("file")
                #ViewCVS 处理
                his = re[proj]["mods"][mod]["viewcvs"][view] 
                #print re[proj]["mods"][mod]["viewcvs"][view]        
                file.set("name", view) 
                # 小心谨慎的拼合！
                file.set("view", self.viewcvs+his[3]+"/"+his[5]+"?root="+proj+"&amp;rev="+his[4]+"&amp;view=auto")
                file.set("load", self.viewcvs+"*checkout*/"+his[3]+"/"+his[5]+"?rev="+his[4])
                module.append(file)
            #print re[proj]["mods"][mod]
        neweek.set("commits", str(statcount["commits"]))
        neweek.set("files", str(statcount["files"]))     
    tree.append(neweek)
    #ElementTree.ElementTree(tree).write("out.xml")
    code = tostring(tree)
    #print code
    print self.xml
    open(self.xml,"w").write(self.xmlhead+code)</t>
<t tx="Zoomq.20041231133550"># 作为参照的 Limodou 版本的日志分析脚本！
@ignore
@language python
&lt;&lt; cvsdelta declarations &gt;&gt;
@others

if __name__=="__main__":
    main()


</t>
<t tx="Zoomq.20041231133550.1">"""cvsdelta 1.0

Copyright (c) 2001-2002 by limodou(chatme@263.net)

version 1.0 $Date: 2005/01/05 07:13:36 $

Sometimes you want to know which files was modified from a tagged or
a special time in cvs. I know the 'history' file in cvs repository saved
all changed events that you have made. But I cann't find a good command
to list all changed files, so I write this little program to do this. I
wish it will be some helpful for you. Good luck.

This program is free software; you can redistribute and/or modify them under the 
terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2 of the License, or (at your option) any later version. 
A copy of the license is included in GNU General Public License.

$Id: CVSanalyser.leo,v 1.13 2005/01/05 07:13:36 zhouqi Exp $
"""

import getopt, sys, os

version="cvsdelta 1.0 build 2001-08-24"

</t>
<t tx="Zoomq.20041231133550.2">def usage():
    print """cvsdelta version 1.0 copyright (c) 2001-2002 limodou

This program is used with cvs. It'll list the changed files from a tagged
or a special time.

This program is free software; you can redistribute and/or modify them under the 
terms of the GNU General Public License as published by the Free Software 
Foundation; either version 2 of the License, or (at your option) any later version. 
A copy of the license is included in GNU General Public License.

Usage:

python cvsdelta.py &lt;-t tag|-d date&gt; [-r cvsroot|-f historyfile] [-vu] module

    -t tag          A tag that you have added on to the module
    -d date         Special time. You can use these:
                    yyyy-mm-dd, yyyy-mm-dd hh:mm:ss

This two option will be only one available.

    -r cvsroot      Cvs root path. It can be pserver mode or a local path.
    -f historyfile  Cvs history file. You can specify the history file without 
                    needing a real cvs repository.

If above two option is not given, the program will use CVSROOT enviroment
variable.

    -v              Print the program version.
    -u              Print this infomation."""
</t>
<t tx="Zoomq.20041231133550.3">def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "uvt:d:r:f:", [])
    except getopt.GetoptError:
        usage()
        sys.exit(2)
    mode='' #record check mode : tag or date
    info=''
    hisfile=''
    if os.environ.has_key('CVSROOT'):   #get cvsroot path
        cvsroot = os.environ['CVSROOT']
    else:
        cvsroot = ''
    for o, a in opts:
        if o == '-u':
            usage()
            sys.exit()
        elif o == '-v':
            print version
            sys.exit()
        elif o == '-t':
            mode='tag'
            info=a
        elif o == '-d':
            mode='date'
            info=a
        elif o == '-r':
            cvsroot = a
        elif o == '-f':
            hisfile = a
    
    #find history file
    if cvsroot :
        if cvsroot.count('pserver'):
            a=cvsroot.split(':')
            cvsroot=a[3]
            hisfile=makepath(cvsroot, 'CVSROOT/history')
            if sys.platform == 'win32':
                hisfile=hisfile.replace('\\', '/')
            user, host=a[2].split('@')
            if ftp_getfile(hisfile, 'history', host, user, ''):
                hisfile='history'
            else:
                sys.exit(4)
        else:
            hisfile=makepath(cvsroot, 'CVSROOT/history')

    if mode == '' or hisfile == '' or len(args)!=1 :
        usage()
        sys.exit(1)

    if mode == 'date':
        info=getdate(info)

    module=args[0]

    run(hisfile, module, mode, info)
</t>
<t tx="Zoomq.20041231133550.4">etags=['M', 'A']

#parse a time string into hex value
def getdate(date):
    import re,time
    mode=[re.compile(r"(\d{4})-(\d{2})-(\d{2})"),
          re.compile(r"(\d{4})-(\d{2})-(\d{2}) (\d){2}:(\d){2}:(\d){2}")]
    for r in mode:
        result=r.search(date)
        if result:
            t=tuple([int(i) for i in result.groups()])
            return "%08x" % (int(time.mktime(t+(0,)*(9-len(t)))),)
    return 0
</t>
<t tx="Zoomq.20041231133550.5">#depend on there exist pserver mode, will retrive the file through ftp
def ftp_getfile(desfile, locfile, host, user='anonymous', passwd=''):
    from ftplib import FTP
    if passwd == '':
        from getpass import getpass
        passwd=getpass('\nUser '+user+'\nInput password:')
    try:
        ftp=FTP(host, user, passwd)
        ftp.retrbinary('RETR '+desfile, open(locfile, 'w').write)
    except Exception, err:
        print err
        return 0
    else:
        ftp.quit()
        return 1
</t>
<t tx="Zoomq.20041231133550.6">#join path and file
def makepath(path, file):
    import os.path
    return os.path.normpath(os.path.join(path, file))
</t>
<t tx="Zoomq.20041231133550.7">def run(hisfile, module, mode, info):
    files={}
    maxpathlen=0
    maxfilelen=0
    for line in open(hisfile).readlines():
        status, date, path, revision, file = analyseline(line.strip())
        if mode == 'tag':   #use tag search mode
            if status != 'T':   #if 'T' status, not then skip
                continue
            else:
                if revision == info :   #found the tag, then change into date search mode
                    info = date
                    mode = 'date'
        elif mode == 'date':    #use date search mode
            if status in etags and path.startswith(module) and date&gt;=info: #if available status and special module name
                import time
                sdate=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(date, 16)))
                v=(path, file)
                files[v]=sdate
                maxpathlen=max((maxpathlen, len(path), 20))
                maxfilelen=max((maxfilelen, len(file), 20))
    s=''
    head="\n%-*s\tDate\t\t\t%-*s\n%*s\t-------------------\t%*s" % \
        (maxpathlen, 'Module/Path', maxfilelen, 'Filename', maxpathlen, '-'*maxpathlen, maxfilelen, '-'*maxfilelen)
    s+=head+'\n'
    print head
    items=files.items()
    items.sort()
    for (p, f), d in items:
        t="%-*s\t%s\t%-*s" % (maxpathlen, p, d, maxfilelen, f)
        print t
        s+=t+'\n'
    open("result.txt", "w").write(s)
</t>
<t tx="Zoomq.20041231133550.8">def analyseline(line):
    fields=line.split('|')
    return (fields[0][0], fields[0][1:], fields[3], fields[4], fields[5])
</t>
<t tx="Zoomq.20041231133733">def __repr__(self):
    """类自述定义,记录手册等等信息
    """
    return """
    使用手册:
    设置 cvsanalyser.conf 指定对应的 CVS root 的目录，和输出的XML文件，以及文件的编码约定
    cvsanalyser.py 将自动追查所有CVS模块的更新信息
    """</t>
<t tx="Zoomq.20041231134319">def chkFiles(self):
    """逐一搜索有效目录获得History 文件列表
        - 好象没有必要? CVSROOT 目录是每个库的唯一!
    """
    files = []
    for key in self.cvs:
        files.append(key)
    return files</t>
<t tx="Zoomq.20041231135046"># 标准设置文件用以集中控制分析行为
#$Id: cvsanalyser.conf,v 1.5 2005/01/04 12:07:28 zhouqi Exp $
# 升级为 203 的 ViewCVS 环境
[Path]
cvsroot = /cvs/
[Target]
#日期区间设置,单位是天
time=7
# cvs仓库列表 使用空格指定多个仓库名
# 此名称必须与实际CVS目录；ViewCVS设置；全部一致！
cvs=scm MTA sinaInterface sina668 sinasys webmail runmanage sinaIndex
# ViewCVS 的设置
viewcvs = http://10.88.15.203/viewcvs/
#输出的XML相关设定
xml = /usr/local/www/data/statcvs/historystat.xml
#/usr/local/www/data/statcvs/historystat.xml
</t>
<t tx="Zoomq.20041231151106">def analyseDate(self,historic):
    """根据日期进行统计
        - 是每个CVS 的针对性分析
    """
    rep = []
    #stat = 0
    for line in historic:
        info = self.analyseLine(line)
        #'%Y-%m-%d %H:%M:%S'
        sdate=time.strftime('%Y-%m-%d', time.localtime(int(info[1], 16)))
        if(sdate&gt;=self.stime):            
            if(info[0]in"AMT"):
                #stat+=1
                rep.append(info)
    # 数组长度就是CVS 的总提交修改数！commits
    
    print "&lt;&lt;history in date right"
    print len(rep)    
    return self.analyseAct(rep)
</t>
<t tx="Zoomq.20041231151106.1">def analyseAct(self,list):
    """根据行为分析
        - 关注 M|A 作为更新
        - T 作为版本标记行为
        - 统计不同模块中的更新情况！
            - 变更次数
            - 文件数            
        - 统计整个库的修改文件数
    """
    rep = {}
    rep["commits"]=0
    rep["files"]=0
    modict={}   #记录有更新的模板信息
    fdict={}   #记录有更新的文件    
    for line in list:
        if(line[0] in "AMT"):
            rep["commits"]+=1
            #print line
            #模块处理
            moudle = line[3].split("/")[0]
            if(moudle in modict):
                modict[moudle]["commits"]+=1
                fdict=self.analyseFile(fdict,moudle,line)
            else:
                #新发现的模块
                print "moudle:::"+moudle
                modict[moudle]={}
                modict[moudle]["commits"]=1
                modict[moudle]["files"]=1                    
                # 文件处理
                fdict=self.analyseFile(fdict,moudle,line)
        else:
            pass
    rep["mods"]=modict
    for mod in rep["mods"]:
        # 统计每模块的文件信息
        rep["mods"][mod]["viewcvs"]=fdict[mod]
        rep["mods"][mod]["files"]=len(fdict[mod])
        # 统计整个库的文件信息
        rep["files"]+=rep["mods"][mod]["files"]
    #rep["viewcvs"]=self.viewcvsFiles(fdict)
    
    """"
    for m in fdict:
        print len(fdict[m])
        for f in fdict[m]:
            print fdict[m][f]
    """
    return rep
    </t>
<t tx="Zoomq.20041231153937">def analyseLine(self,line):
    """分析日志行，分解得到信息元组
        - 操作类型 
        - 操作日期
        - 提交人
        - 模块
        - 版本
        - 文件名
    """
    fields=line.split('|')
    return (fields[0][0], fields[0][1:], fields[1],fields[3], fields[4], fields[5][:-1])
</t>
<t tx="Zoomq.20041231162737">#@ignore
#@language python
&lt;&lt; weeklystat declarations &gt;&gt;
@others


if __name__ == '__main__':
    """基本运行模式
    """
    week = WeeklyStat()
    week.ckAll()
</t>
<t tx="Zoomq.20041231162737.1"># -*- coding: UTF-8 -*-
"""weeklystat auto WeekLy StatCVS HTML analyze
    - 每周StatCVS 分析结果汇总！
    - 通过 cvs log -d "yyyy-mm-dd"\&lt; &gt; cvs.log
    - 限制Log 分析的配合得到本周的变更信息！
    - 汇出为XML

@version: $Id: weeklystat.py,v 1.5 2005/01/04 10:16:09 zhouqi Exp $
@author: U{Zoom.Quiet&lt;mailto:Zoom.Quiet@gmail.com&gt;}
@see: U{Zoomq@mail.sina&lt;http://10.88.15.200/mailwiki/ZoomQuiet&gt;}

"""
import sys,os,string
import time
from elementtree import ElementTree
from elementtree.ElementTree import Element, SubElement, tostring

</t>
<t tx="Zoomq.20041231162737.2">class WeeklyStat:
    """主类，集成所有处理
    """
	@others
</t>
<t tx="Zoomq.20041231162737.3">def __init__(self):
    """初始化参数
        - "scm"
        ,"MTA"
        ,"sinaInterface"
        ,"sina668"
        ,"sinasys"
        ,"webmail"
        ,"runmanage"
        ,"sinaIndex"
    """
    self.xml = "/usr/home/statcvs/snapcvs/pub/weeklystat.xml"
    self.log = ""
    self.xmlhead = """&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!-- edited with elementtree (http://effbot.org/zone/element-index.htm) by Zoom.Quiet  --&gt;
&lt;?xml-stylesheet type="text/xsl" href="weeklystat.xsl"?&gt;
    """
    self.cvsroot = "/usr/home/statcvs/snapcvs/"
    self.pubroot = "/usr/home/statcvs/snapcvs/pub"
    self.zday = time.strftime("%Y-%m-%d",time.localtime(time.time()))
    self.mFiles="cat %s/index.html | grep \"Files: \" | cut -d \" \" -f 2|cut -d \"&lt;\" -f 1"
    self.mRevisions="cat %s/index.html | grep \"Revisions: \" | cut -d \" \" -f 2|cut -d \"&lt;\" -f 1"
    self.mLines="cat %s/index.html | grep \"Code: \" | cut -d \":\" -f 2 | cut -d \"&lt;\" -f 1 | cut -d \" \" -f 2"

    self.report = {}
    self.cvs = ("scm"
        ,"MTA"
        ,"sinaInterface"
        ,"sinasys"
        ,"webmail"
        ,"runmanage"
        ,"sinaIndex")
</t>
<t tx="Zoomq.20041231162737.4">def wlkCvsCo(self):
    """逐一搜索所有模块综合汇报信息
    """
    dirs = {}
    os.chdir(self.cvsroot)
    for key in self.cvs:
        #os.chdir(self.cvsroot+key)
        dirs[key]={}
        subdir = os.listdir(self.cvsroot+key)
        for node in subdir:
            if("CVS"==node or "CVSROOT"==node or os.path.isfile(self.cvsroot+key+"/"+node)):
                pass
            else:
                dirs[key][node]={}
    return dirs
</t>
<t tx="Zoomq.20041231162737.5">def ckAll(self):
    """逐一搜索所有模块综合汇报信息
    """
    dirs = self.wlkCvsCo()
    print dirs
    for cvs in dirs:
        os.chdir(self.cvsroot+cvs)
        #print self.cvsroot+cvs
        for module in dirs[cvs]:
            page = self.pubroot+"/"+cvs+"/"+module
            # 修改文件分析
            findout = os.popen(self.mFiles%page)
            r = findout.read()
            if(0!= len(r)):
                dirs[cvs][module]["files"]=r[:-1]
            # 修改次数分析
            findout = os.popen(self.mRevisions%page)
            r = findout.read()
            if(0!= len(r)):
                dirs[cvs][module]["commits"]=r[:-1]
            # 修改行数分析
            findout = os.popen(self.mLines%page)
            r = findout.read()
            if(0!= len(r)):
                dirs[cvs][module]["lines"]=r[:-1]
    self.report = dirs
    self.put2xml()
</t>
<t tx="Zoomq.20041231162737.6">def put2xml(self):
    """汇出数据为XML文件！
        - 使用轻型XML操作库 Elements and Element Trees
        - @see: U{Elements&lt;http://effbot.org/zone/element.htm&gt;}
    """
    stat = self.report
    print stat
    tree = ElementTree.parse(self.xml).getroot()
    week = tree.findall("week")
    # 先判定是否要记录
    done = 0
    for node in week:
        if(self.zday==node.attrib["date"]):
              done = 1
              break
        cvs = node.findall("cvs")
    #tree.SubElement(tree, "week")
    if(0==done):
        print "need recording...will exp. as xml file"

        neweek = Element("week")
        neweek.set("date", self.zday)
        statcount = {'files':0
            ,'commits':0
            ,'lines':0
            }                
        for proj in stat:
            #print stat[proj]
            newcvs = SubElement(neweek, "cvs")
            newcvs.set("name", proj)
            #print stat[proj]
            #{'scm': {'files': '2', 'reverions': '4', 'lines': '15'}, 'Jira-Chinese': {}}
            modcount = {'files':0
            ,'commits':0
            ,'lines':0
            }
            for moudle in stat[proj]:                  
                submod = SubElement(newcvs, "module")
                submod.set("name", moudle)
                if(0==len(stat[proj][moudle])):
                    submod.set("files", "0")
                    submod.set("commits", "0")
                    submod.set("lines", "0")
                else:
                    for item in stat[proj][moudle]:
                        #print stat[proj][moudle][item]                            
                        submod.set(item, str(stat[proj][moudle][item]))
                        modcount[item]+=int(stat[proj][moudle][item])
                        statcount[item]+=int(stat[proj][moudle][item])
            for totl in modcount:                    
                newcvs.set(totl, str(modcount[totl]))
            #print tostring(newcvs)
            #print modcount
        #print statcount
        for totl in statcount:                    
            neweek.set(totl, str(statcount[totl]))
        #print tostring(neweek)
        tree.append(neweek)
        #print tree
    else:
        print "recorded ...xml file not edit!"
        return
    #ElementTree.ElementTree(tree).write("out.xml")
    code = tostring(tree)
    #print code
    #open(self.xml,"w").write(self.xmlhead+code)</t>
<t tx="Zoomq.20050104162522">def viewcvsFiles(self,hisline):
    """根据行为列表组合 ViewCVS 链接
        - 在线观看
        - 下载
    仅仅在输出XML等等其它文件时调用
    """
    url=""
    
    
    return url
            
    

</t>
<t tx="Zoomq.20050104164931">def analyseFile(self,fdict,mod,hisline):
    """使用专门的容器,累计分析文件信息
        - fdict 上级的文件统计容器
        - 当前的模块信息
        - 当前的文件History 行信息
    """
    file = hisline[5]
    if mod in fdict:
        if file in fdict[mod]:
            fdict[mod][file]=hisline
        else:
            fdict[mod][file]=hisline
    else:
        #创建新的模块文件信息容器
        fdict[mod]={}
        fdict[mod][file]=hisline
        
    return fdict</t>
<t tx="Zoomq.20050104171344">#@ignore
@silent
@root-code historystat.xsl
&lt;&lt;XSL head&gt;&gt;
&lt;html&gt;
&lt;head&gt;
&lt;!--"""
StatCVS 分析结果XML 快速XSLT模板
Zoomq::041227 使用 CSS+JS 进行点击支持

$Id: CVSanalyser.leo,v 1.13 2005/01/05 07:13:36 zhouqi Exp $
"""--&gt;
&lt;title&gt;新浪·研发·邮件-CVS每周活动History统计
 @ 
FreeBSD+Python+XML&lt;/title&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;

&lt;link href="sinaeye.ico" rel="shortcut icon" /&gt;
&lt;link rel="stylesheet" type="text/css" href="style.css" /&gt;

&lt;&lt;Script&gt;&gt;

&lt;/head&gt;

&lt;body  leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" &gt;

&lt;&lt;root&gt;&gt;


&lt;/body&gt;
&lt;/html&gt;
&lt;&lt;XSL tail&gt;&gt;</t>
<t tx="Zoomq.20050104171344.1">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:function="http://www.infopro.cn/epservernamespace"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
&gt;
&lt;xsl:template match="/"&gt;</t>
<t tx="Zoomq.20050104171344.2">&lt;script language="JavaScript" &gt; 
//o=document.getElementById('xxx');o.style.display=o.style.display=='none' ? '' : 'none'
function _showDIV(divID){
    //alert(divID);
    var _obj = document.getElementById(divID);
    //alert(divID+"\n"+_obj);
    _obj.style.display = (_obj.style.display=='none')? '' : 'none';    
    return;
}
&lt;/script&gt;</t>
<t tx="Zoomq.20050104171344.3">&lt;xsl:for-each select="root"&gt;
&lt;xsl:for-each select="week"&gt;
&lt;h1 style="cursor : hand"&gt;
	&lt;xsl:attribute name="onclick"&gt;
	_showDIV("stat-&lt;xsl:value-of select="@date" /&gt;");
	&lt;/xsl:attribute&gt;
CVS活动周分析 截止日期&lt;xsl:value-of select="@date" /&gt;
&lt;/h1&gt;
&lt;ul&gt;
    &lt;li&gt;分析时间:   &lt;xsl:value-of select="@time" /&gt;
        &lt;/li&gt;
    &lt;li&gt;总更新文件数:   &lt;xsl:value-of select="@files" /&gt;
        &lt;/li&gt;
    &lt;li&gt;总提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
        &lt;/li&gt;
    &lt;li&gt;
    &lt;div style="border : 1px dotted #ede;
                display : none;"&gt;
            &lt;xsl:attribute name="id"&gt;stat-&lt;xsl:value-of select="@date" /&gt;&lt;/xsl:attribute&gt;
            
    &lt;ul&gt;
    &lt;&lt;cvs&gt;&gt;
    &lt;/ul&gt;
&lt;/xsl:for-each&gt;&lt;!--week loop--&gt;
&lt;hr/&gt;

&lt;/xsl:for-each&gt;&lt;!--root--&gt;
&lt;!-- end of Page--&gt;</t>
<t tx="Zoomq.20050104171344.4">&lt;xsl:for-each select="cvs"&gt;
&lt;h3 style="cursor : hand"&gt;
&lt;xsl:attribute name="onclick"&gt;
_showDIV("cvs-&lt;xsl:value-of select="../@date" /&gt;-&lt;xsl:value-of select="@name" /&gt;");
//alert("cvs-&lt;xsl:value-of select="@name" /&gt;");
&lt;/xsl:attribute&gt;

&lt;xsl:value-of select="@name" /&gt; 库 中:&lt;/h3&gt;
&lt;li&gt;总更新文件数:   &lt;xsl:value-of select="@files" /&gt;
    &lt;/li&gt;
&lt;li&gt;总提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
    &lt;/li&gt;
&lt;li&gt;

    &lt;ul&gt;
    
    &lt;div style="border : 0px dotted #993300;
        display : none;
        background-color : #336699;
        color:#fff;"&gt;
        
    &lt;xsl:attribute name="id"&gt;cvs-&lt;xsl:value-of select="../@date" /&gt;-&lt;xsl:value-of select="@name" /&gt;&lt;/xsl:attribute&gt;
    &lt;&lt;module&gt;&gt;
    &lt;/div&gt;
    
    &lt;/ul&gt;
&lt;/li&gt;
&lt;/xsl:for-each&gt;
&lt;/ul&gt;

&lt;/div&gt;
&lt;/li&gt;
</t>
<t tx="Zoomq.20050104171344.5">&lt;xsl:for-each select="module"&gt;
&lt;h5&gt;模块 &lt;xsl:value-of select="@name" /&gt; 更新细节:&lt;/h5&gt;
    &lt;li&gt;更新文件数:   &lt;xsl:value-of select="@files" /&gt;
        &lt;/li&gt;
    &lt;li&gt;提交修改数:   &lt;xsl:value-of select="@commits" /&gt;
        &lt;/li&gt;
    &lt;li&gt;文件:
        &lt;&lt;file&gt;&gt;
    &lt;/li&gt; 
               
&lt;/xsl:for-each&gt;</t>
<t tx="Zoomq.20050104171344.6">&lt;/xsl:template&gt;
&lt;/xsl:stylesheet&gt;</t>
<t tx="Zoomq.20050104183828">&lt;ul class="deep0"&gt;&lt;xsl:for-each select="file"&gt;
    &lt;li&gt;[&lt;a target="_blank"&gt;
    &lt;xsl:attribute name="href"&gt;&lt;xsl:value-of select="@view" /&gt;&lt;/xsl:attribute&gt;
        查阅   
        &lt;/a&gt;
    | &lt;a target="_blank"&gt;
    &lt;xsl:attribute name="href"&gt;&lt;xsl:value-of select="@load" /&gt;&lt;/xsl:attribute&gt;
        下载
        &lt;/a&gt;
    ]文件: 
    &lt;xsl:value-of select="@name" /&gt;
    
    &lt;/li&gt;
    
    &lt;/xsl:for-each&gt;
&lt;/ul&gt;</t>
</tnodes>
</leo_file>
