Exemplo n.º 1
0
    def digest(self, path=os.curdir, hasher=utils.DEFAULT_HASHER):
        """
        Compute the digest of the file.  Returns the hex digest of the
        file; to retrieve the digest in other forms, pass an explicit
        hasher or tuple of hashers.

        :param path: An optional path to a subelement of this
                     directory.
        :param hasher: The string name of the desired hash algorithm,
                       or a digester object as returned by one of the
                       hashers present in ``hashlib``, or a tuple of
                       such objects.  If not given, defaults to
                       ``utils.DEFAULT_HASHER``.

        :returns: The digest of the file, in hex.  If a tuple of
                  hashers was passed for ``hasher``, then the first
                  hasher will be returned.
        """

        # Set up the hasher, first
        if not hasher:
            raise ValueError('a hasher must be specified')
        elif isinstance(hasher, six.string_types):
            hasher = (utils.get_hasher(hasher)(),)
        elif not isinstance(hasher, tuple):
            hasher = (hasher,)

        # Open the desired file and digest it
        with self.open(path) as f:
            return utils.digest(f, hasher)
Exemplo n.º 2
0
    def test_basic(self):
        fo = io.BytesIO(six.b("12345678901234"))
        digesters = [
            mock.Mock(**{'hexdigest.return_value': 'd16e57'}),
            mock.Mock(),
            mock.Mock(),
        ]

        result = utils.digest(fo, digesters)

        self.assertEqual(result, 'd16e57')
        for i, digester in enumerate(digesters):
            digester.update.assert_has_calls([
                mock.call(six.b('1234')),
                mock.call(six.b('5678')),
                mock.call(six.b('9012')),
                mock.call(six.b('34')),
            ])
            self.assertEqual(digester.update.call_count, 4)
            if i == 0:
                digester.hexdigest.assert_called_once_with()
            else:
                self.assertFalse(digester.hexdigest.called)
Exemplo n.º 3
0
    def tar(self, filename, start=os.curdir, compression=utils.unset,
            hasher=None):
        """
        Create a tar file with the given filename.

        :param filename: The filename of the tar file to create.  If
                         ``compression`` is not given, it will be
                         inferred from the filename.  The appropriate
                         extensions will be added to the filename, if
                         necessary.  If a compression extension on the
                         filename does not match the specified
                         compression, a ``ValueError`` will be raised.
        :param start: The directory from which to start the tar
                      process.  If not given, starts from the current
                      directory and includes all files in the
                      directory.  If it is a parent of the current
                      directory, only the current directory will be
                      included in the tarball.  A ``ValueError`` will
                      be raised if the tar process cannot start from
                      the given location.
        :param compression: If given, specifies the compression to
                            use.  The ``filename`` will be modified to
                            include the appropriate extension.  A
                            ``ValueError`` will be raised if the given
                            compression is not supported or if a
                            compression was inferred from the
                            filename.
        :param hasher: If given, requests that a hash of the resulting
                       tar file be computed.  May be a ``True`` value
                       to use the default hasher; a string to specify
                       a hasher; or a tuple of hashers.

        :returns: The final filename that was created.  If ``hasher``
                  was specified, a tuple will be returned, with the
                  second element consisting of the hex digest of the
                  tar file.
        """

        # If the filename is a FSEntry, use its path
        if isinstance(filename, FSEntry):
            filename = filename.path

        # Parse the file name and set the compression
        filename = tarname.TarFileName(utils.abspath(filename, cwd=self.path))
        if compression is not utils.unset:
            filename.compression = compression

        # Determine the starting location and file list
        start = self._rel(start, False)
        filelist = None
        rel_path = utils.RelPath(start, self.name)
        if rel_path.parents and rel_path.remainder:
            raise ValueError("cannot start tar-ing from '%s'" % rel_path)
        elif not rel_path.parents and not rel_path.remainder:
            start = self.path
        elif rel_path.parents:
            start = os.path.normpath(
                os.path.join(self.path, [os.pardir] * rel_path.parents))
            filelist = [os.path.join(*rel_path.path_list[-rel_path.parents:])]
        start = self.tree._full(start)
        if filelist is None:
            filelist = os.listdir(start)

        # OK, let's build the tarball
        tar = tarfile.open(str(filename), 'w:%s' % filename.compression or '')
        try:
            with utils.workdir(start):
                for fname in filelist:
                    try:
                        tar.add(fname)
                    except Exception:
                        pass
        finally:
            tar.close()

        # Begin building the result
        result = str(filename)

        # If a hash was requested, generate it
        if hasher:
            # Select the hasher(s)
            if hasher is True:
                hasher = (utils.get_hasher(utils.DEFAULT_HASHER)(),)
            elif isinstance(hasher, six.string_types):
                hasher = (utils.get_hasher(hasher)(),)
            elif not isinstance(hasher, tuple):
                hasher = (hasher,)

            # Open the file
            with open(result) as f:
                result = (result, utils.digest(f, hasher))

        return result