Package trac ::
Package versioncontrol ::
Module cache
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2005-2009 Edgewall Software
4 # Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
5 # All rights reserved.
6 #
7 # This software is licensed as described in the file COPYING, which
8 # you should have received as part of this distribution. The terms
9 # are also available at http://trac.edgewall.org/wiki/TracLicense.
10 #
11 # This software consists of voluntary contributions made by many
12 # individuals. For the exact contribution history, see the revision
13 # history and logs, available at http://trac.edgewall.org/log/.
14 #
15 # Author: Christopher Lenz <cmlenz@gmx.de>
16
17 import os
18
19 from trac .cache import cached
20 from trac .core import TracError
21 from trac .util .datefmt import from_utimestamp , to_utimestamp
22 from trac .util .translation import _
23 from trac .versioncontrol import Changeset , Node , Repository , NoSuchChangeset
24
25
26 _kindmap = {'D': Node .DIRECTORY , 'F': Node .FILE }
27 _actionmap = {'A': Changeset .ADD , 'C': Changeset .COPY ,
28 'D': Changeset .DELETE , 'E': Changeset .EDIT ,
29 'M': Changeset .MOVE }
32 return dict(zip(d .values(), d .keys ()))
33
34 _inverted_kindmap = _invert_dict(_kindmap )
35 _inverted_actionmap = _invert_dict(_actionmap )
36
37 CACHE_REPOSITORY_DIR = 'repository_dir'
38 CACHE_YOUNGEST_REV = 'youngest_rev'
39
40 CACHE_METADATA_KEYS = (CACHE_REPOSITORY_DIR , CACHE_YOUNGEST_REV )
44
45 has_linear_changesets = False
46
47 scope = property(lambda self: self.repos.scope )
48
56
59
62
65
68
71
74
87
89 cset = self.repos.get_changeset (rev)
90 srev = self.db_rev (cset.rev)
91 old_cset = [None]
92
93 @self.env .with_transaction ()
94 def do_sync(db):
95 cursor = db .cursor ()
96 cursor .execute ("""
97 SELECT time,author,message FROM revision
98 WHERE repos=%s AND rev=%s
99 """, (self.id , srev))
100 for time, author, message in cursor :
101 old_cset[0] = Changeset (self.repos, cset.rev, message , author,
102 from_utimestamp (time))
103 if old_cset[0]:
104 cursor .execute ("""
105 UPDATE revision SET time=%s, author=%s, message=%s
106 WHERE repos=%s AND rev=%s
107 """, (to_utimestamp (cset.date), cset.author, cset.message ,
108 self.id , srev))
109 else:
110 self._insert_changeset(cursor , cset.rev, cset)
111 return old_cset[0]
112
113 @cached('_metadata_id')
122
123 - def sync (self, feedback=None, clean=False):
124 if clean:
125 self.log .info('Cleaning cache')
126 @self.env .with_transaction ()
127 def do_clean(db):
128 cursor = db .cursor ()
129 cursor .execute ("DELETE FROM revision WHERE repos=%s",
130 (self.id ,))
131 cursor .execute ("DELETE FROM node_change WHERE repos=%s",
132 (self.id ,))
133 cursor .executemany ("""
134 DELETE FROM repository WHERE id=%s AND name=%s
135 """, [(self.id , k) for k in CACHE_METADATA_KEYS ])
136 cursor .executemany ("""
137 INSERT INTO repository (id,name,value) VALUES (%s,%s,%s)
138 """, [(self.id , k, '') for k in CACHE_METADATA_KEYS ])
139 del self.metadata
140
141 metadata = self.metadata
142
143 @self.env .with_transaction ()
144 def do_transaction(db):
145 cursor = db .cursor ()
146 invalidate = False
147
148 # -- check that we're populating the cache for the correct
149 # repository
150 repository_dir = metadata .get (CACHE_REPOSITORY_DIR )
151 if repository_dir :
152 # directory part of the repo name can vary on case insensitive
153 # fs
154 if os.path .normcase(repository_dir ) \
155 != os.path .normcase(self.name ):
156 self.log .info("'repository_dir' has changed from %r to %r",
157 repository_dir , self.name )
158 raise TracError (_ ("The repository directory has changed, "
159 "you should resynchronize the "
160 "repository with: trac-admin $ENV "
161 "repository resync '%(reponame)s'",
162 reponame=self.reponame or '(default)'))
163 elif repository_dir is None: #
164 self.log .info('Storing initial "repository_dir": %s',
165 self.name )
166 cursor .execute ("""
167 INSERT INTO repository (id,name,value) VALUES (%s,%s,%s)
168 """, (self.id , CACHE_REPOSITORY_DIR , self.name ))
169 invalidate = True
170 else: # 'repository_dir' cleared by a resync
171 self.log .info('Resetting "repository_dir": %s', self.name )
172 cursor .execute ("""
173 UPDATE repository SET value=%s WHERE id=%s AND name=%s
174 """, (self.name , self.id , CACHE_REPOSITORY_DIR ))
175 invalidate = True
176
177 # -- insert a 'youngeset_rev' for the repository if necessary
178 if metadata .get (CACHE_YOUNGEST_REV ) is None:
179 cursor .execute ("""
180 INSERT INTO repository (id,name,value) VALUES (%s,%s,%s)
181 """, (self.id , CACHE_YOUNGEST_REV , ''))
182 invalidate = True
183
184 if invalidate :
185 del self.metadata