File: rlog.py

package info (click to toggle)
viewcvs 0.9.2%2Bcvs.1.0.dev.2004.07.28-4.1etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 1,452 kB
  • ctags: 1,355
  • sloc: python: 10,100; cpp: 840; ansic: 763; yacc: 526; sh: 163; makefile: 115
file content (143 lines) | stat: -rw-r--r-- 4,223 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- Mode: python -*-
#
# Copyright (C) 2000-2002 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
#   Greg Stein, PO Box 760, Palo Alto, CA, 94302
#   gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

import os
import string

from vclib import bincvs

## exception for this class
error = 'rlog error'


class RLogData:
    "Container object for all data parsed from a 'rlog' output."
  
    def __init__(self, filename):
        self.filename = filename
        self.symbolic_name_hash = {}
        self.rlog_entry_list = []

    def LookupBranch(self, rlog_entry):
        index = string.rfind(rlog_entry.revision, '.')
        branch_revision = rlog_entry.revision[:index]

        return self.symbolic_name_hash.get(branch_revision, '')
    

class RLogEntry:
    ## static constants for type of log entry; this will be changed
    ## to strings I guess -JMP
    CHANGE = 0
    ADD = 1
    REMOVE = 2

## Here's the init function, which isn't needed since this class
## is fully initalized by RLogParser when creating a new log entry.
## Let's keep this initializer as a description of what is held in
## the class, but keep it commented out since it only makes things
## slow.
##
##     def __init__(self):
##         self.revision = ''
##         self.author = ''
##         self.branch = ''
##         self.pluscount = ''
##         self.minuscount = ''
##         self.description = ''
##         self.time = None
##         self.type = RLogEntry.CHANGE


def _get_v_file(filename):
    # all RCS files have the ",v" ending
    if filename[-2:] != ",v":
        filename = filename + ',v'

    if os.path.isfile(filename):
        return filename

    # check the Attic for the RCS file
    path, basename = os.path.split(filename)
    filename = os.path.join(path, "Attic", basename)

    if os.path.isfile(filename):
        return filename

    ### create an exception class
    raise error, "rlog file not found: %s" % (filename)

def _get_co_file(v_file):
    # remove the ",v" suffix
    co_file = v_file[:-2]

    # look for, and remove, any Attic component
    path, basename = os.path.split(co_file)
    if path[-6:] == '/Attic':
        return os.path.join(path[:-6], basename)

    return co_file

def GetRLogData(repository, path, revision=''):
    v_file = _get_v_file(path)
    branch, taginfo, revs = bincvs.fetch_log(repository, v_file, revision)
    class _blank:
      pass

    data = RLogData(_get_co_file(v_file))

    for name, rev in taginfo.items():
        # if this is a branch (X.Y.0.Z), then remove the .0 portion
        idx = string.rfind(rev, '.')
        if rev[idx-2:idx] == '.0':
            rev = rev[:idx-2] + rev[idx:]

        ### hmm. this is only useful for *branch names*, which won't overlap
        ### on a specific rev.
        ### note: the tag name associated with a revision will be
        ### non-deterministic because of this overlap.
        ### maybe just omit the name for non-branch tags?
        data.symbolic_name_hash[rev] = name

    for entry in revs:
        new_entry = _blank()

        if entry.changed:
            # extract the plus/minus and drop the sign
            plus, minus = string.split(entry.changed)
            new_entry.pluscount = plus[1:]
            new_entry.minuscount = minus[1:]

            if entry.dead:
                new_entry.type = RLogEntry.REMOVE
            else:
                new_entry.type = RLogEntry.CHANGE
        else:
            new_entry.type = RLogEntry.ADD
            new_entry.pluscount = new_entry.minuscount = ''

        # some goop to drop a trailing newline
        if entry.log[-1:] == '\n':
          new_entry.description = entry.log[:-1]
        else:
          new_entry.description = entry.log

        new_entry.revision = entry.string
        new_entry.author = entry.author
        new_entry.time = entry.date

        data.rlog_entry_list.append(new_entry)

    return data