Skip to content

Commit 761b13a

Browse files
committed
csgrep --file-glob: expand glob patterns
... 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: #212
1 parent c3c6670 commit 761b13a

File tree

7 files changed

+99875
-10
lines changed

7 files changed

+99875
-10
lines changed

src/csgrep.cc

+25-10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "abstract-filter.hh"
2121
#include "filter.hh"
2222
#include "finger-print.hh"
23+
#include "glob-expand.hh"
2324
#include "msg-filter.hh"
2425
#include "parser.hh"
2526
#include "parser-common.hh"
@@ -615,6 +616,7 @@ int main(int argc, char *argv[])
615616
("strip-path-prefix", po::value<string>(), "string prefix to strip from path (applied after all filters)")
616617
("prepend-path-prefix", po::value<string>(), "string prefix to prepend to relative paths (applied after all filters)")
617618

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

685+
// if the --file-glob flag was used, check whether a glob pattern was given
686+
const bool fileGlob = !!vm.count("file-glob");
687+
const bool hasInputFile = !!vm.count("input-file");
688+
if (fileGlob && !hasInputFile) {
689+
std::cerr << name
690+
<< ": error: glob pattern is required with --file-glob\n";
691+
return 1;
692+
}
693+
683694
// create a writer according to the selected mode
684695
WriterFactory factory;
685696
AbstractWriter *eng = factory.create(mode);
@@ -726,16 +737,20 @@ int main(int argc, char *argv[])
726737

727738
bool hasError = false;
728739

729-
if (!vm.count("input-file")) {
730-
hasError = !eng->handleFile("-", silent);
731-
}
732-
else {
733-
const TStringList &files = vm["input-file"].as<TStringList>();
734-
for (const string &fileName : files) {
735-
if (!eng->handleFile(fileName, silent))
736-
hasError = true;
737-
}
738-
}
740+
// if no input file is given, read from stdin
741+
TStringList files = { "-" };
742+
743+
if (hasInputFile)
744+
// use the given list of input files (or glob patterns)
745+
files = vm["input-file"].as<TStringList>();
746+
747+
if (fileGlob)
748+
// expand file globs
749+
hasError |= !globExpand(&files);
750+
751+
// process all input files one by one
752+
for (const string &fileName : files)
753+
hasError |= !eng->handleFile(fileName, silent);
739754

740755
eng->flush();
741756
delete eng;

src/lib/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_library(cs STATIC
2626
deflookup.cc
2727
filter.cc
2828
finger-print.cc
29+
glob-expand.cc
2930
instream.cc
3031
msg-filter.cc
3132
parser.cc

src/lib/glob-expand.cc

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2024 Red Hat, Inc.
3+
*
4+
* This file is part of csdiff.
5+
*
6+
* csdiff is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* any later version.
10+
*
11+
* csdiff is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "glob-expand.hh"
21+
22+
#include <glob.h>
23+
24+
bool globExpand(TStringList *pDst, const std::string &globPat)
25+
{
26+
// use POSIX glob() to expand the glob pattern
27+
glob_t results;
28+
results.gl_pathc = 0U;
29+
const bool success = !glob(globPat.c_str(), 0, nullptr, &results);
30+
31+
// store the results to *pDst
32+
for (unsigned i = 0U; i < results.gl_pathc; ++i)
33+
pDst->push_back(results.gl_pathv[i]);
34+
35+
// free the original data structure returned by glob()
36+
globfree(&results);
37+
return success;
38+
}
39+
40+
bool globExpand(TStringList *pDstSrc)
41+
{
42+
bool success = true;
43+
44+
// expand all globs one by one
45+
TStringList dst;
46+
for (const auto &globPat : *pDstSrc)
47+
success &= globExpand(&dst, globPat);
48+
49+
// store the results to *pDstSrc
50+
*pDstSrc = std::move(dst);
51+
return success;
52+
}

src/lib/glob-expand.hh

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (C) 2024 Red Hat, Inc.
3+
*
4+
* This file is part of csdiff.
5+
*
6+
* csdiff is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* any later version.
10+
*
11+
* csdiff is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#ifndef H_GUARD_GLOB_EXPAND_H
21+
#define H_GUARD_GLOB_EXPAND_H
22+
23+
#include <string>
24+
#include <vector>
25+
26+
using TStringList = std::vector<std::string>;
27+
28+
/// expand the `globPat` pattern and store resulting file names to `*pDst`
29+
bool globExpand(TStringList *pDst, const std::string &globPat);
30+
31+
/// expand all glob patterns in `*pDstSrc` and store results to `*pDstSrc`
32+
bool globExpand(TStringList *pDstSrc);
33+
34+
#endif /* H_GUARD_GLOB_EXPAND_H */

tests/csgrep/0130-file-glob-args.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--mode=json --file-glob "$PROJECT_ROOT/tests/csgrep/000[4-9]-*-stdin.txt" "$PROJECT_ROOT/tests/csgrep/000?-*-stdout.txt"

0 commit comments

Comments
 (0)