aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-05-02 15:15:26 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-05-02 15:15:26 +0000
commitb9fa8b3aaf69a387589da88ea17c97ac838d72bd (patch)
treeeea28778f0becfe1b1bfc5d58adb9e695fa5dad6
parente1a0c7f22ec94da7e063c5021c636ea66b5ced0e (diff)
downloadpaludis-b9fa8b3aaf69a387589da88ea17c97ac838d72bd.tar.gz
paludis-b9fa8b3aaf69a387589da88ea17c97ac838d72bd.tar.xz
Allow symlinks in repositories (PMS compliance). Fixes: ticket:158
-rw-r--r--paludis/repositories/gentoo/portage_repository.cc12
-rw-r--r--paludis/repositories/gentoo/portage_repository_news.cc8
-rw-r--r--paludis/repositories/gentoo/portage_repository_profile.cc2
-rw-r--r--paludis/repositories/gentoo/portage_repository_sets.cc2
-rw-r--r--paludis/repositories/gentoo/use_desc.cc4
-rw-r--r--paludis/repositories/gentoo/vdb_merger.cc2
-rw-r--r--paludis/repositories/gentoo/vdb_repository.cc16
-rw-r--r--paludis/util/fs_entry.cc36
-rw-r--r--paludis/util/fs_entry.hh21
-rw-r--r--paludis/util/fs_entry_TEST.cc13
10 files changed, 89 insertions, 27 deletions
diff --git a/paludis/repositories/gentoo/portage_repository.cc b/paludis/repositories/gentoo/portage_repository.cc
index 82798ff..a53fc03 100644
--- a/paludis/repositories/gentoo/portage_repository.cc
+++ b/paludis/repositories/gentoo/portage_repository.cc
@@ -363,7 +363,7 @@ PortageRepository::do_has_package_named(const QualifiedPackageName & q) const
FSEntry fs(_imp->params.location);
fs /= stringify(q.category);
fs /= stringify(q.package);
- if (! fs.is_directory())
+ if (! fs.is_directory_or_symlink_to_directory())
return false;
_imp->package_names.insert(std::make_pair(q, false));
return true;
@@ -429,10 +429,10 @@ PortageRepository::do_package_names(const CategoryNamePart & c) const
if (_imp->category_names.end() == _imp->category_names.find(c))
return std::tr1::shared_ptr<QualifiedPackageNameCollection>(new QualifiedPackageNameCollection::Concrete);
- if ((_imp->params.location / stringify(c)).is_directory())
+ if ((_imp->params.location / stringify(c)).is_directory_or_symlink_to_directory())
for (DirIterator d(_imp->params.location / stringify(c)), d_end ; d != d_end ; ++d)
{
- if (! d->is_directory())
+ if (! d->is_directory_or_symlink_to_directory())
continue;
if (DirIterator() == std::find_if(DirIterator(*d), DirIterator(),
std::tr1::bind(&is_file_with_extension, _1, _imp->entries_ptr->file_extension(), IsFileWithOptions())))
@@ -537,7 +537,7 @@ PortageRepository::need_category_names() const
+ stringify(_imp->params.location) + "', faking it");
for (DirIterator d(_imp->params.location), d_end ; d != d_end ; ++d)
{
- if (! d->is_directory())
+ if (! d->is_directory_or_symlink_to_directory())
continue;
std::string n(d->basename());
@@ -779,12 +779,12 @@ PortageRepository::do_license_exists(const std::string & license) const
{
FSEntry l(_imp->params.master_repository->params().location /
"licenses" / license);
- if (l.exists() && l.is_regular_file())
+ if (l.exists() && l.is_regular_file_or_symlink_to_regular_file())
p.reset(new FSEntry(l));
}
FSEntry l(_imp->params.location / "licenses" / license);
- if (l.exists() && l.is_regular_file())
+ if (l.exists() && l.is_regular_file_or_symlink_to_regular_file())
p.reset(new FSEntry(l));
return p;
diff --git a/paludis/repositories/gentoo/portage_repository_news.cc b/paludis/repositories/gentoo/portage_repository_news.cc
index 0223e35..5cabee2 100644
--- a/paludis/repositories/gentoo/portage_repository_news.cc
+++ b/paludis/repositories/gentoo/portage_repository_news.cc
@@ -83,12 +83,12 @@ PortageRepositoryNews::update_news() const
stringify(_imp->params.newsdir) + "' for repository '" +
stringify(_imp->portage_repository->name()) + "':");
- if (! _imp->params.newsdir.is_directory())
+ if (! _imp->params.newsdir.is_directory_or_symlink_to_directory())
return;
std::set<std::string> skip;
- if (_imp->skip_file.is_regular_file())
+ if (_imp->skip_file.is_regular_file_or_symlink_to_regular_file())
{
Context local_context("When handling news skip file '" + stringify(
_imp->skip_file) + "':");
@@ -107,9 +107,9 @@ PortageRepositoryNews::update_news() const
return;
}
- if (! d->is_directory())
+ if (! d->is_directory_or_symlink_to_directory())
continue;
- if (! (*d / (d->basename() + ".en.txt")).is_regular_file())
+ if (! (*d / (d->basename() + ".en.txt")).is_regular_file_or_symlink_to_regular_file())
continue;
if (skip.end() != skip.find(d->basename()))
diff --git a/paludis/repositories/gentoo/portage_repository_profile.cc b/paludis/repositories/gentoo/portage_repository_profile.cc
index 91535d5..48da248 100644
--- a/paludis/repositories/gentoo/portage_repository_profile.cc
+++ b/paludis/repositories/gentoo/portage_repository_profile.cc
@@ -191,7 +191,7 @@ Implementation<PortageRepositoryProfile>::load_profile_directory_recursively(con
Context context("When adding profile directory '" + stringify(dir) + ":");
Log::get_instance()->message(ll_debug, lc_context, "Loading profile directory '" + stringify(dir) + "'");
- if (! dir.is_directory())
+ if (! dir.is_directory_or_symlink_to_directory())
{
Log::get_instance()->message(ll_warning, lc_context,
"Profile component '" + stringify(dir) + "' is not a directory");
diff --git a/paludis/repositories/gentoo/portage_repository_sets.cc b/paludis/repositories/gentoo/portage_repository_sets.cc
index ec87840..b2ed1a7 100644
--- a/paludis/repositories/gentoo/portage_repository_sets.cc
+++ b/paludis/repositories/gentoo/portage_repository_sets.cc
@@ -240,7 +240,7 @@ PortageRepositorySets::security_set(bool insecurity) const
Context context("When building security or insecurity package set:");
std::tr1::shared_ptr<AllDepSpec> security_packages(new AllDepSpec);
- if (!_imp->params.securitydir.is_directory())
+ if (!_imp->params.securitydir.is_directory_or_symlink_to_directory())
return security_packages;
std::map<std::string, std::tr1::shared_ptr<GLSADepTag> > glsa_tags;
diff --git a/paludis/repositories/gentoo/use_desc.cc b/paludis/repositories/gentoo/use_desc.cc
index 6cefc15..28596b4 100644
--- a/paludis/repositories/gentoo/use_desc.cc
+++ b/paludis/repositories/gentoo/use_desc.cc
@@ -38,7 +38,7 @@ namespace paludis
void add(const FSEntry & f, const std::string & prefix)
{
- if (f.is_regular_file())
+ if (f.is_regular_file_or_symlink_to_regular_file())
{
LineConfigFile ff(f, LineConfigFileOptions());
for (LineConfigFile::Iterator line(ff.begin()), line_end(ff.end()) ;
@@ -58,7 +58,7 @@ namespace paludis
add(f / "use.desc", "");
add(f / "use.local.desc", "");
- if ((f / "desc").is_directory())
+ if ((f / "desc").is_directory_or_symlink_to_directory())
for (DirIterator d(f / "desc"), d_end ; d != d_end ; ++d)
if (is_file_with_extension(*d, ".desc", IsFileWithOptions()))
add(*d, strip_trailing_string(d->basename(), ".desc") + "_");
diff --git a/paludis/repositories/gentoo/vdb_merger.cc b/paludis/repositories/gentoo/vdb_merger.cc
index bac154d..dc69565 100644
--- a/paludis/repositories/gentoo/vdb_merger.cc
+++ b/paludis/repositories/gentoo/vdb_merger.cc
@@ -195,7 +195,7 @@ VDBMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
if (! (_imp->options.root / dst / result_name).exists())
break;
- if ((_imp->options.root / dst / result_name).is_regular_file())
+ if ((_imp->options.root / dst / result_name).is_regular_file_or_symlink_to_regular_file())
{
std::ifstream other_md5_file(stringify(_imp->options.root / dst / result_name).c_str());
if (other_md5_file)
diff --git a/paludis/repositories/gentoo/vdb_repository.cc b/paludis/repositories/gentoo/vdb_repository.cc
index ff52acb..e143e51 100644
--- a/paludis/repositories/gentoo/vdb_repository.cc
+++ b/paludis/repositories/gentoo/vdb_repository.cc
@@ -226,7 +226,7 @@ namespace
FSEntry f(location / stringify(name.category) /
(stringify(name.package) + "-" + stringify(v)));
- if (! (f / key).is_regular_file())
+ if (! (f / key).is_regular_file_or_symlink_to_regular_file())
return "";
std::ifstream ff(stringify(f / key).c_str());
@@ -347,7 +347,7 @@ namespace paludis
try
{
for (DirIterator cat_i(location), cat_iend ; cat_i != cat_iend ; ++cat_i)
- if (cat_i->is_directory())
+ if (cat_i->is_directory_or_symlink_to_directory())
load_entries_for(CategoryNamePart(cat_i->basename()));
std::sort(entries.begin(), entries.end());
@@ -379,12 +379,12 @@ namespace paludis
category_entries_valid.insert(cat);
FSEntry dir(location / stringify(cat));
- if (! dir.is_directory())
+ if (! dir.is_directory_or_symlink_to_directory())
return;
for (DirIterator pkg_i(dir), pkg_iend ; pkg_i != pkg_iend ; ++pkg_i)
{
- if (! pkg_i->is_directory())
+ if (! pkg_i->is_directory_or_symlink_to_directory())
continue;
if ('-' == pkg_i->basename().at(0))
@@ -702,7 +702,7 @@ VDBRepository::do_contents(
FSEntry f(_imp->location / stringify(q.category) /
(stringify(q.package) + "-" + stringify(v)));
- if (! (f / "CONTENTS").is_regular_file())
+ if (! (f / "CONTENTS").is_regular_file_or_symlink_to_regular_file())
{
Log::get_instance()->message(ll_warning, lc_context,
"CONTENTS lookup failed for request for '" +
@@ -1189,11 +1189,11 @@ VDBRepository::get_environment_variable(
/ (stringify(for_package.name.package) + "-" +
stringify(for_package.version)));
- if (! vdb_dir.is_directory())
+ if (! vdb_dir.is_directory_or_symlink_to_directory())
throw EnvironmentVariableActionError("Could not find VDB entry for '"
+ stringify(for_package) + "'");
- if ((vdb_dir / var).is_regular_file())
+ if ((vdb_dir / var).is_regular_file_or_symlink_to_regular_file())
{
std::ifstream f(stringify(vdb_dir / var).c_str());
if (! f)
@@ -1203,7 +1203,7 @@ VDBRepository::get_environment_variable(
std::string((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>()), "\n");
}
- else if ((vdb_dir / "environment.bz2").is_regular_file())
+ else if ((vdb_dir / "environment.bz2").is_regular_file_or_symlink_to_regular_file())
{
PStream p("bash -c '( bunzip2 < " + stringify(vdb_dir / "environment.bz2" ) +
" ; echo echo \\$" + var + " ) | bash 2>/dev/null'");
diff --git a/paludis/util/fs_entry.cc b/paludis/util/fs_entry.cc
index b3f6080..ed592a9 100644
--- a/paludis/util/fs_entry.cc
+++ b/paludis/util/fs_entry.cc
@@ -130,6 +130,18 @@ FSEntry::is_directory() const
}
bool
+FSEntry::is_directory_or_symlink_to_directory() const
+{
+ _stat();
+
+ if (_exists)
+ return S_ISDIR((*_stat_info).st_mode) ||
+ (is_symbolic_link() && realpath_if_exists().is_directory());
+
+ return false;
+}
+
+bool
FSEntry::is_fifo() const
{
_stat();
@@ -163,6 +175,18 @@ FSEntry::is_regular_file() const
}
bool
+FSEntry::is_regular_file_or_symlink_to_regular_file() const
+{
+ _stat();
+
+ if (_exists)
+ return S_ISREG((*_stat_info).st_mode) ||
+ (is_symbolic_link() && realpath_if_exists().is_regular_file());
+
+ return false;
+}
+
+bool
FSEntry::is_symbolic_link() const
{
_stat();
@@ -348,6 +372,18 @@ FSEntry::realpath() const
}
FSEntry
+FSEntry::realpath_if_exists() const
+{
+ Context context("When fetching realpath of '" + stringify(_path) + "', if it exists:");
+
+ char r[PATH_MAX + 1];
+ std::memset(r, 0, PATH_MAX + 1);
+ if (! ::realpath(_path.c_str(), r))
+ return *this;
+ return FSEntry(r);
+}
+
+FSEntry
FSEntry::cwd()
{
char r[PATH_MAX + 1];
diff --git a/paludis/util/fs_entry.hh b/paludis/util/fs_entry.hh
index 0c5bff1..c4a55e6 100644
--- a/paludis/util/fs_entry.hh
+++ b/paludis/util/fs_entry.hh
@@ -194,6 +194,13 @@ namespace paludis
/**
* Does a filesystem entry exist at our location, and if it does,
+ * is it a directory?
+ */
+ bool is_directory_or_symlink_to_directory() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Does a filesystem entry exist at our location, and if it does,
* is it a regular file?
*/
bool is_regular_file() const
@@ -201,6 +208,13 @@ namespace paludis
/**
* Does a filesystem entry exist at our location, and if it does,
+ * is it a regular file?
+ */
+ bool is_regular_file_or_symlink_to_regular_file() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Does a filesystem entry exist at our location, and if it does,
* is it a symbolic link?
*/
bool is_symbolic_link() const
@@ -241,6 +255,13 @@ namespace paludis
PALUDIS_ATTRIBUTE((warn_unused_result));
/**
+ * Return the canonicalised version of our path, if it exists, or
+ * ourself if it doesn't.
+ */
+ FSEntry realpath_if_exists() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
* Return our destination, if we are a symlink.
*
* \exception FSError if we are not a symlink, or if the system call
diff --git a/paludis/util/fs_entry_TEST.cc b/paludis/util/fs_entry_TEST.cc
index aca7e32..0702547 100644
--- a/paludis/util/fs_entry_TEST.cc
+++ b/paludis/util/fs_entry_TEST.cc
@@ -142,13 +142,17 @@ namespace test_cases
d = FSEntry("fs_entry_TEST_dir/symlink_to_dir_a");
TEST_CHECK(d.is_symbolic_link());
TEST_CHECK(! d.is_directory());
+ TEST_CHECK(d.is_directory_or_symlink_to_directory());
TEST_CHECK(! d.is_regular_file());
+ TEST_CHECK(! d.is_regular_file_or_symlink_to_regular_file());
e = FSEntry("fs_entry_TEST_dir/doesnotexist_symlink");
- TEST_CHECK(d.is_symbolic_link());
- TEST_CHECK(d.exists());
- TEST_CHECK(! d.is_directory());
- TEST_CHECK(! d.is_regular_file());
+ TEST_CHECK(e.is_symbolic_link());
+ TEST_CHECK(e.exists());
+ TEST_CHECK(! e.is_directory());
+ TEST_CHECK(! e.is_directory_or_symlink_to_directory());
+ TEST_CHECK(! e.is_regular_file());
+ TEST_CHECK(! e.is_regular_file_or_symlink_to_regular_file());
FSEntry f("fs_entry_TEST_dir/symlink_to_dir_a/file_in_a");
TEST_CHECK(f.is_regular_file());
@@ -161,6 +165,7 @@ namespace test_cases
FSEntry h("fs_entry_TEST_dir/symlink_to_file_in_a");
TEST_CHECK(h.is_symbolic_link());
TEST_CHECK(! h.is_regular_file());
+ TEST_CHECK(h.is_regular_file_or_symlink_to_regular_file());
TEST_CHECK_EQUAL(h.readlink(), "dir_a/file_in_a");
FSEntry i("fs_entry_TEST_dir/dir_to_make");