mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
License cpp jun13 (#170620)
Still executing around 35s. It still doesn't match licenses against the database. I don't expect that to add much time considering how we plan to do it. 1) fixes the way c strings strip out comments 1) started handling LICENSE files more correctly ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This commit is contained in:
parent
1cc9fcb587
commit
b0735bfa73
@ -3,3 +3,7 @@
|
||||
.*\/test\/.*
|
||||
.*\/testing\/.*
|
||||
.*\/tests\/.*
|
||||
.*/third_party/swiftshader/third_party/llvm-16.0/.*
|
||||
.*/third_party/swiftshader/third_party/llvm-10.0/.*
|
||||
.*/third_party/llvm-project/.*
|
||||
.*/third_party/ocmock/.*
|
||||
|
||||
@ -349,9 +349,9 @@ struct yy_trans_info {
|
||||
flex_int32_t yy_verify;
|
||||
flex_int32_t yy_nxt;
|
||||
};
|
||||
static const flex_int16_t yy_accept[28] = {0, 0, 0, 0, 0, 0, 0, 9, 7, 7,
|
||||
1, 7, 4, 4, 6, 6, 0, 1, 0, 1,
|
||||
2, 3, 0, 5, 0, 2, 5, 0};
|
||||
static const flex_int16_t yy_accept[37] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 9, 7, 7, 1, 7, 8, 4, 8, 6, 6, 0, 1,
|
||||
0, 1, 2, 0, 4, 0, 0, 0, 5, 0, 2, 2, 0, 3, 0, 5, 0, 0};
|
||||
|
||||
static const YY_CHAR yy_ec[256] = {
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
@ -371,23 +371,27 @@ static const YY_CHAR yy_ec[256] = {
|
||||
|
||||
static const YY_CHAR yy_meta[7] = {0, 1, 1, 2, 1, 1, 3};
|
||||
|
||||
static const flex_int16_t yy_base[36] = {
|
||||
0, 0, 0, 27, 24, 14, 12, 10, 34, 5, 0, 7, 34, 0, 34, 12, 0, 0,
|
||||
0, 0, 0, 34, 0, 0, 0, 34, 0, 34, 18, 21, 24, 27, 5, 3, 30, 0};
|
||||
static const flex_int16_t yy_base[45] = {
|
||||
0, 0, 0, 4, 7, 18, 13, 14, 62, 11, 0, 13, 17, 62, 20,
|
||||
62, 25, 0, 0, 0, 0, 29, 5, 62, 0, 32, 0, 0, 0, 62,
|
||||
0, 35, 62, 2, 0, 0, 62, 40, 43, 46, 49, 52, 55, 58, 0};
|
||||
|
||||
static const flex_int16_t yy_def[36] = {
|
||||
0, 28, 28, 29, 29, 30, 30, 27, 27, 27, 31, 27, 27, 32, 27, 27, 9, 31,
|
||||
11, 31, 33, 27, 15, 34, 35, 27, 34, 0, 27, 27, 27, 27, 27, 27, 27, 27};
|
||||
static const flex_int16_t yy_def[45] = {
|
||||
0, 37, 37, 38, 38, 39, 39, 36, 36, 36, 40, 36, 41, 36, 41,
|
||||
36, 36, 9, 40, 11, 40, 36, 14, 36, 14, 42, 16, 43, 44, 36,
|
||||
21, 42, 36, 31, 43, 31, 0, 36, 36, 36, 36, 36, 36, 36, 36};
|
||||
|
||||
static const flex_int16_t yy_nxt[41] = {
|
||||
0, 27, 9, 23, 10, 25, 11, 16, 21, 17, 27, 18, 20, 17,
|
||||
22, 15, 23, 15, 24, 8, 8, 8, 12, 12, 12, 14, 14, 14,
|
||||
19, 13, 19, 26, 13, 26, 7, 27, 27, 27, 27, 27, 27};
|
||||
static const flex_int16_t yy_nxt[69] = {
|
||||
0, 36, 9, 27, 10, 36, 11, 13, 35, 14, 13, 22, 14, 17, 36, 18, 16, 19,
|
||||
21, 18, 23, 16, 24, 23, 36, 24, 25, 26, 36, 27, 36, 28, 29, 36, 30, 32,
|
||||
36, 33, 32, 36, 33, 8, 8, 8, 12, 12, 12, 15, 15, 15, 20, 36, 20, 22,
|
||||
22, 22, 31, 31, 31, 34, 36, 34, 7, 36, 36, 36, 36, 36, 36};
|
||||
|
||||
static const flex_int16_t yy_chk[41] = {
|
||||
0, 0, 2, 35, 2, 33, 2, 9, 32, 9, 7, 9, 11, 11,
|
||||
15, 6, 15, 5, 15, 28, 28, 28, 29, 29, 29, 30, 30, 30,
|
||||
31, 4, 31, 34, 3, 34, 27, 27, 27, 27, 27, 27, 27};
|
||||
static const flex_int16_t yy_chk[69] = {
|
||||
0, 0, 2, 44, 2, 0, 2, 3, 33, 3, 4, 22, 4, 9, 7, 9, 6, 9,
|
||||
11, 11, 12, 5, 12, 14, 0, 14, 14, 16, 0, 16, 0, 16, 21, 0, 21, 25,
|
||||
0, 25, 31, 0, 31, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 0, 40, 41,
|
||||
41, 41, 42, 42, 42, 43, 0, 43, 36, 36, 36, 36, 36, 36, 36};
|
||||
|
||||
/* The intent behind this definition is that it'll catch
|
||||
* any uses of REJECT which flex missed.
|
||||
@ -421,9 +425,9 @@ struct LexerContext {
|
||||
std::function<void(std::string_view)> callback;
|
||||
std::string buffer;
|
||||
};
|
||||
#line 462 "comments.cc"
|
||||
#line 471 "comments.cc"
|
||||
|
||||
#line 464 "comments.cc"
|
||||
#line 473 "comments.cc"
|
||||
|
||||
#define INITIAL 0
|
||||
#define C_COMMENT 1
|
||||
@ -681,7 +685,7 @@ YY_DECL {
|
||||
{
|
||||
#line 40 "comments.l"
|
||||
|
||||
#line 729 "comments.cc"
|
||||
#line 738 "comments.cc"
|
||||
|
||||
while (/*CONSTCOND*/ 1) /* loops until end-of-file is reached */
|
||||
{
|
||||
@ -706,12 +710,12 @@ YY_DECL {
|
||||
}
|
||||
while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
|
||||
yy_current_state = (int)yy_def[yy_current_state];
|
||||
if (yy_current_state >= 28)
|
||||
if (yy_current_state >= 37)
|
||||
yy_c = yy_meta[yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
||||
++yy_cp;
|
||||
} while (yy_base[yy_current_state] != 34);
|
||||
} while (yy_base[yy_current_state] != 62);
|
||||
|
||||
yy_find_action:
|
||||
yy_act = yy_accept[yy_current_state];
|
||||
@ -751,10 +755,12 @@ YY_DECL {
|
||||
YY_BREAK
|
||||
|
||||
case 3:
|
||||
/* rule 3 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 50 "comments.l"
|
||||
{
|
||||
BEGIN(INITIAL);
|
||||
CommentsUtil::AddCEndTrimLine(&yyextra->buffer, yytext, yyleng - 2);
|
||||
yyextra->callback(yyextra->buffer);
|
||||
yyextra->buffer.clear();
|
||||
}
|
||||
@ -762,16 +768,16 @@ YY_DECL {
|
||||
case 4:
|
||||
/* rule 4 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 55 "comments.l"
|
||||
#line 56 "comments.l"
|
||||
{
|
||||
yyextra->buffer.append(yytext, yyleng);
|
||||
CommentsUtil::AddCTrimLine(&yyextra->buffer, yytext, yyleng);
|
||||
}
|
||||
YY_BREAK
|
||||
|
||||
case 5:
|
||||
/* rule 5 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 61 "comments.l"
|
||||
#line 62 "comments.l"
|
||||
{
|
||||
yyextra->buffer.append("\n", 1);
|
||||
CommentsUtil::AddTrimLine(&yyextra->buffer, yytext + 1, yyleng - 1);
|
||||
@ -780,7 +786,7 @@ YY_DECL {
|
||||
case 6:
|
||||
/* rule 6 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 65 "comments.l"
|
||||
#line 66 "comments.l"
|
||||
{
|
||||
BEGIN(INITIAL);
|
||||
yyextra->callback(yyextra->buffer);
|
||||
@ -791,16 +797,16 @@ YY_DECL {
|
||||
case 7:
|
||||
/* rule 7 can match eol */
|
||||
YY_RULE_SETUP
|
||||
#line 72 "comments.l"
|
||||
#line 73 "comments.l"
|
||||
{
|
||||
}
|
||||
YY_BREAK
|
||||
case 8:
|
||||
YY_RULE_SETUP
|
||||
#line 73 "comments.l"
|
||||
#line 74 "comments.l"
|
||||
ECHO;
|
||||
YY_BREAK
|
||||
#line 854 "comments.cc"
|
||||
#line 865 "comments.cc"
|
||||
case YY_STATE_EOF(INITIAL):
|
||||
case YY_STATE_EOF(C_COMMENT):
|
||||
case YY_STATE_EOF(BLOCK):
|
||||
@ -1080,7 +1086,7 @@ static yy_state_type yy_get_previous_state(yyscan_t yyscanner) {
|
||||
}
|
||||
while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
|
||||
yy_current_state = (int)yy_def[yy_current_state];
|
||||
if (yy_current_state >= 28)
|
||||
if (yy_current_state >= 37)
|
||||
yy_c = yy_meta[yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
||||
@ -1108,11 +1114,11 @@ static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state,
|
||||
}
|
||||
while (yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) {
|
||||
yy_current_state = (int)yy_def[yy_current_state];
|
||||
if (yy_current_state >= 28)
|
||||
if (yy_current_state >= 37)
|
||||
yy_c = yy_meta[yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
||||
yy_is_jam = (yy_current_state == 27);
|
||||
yy_is_jam = (yy_current_state == 36);
|
||||
|
||||
(void)yyg;
|
||||
return yy_is_jam ? 0 : yy_current_state;
|
||||
@ -1909,7 +1915,7 @@ void yyfree(void* ptr, yyscan_t yyscanner) {
|
||||
|
||||
#define YYTABLES_NAME "yytables"
|
||||
|
||||
#line 73 "comments.l"
|
||||
#line 74 "comments.l"
|
||||
|
||||
void IterateComments(const char* buffer,
|
||||
size_t size,
|
||||
|
||||
@ -42,18 +42,19 @@ COMMENT_START (\/\/|#)
|
||||
BEGIN(BLOCK);
|
||||
CommentsUtil::AddTrimLine(&yyextra->buffer, yytext, yyleng);
|
||||
}
|
||||
^[ \t]*\/\*[\n]? {
|
||||
^[ \t]*\/\*[\*]*[\n]? {
|
||||
BEGIN(C_COMMENT);
|
||||
}
|
||||
|
||||
<C_COMMENT>{
|
||||
\*\/ {
|
||||
.*\*\/.*\n {
|
||||
BEGIN(INITIAL);
|
||||
CommentsUtil::AddCEndTrimLine(&yyextra->buffer, yytext, yyleng - 2);
|
||||
yyextra->callback(yyextra->buffer);
|
||||
yyextra->buffer.clear();
|
||||
}
|
||||
\n|. {
|
||||
yyextra->buffer.append(yytext, yyleng);
|
||||
.*\n {
|
||||
CommentsUtil::AddCTrimLine(&yyextra->buffer, yytext, yyleng);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -66,3 +66,35 @@ daa
|
||||
ASSERT_EQ(comments.size(), 1u);
|
||||
EXPECT_EQ(comments[0], "hello\nworld");
|
||||
}
|
||||
|
||||
TEST(CommentsTest, CWithLeadingStars) {
|
||||
std::string test = R"test(
|
||||
/*************
|
||||
* hello
|
||||
* world
|
||||
*/
|
||||
)test";
|
||||
|
||||
std::vector<std::string> comments;
|
||||
IterateComments(test.c_str(), test.size(), [&](std::string_view comment) {
|
||||
comments.push_back(std::string(comment));
|
||||
});
|
||||
|
||||
ASSERT_EQ(comments.size(), 1u);
|
||||
EXPECT_EQ(comments[0], "hello\nworld\n");
|
||||
}
|
||||
|
||||
TEST(CommentsTest, CTextOnEndingLine) {
|
||||
std::string test = R"test(
|
||||
/*hello
|
||||
world*/
|
||||
)test";
|
||||
|
||||
std::vector<std::string> comments;
|
||||
IterateComments(test.c_str(), test.size(), [&](std::string_view comment) {
|
||||
comments.push_back(std::string(comment));
|
||||
});
|
||||
|
||||
ASSERT_EQ(comments.size(), 1u);
|
||||
EXPECT_EQ(comments[0], "hello\nworld");
|
||||
}
|
||||
|
||||
@ -13,3 +13,21 @@ void CommentsUtil::AddTrimLine(std::string* buffer,
|
||||
RE2::FullMatch(re2::StringPiece(text), regex, &captured_content);
|
||||
buffer->append(captured_content);
|
||||
}
|
||||
|
||||
void CommentsUtil::AddCTrimLine(std::string* buffer,
|
||||
const char* text,
|
||||
size_t length) {
|
||||
std::string chopped(text, length);
|
||||
RE2 regex(R"regex(^\s*\**\s?)regex");
|
||||
RE2::Replace(&chopped, regex, "");
|
||||
buffer->append(chopped);
|
||||
}
|
||||
|
||||
void CommentsUtil::AddCEndTrimLine(std::string* buffer,
|
||||
const char* text,
|
||||
size_t length) {
|
||||
RE2 regex(R"regex(^\s*(.*?)\*/)regex");
|
||||
re2::StringPiece captured_content;
|
||||
RE2::PartialMatch(re2::StringPiece(text), regex, &captured_content);
|
||||
buffer->append(captured_content);
|
||||
}
|
||||
|
||||
@ -11,6 +11,12 @@
|
||||
class CommentsUtil {
|
||||
public:
|
||||
static void AddTrimLine(std::string* buffer, const char* text, size_t length);
|
||||
static void AddCTrimLine(std::string* buffer,
|
||||
const char* text,
|
||||
size_t length);
|
||||
static void AddCEndTrimLine(std::string* buffer,
|
||||
const char* text,
|
||||
size_t length);
|
||||
};
|
||||
|
||||
#endif // FLUTTER_TOOLS_LICENSES_CPP_SRC_COMMENTS_UTIL_H_
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
@ -67,15 +68,14 @@ absl::StatusOr<std::vector<std::string>> GitLsFiles(const fs::path& repo_path) {
|
||||
return files;
|
||||
}
|
||||
|
||||
absl::Status CheckLicense(const fs::path& git_repo) {
|
||||
std::optional<fs::path> FindLicense(const fs::path& path) {
|
||||
for (std::string_view license_name : kLicenseFileNames) {
|
||||
fs::path license_path = git_repo / license_name;
|
||||
fs::path license_path = path / license_name;
|
||||
if (fs::exists(license_path)) {
|
||||
return absl::UnimplementedError("");
|
||||
return license_path;
|
||||
}
|
||||
}
|
||||
return absl::NotFoundError(
|
||||
absl::StrCat("Expected LICENSE at ", git_repo.string()));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void PrintProgress(size_t idx, size_t count) {
|
||||
@ -124,20 +124,76 @@ class LicensesWriter {
|
||||
bool first_write_ = true;
|
||||
};
|
||||
|
||||
std::string GetPackageName(const fs::path& full_path) {
|
||||
std::optional<std::string> result;
|
||||
struct Package {
|
||||
std::string name;
|
||||
std::optional<fs::path> license_file;
|
||||
};
|
||||
|
||||
Package GetPackage(const fs::path& working_dir, const fs::path& full_path) {
|
||||
Package result = {
|
||||
.name = "engine",
|
||||
.license_file = FindLicense(working_dir),
|
||||
};
|
||||
fs::path relative = fs::relative(full_path, working_dir);
|
||||
bool after_third_party = false;
|
||||
for (const fs::path& component : full_path) {
|
||||
fs::path current = working_dir;
|
||||
for (const fs::path& component : relative) {
|
||||
current /= component;
|
||||
if (after_third_party) {
|
||||
result = component;
|
||||
result.name = component;
|
||||
after_third_party = false;
|
||||
result.license_file = FindLicense(current);
|
||||
} else if (component.string() == "third_party") {
|
||||
after_third_party = true;
|
||||
result.license_file = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return result.has_value() ? result.value() : "engine";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ReadFile(const fs::path& path) {
|
||||
std::ifstream stream(path);
|
||||
assert(stream.good());
|
||||
std::string license((std::istreambuf_iterator<char>(stream)),
|
||||
std::istreambuf_iterator<char>());
|
||||
if (license[license.size() - 1] == '\n') {
|
||||
license.pop_back();
|
||||
}
|
||||
return license;
|
||||
}
|
||||
|
||||
class LicenseMap {
|
||||
public:
|
||||
void Add(std::string_view package, std::string_view license) {
|
||||
auto package_emplace_result =
|
||||
map_.try_emplace(license, absl::flat_hash_set<std::string>());
|
||||
absl::flat_hash_set<std::string>& comment_set =
|
||||
package_emplace_result.first->second;
|
||||
if (comment_set.find(package) == comment_set.end()) {
|
||||
// License is already seen.
|
||||
comment_set.emplace(std::string(package));
|
||||
}
|
||||
}
|
||||
|
||||
void AddFile(std::string_view package, const fs::path& path) {
|
||||
if (!license_files_.contains(path.string())) {
|
||||
Add(package, ReadFile(path));
|
||||
license_files_.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(std::ostream& licenses) {
|
||||
LicensesWriter writer(licenses);
|
||||
for (const auto& comment_entry : map_) {
|
||||
writer.Write(comment_entry.second, comment_entry.first);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
absl::btree_map<std::string, absl::flat_hash_set<std::string>> map_;
|
||||
absl::flat_hash_set<std::string> license_files_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::vector<absl::Status> LicenseChecker::Run(std::string_view working_dir,
|
||||
@ -145,27 +201,22 @@ std::vector<absl::Status> LicenseChecker::Run(std::string_view working_dir,
|
||||
const Data& data) {
|
||||
std::vector<absl::Status> errors;
|
||||
std::vector<fs::path> git_repos = GetGitRepos(working_dir);
|
||||
fs::path working_dir_path(working_dir);
|
||||
|
||||
RE2 pattern(kHeaderLicenseRegex);
|
||||
|
||||
size_t count = 0;
|
||||
LicenseMap license_map;
|
||||
for (const fs::path& git_repo : git_repos) {
|
||||
if (IsStdoutTerminal()) {
|
||||
PrintProgress(count++, git_repos.size());
|
||||
}
|
||||
absl::Status license_status = CheckLicense(git_repo);
|
||||
if (!license_status.ok() &&
|
||||
license_status.code() != absl::StatusCode::kUnimplemented) {
|
||||
errors.push_back(license_status);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::vector<std::string>> git_files = GitLsFiles(git_repo);
|
||||
if (!git_files.ok()) {
|
||||
errors.push_back(git_files.status());
|
||||
return errors;
|
||||
}
|
||||
LicensesWriter writer(licenses);
|
||||
absl::btree_map<std::string, absl::flat_hash_set<std::string>> license_map;
|
||||
for (const std::string& git_file : git_files.value()) {
|
||||
bool did_find_copyright = false;
|
||||
fs::path full_path = git_repo / git_file;
|
||||
@ -175,7 +226,10 @@ std::vector<absl::Status> LicenseChecker::Run(std::string_view working_dir,
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string package = GetPackageName(full_path);
|
||||
Package package = GetPackage(working_dir_path, full_path);
|
||||
if (package.license_file.has_value()) {
|
||||
license_map.AddFile(package.name, package.license_file.value());
|
||||
}
|
||||
|
||||
VLOG(1) << full_path.string();
|
||||
absl::StatusOr<MMapFile> file = MMapFile::Make(full_path.string());
|
||||
@ -196,27 +250,18 @@ std::vector<absl::Status> LicenseChecker::Run(std::string_view working_dir,
|
||||
if (RE2::PartialMatch(comment, pattern, &match)) {
|
||||
did_find_copyright = true;
|
||||
VLOG(1) << comment;
|
||||
|
||||
auto package_emplace_result = license_map.try_emplace(
|
||||
comment, absl::flat_hash_set<std::string>());
|
||||
absl::flat_hash_set<std::string>& comment_set =
|
||||
package_emplace_result.first->second;
|
||||
if (comment_set.find(package) != comment_set.end()) {
|
||||
// License is already seen.
|
||||
return;
|
||||
if (!package.license_file.has_value()) {
|
||||
license_map.Add(package.name, comment);
|
||||
}
|
||||
comment_set.emplace(std::string(package));
|
||||
}
|
||||
});
|
||||
if (!did_find_copyright) {
|
||||
if (!did_find_copyright && !package.license_file.has_value()) {
|
||||
errors.push_back(
|
||||
absl::NotFoundError("Expected copyright in " + full_path.string()));
|
||||
}
|
||||
}
|
||||
for (const auto& comment_entry : license_map) {
|
||||
writer.Write(comment_entry.second, comment_entry.first);
|
||||
}
|
||||
}
|
||||
license_map.Write(licenses);
|
||||
if (IsStdoutTerminal()) {
|
||||
PrintProgress(count++, git_repos.size());
|
||||
std::cout << std::endl;
|
||||
|
||||
@ -65,8 +65,7 @@ void main() {
|
||||
}
|
||||
)header";
|
||||
|
||||
const char* kLicense = R"lic(
|
||||
Test License
|
||||
const char* kLicense = R"lic(Test License
|
||||
v2.0
|
||||
)lic";
|
||||
|
||||
@ -109,6 +108,30 @@ bool FindError(const std::vector<absl::Status>& errors,
|
||||
RE2::PartialMatch(status.message(), regex);
|
||||
}) != errors.end();
|
||||
}
|
||||
|
||||
class Repo {
|
||||
public:
|
||||
void Add(const std::string& file) { files_.emplace_back(std::string(file)); }
|
||||
|
||||
absl::Status Commit() {
|
||||
if (std::system("git init") != 0) {
|
||||
return absl::InternalError("git init failed");
|
||||
}
|
||||
for (const std::string& file : files_) {
|
||||
if (std::system(("git add " + file).c_str()) != 0) {
|
||||
return absl::InternalError("git add failed: " + file);
|
||||
}
|
||||
}
|
||||
if (std::system("git commit -m \"test\"") != 0) {
|
||||
return absl::InternalError("git commit failed");
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> files_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimplePass) {
|
||||
@ -119,12 +142,12 @@ TEST_F(LicenseCheckerTest, SimplePass) {
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "main.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_EQ(std::system("git add main.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add(*temp_path / "main.cc");
|
||||
repo.Add(*temp_path / "LICENSE");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
@ -132,7 +155,7 @@ TEST_F(LicenseCheckerTest, SimplePass) {
|
||||
EXPECT_EQ(errors.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimpleMissingLicense) {
|
||||
TEST_F(LicenseCheckerTest, SimpleMissingFileLicense) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
@ -140,22 +163,20 @@ TEST_F(LicenseCheckerTest, SimpleMissingLicense) {
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_EQ(std::system("echo \"Hello world!\" > main.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add main.cc"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add(*temp_path / "main.cc");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
LicenseChecker::Run(temp_path->string(), ss, *data);
|
||||
EXPECT_EQ(errors.size(), 2u);
|
||||
EXPECT_TRUE(
|
||||
FindError(errors, absl::StatusCode::kNotFound, "Expected LICENSE at"));
|
||||
EXPECT_EQ(errors.size(), 1u);
|
||||
EXPECT_TRUE(FindError(errors, absl::StatusCode::kNotFound,
|
||||
"Expected copyright in.*main.cc"));
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesLicensesFile) {
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesFileLicensesFile) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
@ -163,12 +184,10 @@ TEST_F(LicenseCheckerTest, SimpleWritesLicensesFile) {
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "main.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_EQ(std::system("git add main.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add(*temp_path / "main.cc");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
@ -181,7 +200,7 @@ Copyright Test
|
||||
)output");
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesTwoLicensesFiles) {
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesTwoFileLicensesFiles) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
@ -189,14 +208,12 @@ TEST_F(LicenseCheckerTest, SimpleWritesTwoLicensesFiles) {
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "main.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kCHeader, *temp_path / "cmain.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_EQ(std::system("git add main.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add cmain.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add("main.cc");
|
||||
repo.Add("cmain.cc");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
@ -214,7 +231,7 @@ Copyright Test
|
||||
)output");
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesDuplicateLicensesFiles) {
|
||||
TEST_F(LicenseCheckerTest, SimpleWritesDuplicateFileLicensesFiles) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
@ -222,14 +239,12 @@ TEST_F(LicenseCheckerTest, SimpleWritesDuplicateLicensesFiles) {
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "a.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "b.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_EQ(std::system("git add a.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add b.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add("a.cc");
|
||||
repo.Add("b.cc");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
@ -242,7 +257,7 @@ Copyright Test
|
||||
)output");
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, MultiplePackages) {
|
||||
TEST_F(LicenseCheckerTest, FileLicenseMultiplePackages) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
@ -251,19 +266,13 @@ TEST_F(LicenseCheckerTest, MultiplePackages) {
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("mkdir -p third_party/foobar"), 0);
|
||||
ASSERT_EQ(std::system("git init"), 0);
|
||||
ASSERT_TRUE(WriteFile(kHeader, *temp_path / "a.cc").ok());
|
||||
ASSERT_TRUE(
|
||||
WriteFile(kHeader, *temp_path / "third_party" / "foobar" / "b.cc").ok());
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_TRUE(
|
||||
WriteFile(kLicense, *temp_path / "third_party" / "foobar" / "LICENSE")
|
||||
.ok());
|
||||
ASSERT_EQ(std::system("git add a.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add third_party/foobar/b.cc"), 0);
|
||||
ASSERT_EQ(std::system("git add third_party/foobar/LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git add LICENSE"), 0);
|
||||
ASSERT_EQ(std::system("git commit -m \"test\""), 0);
|
||||
Repo repo;
|
||||
repo.Add("a.cc");
|
||||
repo.Add("third_party/foobar/b.cc");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
@ -276,3 +285,66 @@ foobar
|
||||
Copyright Test
|
||||
)output");
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, SimpleDirectoryLicense) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
absl::StatusOr<Data> data = MakeTestData();
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("echo \"Hello world!\" > main.cc"), 0);
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
Repo repo;
|
||||
repo.Add("main.cc");
|
||||
repo.Add("LICENSE");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
LicenseChecker::Run(temp_path->string(), ss, *data);
|
||||
EXPECT_EQ(errors.size(), 0u);
|
||||
|
||||
EXPECT_EQ(ss.str(), R"output(engine
|
||||
|
||||
Test License
|
||||
v2.0
|
||||
)output");
|
||||
}
|
||||
|
||||
TEST_F(LicenseCheckerTest, ThirdyPartyDirectoryLicense) {
|
||||
absl::StatusOr<fs::path> temp_path = MakeTempDir();
|
||||
ASSERT_TRUE(temp_path.ok());
|
||||
|
||||
absl::StatusOr<Data> data = MakeTestData();
|
||||
ASSERT_TRUE(data.ok());
|
||||
|
||||
fs::current_path(*temp_path);
|
||||
ASSERT_EQ(std::system("mkdir -p third_party/foobar"), 0);
|
||||
ASSERT_EQ(std::system("echo \"Hello world!\" > main.cc"), 0);
|
||||
ASSERT_EQ(std::system("echo \"Hello world!\" > third_party/foobar/foo.cc"),
|
||||
0);
|
||||
ASSERT_TRUE(WriteFile(kLicense, *temp_path / "LICENSE").ok());
|
||||
ASSERT_TRUE(
|
||||
WriteFile(kLicense, *temp_path / "third_party" / "foobar" / "LICENSE")
|
||||
.ok());
|
||||
Repo repo;
|
||||
repo.Add("main.cc");
|
||||
repo.Add("LICENSE");
|
||||
repo.Add("third_party/foobar/foo.cc");
|
||||
repo.Add("third_party/foobar/LICENSE");
|
||||
ASSERT_TRUE(repo.Commit().ok());
|
||||
|
||||
std::stringstream ss;
|
||||
std::vector<absl::Status> errors =
|
||||
LicenseChecker::Run(temp_path->string(), ss, *data);
|
||||
EXPECT_EQ(errors.size(), 0u);
|
||||
|
||||
EXPECT_EQ(ss.str(), R"output(engine
|
||||
foobar
|
||||
|
||||
Test License
|
||||
v2.0
|
||||
)output");
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ int main(int argc, char** argv) {
|
||||
absl::SetGlobalVLogLevel(absl::GetFlag(FLAGS_v));
|
||||
|
||||
std::optional<std::string> working_dir = absl::GetFlag(FLAGS_working_dir);
|
||||
std::optional<std::string> data_dir = absl::GetFlag(FLAGS_working_dir);
|
||||
std::optional<std::string> data_dir = absl::GetFlag(FLAGS_data_dir);
|
||||
std::optional<std::string> licenses_path = absl::GetFlag(FLAGS_licenses_path);
|
||||
if (working_dir.has_value() && data_dir.has_value() &&
|
||||
licenses_path.has_value()) {
|
||||
@ -51,6 +51,10 @@ int main(int argc, char** argv) {
|
||||
std::cerr << "Expected --working_dir flag." << std::endl;
|
||||
}
|
||||
|
||||
if (!licenses_path.has_value()) {
|
||||
std::cerr << "Expected --licenses_path flag." << std::endl;
|
||||
}
|
||||
|
||||
if (!data_dir.has_value()) {
|
||||
std::cerr << "Expected --data_dir flag." << std::endl;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user