def _move_delete_request(self, req, handler): self.log.debug('Handling move/delete for %s', req.authname) operation = req.args.get('bsop_mvdel_op') #Moving or deleting? src_names = req.args.getlist('bsop_mvdel_src_name') # Items to move/del dst_name = req.args.get('bsop_mvdel_dst_name') # Destination if move commit_msg = req.args.get('bsop_mvdel_commit') # ContextMenuPlugin provides each src as [reponame/][page_path/]node_path # The Trac request path is of the form /[reponame/][page_path] # Retrieve just the portion of the src items that is relative to this # page by stripping the request path. Do this before the request path # is itself stripped of reponame when retrieving the repository path = req.args.get('path') src_names = [posixpath.join('/', src_name) for src_name in src_names] src_names = [src_name.split(path, 1)[1] for src_name in src_names] self.log.debug('Received %i source items to "%s"', len(src_names), operation) # Enforce rename_only mode if operation == 'move' and self.rename_only: # Do not allow move operation to place src in dst, if dst exists move_as_child = False # Check that move affects only one node if len(src_names) > 1: self.log.error('Attempted to rename %i nodes, only 1 node can' 'be renamed at a time', len(src_names)) raise TracError('Cannot rename multiple files or folders.') # Check that destination is just filename # i.e. it doesn't contain any path components elif '/' in dst_name: self.log.error('Rename encountered path seperator "/" in' 'destination ("%s", "%s")', src_names[0], dst_name) raise TracError(_('A filename can not contain "/"')) # Check whether the source is in a sub-folder - probably because # the user chose a node delivered by XMLHTTPRequest # Ensure destination directory is the same directory as the source elif '/' in src_names[0]: src_dir, src_base = posixpath.split(src_names[0]) dst_name = posixpath.join(src_dir, dst_name) else: # Rename only mode is not in effect, allow src to be moved inside # dst if dst exists or there is more than one src item move_as_child = True self.log.debug('Opening repository for %s', operation) reponame, repos, path = _get_repository(self.env, req) try: src_paths = [repos.normalize_path('/'.join([path, src_name])) for src_name in src_names] dst_path = repos.normalize_path('/'.join([path, dst_name])) svn_writer = SubversionWriter(self.env, repos, req.authname) try: if operation == 'delete': self.log.info('Deleting %i items in repository %s', len(src_paths), reponame) svn_writer.delete(src_paths, commit_msg) elif operation == 'move': self.log.info('Moving %i items to %s in repository %s', len(src_paths), repr(dst_path), reponame) svn_writer.move(src_paths, dst_path, move_as_child, commit_msg) else: raise TracError("Unknown operation %s" % operation) verb = _describe_op(operation, self.rename_only, 'Deleted', 'Moved', 'Renamed') add_notice(req, "%s %i item(s) successfully" % (verb, len(src_paths))) except Exception, e: self.log.exception("Failed when attempting svn operation " "%s with rename_only=%s: %s", operation, self.rename_only, e) verb = _describe_op(operation, self.rename_only, 'Delete', 'Move', 'Rename') add_warning(req, "%s failed: %s" % (verb, e)) finally: repos.sync() self.log.debug('Closing repository') repos.close() # Perform http redirect back to this page in order to rerender # template according to new repository state req.redirect(req.href(req.path_info))
def _move_delete_request(self, req, handler): self.log.debug('Handling move/delete for %s', req.authname) operation = req.args.get('bsop_mvdel_op') #Moving or deleting? src_names = req.args.getlist( 'bsop_mvdel_src_name') # Items to move/del dst_name = req.args.get('bsop_mvdel_dst_name') # Destination if move commit_msg = req.args.get('bsop_mvdel_commit') # ContextMenuPlugin provides each src as [reponame/][page_path/]node_path # The Trac request path is of the form /[reponame/][page_path] # Retrieve just the portion of the src items that is relative to this # page by stripping the request path. Do this before the request path # is itself stripped of reponame when retrieving the repository path = req.args.get('path') src_names = [posixpath.join('/', src_name) for src_name in src_names] src_names = [src_name.split(path, 1)[1] for src_name in src_names] self.log.debug('Received %i source items to "%s"', len(src_names), operation) # Enforce rename_only mode if operation == 'move' and self.rename_only: # Do not allow move operation to place src in dst, if dst exists move_as_child = False # Check that move affects only one node if len(src_names) > 1: self.log.error( 'Attempted to rename %i nodes, only 1 node can' 'be renamed at a time', len(src_names)) raise TracError('Cannot rename multiple files or folders.') # Check that destination is just filename # i.e. it doesn't contain any path components elif '/' in dst_name: self.log.error( 'Rename encountered path seperator "/" in' 'destination ("%s", "%s")', src_names[0], dst_name) raise TracError(_('A filename can not contain "/"')) # Check whether the source is in a sub-folder - probably because # the user chose a node delivered by XMLHTTPRequest # Ensure destination directory is the same directory as the source elif '/' in src_names[0]: src_dir, src_base = posixpath.split(src_names[0]) dst_name = posixpath.join(src_dir, dst_name) else: # Rename only mode is not in effect, allow src to be moved inside # dst if dst exists or there is more than one src item move_as_child = True self.log.debug('Opening repository for %s', operation) reponame, repos, path = _get_repository(self.env, req) try: src_paths = [ repos.normalize_path('/'.join([path, src_name])) for src_name in src_names ] dst_path = repos.normalize_path('/'.join([path, dst_name])) svn_writer = SubversionWriter(self.env, repos, req.authname) try: if operation == 'delete': self.log.info('Deleting %i items in repository %s', len(src_paths), reponame) svn_writer.delete(src_paths, commit_msg) elif operation == 'move': self.log.info('Moving %i items to %s in repository %s', len(src_paths), repr(dst_path), reponame) svn_writer.move(src_paths, dst_path, move_as_child, commit_msg) else: raise TracError("Unknown operation %s" % operation) verb = _describe_op(operation, self.rename_only, 'Deleted', 'Moved', 'Renamed') add_notice( req, "%s %i item(s) successfully" % (verb, len(src_paths))) except Exception, e: self.log.exception( "Failed when attempting svn operation " "%s with rename_only=%s: %s", operation, self.rename_only, e) verb = _describe_op(operation, self.rename_only, 'Delete', 'Move', 'Rename') add_warning(req, "%s failed: %s" % (verb, e)) finally: repos.sync() self.log.debug('Closing repository') repos.close() # Perform http redirect back to this page in order to rerender # template according to new repository state req.redirect(req.href(req.path_info))