def revisions(self, paths=None, start=0, stop=0, chunk_size=common.chunk_size): """Load the history of this repo. This is LAZY. It returns a generator, and fetches a small number of revisions at a time. The reason this is lazy is so that you can use the same repo object to perform RA calls to get deltas. """ if paths is None: paths = [''] if not stop: stop = self.HEAD while stop > start: def callback(paths, revnum, author, date, message, pool): r = common.Revision(revnum, author, message, date, paths, strip_path=self.subdir) revisions.append(r) # we only access revisions in a FIFO manner revisions = collections.deque() try: # TODO: using min(start + chunk_size, stop) may be preferable; # ra.get_log(), even with chunk_size set, takes a while # when converting the 65k+ rev. in LLVM. ra.get_log(self.ra, paths, start + 1, stop, chunk_size, # limit of how many log messages to load True, # don't need to know changed paths True, # stop on copies callback, self.pool) except core.SubversionException, e: if e.apr_err == core.SVN_ERR_FS_NOT_FOUND: msg = ('%s not found at revision %d!' % (self.subdir.rstrip('/'), stop)) raise common.SubversionConnectionException(msg) elif e.apr_err == core.SVN_ERR_FS_NO_SUCH_REVISION: raise common.SubversionConnectionException(e.message) else: raise while len(revisions) > 1: yield revisions.popleft() if len(revisions) == 0: # exit the loop; there is no history for the path. break else: r = revisions.popleft() start = r.revnum yield r self.init_ra_and_client()
def last_changed_rev(self): try: holder = [] ra.get_log(self.ra, [''], self.HEAD, 1, 1, # limit of how many log messages to load True, # don't need to know changed paths True, # stop on copies lambda paths, revnum, author, date, message, pool: holder.append(revnum), self.pool) return holder[-1] except SubversionException, e: if e.apr_err not in [core.SVN_ERR_FS_NOT_FOUND]: raise else: return self.HEAD
def test_delta_driver_commit(self): # Setup paths we'll commit in this test. to_delete = ['trunk/README.txt', 'trunk/dir1/dir2'] to_mkdir = ['test_delta_driver_commit.d', 'test_delta_driver_commit2.d'] to_add = ['test_delta_driver_commit', 'test_delta_driver_commit2'] to_dir_prop = ['trunk/dir1/dir3', 'test_delta_driver_commit2.d'] to_file_prop = ['trunk/README2.txt', 'test_delta_driver_commit2'] all_paths = {} for i in to_delete + to_mkdir + to_add + to_dir_prop + to_file_prop: all_paths[i] = True # base revision for the commit revision = fs.youngest_rev(self.fs) commit_info = [] def commit_cb(info, pool): commit_info.append(info) revprops = {"svn:log": "foobar", "testprop": ""} (editor, edit_baton) = ra.get_commit_editor3(self.ra_ctx, revprops, commit_cb, None, False) try: def driver_cb(parent, path, pool): self.assert_(path in all_paths) dir_baton = file_baton = None if path in to_delete: # Leave dir_baton alone, as it must be None for delete. editor.delete_entry(path, revision, parent, pool) elif path in to_mkdir: dir_baton = editor.add_directory(path, parent, None, -1, # copyfrom pool) elif path in to_add: file_baton = editor.add_file(path, parent, None, -1, # copyfrom pool) # wc.py:test_commit tests apply_textdelta . if path in to_dir_prop: if dir_baton is None: dir_baton = editor.open_directory(path, parent, revision, pool) editor.change_dir_prop(dir_baton, 'test_delta_driver_commit', 'foo', pool) elif path in to_file_prop: if file_baton is None: file_baton = editor.open_file(path, parent, revision, pool) editor.change_file_prop(file_baton, 'test_delta_driver_commit', 'foo', pool) if file_baton is not None: editor.close_file(file_baton, None, pool) return dir_baton delta.path_driver(editor, edit_baton, -1, all_paths.keys(), driver_cb) editor.close_edit(edit_baton) except: try: editor.abort_edit(edit_baton) except: # We already have an exception in progress, not much we can do # about this. pass raise info = commit_info[0] if info.author is not None: revprops['svn:author'] = info.author revprops['svn:date'] = info.date self.assertEqual(ra.rev_proplist(self.ra_ctx, info.revision), revprops) receiver_called = [False] def receiver(changed_paths, revision, author, date, message, pool): receiver_called[0] = True self.assertEqual(revision, info.revision) self.assertEqual(author, info.author) self.assertEqual(date, info.date) self.assertEqual(message, revprops['svn:log']) for (path, change) in changed_paths.iteritems(): path = path.lstrip('/') self.assert_(path in all_paths) if path in to_delete: self.assertEqual(change.action, 'D') elif path in to_mkdir or path in to_add: self.assertEqual(change.action, 'A') elif path in to_dir_prop or path in to_file_prop: self.assertEqual(change.action, 'M') ra.get_log(self.ra_ctx, [''], info.revision, info.revision, 0, # limit True, # discover_changed_paths True, # strict_node_history receiver) self.assert_(receiver_called[0])
def test_delta_driver_commit(self): # Setup paths we'll commit in this test. to_delete = ['trunk/README.txt', 'trunk/dir1/dir2'] to_mkdir = [ 'test_delta_driver_commit.d', 'test_delta_driver_commit2.d' ] to_add = ['test_delta_driver_commit', 'test_delta_driver_commit2'] to_dir_prop = ['trunk/dir1/dir3', 'test_delta_driver_commit2.d'] to_file_prop = ['trunk/README2.txt', 'test_delta_driver_commit2'] all_paths = {} for i in to_delete + to_mkdir + to_add + to_dir_prop + to_file_prop: all_paths[i] = True # base revision for the commit revision = fs.youngest_rev(self.fs) commit_info = [] def commit_cb(info, pool): commit_info.append(info) revprops = {"svn:log": "foobar", "testprop": ""} (editor, edit_baton) = ra.get_commit_editor3(self.ra_ctx, revprops, commit_cb, None, False) try: def driver_cb(parent, path, pool): self.assert_(path in all_paths) dir_baton = file_baton = None if path in to_delete: # Leave dir_baton alone, as it must be None for delete. editor.delete_entry(path, revision, parent, pool) elif path in to_mkdir: dir_baton = editor.add_directory( path, parent, None, -1, # copyfrom pool) elif path in to_add: file_baton = editor.add_file( path, parent, None, -1, # copyfrom pool) # wc.py:test_commit tests apply_textdelta . if path in to_dir_prop: if dir_baton is None: dir_baton = editor.open_directory( path, parent, revision, pool) editor.change_dir_prop(dir_baton, 'test_delta_driver_commit', 'foo', pool) elif path in to_file_prop: if file_baton is None: file_baton = editor.open_file(path, parent, revision, pool) editor.change_file_prop(file_baton, 'test_delta_driver_commit', 'foo', pool) if file_baton is not None: editor.close_file(file_baton, None, pool) return dir_baton delta.path_driver(editor, edit_baton, -1, list(all_paths.keys()), driver_cb) editor.close_edit(edit_baton) except: try: editor.abort_edit(edit_baton) except: # We already have an exception in progress, not much we can do # about this. pass raise info = commit_info[0] if info.author is not None: revprops['svn:author'] = info.author revprops['svn:date'] = info.date self.assertEqual(ra.rev_proplist(self.ra_ctx, info.revision), revprops) receiver_called = [False] def receiver(changed_paths, revision, author, date, message, pool): receiver_called[0] = True self.assertEqual(revision, info.revision) self.assertEqual(author, info.author) self.assertEqual(date, info.date) self.assertEqual(message, revprops['svn:log']) for (path, change) in changed_paths.items(): path = path.lstrip('/') self.assert_(path in all_paths) if path in to_delete: self.assertEqual(change.action, 'D') elif path in to_mkdir or path in to_add: self.assertEqual(change.action, 'A') elif path in to_dir_prop or path in to_file_prop: self.assertEqual(change.action, 'M') ra.get_log( self.ra_ctx, [''], info.revision, info.revision, 0, # limit True, # discover_changed_paths True, # strict_node_history receiver) self.assert_(receiver_called[0])