Skip to content

Commit

Permalink
csgrep --file-glob: expand glob patterns
Browse files Browse the repository at this point in the history
... in the names of input files.  If we have too many input files, we
cannot rely on the glob expansion implemented in the shell because the
expanded command might exceed the maximum command line length.  Running
`csgrep` for multiple batches of input files is difficult when we use
a JSON-based output format, which cannot be concatenated as plain text.

Related: csutils/csmock#187
Closes: csutils#212
  • Loading branch information
kdudka committed Oct 15, 2024
1 parent b8aeaa2 commit e768a87
Show file tree
Hide file tree
Showing 7 changed files with 99,875 additions and 10 deletions.
35 changes: 25 additions & 10 deletions src/csgrep.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "abstract-filter.hh"
#include "filter.hh"
#include "finger-print.hh"
#include "glob-expand.hh"
#include "msg-filter.hh"
#include "parser.hh"
#include "parser-common.hh"
Expand Down Expand Up @@ -615,6 +616,7 @@ int main(int argc, char *argv[])
("strip-path-prefix", po::value<string>(), "string prefix to strip from path (applied after all filters)")
("prepend-path-prefix", po::value<string>(), "string prefix to prepend to relative paths (applied after all filters)")

("file-glob", "expand glob patterns in the names of input files")
("ignore-case,i", "ignore case when matching regular expressions")
("ignore-parser-warnings", "if enabled, parser warnings about the input files do not affect exit code")
("invert-match,v", "select defects that do not match the selected criteria")
Expand Down Expand Up @@ -680,6 +682,15 @@ int main(int argc, char *argv[])
return 1;
}

// if the --file-glob flag was used, check whether a glob pattern was given
const bool fileGlob = !!vm.count("file-glob");
const bool hasInputFile = !!vm.count("input-file");
if (fileGlob && !hasInputFile) {
std::cerr << name
<< ": error: glob pattern is required with --file-glob\n";
return 1;
}

// create a writer according to the selected mode
WriterFactory factory;
AbstractWriter *eng = factory.create(mode);
Expand Down Expand Up @@ -726,16 +737,20 @@ int main(int argc, char *argv[])

bool hasError = false;

if (!vm.count("input-file")) {
hasError = !eng->handleFile("-", silent);
}
else {
const TStringList &files = vm["input-file"].as<TStringList>();
for (const string &fileName : files) {
if (!eng->handleFile(fileName, silent))
hasError = true;
}
}
// if no input file is given, read from stdin
TStringList files = { "-" };

if (hasInputFile)
// use the given list of input files (or glob patterns)
files = vm["input-file"].as<TStringList>();

if (fileGlob)
// expand file globs
hasError |= !globExpand(&files);

// process all input files one by one
for (const string &fileName : files)
hasError |= !eng->handleFile(fileName, silent);

eng->flush();
delete eng;
Expand Down
1 change: 1 addition & 0 deletions src/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_library(cs STATIC
deflookup.cc
filter.cc
finger-print.cc
glob-expand.cc
instream.cc
msg-filter.cc
parser.cc
Expand Down
52 changes: 52 additions & 0 deletions src/lib/glob-expand.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 Red Hat, Inc.
*
* This file is part of csdiff.
*
* csdiff is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* csdiff is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
*/

#include "glob-expand.hh"

#include <glob.h>

bool globExpand(TStringList *pDst, const std::string &globPat)
{
// use POSIX glob() to expand the glob pattern
glob_t results;
results.gl_pathc = 0U;
const bool success = !glob(globPat.c_str(), 0, nullptr, &results);

// store the results to *pDst
for (unsigned i = 0U; i < results.gl_pathc; ++i)
pDst->push_back(results.gl_pathv[i]);

// free the original data structure returned by glob()
globfree(&results);
return success;
}

bool globExpand(TStringList *pDstSrc)
{
bool success = true;

// expand all globs one by one
TStringList dst;
for (const auto &globPat : *pDstSrc)
success &= globExpand(&dst, globPat);

// store the results to *pDstSrc
*pDstSrc = std::move(dst);
return success;
}
34 changes: 34 additions & 0 deletions src/lib/glob-expand.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2024 Red Hat, Inc.
*
* This file is part of csdiff.
*
* csdiff is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* csdiff is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef H_GUARD_GLOB_EXPAND_H
#define H_GUARD_GLOB_EXPAND_H

#include <string>
#include <vector>

using TStringList = std::vector<std::string>;

/// expand the `globPat` pattern and store resulting file names to `*pDst`
bool globExpand(TStringList *pDst, const std::string &globPat);

/// expand all glob patterns in `*pDstSrc` and store results to `*pDstSrc`
bool globExpand(TStringList *pDstSrc);

#endif /* H_GUARD_GLOB_EXPAND_H */
1 change: 1 addition & 0 deletions tests/csgrep/0130-file-glob-args.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--mode=json --file-glob "$PROJECT_ROOT/tests/csgrep/000[4-9]-*-stdin.txt" "$PROJECT_ROOT/tests/csgrep/000?-*-stdout.txt"
Loading

0 comments on commit e768a87

Please sign in to comment.