aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/cc/windows-rpath.cxx72
-rw-r--r--libbuild2/algorithm.cxx77
-rw-r--r--libbuild2/test/script/builtin.cxx2
3 files changed, 61 insertions, 90 deletions
diff --git a/build2/cc/windows-rpath.cxx b/build2/cc/windows-rpath.cxx
index 5b49033..2d2e100 100644
--- a/build2/cc/windows-rpath.cxx
+++ b/build2/cc/windows-rpath.cxx
@@ -306,68 +306,36 @@ namespace build2
// First we try to create a symlink. If that fails (e.g., "Windows
// happens"), then we resort to hard links. If that doesn't work
// out either (e.g., not on the same filesystem), then we fall back
- // to copies. So things are going to get a bit nested.
+ // to copies.
+ //
+ // For the symlink use a relative target path if both paths are part
+ // of the same amalgamation. This way if the amalgamation is moved
+ // as a whole, the links will remain valid.
//
try
{
- // For the symlink use a relative target path if both paths are
- // part of the same amalgamation. This way if the amalgamation is
- // moved as a whole, the links will remain valid.
- //
- if (!dry_run)
+ switch (mkanylink (f, l,
+ true /* copy */,
+ f.sub (as.out_path ()) /* relative */))
{
- if (f.sub (as.out_path ()))
- mksymlink (f.relative (ad), l);
- else
- mksymlink (f, l);
+ case entry_type::regular: print ("cp"); break;
+ case entry_type::symlink: print ("ln -s"); break;
+ case entry_type::other: print ("ln"); break;
+ default: assert (false);
}
-
- print ("ln -s");
}
- catch (const system_error& e)
+ catch (const pair<entry_type, system_error>& e)
{
- // Note: can never end up here on dry-run.
-
- // Note that we are not guaranteed (here and below) that the
- // system_error exception is of the generic category.
- //
- int c (e.code ().value ());
- if (!(e.code ().category () == generic_category () &&
- (c == ENOSYS || // Not implemented.
- c == EPERM))) // Not supported by the filesystem(s).
+ const char* w (nullptr);
+ switch (e.first)
{
- print ("ln -s");
- fail << "unable to create symlink " << l << ": " << e;
+ case entry_type::regular: print ("cp"); w = "copy"; break;
+ case entry_type::symlink: print ("ln -s"); w = "symlink"; break;
+ case entry_type::other: print ("ln"); w = "hardlink"; break;
+ default: assert (false);
}
- try
- {
- mkhardlink (f, l);
- print ("ln");
- }
- catch (const system_error& e)
- {
- c = e.code ().value ();
- if (!(e.code ().category () == generic_category () &&
- (c == ENOSYS || // Not implemented.
- c == EPERM || // Not supported by the filesystem(s).
- c == EXDEV))) // On different filesystems.
- {
- print ("ln");
- fail << "unable to create hardlink " << l << ": " << e;
- }
-
- try
- {
- cpfile (f, l);
- print ("cp");
- }
- catch (const system_error& e)
- {
- print ("cp");
- fail << "unable to create copy " << l << ": " << e;
- }
- }
+ fail << "unable to make " << w << ' ' << l << ": " << e.second;
}
};
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 2f59c73..75b0f5a 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -1192,22 +1192,31 @@ namespace build2
try
{
- // Normally will be there.
- //
- if (!dry_run)
- try_rmbacklink (l, m);
-
- // Skip (ad hoc) targets that don't exist.
- //
- if (!(d ? dir_exists (p) : file_exists (p)))
- return;
-
- for (; !dry_run; ) // Retry/fallback loop.
try
{
+ // Normally will be there.
+ //
+ if (!dry_run)
+ try_rmbacklink (l, m);
+
+ // Skip (ad hoc) targets that don't exist.
+ //
+ if (!(d ? dir_exists (p) : file_exists (p)))
+ return;
+
switch (m)
{
case mode::link:
+ if (!d)
+ {
+ mkanylink (p, l, false /* copy */);
+ break;
+ }
+ // Directory hardlinks are not widely supported so for them we will
+ // only try the symlink.
+ //
+ // Fall through.
+
case mode::symbolic: mksymlink (p, l, d); break;
case mode::hard: mkhardlink (p, l, d); break;
case mode::copy:
@@ -1225,8 +1234,8 @@ namespace build2
try_mkdir (to);
- for (const auto& de: dir_iterator (fr,
- false /* ignore_dangling */))
+ for (const auto& de:
+ dir_iterator (fr, false /* ignore_dangling */))
{
path f (fr / de.path ());
path t (to / de.path ());
@@ -1241,45 +1250,37 @@ namespace build2
break;
}
}
-
- break; // Success.
}
- catch (const system_error& e)
+ catch (system_error& e)
{
- // If symlinks not supported, try a hardlink.
+ // Translate to mkanylink()-like failure.
//
- if (m == mode::link)
+ entry_type t (entry_type::unknown);
+ switch (m)
{
- // Note that we are not guaranteed that the system_error exception
- // is of the generic category.
- //
- int c (e.code ().value ());
- if (e.code ().category () == generic_category () &&
- (c == ENOSYS || // Not implemented.
- c == EPERM)) // Not supported by the filesystem(s).
- {
- m = mode::hard;
- continue;
- }
+ case mode::link:
+ case mode::symbolic: t = entry_type::symlink; break;
+ case mode::hard: t = entry_type::other; break;
+ case mode::copy:
+ case mode::overwrite: t = entry_type::regular; break;
}
- throw;
+ throw pair<entry_type, system_error> (t, move (e));
}
}
- catch (const system_error& e)
+ catch (const pair<entry_type, system_error>& e)
{
const char* w (nullptr);
- switch (m)
+ switch (e.first)
{
- case mode::link:
- case mode::symbolic: w = "symbolic link"; break;
- case mode::hard: w = "hard link"; break;
- case mode::copy:
- case mode::overwrite: w = "copy"; break;
+ case entry_type::regular: w = "copy"; break;
+ case entry_type::symlink: w = "symlink"; break;
+ case entry_type::other: w = "hardlink"; break;
+ default: assert (false);
}
print ();
- fail << "unable to make " << w << ' ' << l << ": " << e;
+ fail << "unable to make " << w << ' ' << l << ": " << e.second;
}
print ();
diff --git a/libbuild2/test/script/builtin.cxx b/libbuild2/test/script/builtin.cxx
index 2c3d83c..ae979da 100644
--- a/libbuild2/test/script/builtin.cxx
+++ b/libbuild2/test/script/builtin.cxx
@@ -618,6 +618,8 @@ namespace build2
// either (e.g., not on the same filesystem), then we fall back to
// copies. So things are going to get a bit nested.
//
+ // Note: similar to mkanylink() but with support for directories.
+ //
try
{
mksymlink (target, link, dir);