@@ -293,6 +293,91 @@ namespace mamba
293293 }
294294 }
295295
296+ namespace {
297+ TEST_CASE (" has_permissions()" )
298+ {
299+ // Create temp folder
300+ const auto tmp_dir = fs::temp_directory_path ()
301+ / " mamba-fs-has_permissions" ;
302+ fs::create_directories (tmp_dir);
303+
304+ // Create file
305+ const auto some_file = tmp_dir / " some_file" ;
306+ {
307+ std::ofstream ofs{ some_file.std_path (),
308+ std::ofstream::binary
309+ | std::ofstream::trunc };
310+ ofs << " ABC" << std::endl;
311+ }
312+
313+ // Set permissions
314+ const auto perms = fs::perms::owner_read | fs::perms::owner_write
315+ | fs::perms::group_read;
316+ fs::permissions (some_file, perms, fs::perm_options::replace);
317+
318+ // Check permissions
319+ REQUIRE (fs::has_permissions (some_file, perms));
320+ REQUIRE (fs::has_permissions (some_file, fs::perms::owner_read));
321+ REQUIRE (fs::has_permissions (some_file, fs::perms::owner_write));
322+ REQUIRE (fs::has_permissions (some_file, fs::perms::group_read));
323+ REQUIRE (fs::has_permissions (some_file, fs::perms::owner_read
324+ | fs::perms::owner_write));
325+ REQUIRE (fs::has_permissions (some_file, fs::perms::owner_read
326+ | fs::perms::group_read));
327+ REQUIRE (fs::has_permissions (some_file, fs::perms::owner_write
328+ | fs::perms::group_read));
329+ REQUIRE_FALSE (fs::has_permissions (some_file,
330+ fs::perms::owner_exec));
331+ REQUIRE_FALSE (fs::has_permissions (some_file,
332+ fs::perms::group_write));
333+ REQUIRE_FALSE (fs::has_permissions (some_file,
334+ fs::perms::group_exec));
335+ REQUIRE_FALSE (fs::has_permissions (some_file,
336+ fs::perms::others_read));
337+ REQUIRE_FALSE (fs::has_permissions (some_file,
338+ fs::perms::others_write));
339+ REQUIRE_FALSE (fs::has_permissions (some_file,
340+ fs::perms::others_exec));
341+ REQUIRE_FALSE (fs::has_permissions (some_file, fs::perms::owner_read
342+ | fs::perms::owner_exec));
343+
344+ fs::remove_all (tmp_dir);
345+ }
346+
347+ // 2025-11-27 make_executable() bug
348+ TEST_CASE (" Bug: failure when calling make_executable()"
349+ " on already executable file inside non-writable folder." )
350+ {
351+ // Create temp folder
352+ const auto tmp_dir = fs::temp_directory_path ()
353+ / " mamba-fs-make_executable-2025-11-27-bug" ;
354+ mamba::on_scope_exit _ ([&] { fs::remove_all (tmp_dir); });
355+ const auto folder = tmp_dir / " some_folder" ;
356+ fs::create_directories (folder);
357+
358+ // Create file
359+ const auto some_file = tmp_dir / " some_file" ;
360+ {
361+ std::ofstream ofs{ some_file.std_path (),
362+ std::ofstream::binary
363+ | std::ofstream::trunc };
364+ ofs << " ABC" << std::endl;
365+ }
366+
367+ // Make executable
368+ make_executable (some_file);
369+
370+ // Remove write permissions on folder
371+ const auto perms = fs::perms::owner_read
372+ | fs::perms::group_read | fs::perms::others_read;
373+ fs::permissions (folder, perms, fs::perm_options::replace);
374+
375+ // Make executable (again!)
376+ // This should not fail
377+ make_executable (some_file);
378+ }
379+ }
380+
296381 namespace
297382 {
298383 TEST_CASE (" remove_readonly_file" )
0 commit comments