def __init__(self, url='', username='', password='', head=None, password_stores=None): parsed = common.parse_url(url, username, password) # --username and --password override URL credentials self.username = parsed[0] self.password = parsed[1] self.svn_url = core.svn_path_canonicalize(parsed[2]) self.auth_baton_pool = core.Pool() self.auth_baton = _create_auth_baton(self.auth_baton_pool, password_stores) # self.init_ra_and_client() assumes that a pool already exists self.pool = core.Pool() self.init_ra_and_client() self.uuid = ra.get_uuid(self.ra, self.pool) self.svn_url = ra.get_session_url(self.ra, self.pool) self.root = ra.get_repos_root(self.ra, self.pool) assert self.svn_url.startswith(self.root) # *will* have a leading '/', would not if we used get_repos_root2 self.subdir = self.svn_url[len(self.root):] if not self.subdir or self.subdir[-1] != '/': self.subdir += '/' # the RA interface always yields quoted paths, but the editor interface # expects unquoted paths self.subdir = urllib.unquote(self.subdir) self.hasdiff3 = True self.autoprops_config = common.AutoPropsConfig()
def save(self, req, text, comment): """ Save the specified text into this document. """ if not isinstance(self.node.repos, SubversionRepository): raise TracError("The '%s' repository is not supported" % type(self.node.repos)) from svn import core as _core from svn import fs as _fs from svn import repos as _repos repos = self.node.repos.repos #.repos revnum = self.node._requested_rev author = req.authname message = 'Edited %s' % self.base[1:] if comment: message += ' (%s)' % comment pool = _core.Pool() fs_txn = _repos.fs_begin_txn_for_commit(repos, revnum, author, message, pool) fs_root = _fs.svn_fs_txn_root(fs_txn, pool) if hasattr(self.node, '_scoped_svn_path'): fs_path = self.node._scoped_svn_path else: fs_path = self.node._scoped_path_utf8 stream = _fs.svn_fs_apply_text(fs_root, fs_path, None, pool) _core.svn_stream_write(stream, text) _core.svn_stream_close(stream) return _repos.fs_commit_txn(repos, fs_txn, pool)
def test_conflict(self): """Test conflict api.""" rev = core.svn_opt_revision_t() rev.kind = core.svn_opt_revision_number rev.value.number = 0 path = self.temper.alloc_empty_dir('-conflict') client.checkout2(self.repos_uri, path, rev, rev, True, True, self.client_ctx) trunk_path = core.svn_dirent_join(path, b'trunk') # Create a conflicting path os.mkdir(core.svn_dirent_local_style(trunk_path)) rev.value.number = 2 client.update4((path,), rev, core.svn_depth_unknown, True, False, False, False, False, self.client_ctx) pool = core.Pool() conflict = client.conflict_get(trunk_path, self.client_ctx, pool) self.assertTrue(isinstance(conflict, client.svn_client_conflict_t)) conflict_opts = client.conflict_tree_get_resolution_options(conflict, self.client_ctx) self.assertTrue(isinstance(conflict_opts, list)) self.assert_all_instances_of(conflict_opts, client.svn_client_conflict_option_t) pool.clear()
def test_log5_revprops(self): """Test svn_client_log5 revprops (for typemap(in) apr_array_t *STRINGLIST)""" directory = urljoin(self.repos_uri+b"/", b"trunk/dir1") start = core.svn_opt_revision_t() end = core.svn_opt_revision_t() core.svn_opt_parse_revision(start, end, b"4:0") rev_range = core.svn_opt_revision_range_t() rev_range.start = start rev_range.end = end entry_pool = core.Pool() def log_entry_receiver_whole(log_entry, pool): """An implementation of svn_log_entry_receiver_t, holds whole log entries.""" self.received_log_entries.append(core.svn_log_entry_dup(log_entry, entry_pool)) self.received_log_entries = [] # (Python 3: pass tuple of bytes and str mixture as revprops argment) client.log5((directory,), start, (rev_range,), 1, True, False, False, ('svn:author', b'svn:log'), log_entry_receiver_whole, self.client_ctx) self.assertEqual(len(self.received_log_entries), 1) revprops = self.received_log_entries[0].revprops self.assertEqual(revprops[b'svn:log'], b"More directories.") self.assertEqual(revprops[b'svn:author'], b"john") with self.assertRaises(KeyError): commit_date = revprops['svn:date'] with self.assertRaises(UnicodeEncodeError): client.log5((directory,), start, (rev_range,), 1, True, False, False, (u'svn:\udc61uthor', b'svn:log'), log_entry_receiver_whole, self.client_ctx)
def test_client_ctx_baton_lifetime(self): pool = core.Pool() temp_client_ctx = client.svn_client_create_context(pool) # We keep track of these objects in separate variables here # because you can't get a PyObject back out of a PY_AS_VOID field test_object1 = lambda *args: b"message 1" test_object2 = lambda *args: b"message 2" # Verify that the refcount of a Python object is incremented when # you insert it into a PY_AS_VOID field. temp_client_ctx.log_msg_baton2 = test_object1 test_object1 = weakref.ref(test_object1) self.assertNotEqual(test_object1(), None) # Verify that the refcount of the previous Python object is decremented # when a PY_AS_VOID field is replaced. temp_client_ctx.log_msg_baton2 = test_object2 self.assertEqual(test_object1(), None) # Verify that the reference count of the new Python object (which # replaced test_object1) was incremented. test_object2 = weakref.ref(test_object2) self.assertNotEqual(test_object2(), None) # Verify that the reference count of test_object2 is decremented when # test_client_ctx is destroyed. temp_client_ctx = None self.assertEqual(test_object2(), None)
def create_and_load(repopath, dumpfd): ''' create a new repository at repopath and load the given dump into it ''' pool = core.Pool() r = repos.svn_repos_create(repopath, '', '', None, None, pool) with open(os.path.join(repopath, 'db', 'fsfs.conf'), 'w') as f: f.write( textwrap.dedent("""\ # config settings for svn repos to try and speed up the testsuite [rep-sharing] enable-rep-sharing = false [deltification] enable-dir-deltification = false enable-props-deltification = false [compression] compression-level=1 """)) try: repos.svn_repos_load_fs2(r, dumpfd, None, repos.svn_repos_load_uuid_force, '', False, False, None, pool) finally: dumpfd.close() pool.destroy()
def init_ra_and_client(self): """Initializes the RA and client layers, because sometimes getting unified diffs runs the remote server out of open files. """ # while we're in here we'll recreate our pool self.pool = core.Pool() if self.username: core.svn_auth_set_parameter(self.auth_baton, core.SVN_AUTH_PARAM_DEFAULT_USERNAME, self.username) if self.password: core.svn_auth_set_parameter(self.auth_baton, core.SVN_AUTH_PARAM_DEFAULT_PASSWORD, self.password) self.client_context = client.create_context() self.client_context.auth_baton = self.auth_baton self.client_context.config = svn_config callbacks = RaCallbacks() callbacks.auth_baton = self.auth_baton self.callbacks = callbacks try: self.ra = ra.open2(self.svn_url, callbacks, svn_config, self.pool) except SubversionException, e: # e.child contains a detailed error messages msglist = [] svn_exc = e while svn_exc: if svn_exc.args[0]: msglist.append(svn_exc.args[0]) svn_exc = svn_exc.child msg = '\n'.join(msglist) raise common.SubversionConnectionException(msg)
def test_lock(self): readme_path = b'%s/trunk/README.txt' % self.path lock = core.svn_lock_create(core.Pool()) lock.token = b'http://svnbook.org/nightly/en/svn.advanced.locking.html' wc.add_lock(readme_path, lock, self.wc) self.assertEqual(True, wc.adm_locked(self.wc)) self.assertEqual(True, wc.locked(self.path)) wc.remove_lock(readme_path, self.wc)
def test_shelf(self): """Test shelf api.""" rev = core.svn_opt_revision_t() rev.kind = core.svn_opt_revision_number rev.value.number = 2 path = self.temper.alloc_empty_dir('-shelf') client.checkout2(self.repos_uri, path, rev, rev, True, True, self.client_ctx) pool = core.Pool() shelf = client._shelf_open_or_create(b"test1", path, self.client_ctx, pool) self.assertTrue(isinstance(shelf, client.svn_client__shelf_t)) new_subpath = core.svn_relpath_join(b'trunk', b'new-shelf-test.txt') new_path = core.svn_dirent_join(path, new_subpath) with open(core.svn_dirent_local_style(new_path), "wb") as fp: fp.write("A new text file\n".encode('utf8')) client.add5(new_path, core.svn_depth_unknown, False, False, False, True, self.client_ctx, pool) statused_paths = [] def shelf_status(path, status, pool): statused_paths.append(path) shelf_version = client._shelf_save_new_version3( shelf, (new_path, ), core.svn_depth_unknown, None, shelf_status, None, pool) self.assertTrue( isinstance(shelf_version, client.svn_client__shelf_version_t)) all_versions = client._shelf_get_all_versions(shelf, pool, pool) self.assertEqual(1, len(all_versions)) self.assertTrue( isinstance(all_versions[0], client.svn_client__shelf_version_t)) self.assertEqual(shelf_version.version_number, all_versions[0].version_number) self.assertIn(new_subpath, statused_paths) client._shelf_close(shelf, pool) pool.clear()
def list_files(self, dirpath, revision): """List the content of a directory at a given revision, recursively. Yield tuples (path, kind) where 'path' is the entry path relatively to 'dirpath' and 'kind' is 'f' if the entry is a file, 'd' if it is a directory. Raise IOError if the directory cannot be found at given revision. """ rpath = self.path2url(dirpath) pool = core.Pool() rev = optrev(revision) try: entries = client.ls(rpath, rev, True, self.client_context, pool) except SubversionException, e: if e.apr_err == core.SVN_ERR_FS_NOT_FOUND: raise IOError(errno.ENOENT, '%s cannot be found at r%d' % (dirpath, revision)) raise
def init_ra_and_client(self): """Initializes the RA and client layers, because sometimes getting unified diffs runs the remote server out of open files. """ # while we're in here we'll recreate our pool self.pool = core.Pool() if self.username: core.svn_auth_set_parameter(self.auth_baton, core.SVN_AUTH_PARAM_DEFAULT_USERNAME, self.username) if self.password: core.svn_auth_set_parameter(self.auth_baton, core.SVN_AUTH_PARAM_DEFAULT_PASSWORD, self.password) self.client_context = client.create_context() self.client_context.auth_baton = self.auth_baton self.client_context.config = svn_config callbacks = RaCallbacks() callbacks.auth_baton = self.auth_baton self.callbacks = callbacks try: self.ra = ra.open2(self.svn_url, callbacks, svn_config, self.pool) except SubversionException, e: if e.apr_err == core.SVN_ERR_RA_SERF_SSL_CERT_UNTRUSTED: msg = ( 'Subversion does not trust the SSL certificate for this ' 'site; please try running \'svn ls %s\' first.' % self.svn_url) elif e.apr_err == core.SVN_ERR_RA_DAV_REQUEST_FAILED: msg = ('Failed to open Subversion repository; please try ' 'running \'svn ls %s\' for details.' % self.svn_url) else: msg = e.args[0] for k, v in vars(core).iteritems(): if k.startswith('SVN_ERR_') and v == e.apr_err: msg = '%s (%s)' % (msg, k) break raise common.SubversionConnectionException(msg)
def test_log5_revprops(self): """Test svn_client_log5 revprops (for typemap(in) apr_array_t *STRINGLIST)""" directory = urljoin(self.repos_uri + b"/", b"trunk/dir1") start = core.svn_opt_revision_t() end = core.svn_opt_revision_t() core.svn_opt_parse_revision(start, end, b"4:0") rev_range = core.svn_opt_revision_range_t() rev_range.start = start rev_range.end = end entry_pool = core.Pool() def log_entry_receiver_whole(log_entry, pool): """An implementation of svn_log_entry_receiver_t, holds whole log entries.""" self.received_log_entries.append( core.svn_log_entry_dup(log_entry, entry_pool)) self.received_log_entries = [] # (Pass tuple of bytes and str(unicode) mixture as revprops argument) client.log5((directory, ), start, (rev_range, ), 1, True, False, False, (u'svn:author', b'svn:log'), log_entry_receiver_whole, self.client_ctx) self.assertEqual(len(self.received_log_entries), 1) revprops = self.received_log_entries[0].revprops self.assertEqual(revprops[b'svn:log'], b"More directories.") self.assertEqual(revprops[b'svn:author'], b"john") with self.assertRaises(KeyError): commit_date = revprops['svn:date'] if utils.IS_PY3 or not utils.is_defaultencoding_utf8(): # 'utf-8' codecs on Python 2 does not raise UnicodeEncodeError # on surrogate code point U+dc00 - U+dcff. So we need to skip # below in such a case. with self.assertRaises(UnicodeEncodeError): client.log5((directory, ), start, (rev_range, ), 1, True, False, False, (u'svn:\udc61uthor', b'svn:log'), log_entry_receiver_whole, self.client_ctx)
def test_lock(self): lock = wc.add_lock(self.path, core.svn_lock_create(core.Pool()), self.wc) self.assertEqual(True, wc.adm_locked(self.wc)) self.assertEqual(True, wc.locked(self.path)) wc.remove_lock(self.path, self.wc)