Example #1
0
    def check_file(self, path, content):
        """Check if there is a file at path with content.

        :raises: ValueError if there a non-file at path.
        :return: True if there is a file present with the right content.
        """
        try:
            st = self.contentdir.stat(path)
            if osutils.file_kind_from_stat_mode(st.st_mode) != 'file':
                raise ValueError('unexpected non-file at %r' % path)
            f = self.contentdir.get(path)
            try:
                self.ui.output_log(4, __name__, 'Hashing %s %r' % (content.kind, path))
                size, sha1 = osutils.size_sha_file(f)
            finally:
                f.close()
            return sha1 == content.sha1 and size == content.length
        except errors.NoSuchFile:
            return False
Example #2
0
 def _finished_scan(self, dir_contents, missing_is_unchanged=False):
     """Perform finished() by scanning the disk.
     
     :param dir_contents: A callback to get the contents of a directory.
     :param missing_is_unchanged: If True, a path not listed in a directory
         is unchanged, rather than missing.
     """
     pending = ['']
     while pending:
         dirname = pending.pop(-1)
         names = dir_contents(dirname)
         # NB: quadratic in lookup here due to presence in inner loop:
         # consider tuning.
         segments = dirname.split('/')
         cwd = self.tree
         for segment in segments:
             if not segment:
                 continue
             try:
                 cwd = cwd[segment]
             except KeyError:
                 # totally new directory - added to journal by the directory
                 # above.
                 cwd = {}
         # tree_names contains the last recorded set of names.
         tree_names = set(cwd)
         names = set(names)
         if not missing_is_unchanged:
             for name in tree_names - names:
                 # deletes
                 path = dirname and ('%s/%s' % (dirname, name)) or name
                 old_kind_details = cwd[name]
                 if type(old_kind_details) is dict:
                     self._gather_deleted_dir(path, old_kind_details)
                     old_kind_details = DirContent()
                 self.journal.add(path, 'del', old_kind_details)
         new_names = names - tree_names
         for name in names:
             path = dirname and ('%s/%s' % (dirname, name)) or name
             if self._skip_path(path):
                 if name in tree_names:
                     # Newly excluded.
                     old_kind_details = cwd[name]
                     if type(old_kind_details) is dict:
                         self._gather_deleted_dir(path, old_kind_details)
                         old_kind_details = DirContent()
                     self.journal.add(path, 'del', old_kind_details)
                 continue
             try:
                 statinfo = self.transport.stat(path)
             except errors.NoSuchFile:
                 # This file doesn't actually exist: may be concurrent
                 # delete, or a seen change from a changes list.
                 if name in tree_names:
                     # A delete.
                     old_kind_details = cwd[name]
                     if type(old_kind_details) is dict:
                         self._gather_deleted_dir(path, old_kind_details)
                         old_kind_details = DirContent()
                     self.journal.add(path, 'del', old_kind_details)
                 continue
             mtime = getattr(statinfo, 'st_mtime', 0)
             kind = osutils.file_kind_from_stat_mode(statinfo.st_mode)
             if (kind != 'directory' and
                 (self.last_timestamp - mtime > 3 and mtime)
                 and name not in new_names):
                 # We have to look inside directories always; things that
                 # are older than 3 seconds we can trust even FAT to not
                 # be lying about the last-modification (it has 2 second
                 # granularity) and finally its not new (new things have
                 # to be scanned always).
                 continue
             if kind == 'file':
                 f = self.transport.get(path)
                 try:
                     disk_size, disk_sha1 = osutils.size_sha_file(f)
                 finally:
                     f.close()
                 new_kind_details = FileContent(disk_sha1, disk_size, statinfo.st_mtime)
             elif kind == 'symlink':
                 new_kind_details = SymlinkContent(os.readlink(self.transport.local_abspath(path)))
             elif kind == 'directory':
                 new_kind_details = DirContent()
                 pending.append(path)
             else:
                 raise ValueError('unknown kind %r for %r' % (kind, path))
             if name in new_names:
                 self.journal.add(path, 'new', new_kind_details)
             else:
                 old_kind_details = cwd[name]
                 if type(old_kind_details) is dict:
                     old_kind_details = DirContent()
                 if old_kind_details != new_kind_details:
                     self.journal.add(path, 'replace', (old_kind_details,
                         new_kind_details))
     for path, (action, details) in self.journal.paths.iteritems():
         self.ui.output_log(4, __name__, 'Journalling action %s for %r' % (
             action, path))
     return self.journal