Changeset 29

Show
Ignore:
Timestamp:
2008年07月30日 16时18分37秒 (4 years ago)
Author:
jiangx
Message:

See #7: add get_logs, get_page_logs method to RcsLog? class.

Location:
trunk/pysvnmanager
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/pysvnmanager/model/rcsbackup.py

    r28 r29  
    22# -*- coding: utf-8 -*- 
    33 
     4from __future__ import division 
     5 
    46import os 
     7import sys 
     8import re 
     9import math 
    510 
    611import logging 
    712log = logging.getLogger(__name__) 
    813 
    9 import sys 
    1014#reload(sys) # in Python2.5, method sys.setdefaultencoding  
    1115            #will be delete after initialize. we need reload it. 
     
    1519CMD_CO="RCSINIT= co" 
    1620CMD_RCS="RCSINIT= rcs" 
     21CMD_RLOG="RCSINIT= rlog" 
     22CMD_RCSDIFF="RCSINIT= rcsdiff" 
    1723 
    1824 
     
    9197        raise Exception, "Command: %s\nError Message: %s\n" % (cmd, buff) 
    9298     
     99 
     100class RcsLog(object): 
     101     
     102    def __init__(self, filename): 
     103        assert filename and isinstance(filename, basestring) 
     104        self.__file = filename 
     105        self.__log_per_page = 10 
     106        self.p = {} 
     107        self.p['rcs'] = re.compile(r'^RCS file:\s*(.*)$', re.M) 
     108        self.p['head'] = re.compile(r'^head:\s*(.*)$', re.M) 
     109        self.p['total'] = re.compile(r'^total revisions:\s*(.*)$', re.M) 
     110        self.p['revision'] = re.compile(r'^revision\s+([^\s]*)', re.M) 
     111        self.p['date'] = re.compile(r'^date:\s+(.*);\s+author:', re.M) 
     112        self.p['author'] = re.compile(r'^date:.*;\s+author:\s*(.*?);', re.M) 
     113        self.reload() 
     114     
     115    def __get_page_count(self): 
     116        return int(math.ceil(self.__total/self.__log_per_page)) 
     117     
     118    total_page = property(__get_page_count) 
     119 
     120    def __get_log_count(self): 
     121        return self.__total 
     122     
     123    total = property(__get_log_count) 
     124     
     125    def __get_rcsfile(self): 
     126        return self.__rcsfile 
     127     
     128    rcsfile = property(__get_rcsfile) 
     129         
     130    def __get_head(self): 
     131        return self.__head 
     132     
     133    head = property(__get_head) 
     134         
     135    def __get_log_per_page(self): 
     136        return self.__log_per_page 
     137     
     138    def __set_log_per_page(self, count): 
     139        count = int(count) 
     140        if count <=0: 
     141            count = 10 
     142        self.__log_per_page = count 
     143 
     144    log_per_page = property(__get_log_per_page, __set_log_per_page) 
     145     
     146    def reload(self): 
     147        cmd = '%(cmd)s -L -h -N %(file)s' % {'cmd':CMD_RLOG, 'file':self.__file} 
     148        buff = os.popen(cmd).read().strip() 
     149         
     150        # RCS file: 1,v 
     151        m = self.p['rcs'].search(buff) 
     152        if m: 
     153            self.__rcsfile = m.group(1) 
     154        else: 
     155            self.__rcsfile = "" 
     156 
     157        # head: 1.XX 
     158        m = self.p['head'].search(buff) 
     159        if m: 
     160            self.__head = m.group(1) 
     161        else: 
     162            self.__head = "" 
     163             
     164        # total revisions: XX 
     165        m = self.p['total'].search(buff) 
     166        if m: 
     167            self.__total = int(m.group(1)) 
     168        else: 
     169            self.__total = 0 
     170     
     171    def get_page_logs(self, pagenum): 
     172        total_page = self.total_page 
     173         
     174        if total_page ==0: 
     175            return [] 
     176 
     177        if pagenum<=0: 
     178            pagenum=1 
     179        elif pagenum>total_page: 
     180            pagenum=total_page 
     181         
     182        heads = self.__head.rsplit('.',1) 
     183        rev0=int(heads[1]) 
     184         
     185        rev2 = rev0 - ((pagenum-1) * self.__log_per_page) -1 
     186        if rev2<1: rev2=1 
     187        rev1 = rev2 - self.__log_per_page + 1 
     188        if rev1<1: 
     189            rev1=1 
     190 
     191        rev0 = self.__head 
     192        rev1 = "%s.%d" % (heads[0], rev1) 
     193        rev2 = "%s.%d" % (heads[0], rev2) 
     194 
     195        self.get_logs(rev1, rev2, rev0) 
     196        return self.revs 
     197     
     198    def get_logs(self, rev1="", rev2="", rev3=""): 
     199        self.revs=[] 
     200        opts="" 
     201        if not rev1: 
     202            if not rev2: 
     203                opts="" 
     204            else: 
     205                opts="-r:%s" % rev2 
     206        else: 
     207            if not rev2: 
     208                opts="-r%s:" % rev1 
     209            else: 
     210                opts="-r%s:%s" % (rev1, rev2) 
     211 
     212        if rev3: 
     213            opts="%s,%s" % (opts, rev3) 
     214 
     215        cmd = '%(cmd)s %(opts)s -L -N %(file)s' % {'cmd':CMD_RLOG, 'opts':opts, 'file':self.__file} 
     216        log.debug('Command: '+cmd) 
     217        buff = os.popen(cmd).read().strip().rstrip('=').rstrip() 
     218         
     219        while True: 
     220            pos = buff.rfind('\n'+'-'*28+'\n') 
     221            if pos==-1: 
     222                break 
     223            match = buff[pos+30:] 
     224            buff=buff[:pos] 
     225 
     226            lines=match.split('\n') 
     227            if len(lines)<3: 
     228                log.error("wrong rcs format: %s" % match) 
     229                continue 
     230 
     231            # revision 1.XX    locked by: XXX; 
     232            m = self.p['revision'].search(lines[0]) 
     233            commit_revision = "" 
     234            if m: 
     235                commit_revision = m.group(1) 
     236            else: 
     237                log.error("not find revision in line: %s" % lines[1]) 
     238                continue 
     239                         
     240            # date: YYYY/MM/DD hh:mm:ss;  author: XX;  ... 
     241            m = self.p['date'].search(lines[1]) 
     242            commit_time = "" 
     243            if m: 
     244                commit_time = get_unicode(m.group(1)) 
     245            else: 
     246                log.error("not find date in line: %s" % lines[1]) 
     247                continue 
     248 
     249            # date: YYYY/MM/DD hh:mm:ss;  author: XX;  ... 
     250            m = self.p['author'].search(lines[1]) 
     251            commit_author = "" 
     252            if m: 
     253                commit_author = get_unicode(eval("'%s'" % m.group(1))) 
     254            else: 
     255                log.error("not find author in line: %s" % lines[1]) 
     256                continue 
     257             
     258            # logs... 
     259            commit_log = get_unicode('\n'.join(lines[2:])) 
     260             
     261            self.revs.append({'revision':commit_revision, 
     262                              'date':commit_time, 
     263                              'author':commit_author, 
     264                              'log':commit_log}) 
     265         
     266        return self.revs 
  • trunk/pysvnmanager/tests/test_rcs_backup.py

    r27 r29  
    122122 
    123123    def testLogs(self): 
    124         self.writefile() 
    125         assert os.access(self.wcfile, os.R_OK) 
    126         print "testLogs" 
    127         pass 
    128  
     124        for i in range(1,11): 
     125            # new file, backup to r1.1 
     126            self.writefile(i) 
     127            rcs.backup(self.wcfile, comment="Test no. %d" % i, user="User1") 
     128         
     129        rcslog = rcs.RcsLog(self.wcfile) 
     130        assert "rcstest.txt,v" in rcslog.rcsfile, rcslog.rcsfile 
     131        assert rcslog.head=='1.10', rcslog.head 
     132        assert rcslog.total==10, rcslog.total 
     133 
     134        for i in range(11,15): 
     135            # new file, backup to r1.1 
     136            self.writefile(i) 
     137            rcs.backup(self.wcfile, comment="第 %d 次提交测试。" % i, user="蒋鑫") 
     138 
     139        assert rcslog.head=='1.10', rcslog.head 
     140        rcslog.reload() 
     141        assert rcslog.head=='1.14', rcslog.head 
     142        assert rcslog.total==14, rcslog.total 
     143         
     144        logs = rcslog.get_logs() 
     145        assert len(logs)==14, logs 
     146        assert logs[3]['revision'] == u'1.4', logs[3]['revision'] 
     147        assert logs[3]['author'] == u'User1', logs[3]['author'] 
     148        assert logs[3]['log'] == u'Test no. 4', logs[3]['log'] 
     149        assert logs[13]['revision'] == u'1.14', logs[13]['revision'] 
     150        assert logs[13]['author'] == u'蒋鑫', logs[13]['author'].encode('utf-8') 
     151        assert logs[13]['log'] == u'第 14 次提交测试。', logs[13]['log'].encode('utf-8') 
     152         
     153        logs = rcslog.get_logs('1.9','1.12') 
     154        assert len(logs)==4, logs 
     155        assert logs[1]['revision'] == u'1.10', logs[1]['revision'] 
     156        assert logs[1]['author'] == u'User1', logs[1]['author'] 
     157        assert logs[1]['log'] == u'Test no. 10', logs[1]['log'] 
     158        assert logs[2]['revision'] == u'1.11', logs[2]['revision'] 
     159        assert logs[2]['author'] == u'蒋鑫', logs[2]['author'].encode('utf-8') 
     160        assert logs[2]['log'] == u'第 11 次提交测试。', logs[2]['log'].encode('utf-8') 
     161 
     162 
     163        logs = rcslog.get_logs('','1.12') 
     164        assert len(logs)==12, logs 
     165        assert logs[10]['revision'] == u'1.11', logs[10]['revision'] 
     166 
     167        logs = rcslog.get_logs('1.12','') 
     168        assert len(logs)==3, len(logs) 
     169        assert logs[1]['revision'] == u'1.13', logs[1]['revision'] 
     170 
     171        logs = rcslog.get_logs('1.7','1.11', '1.14') 
     172        assert len(logs)==6, len(logs) 
     173        assert logs[4]['revision'] == u'1.11', logs[1]['revision'] 
     174        assert logs[5]['revision'] == u'1.14', logs[1]['revision'] 
     175         
     176        assert rcslog.total_page == 2, rcslog.total_page 
     177        rcslog.log_per_page=0 
     178        assert rcslog.log_per_page==10, rcslog.log_per_page 
     179        rcslog.log_per_page=5 
     180        assert rcslog.log_per_page==5, rcslog.log_per_page 
     181        assert rcslog.total_page == 3, rcslog.total_page 
     182        logs = rcslog.get_page_logs(1) 
     183        logs2= rcslog.get_page_logs(0) 
     184        assert logs == logs2 
     185        assert [x['revision'] for x in logs] == \ 
     186                ['1.9', '1.10', '1.11', '1.12', '1.13', '1.14'], \ 
     187                [x['revision'] for x in logs] 
     188 
     189        logs = rcslog.get_page_logs(2) 
     190        assert [x['revision'] for x in logs] == \ 
     191                ['1.4', '1.5', '1.6', '1.7', '1.8', '1.14'], \ 
     192                [x['revision'] for x in logs] 
     193 
     194        logs = rcslog.get_page_logs(3) 
     195        logs2= rcslog.get_page_logs(30) 
     196        assert logs == logs2 
     197        assert [x['revision'] for x in logs] == \ 
     198                ['1.1', '1.2', '1.3', '1.14'], \ 
     199                [x['revision'] for x in logs] 
     200 
     201         
     202    def testLogsNone(self): 
     203        rcslog = rcs.RcsLog(self.wcfile) 
     204        assert rcslog.rcsfile == "", rcslog.rcsfile 
     205        assert rcslog.total == 0, rcslog.total 
     206        assert rcslog.get_page_logs(1) == [], rcslog.get_page_logs(1) 
     207         
    129208if __name__ == '__main__':  
    130209    import unittest