diff --git a/docs/markdown/Fs-module.md b/docs/markdown/Fs-module.md index 7c2925f90..499b8d272 100644 --- a/docs/markdown/Fs-module.md +++ b/docs/markdown/Fs-module.md @@ -32,6 +32,14 @@ name exists on the file system. This method follows symbolic links. Takes a single string argument and returns true if the path pointed to by the string is a symbolic link. +## File Parameters + +### hash + +The `hash` method computes the requested hash sum of a file. +The available hash methods include: md5, sha1, sha224, sha256, sha384, sha512. + + ## Filename modification ### with_suffix diff --git a/mesonbuild/modules/fs.py b/mesonbuild/modules/fs.py index 1687d0d80..56496251f 100644 --- a/mesonbuild/modules/fs.py +++ b/mesonbuild/modules/fs.py @@ -13,8 +13,10 @@ # limitations under the License. import typing +import hashlib from pathlib import Path, PurePath +from .. import mlog from . import ExtensionModule from . import ModuleReturnValue from ..mesonlib import MesonException @@ -55,6 +57,22 @@ class FSModule(ExtensionModule): def is_dir(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: return self._check('is_dir', state, args) + @stringArgs + @noKwargs + def hash(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: + if len(args) != 2: + MesonException('method takes exactly two arguments.') + file = Path(state.source_root) / state.subdir / Path(args[0]).expanduser() + if not file.is_file(): + raise MesonException('{} is not a file and therefore cannot be hashed'.format(file)) + try: + h = hashlib.new(args[1]) + except ValueError: + raise MesonException('hash algorithm {} is not available'.format(args[1])) + mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size)) + h.update(file.read_bytes()) + return ModuleReturnValue(h.hexdigest(), []) + @stringArgs @noKwargs def with_suffix(self, state: 'ModuleState', args: typing.Sequence[str], kwargs: dict) -> ModuleReturnValue: diff --git a/test cases/common/227 fs module/meson.build b/test cases/common/227 fs module/meson.build index f111d466b..a98ed5601 100644 --- a/test cases/common/227 fs module/meson.build +++ b/test cases/common/227 fs module/meson.build @@ -47,4 +47,12 @@ new_check = is_windows ? 'j:\\foo\\bar.ini' : '/foo/bar.ini' new = fs.with_suffix(original, '.ini') assert(new == new_check, 'absolute path with_suffix failed') +# -- hash + +md5 = fs.hash('subdir/subdirfile.txt', 'md5') +sha256 = fs.hash('subdir/subdirfile.txt', 'sha256') +assert(md5 == 'd0795db41614d25affdd548314b30b3b', 'md5sum did not match') +assert(sha256 == 'be2170b0dae535b73f6775694fffa3fd726a43b5fabea11b7342f0605917a42a', 'sha256sum did not match') + + subdir('subdir')