Ticket #1106: rename_base_functionality.2.diff
| File rename_base_functionality.2.diff, 8.0 KB (added by shookie@…, 2 years ago) |
|---|
-
trac/attachment.py
diff --git a/trac/attachment.py b/trac/attachment.py index a3ed370..2b8b303 100644
a b class Attachment(object): 275 275 except OSError, e: 276 276 env.log.error("Can't delete attachment directory %s: %s", 277 277 attachment_dir, exception_to_unicode(e, traceback=True)) 278 279 @classmethod 280 def reparent_all(cls, env, old_realm, old_id, new_realm, new_id, db=None): 281 """Reparent all attachments of a given resource to another resource. 282 283 :param old_realm: old parent's realm 284 :param old_id: old parent's id 285 :param new_realm: new parent's realm 286 :param new_id: new parent's id 287 :param env: the environent 288 :param db: the database connection 289 """ 290 old_dir = os.path.join(os.path.normpath(env.path), 'attachments', 291 old_realm, old_id) 292 if not os.path.exists(old_dir): 293 return 294 295 new_dir = os.path.join(os.path.normpath(env.path), 'attachments', 296 new_realm, new_id) 297 298 @with_transaction(env, db) 299 def do_reparent(db): 300 cursor = db.cursor() 301 cursor.execute(""" 302 SELECT filename FROM attachment 303 WHERE type=%s AND id=%s 304 """, (old_realm, old_id)) 305 306 renames = [] 307 for filename, in cursor: 308 old_filename = os.path.join(old_dir, filename) 309 new_filename = os.path.join(new_dir, filename) 310 if os.path.exists(new_filename): 311 raise TracError(_("Can't reparent attachment '%(att)s' as " 312 "it already exists in %(realm)s:%(id)s", 313 att=new_filename, 314 realm=new_realm, id=new_id)) 315 renames.append((old_filename, new_filename)) 316 317 try: 318 if not os.path.exists(new_dir): 319 os.makedirs(new_dir) 320 except OSError, e: 321 env.log.error("Can't create attachment directory '%s'", 322 new_dir, exc_info=True) 323 raise TracError(_("Can't create attachment folder for " 324 "%(realm)s:%(id)s: %(err)", 325 realm=new_realm, id=new_id, err=e)) 326 327 for old_filename, new_filename in renames: 328 try: 329 os.rename(old_filename, new_filename) 330 except OSError, e: 331 env.log.error("Can't move attachment from '%s' to '%s'", 332 old_filename, new_filename, exc_info=True) 333 raise TracError(_("Can't move attachment '%(att)s'", 334 att=os.path.basename(new_filename))) 335 cursor.execute(""" 336 UPDATE attachment SET type=%s, id=%s 337 WHERE type=%s AND id=%s 338 """, (new_realm, new_id, old_realm, old_id)) 339 340 env.log.info('Attachments reparented to: %s:%s', new_realm, new_id) 341 342 343 return 278 344 279 345 def open(self): 280 346 self.env.log.debug('Trying to open attachment at %s', self.path) -
trac/wiki/api.py
diff --git a/trac/wiki/api.py b/trac/wiki/api.py index e95c8c1..e79e98f 100644
a b class IWikiChangeListener(Interface): 42 42 def wiki_page_deleted(page): 43 43 """Called when a page has been deleted.""" 44 44 45 def wiki_page_renamed(page,old_page_name): 46 """Called when a page has been renamed in-place.""" 47 45 48 def wiki_page_version_deleted(page): 46 49 """Called when a version of a page has been deleted.""" 47 50 -
trac/wiki/model.py
diff --git a/trac/wiki/model.py b/trac/wiki/model.py index d8183df..ad9805e 100644
a b class WikiPage(object): 157 157 self.old_readonly = self.readonly 158 158 self.old_text = self.text 159 159 160 def rename(self, new_name, db=None): 161 """Rename wiki page in-place, keeping the history intact. 162 Renaming a page this way will eventually leave dangling references 163 to the old page - which litterally doesn't exist anymore. 164 """ 165 assert self.exists, 'Cannot rename non-existent page' 166 167 old_name = self.name 168 169 @with_transaction(self.env, db) 170 def do_rename(db): 171 cursor = db.cursor() 172 new_page = WikiPage(self.env, new_name, version=None, db=db) 173 if new_page.exists: 174 raise TracError(_("Can't rename to existing %(nn)s page.", 175 nn=new_name)) 176 177 cursor.execute("UPDATE wiki SET name=%s WHERE name=%s", 178 (new_name, old_name)) 179 self.name = new_name 180 self._fetch(self.name, None, db) 181 182 from trac.attachment import Attachment 183 Attachment.reparent_all(self.env, 'wiki', old_name, 184 'wiki', self.name, db) 185 186 self.env.log.info('Renamed page %s in-place to %s', old_name, new_name) 187 188 for listener in WikiSystem(self.env).change_listeners: 189 if hasattr(listener, 'wiki_page_renamed'): 190 listener.wiki_page_renamed(self, old_name) 191 192 160 193 def get_history(self, db=None): 161 194 if not db: 162 195 db = self.env.get_db_cnx() -
trac/wiki/tests/model.py
diff --git a/trac/wiki/tests/model.py b/trac/wiki/tests/model.py index 3099e2f..cbbc093 100644
a b 1 1 from datetime import datetime 2 import tempfile 2 3 import unittest 3 4 5 from trac.attachment import Attachment 4 6 from trac.core import * 5 7 from trac.test import EnvironmentStub 6 8 from trac.util.datefmt import utc, to_timestamp … … class TestWikiChangeListener(Component): 14 16 self.changed = [] 15 17 self.deleted = [] 16 18 self.deleted_version = [] 19 self.renamed = {} 17 20 18 21 def wiki_page_added(self, page): 19 22 self.added.append(page) … … class TestWikiChangeListener(Component): 27 30 def wiki_page_version_deleted(self, page): 28 31 self.deleted_version.append(page) 29 32 33 def wiki_page_renamed(self, page, old_page_name): 34 self.renamed[old_page_name] = page 35 30 36 31 37 class WikiPageTestCase(unittest.TestCase): 32 38 … … class WikiPageTestCase(unittest.TestCase): 194 200 listener = TestWikiChangeListener(self.env) 195 201 self.assertEqual(page, listener.deleted[0]) 196 202 203 def test_rename_page(self): 204 cursor = self.db.cursor() 205 data = (1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0) 206 cursor.execute("INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)", 207 ('TestPage',) + data) 208 209 page = WikiPage(self.env, 'TestPage') 210 211 attachment = Attachment(self.env, 'wiki', 'TestPage') 212 attachment.insert('foo.txt', tempfile.TemporaryFile(), 0, 1) 213 214 page.rename('PageRenamed') 215 216 cursor.execute("SELECT version,time,author,ipnr,text,comment," 217 "readonly FROM wiki WHERE name=%s", ('PageRenamed',)) 218 self.assertEqual(data, cursor.fetchone()) 219 self.assertEqual(None, cursor.fetchone()) 220 221 attachments = Attachment.select(self.env, 'wiki', 'PageRenamed') 222 self.assertEqual('foo.txt', attachments.next().filename) 223 self.assertRaises(StopIteration, attachments.next) 224 Attachment.delete_all(self.env, 'wiki', 'PageRenamed', self.db) 225 226 227 old_page = WikiPage(self.env, 'TestPage') 228 229 cursor.execute("SELECT version,time,author,ipnr,text,comment," 230 "readonly FROM wiki WHERE name=%s", ('TestPage',)) 231 self.assertEqual(None, cursor.fetchone()) 232 233 listener = TestWikiChangeListener(self.env) 234 self.assertEqual({'TestPage': page}, listener.renamed) 235 236 197 237 198 238 def suite(): 199 239 return unittest.makeSuite(WikiPageTestCase, 'test')
