Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
On 12/07/2010 12:13 AM, James Cameron wrote: On Mon, Dec 06, 2010 at 10:05:43AM +0100, Simon Schampijer wrote: Small nitpick from me: use os.path.join instead of str methods to concatenate paths. self._pending_files.append(os.path.join(dir_path, entry)) Yes, I saw that too, but the existing code uses for entry in dirs: if entry.startswith('.'): continue full_path = dir_path + '/' + entry and trying to change code unnecessarily is how defects are introduced, as has already been seen. I also don't like the idea of doing changes for portability unless they can be tested on alternate platforms. The same pattern occurs in extensions/cpsection/language/model.py, src/jarabe/model/network.py, src/jarabe/model/shell.py, and src/sugar/activity/activityservice.py if you'd like to change it. Activities InfoSlicer, Read, and TamTam are also afflicted. Ok, patches welcome :) For the patch title I would prefer something like "Make scanning of storage devices more robust OLPC #10140", is slightly more descriptive. Right. Acked-By: Simon Schampijer Thanks. Great, can you please push it? /me wants to do a new 0.84 release. Regards, Simon ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
On Mon, Dec 06, 2010 at 10:05:43AM +0100, Simon Schampijer wrote: > Small nitpick from me: use os.path.join instead of str methods to > concatenate paths. > > self._pending_files.append(os.path.join(dir_path, entry)) Yes, I saw that too, but the existing code uses for entry in dirs: if entry.startswith('.'): continue full_path = dir_path + '/' + entry and trying to change code unnecessarily is how defects are introduced, as has already been seen. I also don't like the idea of doing changes for portability unless they can be tested on alternate platforms. The same pattern occurs in extensions/cpsection/language/model.py, src/jarabe/model/network.py, src/jarabe/model/shell.py, and src/sugar/activity/activityservice.py if you'd like to change it. Activities InfoSlicer, Read, and TamTam are also afflicted. > For the patch title I would prefer something like "Make scanning of > storage devices more robust OLPC #10140", is slightly more > descriptive. Right. > Acked-By: Simon Schampijer Thanks. -- James Cameron http://quozl.linux.org.au/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
On 11/30/2010 03:32 PM, Sascha Silbe wrote: Excerpts from James Cameron's message of Tue Nov 30 01:14:14 +0100 2010: [src/jarabe/journal/model.py] +if self._date_start is not None and self.st_mtime< self._date_start: +return + +if self._date_end is not None and self.st_mtime> self._date_end: +return Both occurrences of self.st_mtime need to read stat.st_mtime instead (found by pylint). With those changes: Tested-By: Sascha Silbe Reviewed-By: Sascha Silbe Sascha Yes, please do those changes noted from Sascha. Small nitpick from me: use os.path.join instead of str methods to concatenate paths. self._pending_files.append(os.path.join(dir_path, entry)) For the patch title I would prefer something like "Make scanning of storage devices more robust OLPC #10140", is slightly more descriptive. Regards, Simon Acked-By: Simon Schampijer ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
On Tue, Nov 30, 2010 at 03:32:57PM +0100, Sascha Silbe wrote: > Excerpts from James Cameron's message of Tue Nov 30 01:14:14 +0100 2010: > > [src/jarabe/journal/model.py] > > > +if self._date_start is not None and self.st_mtime < > > self._date_start: > > +return > > + > > +if self._date_end is not None and self.st_mtime > self._date_end: > > +return > > Both occurrences of self.st_mtime need to read stat.st_mtime instead > (found by pylint). Sigh. You suggested splitting these tests, expanding the scope of my patch. I now regret accepting the suggestion. I think I should stick to the changes I want to make, not the changes other people want me to make. When enthusiasm for a change is low, the defect rate is high. -- James Cameron http://quozl.linux.org.au/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
Excerpts from James Cameron's message of Tue Nov 30 01:14:14 +0100 2010: [src/jarabe/journal/model.py] > +if self._date_start is not None and self.st_mtime < self._date_start: > +return > + > +if self._date_end is not None and self.st_mtime > self._date_end: > +return Both occurrences of self.st_mtime need to read stat.st_mtime instead (found by pylint). With those changes: Tested-By: Sascha Silbe Reviewed-By: Sascha Silbe Sascha -- http://sascha.silbe.org/ http://www.infra-silbe.de/ signature.asc Description: PGP signature ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
This patch was proposed on 14th September and there was no response. -- James Cameron http://quozl.linux.org.au/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
Update the progress bar regularly and prevent the UI from stalling during a scan. Avoid following recursive symlinks, and symlinks that point outside the filesystem being scanned. Do not check for MIME type if file is excluded for other filter reasons. Do not report permission denied errors. --- src/jarabe/journal/model.py | 151 +++--- 1 files changed, 97 insertions(+), 54 deletions(-) diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py index 0773446..a8836e3 100644 --- a/src/jarabe/journal/model.py +++ b/src/jarabe/journal/model.py @@ -1,4 +1,4 @@ -# Copyright (C) 2007-2008, One Laptop Per Child +# Copyright (C) 2007-2010, One Laptop per Child # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,10 +16,11 @@ import logging import os +import errno from datetime import datetime import time import shutil -from stat import S_IFMT, S_IFDIR, S_IFREG +from stat import S_IFLNK, S_IFMT, S_IFDIR, S_IFREG import re from operator import itemgetter @@ -230,7 +231,9 @@ class InplaceResultSet(BaseResultSet): BaseResultSet.__init__(self, query, page_size) self._mount_point = mount_point self._file_list = None -self._pending_directories = 0 +self._pending_directories = [] +self._visited_directories = [] +self._pending_files = [] self._stopped = False query_text = query.get('query', '') @@ -257,7 +260,10 @@ class InplaceResultSet(BaseResultSet): def setup(self): self._file_list = [] -self._recurse_dir(self._mount_point) +self._pending_directories = [self._mount_point] +self._visited_directories = [] +self._pending_files = [] +gobject.idle_add(self._scan) def stop(self): self._stopped = True @@ -298,63 +304,100 @@ class InplaceResultSet(BaseResultSet): return entries, total_count -def _recurse_dir(self, dir_path): -self._pending_directories += 1 -gobject.idle_add(self._idle_recurse_dir, dir_path) - -def _idle_recurse_dir(self, dir_path): -try: -self._real_recurse_dir(dir_path) -finally: -self._pending_directories -= 1 -if self._pending_directories == 0: -self.setup_ready() - -def _real_recurse_dir(self, dir_path): +def _scan(self): if self._stopped: +return False + +self.progress.send(self) + +if self._pending_files: +self._scan_a_file() +return True + +if self._pending_directories: +self._scan_a_directory() +return True + +self.setup_ready() +self._visited_directories = [] +return False + +def _scan_a_file(self): +full_path = self._pending_files.pop(0) + +try: +stat = os.lstat(full_path) +except OSError, e: +if e.errno != errno.ENOENT: +logging.exception( +'Error reading metadata of file %r', full_path) +return + +if S_IFMT(stat.st_mode) == S_IFLNK: +try: +link = os.readlink(full_path) +except OSError, e: +logging.exception( +'Error reading target of link %r', full_path) +return + +if not os.path.abspath(link).startswith(self._mount_point): +return + +try: +stat = os.stat(full_path) + +except OSError, e: +if e.errno != errno.ENOENT: +logging.exception( +'Error reading metadata of linked file %r', full_path) +return + +if S_IFMT(stat.st_mode) == S_IFDIR: +id_tuple = stat.st_ino, stat.st_dev +if not id_tuple in self._visited_directories: +self._visited_directories.append(id_tuple) +self._pending_directories.append(full_path) return +if S_IFMT(stat.st_mode) != S_IFREG: +return + +if self._regex is not None and \ +not self._regex.match(full_path): +return + +if self._date_start is not None and self.st_mtime < self._date_start: +return + +if self._date_end is not None and self.st_mtime > self._date_end: +return + +if self._mime_types: +mime_type = gio.content_type_guess(filename=full_path) +if mime_type not in self._mime_types: +return + +file_info = (full_path, stat, int(stat.st_mtime), stat.st_size) +self._file_list.append(file_info) + +return + +def _scan_a_directory(self): +dir_path = self._pending_directories.pop(0) + try: -dirs = os.listdir(dir_path) -except
[Sugar-devel] [PATCH] fix journal scan of external media, dev.laptop.org #10140
Update the progress bar regularly and prevent the UI from stalling during a scan. Avoid following recursive symlinks, and symlinks that point outside the filesystem being scanned. Do not check for MIME type if file is excluded for other filter reasons. Do not report permission denied errors. Tested on Sugar 0.88 using Ubuntu Sugar Remix (maverick). --- src/jarabe/journal/model.py | 150 --- 1 files changed, 97 insertions(+), 53 deletions(-) diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py index 81ca7d4..5ba3a76 100644 --- a/src/jarabe/journal/model.py +++ b/src/jarabe/journal/model.py @@ -1,4 +1,4 @@ -# Copyright (C) 2007-2008, One Laptop Per Child +# Copyright (C) 2007-2010, One Laptop per Child # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,10 +16,11 @@ import logging import os +import errno from datetime import datetime import time import shutil -from stat import S_IFMT, S_IFDIR, S_IFREG +from stat import S_IFLNK, S_IFMT, S_IFDIR, S_IFREG import re from operator import itemgetter @@ -220,7 +221,9 @@ class InplaceResultSet(BaseResultSet): BaseResultSet.__init__(self, query, page_size) self._mount_point = mount_point self._file_list = None -self._pending_directories = 0 +self._pending_directories = [] +self._visited_directories = [] +self._pending_files = [] self._stopped = False query_text = query.get('query', '') @@ -247,7 +250,10 @@ class InplaceResultSet(BaseResultSet): def setup(self): self._file_list = [] -self._recurse_dir(self._mount_point) +self._pending_directories = [self._mount_point] +self._visited_directories = [] +self._pending_files = [] +gobject.idle_add(self._scan) def stop(self): self._stopped = True @@ -287,62 +293,100 @@ class InplaceResultSet(BaseResultSet): return entries, total_count -def _recurse_dir(self, dir_path): -self._pending_directories += 1 -gobject.idle_add(self._idle_recurse_dir, dir_path) - -def _idle_recurse_dir(self, dir_path): -try: -self._real_recurse_dir(dir_path) -finally: -self._pending_directories -= 1 -if self._pending_directories == 0: -self.setup_ready() - -def _real_recurse_dir(self, dir_path): +def _scan(self): if self._stopped: +return False + +self.progress.send(self) + +if self._pending_files: +self._scan_a_file() +return True + +if self._pending_directories: +self._scan_a_directory() +return True + +self.setup_ready() +self._visited_directories = [] +return False + +def _scan_a_file(self): +full_path = self._pending_files.pop(0) + +try: +stat = os.lstat(full_path) +except OSError, e: +if e.errno != errno.ENOENT: +logging.exception( +'Error reading metadata of file %r', full_path) +return + +if S_IFMT(stat.st_mode) == S_IFLNK: +try: +link = os.readlink(full_path) +except OSError, e: +logging.exception( +'Error reading target of link %r', full_path) +return + +if not os.path.abspath(link).startswith(self._mount_point): +return + +try: +stat = os.stat(full_path) + +except OSError, e: +if e.errno != errno.ENOENT: +logging.exception( +'Error reading metadata of linked file %r', full_path) +return + +if S_IFMT(stat.st_mode) == S_IFDIR: +id_tuple = stat.st_ino, stat.st_dev +if not id_tuple in self._visited_directories: +self._visited_directories.append(id_tuple) +self._pending_directories.append(full_path) return +if S_IFMT(stat.st_mode) != S_IFREG: +return + +if self._regex is not None and \ +not self._regex.match(full_path): +return + +if self._date_start is not None and self.st_mtime < self._date_start: +return + +if self._date_end is not None and self.st_mtime > self._date_end: +return + +if self._mime_types: +mime_type = gio.content_type_guess(filename=full_path) +if mime_type not in self._mime_types: +return + +file_info = (full_path, stat, int(stat.st_mtime), stat.st_size) +self._file_list.append(file_info) + +return + +def _scan_a_directory(self): +dir_path = self._pending_directories.pop(0) + t