Skip to content

Commit

Permalink
Treat sets in subdirectories. Restructure recursive directory reading
Browse files Browse the repository at this point in the history
  • Loading branch information
vaeth committed Aug 25, 2021
1 parent 57e93f8 commit 5b3272a
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 78 deletions.
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

*eix-0.35.3
Martin Väth <martin at mvath.de>:
- Sets can also be directories which are read recursively
- Sets can also be in subdirectories: The name is the full subpath

Florian Schmaus <flo at geekplace.eu>:
- Work if there is no $HOME variable
Expand Down
132 changes: 71 additions & 61 deletions src/eixTk/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,41 +126,40 @@ static bool pushback_lines_file(const char *file, LineVec *v, bool keep_empty, e
return false;
}

/**
Files excluded for pushback_lines in recursive mode
**/
const char *pushback_lines_exclude[] = { "..", ".", "CVS", "RCS", "SCCS", NULLPTR };

/**
push_back every line of file or dir into v.
**/
bool pushback_lines(const char *file, LineVec *v, bool recursive, bool keep_empty, eix::SignedBool keep_comments, string *errtext) {
static int depth(0);
if(!recursive) {
return pushback_lines_file(file, v, keep_empty, keep_comments, errtext);
}
WordVec files;
string dir(file);
dir.append(1, '/');
if(recursive && pushback_files(dir, &files, pushback_lines_exclude, 3)) {
bool rvalue(true);
for(WordVec::const_iterator it(files.begin());
likely(it != files.end()); ++it) {
++depth;
if(depth == 100) {
if(errtext != NULLPTR) {
*errtext = eix::format(_("nesting level too deep in %s")) % dir;
}
return false;
}
if(unlikely(!pushback_lines(it->c_str(), v, true, keep_empty, keep_comments, errtext))) {
rvalue = false;
}
--depth;
bool rvalue(pushback_files_recurse(file, &files, true, errtext));
for(WordVec::const_iterator it(files.begin()); likely(it != files.end()); ++it) {
if(unlikely(!pushback_lines_file(it->c_str(), v, keep_empty, keep_comments, errtext))) {
rvalue = false;
}
return rvalue;
} else {
return pushback_lines_file(file, v, keep_empty, keep_comments, errtext);
}
return rvalue;
}

static bool is_only_type(const string &file, int only_type) {
if (only_type == 0) {
return true;
}
struct stat static_stat;
if(likely(stat(file.c_str(), &static_stat) == 0)) {
if (((only_type & 1) != 0) && S_ISREG(static_stat.st_mode)) {
return true;
}
if (((only_type & 2) != 0) && S_ISDIR(static_stat.st_mode)) {
return true;
}
}
return false;
}


/**
These variables and function are only supposed to be used from
pushback_files. We cannot use a class here, because scandir wants a
Expand All @@ -169,10 +168,10 @@ pushback_files. We cannot use a class here, because scandir wants a
static const char *const *pushback_files_exclude;
static bool pushback_files_no_hidden;
static size_t pushback_files_only_type;
static const string *pushback_files_dir_path; // defined if pushback_files_only_type is nonzero
static string pushback_files_dir_path; // defined if pushback_files_only_type is nonzero
static int pushback_files_selector(SCANDIR_ARG3 dir_entry) {
// Empty names shouldn't occur. Just to be sure, we ignore them:
if(!((dir_entry->d_name)[0])) {
if((dir_entry->d_name)[0] == '\0') {
return 0;
}

Expand All @@ -187,52 +186,24 @@ static int pushback_files_selector(SCANDIR_ARG3 dir_entry) {
return 0;
}
}
if(pushback_files_exclude) {
if(pushback_files_exclude != NULLPTR) {
// Look if it's in exclude
for(const char *const *p(pushback_files_exclude); likely(*p != NULLPTR); ++p) {
if(unlikely(std::strcmp(*p, dir_entry->d_name) == 0)) {
return 0;
}
}
}
if(likely(pushback_files_only_type == 0)) {
return 1;
}
struct stat static_stat;
if(unlikely(stat(((*pushback_files_dir_path) + dir_entry->d_name).c_str(), &static_stat))) {
return 0;
}
if(pushback_files_only_type & 1) {
if(S_ISREG(static_stat.st_mode)) {
return 1;
}
}
if(pushback_files_only_type & 2) {
if(S_ISDIR(static_stat.st_mode)) {
return 1;
}
}
return 0;
return is_only_type(pushback_files_dir_path + dir_entry->d_name, pushback_files_only_type) ? 1 : 0;
}

/**
List of files in directory.
Pushed names of file in directory into string-vector if the don't match any
char * in given exlude list.
@param dir_path Path to directory
@param into pointer to WordVec .. files get append here (with full path)
@param exclude list of char * that don't need to be put into vector
@param only_type: if 1: consider only ordinary files, if 2: consider only dirs, if 3: consider only files or dirs
@param no_hidden ignore hidden files
@param full_path return full pathnames
@return true if everything is ok
**/
bool pushback_files(const string& dir_path, WordVec *into, const char *const exclude[], unsigned char only_type, bool no_hidden, bool full_path) {
pushback_files_exclude = exclude;
pushback_files_no_hidden = no_hidden;
pushback_files_only_type = only_type;
if(only_type) {
pushback_files_dir_path = &dir_path;
if(only_type != 0) {
pushback_files_dir_path.assign(dir_path);
pushback_files_dir_path.append(1, '/');
}
WordVec namelist;
if(!scandir_cc(dir_path, &namelist, pushback_files_selector)) {
Expand All @@ -249,6 +220,45 @@ bool pushback_files(const string& dir_path, WordVec *into, const char *const exc
return true;
}

/**
Files excluded for recursive pushback_files
**/
const char *pushback_files_recurse_exclude[] = { "..", ".", "CVS", "RCS", "SCCS", NULLPTR };

bool pushback_files_recurse(const string& dir_path, const string& subpath, int depth, WordVec *into, bool full_path, string *errtext) {
WordVec files;
if(pushback_files(dir_path, &files, pushback_files_exclude, 3, true, false)) {
string dir(dir_path);
dir.append(1, '/');
string subdir(subpath);
if (depth != 0) {
subdir.append(1, '/');
}
for(WordVec::const_iterator it(files.begin());
likely(it != files.end()); ++it) {
if(depth == 100) {
if(errtext != NULLPTR) {
*errtext = eix::format(_("nesting level too deep in %s")) % dir_path;
}
return false;
}
if(unlikely(!pushback_files_recurse(dir + (*it), subdir + (*it), depth + 1, into, full_path, errtext))) {
return false;
}
}
return true;
}
if ((depth == 0) && !is_only_type(dir_path, 1)) {
return true;
}
if (full_path) {
into->PUSH_BACK(MOVE(dir_path));
} else {
into->PUSH_BACK(MOVE(subpath));
}
return true;
}

void dump_version() {
eix::say() % PACKAGE_VERSION;
std::exit(EXIT_SUCCESS);
Expand Down
21 changes: 13 additions & 8 deletions src/eixTk/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ inline static bool pushback_lines(const char *file, LineVec *v) {
return pushback_lines(file, v, false);
}

/**
Files excluded for pushback_lines in recursive mode
**/
extern const char *pushback_lines_exclude[];

/**
List of files in directory.
Pushed names of file in directory into string-vector if they don't match any
Expand All @@ -74,9 +69,19 @@ char * in given exlude list.
@return true if everything is ok. Nonexisting directory is not ok.
**/
ATTRIBUTE_NONNULL((2)) bool pushback_files(const std::string& dir_path, WordVec *into, const char *const exclude[], unsigned char only_files, bool no_hidden, bool full_path);
ATTRIBUTE_NONNULL((2)) inline static bool pushback_files(const std::string& dir_path, WordVec *into, const char *const exclude[], unsigned char only_files);
inline static bool pushback_files(const std::string& dir_path, WordVec *into, const char *const exclude[], unsigned char only_files) {
return pushback_files(dir_path, into, exclude, only_files, true, true);

/**
Files excluded for pushback_lines in recursive mode
**/
extern const char *pushback_files_recurse_exclude[];

/**
Recursive list of files in directory
*/
ATTRIBUTE_NONNULL((4)) bool pushback_files_recurse(const std::string& dir_path, const std::string& subpath, int depth, WordVec *into, bool full_path, std::string *errtext);
ATTRIBUTE_NONNULL((2)) inline static bool pushback_files_recurse(const std::string& dir_path, WordVec *into, bool full_path, std::string *errtext);
ATTRIBUTE_NONNULL((2)) inline static bool pushback_files_recurse(const std::string& dir_path, WordVec *into, bool full_path, std::string *errtext) {
return pushback_files_recurse(dir_path, "", 0, into, full_path, errtext);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/eixTk/varsreader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ bool VarsReader::read(const char *filename, string *errtext, bool noexist_ok, Wo
string dir(filename);
dir.append(1, '/');
WordVec files;
if(pushback_files(dir, &files, pushback_lines_exclude, 3)) {
if(pushback_files(dir, &files, pushback_files_recurse_exclude, 3, true, true)) {
for(WordVec::const_iterator file(files.begin());
likely(file != files.end()); ++file) {
if(!read(file->c_str(), errtext, false, sourced, false)) {
Expand Down
2 changes: 1 addition & 1 deletion src/portage/conf/cascadingprofile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ bool CascadingProfile::addProfile(const char *profile, WordUnorderedSet *sourced
sourced_files->erase(truename);
}
WordVec filenames;
bool r(pushback_files(truename, &filenames, profile_exclude, 3));
bool r(pushback_files(truename, &filenames, profile_exclude, 3, true, true));
for(WordVec::const_iterator it(filenames.begin());
likely(it != filenames.end()); ++it) {
listaddFile(*it, 0, false);
Expand Down
10 changes: 5 additions & 5 deletions src/portage/conf/portagesettings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -626,9 +626,6 @@ string PortageSettings::get_setnames(const Package *p, bool also_nonlocal) const
return join_to_string(names);
}


static CONSTEXPR const char *sets_exclude[] = { "..", "." , "system", "world", NULLPTR };

void PortageSettings::read_local_sets(const WordVec& dir_list) {
world_setslist_up_to_date = false;
set_names.clear();
Expand All @@ -639,9 +636,12 @@ void PortageSettings::read_local_sets(const WordVec& dir_list) {
all_set_names is used as a cache to find duplicate set names faster
**/
WordUnorderedSet all_set_names;
// We ignore these sets, as they are filled differently:
all_set_names.INSERT("system");
all_set_names.INSERT("world");
for(WordVec::size_type i(0); likely(i != dir_list.size()); ++i) {
WordVec temporary_set_names;
pushback_files(dir_list[i], &temporary_set_names, sets_exclude, 0, true, false);
pushback_files_recurse(dir_list[i], &temporary_set_names, false, NULLPTR);
WordVec::size_type s(set_names.size());
// Avoid duplicate sets
for(WordVec::const_iterator it(temporary_set_names.begin());
Expand All @@ -660,7 +660,7 @@ void PortageSettings::read_local_sets(const WordVec& dir_list) {
string dir_slash(dir_list[i]);
optional_append(&dir_slash, '/');
for(WordVec::size_type j(0); likely(j != dir_size[i]); ++j) {
grab_setmasks((dir_slash + set_names[c]).c_str(), c, &(child_names[c]), true);
grab_setmasks((dir_slash + set_names[c]).c_str(), c, &(child_names[c]), false);
++c;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/portage/extendedversion_bin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ ExtendedVersion::CountBinPkg ExtendedVersion::num_pak_pkg(const PortageSettings
}
const string pkgs = s + "/" + pkg->category + "/" + pkg->name + "/";
WordVec bin_packages;
if(unlikely(!pushback_files(pkgs, &bin_packages, NULLPTR, 1))) {
if(unlikely(!pushback_files(pkgs, &bin_packages, NULLPTR, 1, true, true))) {
return 0;
}
const string pkg_search = pkgs + pkg->name + "-" + getFull() + "-";
Expand Down

0 comments on commit 5b3272a

Please sign in to comment.