wrap: Add basic sftp support to wrap.get_data()

This requires any credentials to be supplied in the url, or some other
means of authentication (such as an identity file configured for the
user) to be used. Supplying a password in the URL is not supported.
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index fe2910f..a9d1b7b 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -743,6 +743,23 @@
             resp = open_wrapdburl(urlstring, allow_insecure=self.allow_insecure, have_opt=self.wrap_frontend)
         elif WHITELIST_SUBDOMAIN in urlstring:
             raise WrapException(f'{urlstring} may be a WrapDB-impersonating URL')
+        elif url.scheme == 'sftp':
+            sftp = shutil.which('sftp')
+            if sftp is None:
+                raise WrapException('Scheme sftp is not available. Install sftp to enable it.')
+            with tempfile.TemporaryDirectory() as workdir, \
+                    tempfile.NamedTemporaryFile(mode='wb', dir=self.cachedir, delete=False) as tmpfile:
+                args = []
+                # Older versions of the sftp client cannot handle URLs, hence the splitting of url below
+                if url.port:
+                    args += ['-P', f'{url.port}']
+                user = f'{url.username}@' if url.username else ''
+                command = [sftp, '-o', 'KbdInteractiveAuthentication=no', *args, f'{user}{url.hostname}:{url.path[1:]}']
+                subprocess.run(command, cwd=workdir, check=True)
+                downloaded = os.path.join(workdir, os.path.basename(url.path))
+                tmpfile.close()
+                shutil.move(downloaded, tmpfile.name)
+                return self.hash_file(tmpfile.name), tmpfile.name
         else:
             headers = {
                 'User-Agent': f'mesonbuild/{coredata.version}',