Skip to content

Commit 3fd9368

Browse files
authored
feat(fmt): count number of formatted files (#1210)
1 parent f1b916a commit 3fd9368

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

src/Cmd/Fmt.cc

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <algorithm>
1313
#include <cstdlib>
14+
#include <filesystem>
1415
#include <ranges>
1516
#include <spdlog/spdlog.h>
1617
#include <string>
@@ -20,6 +21,8 @@
2021

2122
namespace cabin {
2223

24+
namespace fs = std::filesystem;
25+
2326
static Result<void> fmtMain(CliArgsView args);
2427

2528
const Subcmd FMT_CMD =
@@ -33,7 +36,15 @@ const Subcmd FMT_CMD =
3336
"Do not exclude git-ignored files from formatting"))
3437
.setMainFn(fmtMain);
3538

36-
static std::vector<std::string>
39+
struct TargetFile {
40+
std::string path;
41+
fs::file_time_type modTime;
42+
43+
explicit TargetFile(std::string path) noexcept
44+
: path(std::move(path)), modTime(fs::last_write_time(this->path)) {}
45+
};
46+
47+
static std::vector<TargetFile>
3748
collectFormatTargets(const fs::path& manifestDir,
3849
const std::vector<fs::path>& excludes,
3950
bool useVcsIgnoreFiles) {
@@ -59,7 +70,7 @@ collectFormatTargets(const fs::path& manifestDir,
5970
};
6071

6172
// Automatically collects format-target files
62-
std::vector<std::string> sources;
73+
std::vector<TargetFile> files;
6374
for (auto entry = fs::recursive_directory_iterator(manifestDir);
6475
entry != fs::recursive_directory_iterator(); ++entry) {
6576
if (entry->is_directory()) {
@@ -80,11 +91,24 @@ collectFormatTargets(const fs::path& manifestDir,
8091

8192
const std::string ext = path.extension().string();
8293
if (SOURCE_FILE_EXTS.contains(ext) || HEADER_FILE_EXTS.contains(ext)) {
83-
sources.push_back(path.string());
94+
files.emplace_back(path.string());
95+
}
96+
}
97+
}
98+
return files;
99+
}
100+
101+
static std::size_t countModifiedFiles(const std::vector<TargetFile>& files) {
102+
std::size_t changedFiles = 0;
103+
for (const TargetFile& file : files) {
104+
if (fs::exists(file.path)) {
105+
const auto afterTime = fs::last_write_time(file.path);
106+
if (file.modTime != afterTime) {
107+
++changedFiles;
84108
}
85109
}
86110
}
87-
return sources;
111+
return changedFiles;
88112
}
89113

90114
static Result<void> fmtMain(const CliArgsView args) {
@@ -126,9 +150,9 @@ static Result<void> fmtMain(const CliArgsView args) {
126150
};
127151

128152
const fs::path projectPath = manifest.path.parent_path();
129-
const std::vector<std::string> sources =
153+
const std::vector<TargetFile> files =
130154
collectFormatTargets(projectPath, excludes, useVcsIgnoreFiles);
131-
if (sources.empty()) {
155+
if (files.empty()) {
132156
Diag::warn("no files to format");
133157
return Ok();
134158
}
@@ -140,9 +164,10 @@ static Result<void> fmtMain(const CliArgsView args) {
140164
clangFormatArgs.emplace_back("--dry-run");
141165
} else {
142166
clangFormatArgs.emplace_back("-i");
143-
Diag::info("Formatting", "{}", manifest.package.name);
144167
}
145-
clangFormatArgs.insert(clangFormatArgs.end(), sources.begin(), sources.end());
168+
clangFormatArgs.reserve(clangFormatArgs.size() + files.size());
169+
std::ranges::copy(files | std::views::transform(&TargetFile::path),
170+
std::back_inserter(clangFormatArgs));
146171

147172
const char* cabinFmt = std::getenv("CABIN_FMT");
148173
if (cabinFmt == nullptr) {
@@ -154,6 +179,15 @@ static Result<void> fmtMain(const CliArgsView args) {
154179

155180
const ExitStatus exitStatus = Try(execCmd(clangFormat));
156181
if (exitStatus.success()) {
182+
const std::size_t numFiles = files.size();
183+
if (isCheck) {
184+
Diag::info("Checked", "{} file{} with no format required", numFiles,
185+
numFiles == 1 ? "" : "s");
186+
} else {
187+
const std::size_t modifiedFiles = countModifiedFiles(files);
188+
Diag::info("Formatted", "{} out of {} file{}", modifiedFiles, numFiles,
189+
numFiles == 1 ? "" : "s");
190+
}
157191
return Ok();
158192
} else {
159193
Bail("clang-format {}", exitStatus);

tests/03-fmt.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ test_expect_success 'cabin fmt' '
3939
md5sum src/main.cc >after &&
4040
test_must_fail test_cmp before after &&
4141
cat >expected <<-EOF &&
42-
Formatting pkg
42+
Formatted 1 out of 1 file
43+
EOF
44+
test_cmp expected actual &&
45+
46+
md5sum src/main.cc >before &&
47+
"$CABIN" fmt 2>actual &&
48+
md5sum src/main.cc >after &&
49+
test_cmp before after &&
50+
cat >expected <<-EOF &&
51+
Formatted 0 out of 1 file
4352
EOF
4453
test_cmp expected actual
4554
)

0 commit comments

Comments
 (0)