forked from aseprite/laf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
267 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Based on SerenityOS commit linter: | ||
# https://github.com/SerenityOS/serenity/blob/master/.github/workflows/lintcommits.yml | ||
|
||
name: Commit linter | ||
on: [pull_request_target] | ||
jobs: | ||
lint_commits: | ||
runs-on: ubuntu-22.04 | ||
if: always() && github.repository == 'aseprite/laf' | ||
steps: | ||
- name: Lint PR commits | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
const rules = [ | ||
{ | ||
pattern: /^[^\r]*$/, | ||
error: "Commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)", | ||
}, | ||
{ | ||
pattern: /^.+(\r?\n(\r?\n.*)*)?$/, | ||
error: "Empty line between commit title and body is missing", | ||
}, | ||
{ | ||
pattern: /^.{0,72}(?:\r?\n(?:(.{0,72})|(.*?([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&/=]|-)+).*?))*$/, | ||
error: "Commit message lines are too long (maximum allowed is 72 characters, except for URLs)", | ||
}, | ||
{ | ||
pattern: /^.+[^.\n](\r?\n.*)*$/, | ||
error: "Commit title ends in a period", | ||
}, | ||
{ | ||
pattern: /^((?!Signed-off-by: )[\s\S])*$/, | ||
error: "Commit body contains a Signed-off-by tag", | ||
}, | ||
]; | ||
const { repository, pull_request } = context.payload; | ||
// NOTE: This maxes out at 250 commits. If this becomes a problem, see: | ||
// https://octokit.github.io/rest.js/v18#pulls-list-commits | ||
const opts = github.rest.pulls.listCommits.endpoint.merge({ | ||
owner: repository.owner.login, | ||
repo: repository.name, | ||
pull_number: pull_request.number, | ||
}); | ||
const commits = await github.paginate(opts); | ||
const errors = []; | ||
for (const { sha, commit: { message } } of commits) { | ||
const commitErrors = []; | ||
for (const { pattern, error } of rules) { | ||
if (!pattern.test(message)) { | ||
commitErrors.push(error); | ||
} | ||
} | ||
if (commitErrors.length > 0) { | ||
const title = message.split("\n")[0]; | ||
errors.push([`${title} (${sha}):`, ...commitErrors].join("\n ")); | ||
} | ||
} | ||
if (errors.length > 0) { | ||
core.setFailed(`One or more of the commits in this PR do not match the code submission policy:\n\n${errors.join("\n")}`); | ||
} | ||
- name: Comment on PR | ||
if: ${{ failure() && !github.event.pull_request.draft }} | ||
uses: unsplash/comment-on-pr@a9bf050e744c8282dee4bb0dbcf063186d8316c4 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.LINT_COMMIT_TOKEN }} | ||
with: | ||
msg: "Hi there!\n\nOne or more of the commit messages in this PR do not match our [code submission policy](https://github.com/aseprite/laf/blob/main/CONTRIBUTING.md), please check the `lint_commits` CI job for more details on which commits were flagged and why.\nPlease do not close this PR and open another, instead modify your commit message(s) with [git commit --amend](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message) and force push those changes to update this PR." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,25 @@ | ||
# Licensing | ||
|
||
By submitting a pull request, you represent that you have the right to | ||
license your contribution to the Laf project owners and the community, | ||
agree by submitting the patch that your contributions are licensed | ||
and agree by submitting the patch that your contributions are licensed | ||
under the [MIT license](https://raw.githubusercontent.com/aseprite/laf/main/LICENSE.txt) | ||
terms. | ||
|
||
# Code submission policy | ||
|
||
We have some rules for commits that are contributed: | ||
|
||
* Split your changes in the most atomic commits possible: one commit | ||
for feature, or fix. | ||
* Rebase your commits to the `main` branch (or `beta` if you are | ||
targeting the beta version). | ||
* Wrap your commit messages at 72 characters. | ||
* The first line of the commit message is the subject line. | ||
* Write the subject line in the imperative mood, e.g. "Fix something", | ||
not "Fixed something". | ||
* For platform-specific commits start the subject line using | ||
`[win]`, `[osx]`, or `[x11]` prefixes. | ||
* Check the spelling of your code, comments and commit messages. | ||
* We're using some C++17 features, targeting macOS 10.9 mainly as the | ||
oldest platform (and the one limiting us to newer C++ standards). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// LAF Base Library | ||
// Copyright (c) 2024 Igara Studio S.A. | ||
// Copyright (c) 2020 David Capello | ||
// | ||
// This file is released under the terms of the MIT license. | ||
// Read LICENSE.txt for more information. | ||
// | ||
// Based on https://github.com/dacap/tok | ||
|
||
#ifndef BASE_TOK_H_INCLUDED | ||
#define BASE_TOK_H_INCLUDED | ||
#pragma once | ||
|
||
#include <iterator> | ||
#include <string> | ||
|
||
namespace base { | ||
namespace tok { | ||
|
||
struct ignore_empties { enum { allow_empty = false }; }; | ||
struct include_empties { enum { allow_empty = true }; }; | ||
|
||
template<typename T, typename EmptyPolicy> | ||
class token_iterator { | ||
public: | ||
using iterator_category = std::forward_iterator_tag; | ||
using internal_iterator = typename T::const_iterator; | ||
using char_type = typename T::value_type; | ||
using value_type = typename std::remove_const<T>::type; | ||
using difference_type = typename T::difference_type; | ||
using pointer = T*; | ||
using reference = T&; | ||
using const_reference = const T&; | ||
|
||
token_iterator() = delete; | ||
token_iterator(const token_iterator&) = default; | ||
token_iterator(const internal_iterator& begin, | ||
const internal_iterator& end, | ||
char_type chr) : | ||
begin_(begin), | ||
inter_(begin), | ||
end_(end), | ||
chr_(chr) { | ||
operator++(); // Find first word to fill "str_" field | ||
} | ||
|
||
token_iterator& operator++() { | ||
if constexpr (EmptyPolicy::allow_empty) { | ||
if (inter_ != end_ && *inter_ == chr_) { | ||
++inter_; | ||
} | ||
} | ||
else { | ||
while (inter_ != end_ && *inter_ == chr_) { | ||
++inter_; | ||
} | ||
} | ||
begin_ = inter_; | ||
while (inter_ != end_ && *inter_ != chr_) { | ||
++inter_; | ||
} | ||
str_.assign(begin_, inter_); | ||
return *this; | ||
} | ||
|
||
const_reference operator*() { | ||
return str_; | ||
} | ||
|
||
bool operator!=(const token_iterator& that) const { | ||
return (begin_ != that.end_); | ||
} | ||
|
||
private: | ||
internal_iterator begin_, inter_, end_; | ||
char_type chr_; | ||
value_type str_; | ||
}; | ||
|
||
template<typename T, typename Empties> | ||
class token_range { | ||
public: | ||
using char_type = typename T::value_type; | ||
using iterator = token_iterator<T, Empties>; | ||
|
||
token_range(const T& str, char_type chr) : str_(str), chr_(chr) { } | ||
|
||
iterator begin() const { return iterator(str_.begin(), str_.end(), chr_); } | ||
iterator end() const { return iterator(str_.end(), str_.end(), chr_); } | ||
|
||
private: | ||
const T& str_; | ||
char_type chr_; | ||
}; | ||
|
||
template<typename T> | ||
token_range<T, ignore_empties> | ||
split_tokens(const T& str, | ||
typename T::value_type chr) { | ||
return token_range<T, ignore_empties>(str, chr); | ||
} | ||
|
||
template<typename T> | ||
token_range<T, include_empties> | ||
csv(const T& str, | ||
typename T::value_type chr = ',') { | ||
return token_range<T, include_empties>(str, chr); | ||
} | ||
|
||
} // namespace tok | ||
} // namespace base | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// LAF Base Library | ||
// Copyright (c) 2024 Igara Studio S.A. | ||
// Copyright (c) 2020 David Capello | ||
// | ||
// This file is released under the terms of the MIT license. | ||
// Read LICENSE.txt for more information. | ||
// | ||
// Based on https://github.com/dacap/tok | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "base/tok.h" | ||
|
||
TEST(Tok, SplitTokens) | ||
{ | ||
int i = 0; | ||
auto a_result = std::vector<std::string>{ "This", "is", "a", "phrase.", "Several", "whitespaces", "are", "ignored." }; | ||
std::string a = "This is a phrase. Several whitespaces are ignored."; | ||
for (auto& tok : base::tok::split_tokens(a, ' ')) { | ||
std::cout << "\"" << tok << "\"\n"; | ||
EXPECT_EQ(tok, a_result[i++]); | ||
} | ||
} | ||
|
||
TEST(Tok, Csv) | ||
{ | ||
int i = 0; | ||
auto b_result = std::vector<std::string>{ "In comma", "separated", "", "values", "", "", "empties are included" }; | ||
std::string b = "In comma,separated,,values,,,empties are included"; | ||
for (auto& tok : base::tok::csv(b, ',')) { | ||
std::cout << "\"" << tok << "\"\n"; | ||
EXPECT_EQ(tok, b_result[i++]); | ||
} | ||
} | ||
|
||
int main(int argc, char** argv) | ||
{ | ||
::testing::InitGoogleTest(&argc, argv); | ||
return RUN_ALL_TESTS(); | ||
} |