diff --git a/trac/admin/tests/console-tests.txt b/trac/admin/tests/console-tests.txt
|
a
|
b
|
|
| 41 | 41 | repository alias Create an alias for a repository |
| 42 | 42 | repository list List source repositories |
| 43 | 43 | repository remove Remove a source repository |
| 44 | | repository rename Rename a source repository |
| 45 | 44 | repository resync Re-synchronize trac with repositories |
| 46 | 45 | repository set Set an attribute of a repository |
| 47 | 46 | repository sync Resume synchronization of repositories |
diff --git a/trac/db_default.py b/trac/db_default.py
|
a
|
b
|
|
| 86 | 86 | |
| 87 | 87 | # Version control cache |
| 88 | 88 | Table('repository', key=('id', 'name'))[ |
| 89 | | Column('id'), |
| | 89 | Column('id', type='int'), |
| 90 | 90 | Column('name'), |
| 91 | 91 | Column('value')], |
| 92 | 92 | Table('revision', key=('repos', 'rev'))[ |
| 93 | | Column('repos'), |
| | 93 | Column('repos', type='int'), |
| 94 | 94 | Column('rev'), |
| 95 | 95 | Column('time', type='int'), |
| 96 | 96 | Column('author'), |
| 97 | 97 | Column('message'), |
| 98 | 98 | Index(['repos', 'time'])], |
| 99 | 99 | Table('node_change', key=('repos', 'rev', 'path', 'change_type'))[ |
| 100 | | Column('repos'), |
| | 100 | Column('repos', type='int'), |
| 101 | 101 | Column('rev'), |
| 102 | 102 | Column('path'), |
| 103 | 103 | Column('node_type', size=1), |
diff --git a/trac/versioncontrol/admin.py b/trac/versioncontrol/admin.py
|
a
|
b
|
|
| 126 | 126 | cursor = db.cursor() |
| 127 | 127 | for repos in sorted(repositories, key=lambda r: r.reponame): |
| 128 | 128 | reponame = repos.reponame |
| | 129 | id = rm.get_repository_id(reponame) |
| 129 | 130 | printout(_('Resyncing repository history for %(reponame)s... ', |
| 130 | 131 | reponame=reponame or '(default)')) |
| 131 | 132 | if clean: |
| 132 | | cursor.execute("DELETE FROM revision WHERE repos=%s", |
| 133 | | (reponame,)) |
| 134 | | cursor.execute("DELETE FROM node_change " |
| 135 | | "WHERE repos=%s", (reponame,)) |
| | 133 | cursor.execute("DELETE FROM revision WHERE repos=%s", (id,)) |
| | 134 | cursor.execute("DELETE FROM node_change WHERE repos=%s", (id,)) |
| 136 | 135 | cursor.executemany("DELETE FROM repository " |
| 137 | 136 | "WHERE id=%s AND name=%s", |
| 138 | | [(reponame, k) for k in CACHE_METADATA_KEYS]) |
| | 137 | [(id, k) for k in CACHE_METADATA_KEYS]) |
| 139 | 138 | cursor.executemany("INSERT INTO repository (id, name, value) " |
| 140 | 139 | "VALUES (%s, %s, %s)", |
| 141 | | [(reponame, k, '') |
| 142 | | for k in CACHE_METADATA_KEYS]) |
| | 140 | [(id, k, '') for k in CACHE_METADATA_KEYS]) |
| 143 | 141 | db.commit() |
| 144 | 142 | repos.sync(self._sync_feedback) |
| 145 | 143 | cursor.execute("SELECT count(rev) FROM revision WHERE repos=%s", |
| 146 | | (reponame,)) |
| | 144 | (id,)) |
| 147 | 145 | for cnt, in cursor: |
| 148 | 146 | printout(ngettext('%(num)s revision cached.', |
| 149 | 147 | '%(num)s revisions cached.', num=cnt)) |
| … |
… |
|
| 187 | 185 | |
| 188 | 186 | elif db_provider and req.args.get('save'): |
| 189 | 187 | # Modify repository |
| 190 | | changed = False |
| 191 | 188 | changes = {} |
| 192 | 189 | for field in db_provider.repository_attrs: |
| 193 | 190 | value = normalize_whitespace(req.args.get(field)) |
| … |
… |
|
| 196 | 193 | changes[field] = value |
| 197 | 194 | if changes: |
| 198 | 195 | db_provider.modify_repository(reponame, changes) |
| 199 | | changed = True |
| 200 | | # Rename repository |
| | 196 | add_notice(req, _('Your changes have been saved.')) |
| 201 | 197 | name = req.args.get('name') |
| 202 | | if name and name != path_info: |
| 203 | | db_provider.rename_repository(reponame, name) |
| 204 | | changed = True |
| 205 | | if changed: |
| 206 | | add_notice(req, _('Your changes have been saved.')) |
| 207 | 198 | if 'dir' in changes: |
| 208 | 199 | msg = _('You should now run "trac-admin $ENV ' |
| 209 | 200 | 'repository resync %(name)s" to synchronize ' |
diff --git a/trac/versioncontrol/api.py b/trac/versioncontrol/api.py
|
a
|
b
|
|
| 96 | 96 | |
| 97 | 97 | implements(IRepositoryProvider, IAdminCommandProvider) |
| 98 | 98 | |
| 99 | | repository_attrs = ('alias', 'dir', 'hidden', 'type', 'url') |
| | 99 | repository_attrs = ('alias', 'dir', 'hidden', 'name', 'type', 'url') |
| 100 | 100 | |
| 101 | 101 | # IRepositoryProvider methods |
| 102 | 102 | |
| … |
… |
|
| 107 | 107 | cursor.execute("SELECT id,name,value FROM repository " |
| 108 | 108 | "WHERE name IN (%s)" % ",".join( |
| 109 | 109 | "'%s'" % each for each in self.repository_attrs)) |
| | 110 | repos = {} |
| | 111 | for id, name, value in cursor: |
| | 112 | if value is not None: |
| | 113 | repos.setdefault(id, {})[name] = value |
| 110 | 114 | reponames = {} |
| 111 | | for (id, name, value) in cursor: |
| 112 | | if value is not None: |
| 113 | | reponames.setdefault(id, {})[name] = value |
| | 115 | for id, info in repos.iteritems(): |
| | 116 | if 'name' in info and 'dir' in info: |
| | 117 | info['id'] = id |
| | 118 | reponames[info['name']] = info |
| 114 | 119 | return reponames.iteritems() |
| 115 | 120 | |
| 116 | 121 | # IAdminCommandProvider methods |
| … |
… |
|
| 125 | 130 | yield ('repository remove', '<repos>', |
| 126 | 131 | 'Remove a source repository', |
| 127 | 132 | self._complete_repos, self._do_remove) |
| 128 | | yield ('repository rename', '<repos> <newname>', |
| 129 | | 'Rename a source repository', |
| 130 | | self._complete_repos, self._do_rename) |
| 131 | 133 | yield ('repository set', '<repos> <key> <value>', |
| 132 | 134 | """Set an attribute of a repository |
| 133 | 135 | |
| … |
… |
|
| 169 | 171 | def _do_remove(self, reponame): |
| 170 | 172 | self.remove_repository(reponame) |
| 171 | 173 | |
| 172 | | def _do_rename(self, reponame, newname): |
| 173 | | self.rename_repository(reponame, newname) |
| 174 | | |
| 175 | 174 | def _do_set(self, reponame, key, value): |
| 176 | 175 | if key not in self.repository_attrs: |
| 177 | 176 | raise AdminCommandError(_('Invalid key "%(key)s"', key=key)) |
| … |
… |
|
| 194 | 193 | raise TracError(_("The repository type '%(type)s' is not " |
| 195 | 194 | "supported", type=type_)) |
| 196 | 195 | db = self.env.get_db_cnx() |
| | 196 | id = rm.get_repository_id(reponame, db) |
| 197 | 197 | cursor = db.cursor() |
| 198 | 198 | cursor.executemany("INSERT INTO repository (id, name, value) " |
| 199 | 199 | "VALUES (%s, %s, %s)", |
| 200 | | [(reponame, 'dir', dir), |
| 201 | | (reponame, 'type', type_ or '')]) |
| | 200 | [(id, 'dir', dir), |
| | 201 | (id, 'type', type_ or '')]) |
| 202 | 202 | db.commit() |
| 203 | 203 | rm.reload_repositories() |
| 204 | 204 | |
| … |
… |
|
| 208 | 208 | reponame = '' |
| 209 | 209 | if target == '(default)': |
| 210 | 210 | target = '' |
| | 211 | rm = RepositoryManager(self.env) |
| 211 | 212 | db = self.env.get_db_cnx() |
| | 213 | id = rm.get_repository_id(reponame, db) |
| 212 | 214 | cursor = db.cursor() |
| 213 | 215 | cursor.executemany("INSERT INTO repository (id, name, value) " |
| 214 | 216 | "VALUES (%s, %s, %s)", |
| 215 | | [(reponame, 'dir', None), |
| 216 | | (reponame, 'alias', target)]) |
| | 217 | [(id, 'dir', None), |
| | 218 | (id, 'alias', target)]) |
| 217 | 219 | db.commit() |
| 218 | | RepositoryManager(self.env).reload_repositories() |
| | 220 | rm.reload_repositories() |
| 219 | 221 | |
| 220 | 222 | def remove_repository(self, reponame): |
| 221 | 223 | """Remove a repository.""" |
| 222 | 224 | if reponame == '(default)': |
| 223 | 225 | reponame = '' |
| | 226 | rm = RepositoryManager(self.env) |
| 224 | 227 | db = self.env.get_db_cnx() |
| | 228 | id = rm.get_repository_id(reponame, db) |
| 225 | 229 | cursor = db.cursor() |
| 226 | | cursor.execute("DELETE FROM repository WHERE id=%s", (reponame,)) |
| 227 | | cursor.execute("DELETE FROM revision WHERE repos=%s", (reponame,)) |
| 228 | | cursor.execute("DELETE FROM node_change WHERE repos=%s", (reponame,)) |
| | 230 | cursor.execute("DELETE FROM repository WHERE id=%s", (id,)) |
| | 231 | cursor.execute("DELETE FROM revision WHERE repos=%s", (id,)) |
| | 232 | cursor.execute("DELETE FROM node_change WHERE repos=%s", (id,)) |
| 229 | 233 | db.commit() |
| 230 | | RepositoryManager(self.env).reload_repositories() |
| 231 | | |
| 232 | | def rename_repository(self, reponame, newname): |
| 233 | | """Rename a repository.""" |
| 234 | | if reponame == '(default)': |
| 235 | | reponame = '' |
| 236 | | if newname == '(default)': |
| 237 | | newname = '' |
| 238 | | db = self.env.get_db_cnx() |
| 239 | | cursor = db.cursor() |
| 240 | | cursor.execute("UPDATE repository SET id=%s WHERE id=%s", |
| 241 | | (newname, reponame)) |
| 242 | | cursor.execute("UPDATE revision SET repos=%s WHERE repos=%s", |
| 243 | | (newname, reponame)) |
| 244 | | cursor.execute("UPDATE node_change SET repos=%s WHERE repos=%s", |
| 245 | | (newname, reponame)) |
| 246 | | db.commit() |
| 247 | | RepositoryManager(self.env).reload_repositories() |
| | 234 | rm.reload_repositories() |
| 248 | 235 | |
| 249 | 236 | def modify_repository(self, reponame, changes): |
| 250 | 237 | """Modify attributes of a repository.""" |
| 251 | 238 | if reponame == '(default)': |
| 252 | 239 | reponame = '' |
| | 240 | rm = RepositoryManager(self.env) |
| 253 | 241 | db = self.env.get_db_cnx() |
| | 242 | id = rm.get_repository_id(reponame, db) |
| 254 | 243 | cursor = db.cursor() |
| 255 | 244 | for (k, v) in changes.iteritems(): |
| 256 | 245 | if k not in self.repository_attrs: |
| 257 | 246 | continue |
| 258 | | if k == 'alias' and v == '(default)': |
| | 247 | if k in('alias', 'name') and v == '(default)': |
| 259 | 248 | v = '' |
| 260 | 249 | cursor.execute("UPDATE repository SET value=%s " |
| 261 | | "WHERE id=%s AND name=%s", (v, reponame, k)) |
| | 250 | "WHERE id=%s AND name=%s", (v, id, k)) |
| 262 | 251 | cursor.execute("SELECT value FROM repository " |
| 263 | | "WHERE id=%s AND name=%s", (reponame, k)) |
| | 252 | "WHERE id=%s AND name=%s", (id, k)) |
| 264 | 253 | if not cursor.fetchone(): |
| 265 | 254 | cursor.execute("INSERT INTO repository VALUES (%s, %s, %s)", |
| 266 | | (reponame, k, v)) |
| | 255 | (id, k, v)) |
| 267 | 256 | db.commit() |
| 268 | | RepositoryManager(self.env).reload_repositories() |
| | 257 | rm.reload_repositories() |
| 269 | 258 | |
| 270 | 259 | |
| 271 | 260 | class RepositoryManager(Component): |
| … |
… |
|
| 445 | 434 | repositories.append(repos) |
| 446 | 435 | return repositories |
| 447 | 436 | |
| | 437 | def get_repository_id(self, reponame, db=None): |
| | 438 | """Return a unique id for the given repository name.""" |
| | 439 | handle_ta = False |
| | 440 | if db is None: |
| | 441 | db = self.env.get_db_cnx() |
| | 442 | handle_ta = True |
| | 443 | cursor = db.cursor() |
| | 444 | cursor.execute("SELECT id FROM repository " |
| | 445 | "WHERE name='name' AND value=%s", (reponame,)) |
| | 446 | for id, in cursor: |
| | 447 | return id |
| | 448 | cursor.execute("SELECT COALESCE(MAX(id),0) FROM repository") |
| | 449 | id = cursor.fetchone()[0] + 1 |
| | 450 | cursor.execute("INSERT INTO repository VALUES (%s,%s,%s)", |
| | 451 | (id, 'name', reponame)) |
| | 452 | if handle_ta: |
| | 453 | db.commit() |
| | 454 | return id |
| | 455 | |
| 448 | 456 | def get_repository(self, reponame, authname): |
| 449 | 457 | """Retrieve the appropriate Repository for the given name. |
| 450 | 458 | |
| … |
… |
|
| 455 | 463 | :return: if no corresponding repository was defined, |
| 456 | 464 | simply return `None`. |
| 457 | 465 | """ |
| | 466 | reponame = reponame or '' |
| 458 | 467 | repoinfo = self.get_all_repositories().get(reponame, {}) |
| 459 | 468 | if repoinfo and 'alias' in repoinfo: |
| 460 | 469 | reponame = repoinfo['alias'] |
| … |
… |
|
| 489 | 498 | connector = self._get_connector(rtype) |
| 490 | 499 | repos = connector.get_repository(rtype, rdir, repoinfo) |
| 491 | 500 | repos.reponame = reponame |
| | 501 | repos.id = repoinfo['id'] |
| 492 | 502 | repositories[reponame] = repos |
| 493 | 503 | return repos |
| 494 | 504 | finally: |
| … |
… |
|
| 538 | 548 | self.log.warn("Discarding duplicate repository '%s'", |
| 539 | 549 | reponame) |
| 540 | 550 | else: |
| | 551 | if 'id' not in info: |
| | 552 | info['id'] = self.get_repository_id(reponame) |
| 541 | 553 | self._all_repositories[reponame] = info |
| 542 | 554 | return self._all_repositories |
| 543 | 555 | |
| … |
… |
|
| 673 | 685 | self.authz = authz or Authorizer() |
| 674 | 686 | self.log = log |
| 675 | 687 | self.reponame = name # overriden by the reponame key used to create it |
| | 688 | self.id = None |
| 676 | 689 | |
| 677 | 690 | def close(self): |
| 678 | 691 | """Close the connection to the repository.""" |
diff --git a/trac/versioncontrol/cache.py b/trac/versioncontrol/cache.py
|
a
|
b
|
|
| 48 | 48 | self.repos = repos |
| 49 | 49 | self.metadata = CacheProxy(self.__class__.__module__ + '.' |
| 50 | 50 | + self.__class__.__name__ + '.metadata:' |
| 51 | | + self.repos.reponame, self._metadata, |
| | 51 | + str(self.repos.id), self._metadata, |
| 52 | 52 | self.env) |
| 53 | 53 | Repository.__init__(self, repos.name, authz, log) |
| 54 | 54 | |
| 55 | 55 | def _set_reponame(self, value): |
| 56 | 56 | self.repos.reponame = value |
| 57 | | self.metadata.id = self.__class__.__module__ + '.' \ |
| 58 | | + self.__class__.__name__ + '.metadata:' \ |
| 59 | | + value |
| 60 | 57 | |
| 61 | 58 | reponame = property(fget=lambda self: self.repos.reponame, |
| 62 | 59 | fset=_set_reponame) |
| 63 | 60 | |
| | 61 | def _set_id(self, value): |
| | 62 | self.repos.id = value |
| | 63 | self.metadata.id = self.__class__.__module__ + '.' \ |
| | 64 | + self.__class__.__name__ + '.metadata:' \ |
| | 65 | + str(value) |
| | 66 | |
| | 67 | id = property(fget=lambda self: self.repos.id, fset=_set_id) |
| | 68 | |
| 64 | 69 | def close(self): |
| 65 | 70 | self.repos.close() |
| 66 | 71 | |
| … |
… |
|
| 86 | 91 | cursor.execute("SELECT rev FROM revision " |
| 87 | 92 | "WHERE repos=%s AND time >= %s AND time < %s " |
| 88 | 93 | "ORDER BY time DESC, rev DESC", |
| 89 | | (self.reponame, to_timestamp(start), |
| | 94 | (self.id, to_timestamp(start), |
| 90 | 95 | to_timestamp(stop))) |
| 91 | 96 | for rev, in cursor: |
| 92 | 97 | try: |
| … |
… |
|
| 101 | 106 | cursor = db.cursor() |
| 102 | 107 | cursor.execute("SELECT time,author,message FROM revision " |
| 103 | 108 | "WHERE repos=%s AND rev=%s", |
| 104 | | (self.reponame, str(cset.rev))) |
| | 109 | (self.id, str(cset.rev))) |
| 105 | 110 | old_changeset = None |
| 106 | 111 | for time, author, message in cursor: |
| 107 | 112 | date = datetime.fromtimestamp(time, utc) |
| … |
… |
|
| 110 | 115 | cursor.execute("UPDATE revision SET time=%s, author=%s, message=%s " |
| 111 | 116 | "WHERE repos=%s AND rev=%s", |
| 112 | 117 | (to_timestamp(cset.date), cset.author, cset.message, |
| 113 | | self.reponame, str(cset.rev))) |
| | 118 | self.id, str(cset.rev))) |
| 114 | 119 | db.commit() |
| 115 | 120 | return old_changeset |
| 116 | 121 | |
| … |
… |
|
| 120 | 125 | cursor.execute("SELECT name, value FROM repository " |
| 121 | 126 | "WHERE id=%%s AND name IN (%s)" % |
| 122 | 127 | ','.join(['%s'] * len(CACHE_METADATA_KEYS)), |
| 123 | | (self.reponame,) + CACHE_METADATA_KEYS) |
| | 128 | (self.id,) + CACHE_METADATA_KEYS) |
| 124 | 129 | return dict(cursor) |
| 125 | 130 | |
| 126 | 131 | def sync(self, feedback=None): |
| … |
… |
|
| 143 | 148 | self.log.info('Storing initial "repository_dir": %s' % self.name) |
| 144 | 149 | cursor.execute("INSERT INTO repository (id,name,value) " |
| 145 | 150 | "VALUES (%s,%s,%s)", |
| 146 | | (self.reponame, CACHE_REPOSITORY_DIR, self.name)) |
| | 151 | (self.id, CACHE_REPOSITORY_DIR, self.name)) |
| 147 | 152 | do_commit = True |
| 148 | 153 | else: # 'repository_dir' cleared by a resync |
| 149 | 154 | self.log.info('Resetting "repository_dir": %s' % self.name) |
| 150 | 155 | cursor.execute("UPDATE repository SET value=%s " |
| 151 | 156 | "WHERE id=%s AND name=%s", |
| 152 | | (self.name, self.reponame, CACHE_REPOSITORY_DIR)) |
| | 157 | (self.name, self.id, CACHE_REPOSITORY_DIR)) |
| 153 | 158 | do_commit = True |
| 154 | 159 | |
| 155 | 160 | # -- retrieve the youngest revision in the repository |
| … |
… |
|
| 161 | 166 | if youngest is None: |
| 162 | 167 | cursor.execute("INSERT INTO repository (id,name,value) " |
| 163 | 168 | "VALUES (%s,%s,%s)", |
| 164 | | (self.reponame, CACHE_YOUNGEST_REV, '')) |
| | 169 | (self.id, CACHE_YOUNGEST_REV, '')) |
| 165 | 170 | do_commit = True |
| 166 | 171 | |
| 167 | 172 | if do_commit: |
| … |
… |
|
| 205 | 210 | # 0. first check if there's no (obvious) resync in progress |
| 206 | 211 | cursor.execute("SELECT rev FROM revision " |
| 207 | 212 | "WHERE repos=%s AND rev=%s", |
| 208 | | (self.reponame, str(next_youngest))) |
| | 213 | (self.id, str(next_youngest))) |
| 209 | 214 | for rev, in cursor: |
| 210 | 215 | # already there, but in progress, so keep ''previous'' |
| 211 | 216 | # notion of 'youngest' |
| … |
… |
|
| 232 | 237 | cursor.execute("INSERT INTO revision " |
| 233 | 238 | " (repos,rev,time,author,message) " |
| 234 | 239 | "VALUES (%s,%s,%s,%s,%s)", |
| 235 | | (self.reponame, str(next_youngest), |
| | 240 | (self.id, str(next_youngest), |
| 236 | 241 | to_timestamp(cset.date), |
| 237 | 242 | cset.author, cset.message)) |
| 238 | 243 | except Exception, e: # *another* 1.1. resync attempt won |
| … |
… |
|
| 257 | 262 | " (repos,rev,path,node_type," |
| 258 | 263 | " change_type,base_path,base_rev) " |
| 259 | 264 | "VALUES (%s,%s,%s,%s,%s,%s,%s)", |
| 260 | | (self.reponame, str(next_youngest), |
| | 265 | (self.id, str(next_youngest), |
| 261 | 266 | path, kind, action, bpath, brev)) |
| 262 | 267 | |
| 263 | 268 | # 1.3. iterate (1.1 should always succeed now) |
| … |
… |
|
| 268 | 273 | # (minimize possibility of failures at point 0.) |
| 269 | 274 | cursor.execute("UPDATE repository SET value=%s " |
| 270 | 275 | "WHERE id=%s AND name=%s", |
| 271 | | (str(youngest), self.reponame, |
| | 276 | (str(youngest), self.id, |
| 272 | 277 | CACHE_YOUNGEST_REV)) |
| 273 | 278 | self.metadata.invalidate(db) |
| 274 | 279 | db.commit() |
| … |
… |
|
| 336 | 341 | # the changeset revs are sequence of ints: |
| 337 | 342 | sql = "SELECT rev FROM node_change WHERE repos=%s AND " + \ |
| 338 | 343 | db.cast('rev', 'int') + " " + direction + " %s" |
| 339 | | args = [self.reponame, rev] |
| | 344 | args = [self.id, rev] |
| 340 | 345 | |
| 341 | 346 | if path: |
| 342 | 347 | path = path.lstrip('/') |
| … |
… |
|
| 406 | 411 | cursor = db.cursor() |
| 407 | 412 | cursor.execute("SELECT time,author,message FROM revision " |
| 408 | 413 | "WHERE repos=%s AND rev=%s", |
| 409 | | (self.repos.reponame, str(rev))) |
| | 414 | (self.repos.id, str(rev))) |
| 410 | 415 | row = cursor.fetchone() |
| 411 | 416 | if row: |
| 412 | 417 | _date, author, message = row |
| … |
… |
|
| 421 | 426 | cursor = db.cursor() |
| 422 | 427 | cursor.execute("SELECT path,node_type,change_type,base_path,base_rev " |
| 423 | 428 | "FROM node_change WHERE repos=%s AND rev=%s " |
| 424 | | "ORDER BY path", (self.repos.reponame, str(self.rev))) |
| | 429 | "ORDER BY path", (self.repos.id, str(self.rev))) |
| 425 | 430 | for path, kind, change, base_path, base_rev in cursor: |
| 426 | 431 | if not self.authz.has_permission(posixpath.join(self.scope, |
| 427 | 432 | path.strip('/'))): |
diff --git a/trac/versioncontrol/tests/cache.py b/trac/versioncontrol/tests/cache.py
|
a
|
b
|
|
| 33 | 33 | self.db = self.env.get_db_cnx() |
| 34 | 34 | self.log = self.env.log |
| 35 | 35 | cursor = self.db.cursor() |
| 36 | | cursor.execute("INSERT INTO repository (id, name, value) " |
| 37 | | "VALUES (%s,%s,%s)", |
| 38 | | ('test-repos', 'youngest_rev', '')) |
| | 36 | cursor.executemany("INSERT INTO repository (id,name,value) " |
| | 37 | "VALUES (%s,%s,%s)", |
| | 38 | [(1, 'name', 'test-repos'), |
| | 39 | (1, 'youngest_rev', '')]) |
| 39 | 40 | |
| 40 | 41 | def tearDown(self): |
| 41 | 42 | self.env.reset_db() |
| … |
… |
|
| 97 | 98 | t3 = datetime(2003, 1, 1, 1, 1, 1, 0, utc) |
| 98 | 99 | cursor = self.db.cursor() |
| 99 | 100 | cursor.execute("INSERT INTO revision (repos,rev,time,author,message) " |
| 100 | | "VALUES ('test-repos',0,%s,'','')", |
| | 101 | "VALUES (1,0,%s,'','')", |
| 101 | 102 | (to_timestamp(t1),)) |
| 102 | 103 | cursor.execute("INSERT INTO revision (repos,rev,time,author,message) " |
| 103 | | "VALUES ('test-repos',1,%s,'joe','Import')", |
| | 104 | "VALUES (1,1,%s,'joe','Import')", |
| 104 | 105 | (to_timestamp(t2),)) |
| 105 | 106 | cursor.executemany("INSERT INTO node_change (repos,rev,path," |
| 106 | 107 | "node_type,change_type,base_path,base_rev) " |
| 107 | | "VALUES ('test-repos','1',%s,%s,%s,%s,%s)", |
| | 108 | "VALUES (1,'1',%s,%s,%s,%s,%s)", |
| 108 | 109 | [('trunk', 'D', 'A', None, None), |
| 109 | 110 | ('trunk/README', 'F', 'A', None, None)]) |
| 110 | 111 | cursor.execute("UPDATE repository SET value='1' " |
| 111 | | "WHERE id='test-repos' AND name='youngest_rev'") |
| | 112 | "WHERE id=1 AND name='youngest_rev'") |
| 112 | 113 | |
| 113 | 114 | changes = [('trunk/README', Node.FILE, Changeset.EDIT, 'trunk/README', 1)] |
| 114 | 115 | changeset = Mock(Changeset, 2, 'Update', 'joe', t3, |
| … |
… |
|
| 120 | 121 | normalize_rev=lambda x: x, |
| 121 | 122 | next_rev=lambda x: x and int(x) == 1 and 2 or None) |
| 122 | 123 | cache = CachedRepository(self.env, repos, None, self.log) |
| | 124 | cache.id = 1 |
| 123 | 125 | cache.sync() |
| 124 | 126 | |
| 125 | 127 | cursor = self.db.cursor() |
| … |
… |
|
| 137 | 139 | t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc) |
| 138 | 140 | cursor = self.db.cursor() |
| 139 | 141 | cursor.execute("INSERT INTO revision (repos,rev,time,author,message) " |
| 140 | | "VALUES ('test-repos',0,%s,'','')", |
| | 142 | "VALUES (1,0,%s,'','')", |
| 141 | 143 | (to_timestamp(t1),)) |
| 142 | 144 | cursor.execute("INSERT INTO revision (repos,rev,time,author,message) " |
| 143 | | "VALUES ('test-repos',1,%s,'joe','Import')", |
| | 145 | "VALUES (1,1,%s,'joe','Import')", |
| 144 | 146 | (to_timestamp(t2),)) |
| 145 | 147 | cursor.executemany("INSERT INTO node_change (repos,rev,path," |
| 146 | 148 | "node_type,change_type,base_path,base_rev) " |
| 147 | | "VALUES ('test-repos','1',%s,%s,%s,%s,%s)", |
| | 149 | "VALUES (1,'1',%s,%s,%s,%s,%s)", |
| 148 | 150 | [('trunk', 'D', 'A', None, None), |
| 149 | 151 | ('trunk/README', 'F', 'A', None, None)]) |
| 150 | 152 | cursor.execute("UPDATE repository SET value='1' " |
| 151 | | "WHERE id='test-repos' AND name='youngest_rev'") |
| | 153 | "WHERE id=1 AND name='youngest_rev'") |
| 152 | 154 | |
| 153 | 155 | repos = Mock(Repository, 'test-repos', None, self.log, |
| 154 | 156 | get_changeset=lambda x: None, |
| … |
… |
|
| 157 | 159 | next_rev=lambda x: None, |
| 158 | 160 | normalize_rev=lambda rev: rev) |
| 159 | 161 | cache = CachedRepository(self.env, repos, None, self.log) |
| | 162 | cache.id = 1 |
| 160 | 163 | self.assertEqual('1', cache.youngest_rev) |
| 161 | 164 | changeset = cache.get_changeset(1) |
| 162 | 165 | self.assertEqual('joe', changeset.author) |