예제 #1
0
  def test_putfile(self):
    tmpoutdir = None
    tmpindir = None

    try:
      tmpindir = tempfile.mkdtemp(prefix='isolateserver_test')
      infile = os.path.join(tmpindir, u'in')
      with fs.open(infile, 'wb') as f:
        f.write('data')

      tmpoutdir = tempfile.mkdtemp(prefix='isolateserver_test')

      # Copy as fileobj
      fo = os.path.join(tmpoutdir, u'fo')
      isolateserver.putfile(io.BytesIO('data'), fo)
      self.assertEqual(True, fs.exists(fo))
      self.assertEqual(False, fs.islink(fo))
      self.assertFile(fo, 'data')

      # Copy with partial fileobj
      pfo = os.path.join(tmpoutdir, u'pfo')
      fobj = io.BytesIO('adatab')
      fobj.read(1)  # Read the 'a'
      isolateserver.putfile(fobj, pfo, size=4)
      self.assertEqual(True, fs.exists(pfo))
      self.assertEqual(False, fs.islink(pfo))
      self.assertEqual('b', fobj.read())
      self.assertFile(pfo, 'data')

      # Copy as not readonly
      cp = os.path.join(tmpoutdir, u'cp')
      with fs.open(infile, 'rb') as f:
        isolateserver.putfile(f, cp, file_mode=0o755)
      self.assertEqual(True, fs.exists(cp))
      self.assertEqual(False, fs.islink(cp))
      self.assertFile(cp, 'data')

      # Use hardlink
      hl = os.path.join(tmpoutdir, u'hl')
      with fs.open(infile, 'rb') as f:
        isolateserver.putfile(f, hl, use_symlink=False)
      self.assertEqual(True, fs.exists(hl))
      self.assertEqual(False, fs.islink(hl))
      self.assertFile(hl, 'data')

      # Use symlink
      sl = os.path.join(tmpoutdir, u'sl')
      with fs.open(infile, 'rb') as f:
        isolateserver.putfile(f, sl, use_symlink=True)
      self.assertEqual(True, fs.exists(sl))
      self.assertEqual(True, fs.islink(sl))
      self.assertEqual('data', fs.open(sl, 'rb').read())
      self.assertFile(sl, 'data')

    finally:
      if tmpindir:
        file_path.rmtree(tmpindir)
      if tmpoutdir:
        file_path.rmtree(tmpoutdir)
예제 #2
0
    def tryReconnect(self):
        """checks if reconnect needed"""

        if not self.core.config["reconnect"][
                "activated"] or not self.core.api.isTimeReconnect():
            return False

        # only reconnect when all threads are ready
        if not (0 < self.wantReconnect() == len(self.working)):
            return False

        if not exists(self.core.config['reconnect']['method']):
            if exists(join(pypath, self.core.config['reconnect']['method'])):
                self.core.config['reconnect']['method'] = join(
                    pypath, self.core.config['reconnect']['method'])
            else:
                self.core.config["reconnect"]["activated"] = False
                self.log.warning(_("Reconnect script not found!"))
                return

        self.reconnecting.set()

        self.log.info(_("Starting reconnect"))

        # wait until all thread got the event
        while [x.active.plugin.waiting for x in self.working].count(True) != 0:
            sleep(0.25)

        old_ip = get_ip()

        self.core.evm.dispatchEvent("reconnect:before", old_ip)
        self.log.debug("Old IP: %s" % old_ip)

        try:
            call(self.core.config['reconnect']['method'], shell=True)
        except:
            self.log.warning(_("Failed executing reconnect script!"))
            self.core.config["reconnect"]["activated"] = False
            self.reconnecting.clear()
            self.core.print_exc()
            return

        sleep(1)
        ip = get_ip()
        self.core.evm.dispatchEvent("reconnect:after", ip)

        if not old_ip or old_ip == ip:
            self.log.warning(_("Reconnect not successful"))
        else:
            self.log.info(_("Reconnected, new IP: %s") % ip)

        self.reconnecting.clear()
예제 #3
0
    def tryReconnect(self):
        """checks if reconnect needed"""

        if not self.core.config["reconnect"]["activated"] or not self.core.api.isTimeReconnect():
            return False

        # only reconnect when all threads are ready
        if not (0 < self.wantReconnect() == len(self.working)):
            return False

        if not exists(self.core.config['reconnect']['method']):
            if exists(join(pypath, self.core.config['reconnect']['method'])):
                self.core.config['reconnect']['method'] = join(pypath, self.core.config['reconnect']['method'])
            else:
                self.core.config["reconnect"]["activated"] = False
                self.log.warning(_("Reconnect script not found!"))
                return

        self.reconnecting.set()

        self.log.info(_("Starting reconnect"))

        # wait until all thread got the event
        while [x.active.plugin.waiting for x in self.working].count(True) != 0:
            sleep(0.25)

        old_ip = get_ip()

        self.core.evm.dispatchEvent("reconnect:before", old_ip)
        self.log.debug("Old IP: %s" % old_ip)

        try:
            call(self.core.config['reconnect']['method'], shell=True)
        except:
            self.log.warning(_("Failed executing reconnect script!"))
            self.core.config["reconnect"]["activated"] = False
            self.reconnecting.clear()
            self.core.print_exc()
            return

        sleep(1)
        ip = get_ip()
        self.core.evm.dispatchEvent("reconnect:after", ip)

        if not old_ip or old_ip == ip:
            self.log.warning(_("Reconnect not successful"))
        else:
            self.log.info(_("Reconnected, new IP: %s") % ip)

        self.reconnecting.clear()
예제 #4
0
def do(inicio, fim, limit):
    print('Iniciando...')
    start, end = parse_datas(inicio, fim)
    out_filename = 'sizes_recinto%s%s%s.pickle' % (end.year, end.month,
                                                   end.day)
    s0 = time.time()
    sizes_recinto = defaultdict(list)
    query = {
        'metadata.contentType': 'image/jpeg',
        'metadata.recinto': {
            '$exists': True
        },
        'metadata.dataescaneamento': {
            '$gte': start,
            '$lt': end
        }
    }
    projection = {'_id': 1, 'metadata.recinto': 1}
    # r = requests.post('https://ajna.labin.rf08.srf/virasana/grid_data', json=params, verify=False)
    cursor = mongodb.fs.files.find(query, projection).limit(limit)
    for count, doc in enumerate(cursor):
        _id = doc['_id']
        oid = ObjectId(_id)
        if fs.exists(oid):
            grid_out = fs.get(oid)
            image = Image.open(io.BytesIO(grid_out.read()))
            # print(image.size)
            sizes_recinto[doc['metadata']['recinto']].append(image.size)
    s1 = time.time()
    # print(sizes_recinto)
    print('{:0.2f} segundos para processar {:d} registros'.format((s1 - s0),
                                                                  count))
    print('Resultado salvo em %s' % out_filename)
    with open(out_filename, 'wb') as handle:
        pickle.dump(sizes_recinto, handle, protocol=pickle.HIGHEST_PROTOCOL)
예제 #5
0
    def test_clean_cache(self):
        dest_dir = os.path.join(self.tempdir, 'dest')
        cache = self.get_cache(_get_policies())
        self.assertEqual([], fs.listdir(cache.cache_dir))

        a_path = os.path.join(dest_dir, u'a')
        b_path = os.path.join(dest_dir, u'b')

        self.assertEqual(0, cache.install(a_path, u'1'))
        self.assertEqual(0, cache.install(b_path, u'2'))
        self.assertEqual(
            False, fs.exists(os.path.join(cache.cache_dir, cache.NAMED_DIR)))

        self.assertEqual({u'a', u'b'}, set(fs.listdir(dest_dir)))
        self.assertFalse(cache.available)
        self.assertEqual([cache.STATE_FILE], fs.listdir(cache.cache_dir))

        write_file(os.path.join(a_path, u'x'), u'x')
        write_file(os.path.join(b_path, u'y'), u'y')

        self.assertEqual(1, cache.uninstall(a_path, u'1'))
        self.assertEqual(1, cache.uninstall(b_path, u'2'))

        self.assertEqual(4, len(fs.listdir(cache.cache_dir)))
        path1 = os.path.join(cache.cache_dir, cache._lru['1'][0])
        self.assertEqual('x', read_file(os.path.join(path1, u'x')))
        path2 = os.path.join(cache.cache_dir, cache._lru['2'][0])
        self.assertEqual('y', read_file(os.path.join(path2, u'y')))
        self.assertEqual(os.path.join(u'..', cache._lru['1'][0]),
                         fs.readlink(cache._get_named_path('1')))
        self.assertEqual(os.path.join(u'..', cache._lru['2'][0]),
                         fs.readlink(cache._get_named_path('2')))
        self.assertEqual(
            [u'1', u'2'],
            sorted(fs.listdir(os.path.join(cache.cache_dir, cache.NAMED_DIR))))
예제 #6
0
    def install(self, dst, name):
        """Creates the directory |dst| and moves a previous named cache |name| if it
    was in the local named caches cache.

    dst must be absolute, unicode and must not exist.

    Returns the reused named cache size in bytes, or 0 if none was present.

    Raises NamedCacheError if cannot install the cache.
    """
        logging.info('NamedCache.install(%r, %r)', dst, name)
        with self._lock:
            try:
                if fs.isdir(dst):
                    raise NamedCacheError(
                        'installation directory %r already exists' % dst)

                # Remove the named symlink if it exists.
                link_name = self._get_named_path(name)
                if fs.exists(link_name):
                    # Remove the symlink itself, not its destination.
                    fs.remove(link_name)

                if name in self._lru:
                    rel_cache, size = self._lru.get(name)
                    abs_cache = os.path.join(self.cache_dir, rel_cache)
                    if fs.isdir(abs_cache):
                        logging.info('- reusing %r; size was %d', rel_cache,
                                     size)
                        file_path.ensure_tree(os.path.dirname(dst))
                        self._sudo_chown(abs_cache)
                        fs.rename(abs_cache, dst)
                        self._remove(name)
                        return size

                    logging.warning('- expected directory %r, does not exist',
                                    rel_cache)
                    self._remove(name)

                # The named cache does not exist, create an empty directory. When
                # uninstalling, we will move it back to the cache and create an an
                # entry.
                logging.info('- creating new directory')
                file_path.ensure_tree(dst)
                return 0
            except (IOError, OSError) as ex:
                # Raise using the original traceback.
                exc = NamedCacheError(
                    'cannot install cache named %r at %r: %s' %
                    (name, dst, ex))
                six.reraise(type(exc), exc, sys.exc_info()[2])
            finally:
                self._save()
예제 #7
0
    def test_load_corrupted_state(self):
        os.mkdir(self.cache_dir)
        c = local_caching.NamedCache
        with open(os.path.join(self.cache_dir, c.STATE_FILE), 'w') as f:
            f.write('}}}}')
        fs.makedirs(os.path.join(self.cache_dir, '1'), 0777)

        cache = self.get_cache(_get_policies())
        self._add_one_item(cache, 1)
        self.assertTrue(
            fs.exists(os.path.join(cache.cache_dir, cache.NAMED_DIR, '1')))
        self.assertTrue(
            fs.islink(os.path.join(cache.cache_dir, cache.NAMED_DIR, '1')))
        self.assertEqual([], cache.trim())
        self.assertTrue(
            fs.exists(os.path.join(cache.cache_dir, cache.NAMED_DIR, '1')))
        self.assertTrue(
            fs.islink(os.path.join(cache.cache_dir, cache.NAMED_DIR, '1')))
        self.assertEqual(True, cache.cleanup())
        self.assertEqual(
            sorted([cache.NAMED_DIR, cache.STATE_FILE, cache._lru[u'1'][0]]),
            sorted(fs.listdir(cache.cache_dir)))
예제 #8
0
 def test_native_case_not_sensitive_non_existent(self):
     # This test also ensures that the output is independent on the input
     # string case.
     non_existing = os.path.join("trace_input_test_this_dir_should_not_exist", "really not", "")
     path = os.path.expanduser(os.path.join(u"~", non_existing))
     path = path.replace("/", os.path.sep)
     self.assertFalse(fs.exists(path))
     lower = file_path.get_native_path_case(path.lower())
     upper = file_path.get_native_path_case(path.upper())
     # Make sure non-existing element is not modified:
     self.assertTrue(lower.endswith(non_existing.lower()))
     self.assertTrue(upper.endswith(non_existing.upper()))
     self.assertEqual(lower[: -len(non_existing)], upper[: -len(non_existing)])
예제 #9
0
 def test_native_case_not_sensitive_non_existent(self):
   # This test also ensures that the output is independent on the input
   # string case.
   non_existing = os.path.join(
       'trace_input_test_this_dir_should_not_exist', 'really not', '')
   path = os.path.expanduser(os.path.join(u'~', non_existing))
   path = path.replace('/', os.path.sep)
   self.assertFalse(fs.exists(path))
   lower = file_path.get_native_path_case(path.lower())
   upper = file_path.get_native_path_case(path.upper())
   # Make sure non-existing element is not modified:
   self.assertTrue(lower.endswith(non_existing.lower()))
   self.assertTrue(upper.endswith(non_existing.upper()))
   self.assertEqual(lower[:-len(non_existing)], upper[:-len(non_existing)])
예제 #10
0
 def _add_one_item(self, cache, size):
     """Adds one item of |size| bytes in the cache and returns the created name.
 """
     # Don't allow 0 byte items here. This doesn't work for named cache.
     self.assertTrue(size)
     data = _gen_data(size)
     if isinstance(cache, local_caching.ContentAddressedCache):
         # This covers both MemoryContentAddressedCache and
         # DiskContentAddressedCache.
         return cache.write(self._algo(data).hexdigest(), [data])
     elif isinstance(cache, local_caching.NamedCache):
         # In this case, map a named cache, add a file, unmap it.
         dest_dir = os.path.join(self.tempdir, 'dest')
         self.assertFalse(fs.exists(dest_dir))
         name = unicode(size)
         cache.install(dest_dir, name)
         # Put a file in there named 'hello', otherwise it'll stay empty.
         with fs.open(os.path.join(dest_dir, 'hello'), 'wb') as f:
             f.write(data)
         cache.uninstall(dest_dir, name)
         self.assertFalse(fs.exists(dest_dir))
         return name
     self.fail('Unexpected cache type %r' % cache)
     return None
예제 #11
0
 def _allocate_dir(self):
     """Creates and returns relative path of a new cache directory."""
     # We randomly generate directory names that have two lower/upper case
     # letters or digits. Total number of possibilities is (26*2 + 10)^2 = 3844.
     abc_len = len(self._DIR_ALPHABET)
     tried = set()
     while len(tried) < 1000:
         i = random.randint(0, abc_len * abc_len - 1)
         rel_path = (self._DIR_ALPHABET[i / abc_len] +
                     self._DIR_ALPHABET[i % abc_len])
         if rel_path in tried:
             continue
         abs_path = os.path.join(self.root_dir, rel_path)
         if not fs.exists(abs_path):
             return rel_path
         tried.add(rel_path)
     raise Error('could not allocate a new cache dir, too many cache dirs')
예제 #12
0
def extract_yolo(rows: list, min_ratio=MIN_RATIO):
    """Receives a list and generates YOLO annotations.

    Receives a list of MongoDB records. Each line must have _id of the image
    and a predictions field with the bboxes

    """
    if not os.path.exists('yolo'):
        os.mkdir('yolo')
    count = 0
    for count, row in enumerate(rows):
        _id = row['_id']
        predictions = row['metadata']['predictions']
        caminho_atual = os.path.join('yolo', str(_id))
        if os.path.exists(caminho_atual):
            print(str(_id), ' existe, abortando...')
            continue
        oid = ObjectId(_id)
        if fs.exists(oid):
            grid_out = fs.get(oid)
            image = Image.open(io.BytesIO(grid_out.read()))
            xfinal, yfinal = image.size
            if xfinal / yfinal < min_ratio:
                print(image.size, ' - abortando...')
                continue
            os.mkdir(caminho_atual)
            arquivo_atual = os.path.join(caminho_atual, str(_id))
            with open(arquivo_atual + '.txt', 'w') as out_handle:
                for prediction in predictions:
                    bbox = prediction['bbox']
                    print(bbox, image.size)
                    # yolov2
                    coords = [
                        str((bbox[1] + bbox[3]) / 2 / xfinal),
                        str((bbox[0] + bbox[2]) / 2 / yfinal),
                        str((bbox[3] - bbox[1]) / xfinal),
                        str((bbox[2] - bbox[0]) / yfinal)
                    ]
                    out_handle.write('0 ' + ' '.join(coords) + '\n')
            with open(os.path.join(caminho_atual, 'classes.txt'),
                      'w') as out_handle:
                out_handle.write('0 Container')
            image.save(arquivo_atual + '.jpg')
    print('%s arquivos exportados...' % count)
    return count
예제 #13
0
    def install(self, path, name):
        """Moves the directory for the specified named cache to |path|.

    path must be absolute, unicode and must not exist.

    Raises NamedCacheError if cannot install the cache.
    """
        logging.info('Installing named cache %r to %r', name, path)
        with self._lock:
            try:
                if os.path.isdir(path):
                    raise NamedCacheError(
                        'installation directory %r already exists' % path)

                link_name = os.path.join(self.cache_dir, name)
                if fs.exists(link_name):
                    fs.rmtree(link_name)

                if name in self._lru:
                    rel_cache, _size = self._lru.get(name)
                    abs_cache = os.path.join(self.cache_dir, rel_cache)
                    if os.path.isdir(abs_cache):
                        logging.info('Moving %r to %r', abs_cache, path)
                        file_path.ensure_tree(os.path.dirname(path))
                        fs.rename(abs_cache, path)
                        self._remove(name)
                        return

                    logging.warning(
                        'directory for named cache %r does not exist at %s',
                        name, rel_cache)
                    self._remove(name)

                # The named cache does not exist, create an empty directory.
                # When uninstalling, we will move it back to the cache and create an
                # an entry.
                file_path.ensure_tree(path)
            except (IOError, OSError) as ex:
                raise NamedCacheError(
                    'cannot install cache named %r at %r: %s' %
                    (name, path, ex))
            finally:
                self._save()
예제 #14
0
def copy_recursively(src, dst):
  """Efficiently copies a file or directory from src_dir to dst_dir.

  `item` may be a file, directory, or a symlink to a file or directory.
  All symlinks are replaced with their targets, so the resulting
  directory structure in dst_dir will never have any symlinks.

  To increase speed, copy_recursively hardlinks individual files into the
  (newly created) directory structure if possible, unlike Python's
  shutil.copytree().
  """
  orig_src = src
  try:
    # Replace symlinks with their final target.
    while fs.islink(src):
      res = fs.readlink(src)
      src = os.path.join(os.path.dirname(src), res)
    # TODO(sadafm): Explicitly handle cyclic symlinks.

    # Note that fs.isfile (which is a wrapper around os.path.isfile) throws
    # an exception if src does not exist. A warning will be logged in that case.
    if fs.isfile(src):
      file_path.link_file(dst, src, file_path.HARDLINK_WITH_FALLBACK)
      return

    if not fs.exists(dst):
      os.makedirs(dst)

    for child in fs.listdir(src):
      copy_recursively(os.path.join(src, child), os.path.join(dst, child))

  except OSError as e:
    if e.errno == errno.ENOENT:
      logging.warning('Path %s does not exist or %s is a broken symlink',
                      src, orig_src)
    else:
      logging.info("Couldn't collect output file %s: %s", src, e)
예제 #15
0
def rmtree(root):
    """Wrapper around shutil.rmtree() to retry automatically on Windows.

  On Windows, forcibly kills processes that are found to interfere with the
  deletion.

  Returns:
    True on normal execution, False if berserk techniques (like killing
    processes) had to be used.
  """
    logging.info('rmtree(%s)', root)
    assert isinstance(root,
                      six.text_type) or sys.getdefaultencoding() == 'utf-8', (
                          repr(root), sys.getdefaultencoding())
    root = six.text_type(root)
    try:
        make_tree_deleteable(root)
    except OSError as e:
        logging.warning('Swallowing make_tree_deleteable() error: %s', e)

    # First try the soft way: tries 3 times to delete and sleep a bit in between.
    # Retries help if test subprocesses outlive main process and try to actively
    # use or write to the directory while it is being deleted.
    max_tries = 3
    for i in range(max_tries):
        # pylint: disable=cell-var-from-loop
        # errors is a list of tuple(function, path, excinfo).
        errors = []
        fs.rmtree(root, onerror=lambda *args: errors.append(args))
        if not errors or not fs.exists(root):
            if i:
                sys.stderr.write('Succeeded.\n')
            return True
        if not i and sys.platform == 'win32':
            for path in sorted(set(path for _, path, _ in errors)):
                try:
                    change_acl_for_delete(path)
                except Exception as e:
                    sys.stderr.write('- %s (failed to update ACL: %s)\n' %
                                     (path, e))

        if i != max_tries - 1:
            delay = (i + 1) * 2
            sys.stderr.write(
                'Failed to delete %s (%d files remaining).\n'
                '  Maybe the test has a subprocess outliving it.\n'
                '  Sleeping %d seconds.\n' % (root, len(errors), delay))
            time.sleep(delay)

    sys.stderr.write('Failed to delete %s. The following files remain:\n' %
                     root)
    # The same path may be listed multiple times.
    for path in sorted(set(path for _, path, _ in errors)):
        sys.stderr.write('- %s\n' % path)

    # If soft retries fail on Linux, there's nothing better we can do.
    if sys.platform != 'win32':
        six.reraise(errors[0][2][0], errors[0][2][1], errors[0][2][2])

    # The soft way was not good enough. Try the hard way.
    for i in range(max_tries):
        if not kill_children_processes(root):
            break
        if i != max_tries - 1:
            time.sleep((i + 1) * 2)
    else:
        processes = _get_children_processes_win(root)
        if processes:
            sys.stderr.write('Failed to terminate processes.\n')
            six.reraise(errors[0][2][0], errors[0][2][1], errors[0][2][2])

    # Now that annoying processes in root are evicted, try again.
    errors = []
    fs.rmtree(root, onerror=lambda *args: errors.append(args))
    if errors and fs.exists(root):
        # There's no hope: the directory was tried to be removed 4 times. Give up
        # and raise an exception.
        sys.stderr.write('Failed to delete %s. The following files remain:\n' %
                         root)
        # The same path may be listed multiple times.
        for path in sorted(set(path for _, path, _ in errors)):
            sys.stderr.write('- %s\n' % path)
        six.reraise(errors[0][2][0], errors[0][2][1], errors[0][2][2])
    return False
    def uninstall(self, src, name):
        """Moves the cache directory back into the named cache hive for an eventual
    reuse.

    The opposite of install().

    src must be absolute and unicode. Its content is moved back into the local
    named caches cache.

    Returns the named cache size in bytes.

    Raises NamedCacheError if cannot uninstall the cache.
    """
        logging.info('NamedCache.uninstall(%r, %r)', src, name)
        with self._lock:
            try:
                if not fs.isdir(src):
                    logging.warning(
                        'NamedCache: Directory %r does not exist anymore. Cache lost.',
                        src)
                    return

                if name in self._lru:
                    # This shouldn't happen but just remove the preexisting one and move
                    # on.
                    logging.error('- overwriting existing cache!')
                    self._remove(name)

                # Calculate the size of the named cache to keep. It's important because
                # if size is zero (it's empty), we do not want to add it back to the
                # named caches cache.
                size = _get_recursive_size(src)
                logging.info('- Size is %d', size)
                if not size:
                    # Do not save empty named cache.
                    return size

                # Move the dir and create an entry for the named cache.
                rel_cache = self._allocate_dir()
                abs_cache = os.path.join(self.cache_dir, rel_cache)
                logging.info('- Moving to %r', rel_cache)
                file_path.ensure_tree(os.path.dirname(abs_cache))
                fs.rename(src, abs_cache)

                self._lru.add(name, (rel_cache, size))
                self._added.append(size)

                # Create symlink <cache_dir>/<named>/<name> -> <cache_dir>/<short name>
                # for user convenience.
                named_path = self._get_named_path(name)
                if fs.exists(named_path):
                    file_path.remove(named_path)
                else:
                    file_path.ensure_tree(os.path.dirname(named_path))

                try:
                    fs.symlink(os.path.join(u'..', rel_cache), named_path)
                    logging.info('NamedCache: Created symlink %r to %r',
                                 named_path, abs_cache)
                except OSError:
                    # Ignore on Windows. It happens when running as a normal user or when
                    # UAC is enabled and the user is a filtered administrator account.
                    if sys.platform != 'win32':
                        raise
                return size
            except (IOError, OSError) as ex:
                # Raise using the original traceback.
                exc = NamedCacheError(
                    'cannot uninstall cache named %r at %r: %s' %
                    (name, src, ex))
                six.reraise(exc, None, sys.exc_info()[2])
            finally:
                # Call save() at every uninstall. The assumptions are:
                # - The total the number of named caches is low, so the state.json file
                #   is small, so the time it takes to write it to disk is short.
                # - The number of mapped named caches per task is low, so the number of
                #   times save() is called on tear-down isn't high enough to be
                #   significant.
                # - uninstall() sometimes throws due to file locking on Windows or
                #   access rights on Linux. We want to keep as many as possible.
                self._save()
예제 #17
0
def _expand_symlinks(indir, relfile):
    """Finds symlinks in relfile.

  Follows symlinks in |relfile|, but treating symlinks that point outside the
  build tree as if they were ordinary directories/files. Returns the final
  symlink-free target and a list of paths to symlinks encountered in the
  process.

  The rule about symlinks outside the build tree is for the benefit of the
  Chromium OS ebuild, which symlinks the output directory to an unrelated path
  in the chroot.

  Fails when a directory loop is detected, although in theory we could support
  that case.

  Arguments:
  - indir: base directory; symlinks in indir are not processed; this is
    the base directory that is considered 'outside of the tree'.
  - relfile: part of the path to expand symlink.

  Returns:
    tuple(relfile, list(symlinks)): relfile is real path of relfile where all
    symlinks were evaluated. symlinks if the chain of symlinks found along the
    way, if any.
  """
    is_directory = relfile.endswith(os.path.sep)
    done = indir
    todo = relfile.strip(os.path.sep)
    symlinks = []

    while todo:
        pre_symlink, symlink, post_symlink = file_path.split_at_symlink(
            done, todo)
        if not symlink:
            todo = file_path.fix_native_path_case(done, todo)
            done = os.path.join(done, todo)
            break
        symlink_path = os.path.join(done, pre_symlink, symlink)
        post_symlink = post_symlink.lstrip(os.path.sep)
        # readlink doesn't exist on Windows.
        # pylint: disable=E1101
        target = os.path.normpath(os.path.join(done, pre_symlink))
        symlink_target = fs.readlink(symlink_path)
        if os.path.isabs(symlink_target):
            # Absolute path are considered a normal directories. The use case is
            # generally someone who puts the output directory on a separate drive.
            target = symlink_target
        else:
            # The symlink itself could be using the wrong path case.
            target = file_path.fix_native_path_case(target, symlink_target)

        if not fs.exists(target):
            raise MappingError('Symlink target doesn\'t exist: %s -> %s' %
                               (symlink_path, target))
        target = file_path.get_native_path_case(target)
        if not file_path.path_starts_with(indir, target):
            done = symlink_path
            todo = post_symlink
            continue
        if file_path.path_starts_with(target, symlink_path):
            raise MappingError(
                'Can\'t map recursive symlink reference %s -> %s' %
                (symlink_path, target))
        logging.info('Found symlink: %s -> %s', symlink_path, target)
        symlinks.append(os.path.relpath(symlink_path, indir))
        # Treat the common prefix of the old and new paths as done, and start
        # scanning again.
        target = target.split(os.path.sep)
        symlink_path = symlink_path.split(os.path.sep)
        prefix_length = 0
        for target_piece, symlink_path_piece in zip(target, symlink_path):
            if target_piece != symlink_path_piece:
                break
            prefix_length += 1
        done = os.path.sep.join(target[:prefix_length])
        todo = os.path.join(os.path.sep.join(target[prefix_length:]),
                            post_symlink)

    relfile = os.path.relpath(done, indir)
    relfile = relfile.rstrip(os.path.sep) + is_directory * os.path.sep
    return relfile, symlinks
예제 #18
0
 def assertFile(self, path, contents):
   self.assertTrue(fs.exists(path), 'File %s doesn\'t exist!' % path)
   self.assertMultiLineEqual(contents, fs.open(path, 'rb').read())