Bladeren bron

[fb] Trash opens up on user current path if possible

Romain Rigaux 12 jaren geleden
bovenliggende
commit
d370148

+ 1 - 1
apps/filebrowser/src/filebrowser/templates/fb_components.mako

@@ -32,7 +32,7 @@ from django.utils.translation import ugettext as _
         </li>
         </li>
         <li class="pull-right">
         <li class="pull-right">
           <a href="${url('filebrowser.views.view', path=urlencode(path))}?default_to_trash" style="line-height:18px" title="${_('View trash')}">
           <a href="${url('filebrowser.views.view', path=urlencode(path))}?default_to_trash" style="line-height:18px" title="${_('View trash')}">
-            <i class="fa fa-trash-o"></i> ${_('View trash')}
+            <i class="fa fa-trash-o"></i> ${_('Trash')}
           </a>
           </a>
         </li>
         </li>
         % else:
         % else:

+ 7 - 9
apps/filebrowser/src/filebrowser/views.py

@@ -14,11 +14,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # limitations under the License.
-#
-# Implements simple file system browsing operations.
-#
-# Useful resources:
-#   django/views/static.py manages django's internal directory index
 
 
 import errno
 import errno
 import logging
 import logging
@@ -46,6 +41,7 @@ from django.template.defaultfilters import urlencode
 from django.utils.functional import curry
 from django.utils.functional import curry
 from django.utils.http import http_date, urlquote
 from django.utils.http import http_date, urlquote
 from django.utils.html import escape
 from django.utils.html import escape
+from django.utils.translation import ugettext as _
 from cStringIO import StringIO
 from cStringIO import StringIO
 from gzip import GzipFile
 from gzip import GzipFile
 from avro import datafile, io
 from avro import datafile, io
@@ -54,6 +50,9 @@ from desktop.lib import i18n, paginator
 from desktop.lib.conf import coerce_bool
 from desktop.lib.conf import coerce_bool
 from desktop.lib.django_util import make_absolute, render, render_json, format_preserving_redirect
 from desktop.lib.django_util import make_absolute, render, render_json, format_preserving_redirect
 from desktop.lib.exceptions_renderable import PopupException
 from desktop.lib.exceptions_renderable import PopupException
+from hadoop.fs.hadoopfs import Hdfs
+from hadoop.fs.exceptions import WebHdfsException
+
 from filebrowser.conf import MAX_SNAPPY_DECOMPRESSION_SIZE
 from filebrowser.conf import MAX_SNAPPY_DECOMPRESSION_SIZE
 from filebrowser.lib.archives import archive_factory
 from filebrowser.lib.archives import archive_factory
 from filebrowser.lib.rwx import filetype, rwx
 from filebrowser.lib.rwx import filetype, rwx
@@ -61,10 +60,6 @@ from filebrowser.lib import xxd
 from filebrowser.forms import RenameForm, UploadFileForm, UploadArchiveForm, MkDirForm, EditorForm, TouchForm,\
 from filebrowser.forms import RenameForm, UploadFileForm, UploadArchiveForm, MkDirForm, EditorForm, TouchForm,\
                               RenameFormSet, RmTreeFormSet, ChmodFormSet, ChownFormSet, CopyFormSet, RestoreFormSet,\
                               RenameFormSet, RmTreeFormSet, ChmodFormSet, ChownFormSet, CopyFormSet, RestoreFormSet,\
                               TrashPurgeForm
                               TrashPurgeForm
-from hadoop.fs.hadoopfs import Hdfs
-from hadoop.fs.exceptions import WebHdfsException
-
-from django.utils.translation import ugettext as _
 
 
 
 
 DEFAULT_CHUNK_SIZE_BYTES = 1024 * 4 # 4KB
 DEFAULT_CHUNK_SIZE_BYTES = 1024 * 4 # 4KB
@@ -144,6 +139,9 @@ def view(request, path):
 
 
     # default_to_home is set in bootstrap.js
     # default_to_home is set in bootstrap.js
     if 'default_to_trash' in request.GET:
     if 'default_to_trash' in request.GET:
+        home_trash = request.fs.join(request.fs.trash_path, 'Current', request.user.get_home_directory()[1:])
+        if request.fs.isdir(home_trash):
+            return format_preserving_redirect(request, reverse(view, kwargs=dict(path=home_trash)))
         if request.fs.isdir(request.fs.trash_path):
         if request.fs.isdir(request.fs.trash_path):
             return format_preserving_redirect(request, reverse(view, kwargs=dict(path=request.fs.trash_path)))
             return format_preserving_redirect(request, reverse(view, kwargs=dict(path=request.fs.trash_path)))
 
 

+ 41 - 0
apps/filebrowser/src/filebrowser/views_test.py

@@ -1130,3 +1130,44 @@ def test_location_to_url():
   assert_equal('/filebrowser/view/var/lib/hadoop-hdfs', location_to_url('hdfs://localhost:8020/var/lib/hadoop-hdfs'))
   assert_equal('/filebrowser/view/var/lib/hadoop-hdfs', location_to_url('hdfs://localhost:8020/var/lib/hadoop-hdfs'))
   assert_equal('/filebrowser/view/', location_to_url('hdfs://localhost:8020'))
   assert_equal('/filebrowser/view/', location_to_url('hdfs://localhost:8020'))
   assert_equal(None, location_to_url('thrift://10.0.0.1:9083'))
   assert_equal(None, location_to_url('thrift://10.0.0.1:9083'))
+
+@attr('requires_hadoop')
+def test_trash():
+  cluster = pseudo_hdfs4.shared_cluster()
+
+  try:
+    c = make_logged_in_client()
+    USERNAME = 'test'
+    cluster.fs.setuser(USERNAME)
+
+    cluster.fs.do_as_superuser(cluster.fs.chown, '/user/%s' % USERNAME, USERNAME, USERNAME)
+
+    HOME_TRASH_DIR = '/user/%s/.Trash/Current/user/%s' % (USERNAME, USERNAME)
+    prefix = '/tmp/test_trash'
+    PATH_1 = '/%s/1' % prefix
+    cluster.fs.mkdir(prefix)
+    cluster.fs.mkdir(PATH_1)
+
+    c.post('/filebrowser/rmtree?skip_trash=true', dict(path=[HOME_TRASH_DIR]))
+
+    # No trash folder
+    response = c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    assert_equal([], response.redirect_chain)
+
+    c.post('/filebrowser/rmtree', dict(path=[PATH_1]))
+
+    # We have a trash folder so a redirect (Current not always there)
+    response = c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    assert_true(any(['.Trash' in page for page, code in response.redirect_chain]), response.redirect_chain)
+
+    c.post('/filebrowser/rmtree?skip_trash=true', dict(path=[HOME_TRASH_DIR]))
+
+    # No home trash, just regular root trash
+    response = c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    assert_true(any(['.Trash' in page for page, code in response.redirect_chain]), response.redirect_chain)
+  finally:
+    try:
+      cluster.fs.rmtree(prefix)     # Clean up
+    except:
+      pass      # Don't let cleanup errors mask earlier failures
+

+ 4 - 12
desktop/libs/hadoop/src/hadoop/fs/webhdfs.py

@@ -69,8 +69,7 @@ class WebHdfs(Hdfs):
     self._client = self._make_client(url, security_enabled)
     self._client = self._make_client(url, security_enabled)
     self._root = resource.Resource(self._client)
     self._root = resource.Resource(self._client)
 
 
-    # To store user info
-    self._thread_local = threading.local()
+    self._user = None
 
 
     LOG.debug("Initializing Hadoop WebHdfs: %s (security: %s, superuser: %s)" %
     LOG.debug("Initializing Hadoop WebHdfs: %s (security: %s, superuser: %s)" %
               (self._url, self._security_enabled, self._superuser))
               (self._url, self._security_enabled, self._superuser))
@@ -126,20 +125,13 @@ class WebHdfs(Hdfs):
   @property
   @property
   def user(self):
   def user(self):
     try:
     try:
-      return self._thread_local.user
+      return self._user
     except AttributeError:
     except AttributeError:
       return WebHdfs.DEFAULT_USER
       return WebHdfs.DEFAULT_USER
 
 
   @property
   @property
   def trash_path(self):
   def trash_path(self):
-    try:
-      return self._thread_local.trash_path[self.user]
-    except AttributeError:
-      self._thread_local.trash_paths = {}
-      self._thread_local.trash_paths[self.user] = self.join(self.get_home_dir(), '.Trash')
-    except KeyError:
-      self._thread_local.trash_paths[self.user] = self.join(self.get_home_dir(), '.Trash')
-    return self._thread_local.trash_paths[self.user]
+    return self.join(self.get_home_dir(), '.Trash')
 
 
   @property
   @property
   def current_trash_path(self):
   def current_trash_path(self):
@@ -154,7 +146,7 @@ class WebHdfs(Hdfs):
   def setuser(self, user):
   def setuser(self, user):
     """Set a new user. Return the current user."""
     """Set a new user. Return the current user."""
     curr = self.user
     curr = self.user
-    self._thread_local.user = user
+    self._user = user
     return curr
     return curr
 
 
   def listdir_stats(self, path, glob=None):
   def listdir_stats(self, path, glob=None):