Compare commits

...

69 Commits

Author SHA1 Message Date
tastytea f57f3b578d
Fix typo in cmake options.
continuous-integration/drone/push Build is passing Details
2021-05-20 01:11:29 +02:00
tastytea f5dc5e2359
Update installation instructions for Gentoo. 2021-05-18 00:12:14 +02:00
tastytea e1c20bd1bd
Add repology badge. 2021-05-17 23:56:25 +02:00
tastytea 9caeab9b91
Add “commits” to usage info in manpage.
continuous-integration/drone/push Build is passing Details
2021-04-25 10:50:13 +02:00
tastytea aabd458e62
Version bump 0.7.0.
continuous-integration/drone/push Build is passing Details
2021-04-25 10:41:02 +02:00
tastytea a1850db226
Fix test for escape_some_html().
continuous-integration/drone/push Build is passing Details
2021-04-21 12:49:32 +02:00
tastytea 7438f878c2
Use hexadecimal instead of named HTML entities in replacements.
continuous-integration/drone/push Build is failing Details
See <https://www.rssboard.org/rss-profile#data-types-characterdata>.
2021-04-21 12:42:26 +02:00
tastytea 6a4e15df81
Cache only up to 10 minutes in nginx example.
continuous-integration/drone/push Build is passing Details
2021-04-21 12:34:37 +02:00
tastytea 82261aadfb
Escape some HTML in commit message.
continuous-integration/drone/push Build is passing Details
2021-04-21 12:31:04 +02:00
tastytea 23031b0dc9
commits: Replace newlines in commit message with <br>.
continuous-integration/drone/push Build is passing Details
2021-04-21 12:14:26 +02:00
tastytea f869ed9df2
Fix time conversion.
continuous-integration/drone/push Build is passing Details
2021-04-21 12:05:36 +02:00
tastytea 1e52e8edac
Add date to commit items. 2021-04-21 12:05:14 +02:00
tastytea 5cbbca2111
Add documentation for commits. 2021-04-21 11:13:20 +02:00
tastytea 6b08adce38
Add support for commits.
continuous-integration/drone/push Build is passing Details
Bug: #2
2021-04-21 11:03:39 +02:00
tastytea 98b6572b14
Don't call tags releases in RSS output. 2021-04-21 10:32:15 +02:00
tastytea f3b97151f1
Update .clang-format.. 2020-10-30 22:04:01 +01:00
tastytea a83a11d8e2
Add .editorconfig.
continuous-integration/drone/push Build is passing Details
2020-10-27 12:41:08 +01:00
tastytea c3fb4850ae
Add .clang-format. 2020-10-27 12:39:27 +01:00
tastytea 6dc9c1a740
Fix warning in test. 2020-10-27 12:38:14 +01:00
tastytea 9c99aafe87
Version bump 0.6.0.
continuous-integration/drone/push Build is passing Details
2020-10-27 12:19:31 +01:00
tastytea 089534e07d
Add link to release in RSS.
continuous-integration/drone/push Build is passing Details
Previously releases had no own page. Now they have.
2020-10-27 12:17:52 +01:00
tastytea 0bcad56590
Require CMake 3.12.
continuous-integration/drone/push Build is passing Details
2020-10-27 12:07:04 +01:00
tastytea c0eb7494e1
Use namespace, fix some warnings. 2020-10-27 12:05:50 +01:00
tastytea fa225ff8e7
Remove debug statement.
continuous-integration/drone/push Build is passing Details
Oops! 🤭
2020-10-24 20:56:41 +02:00
tastytea 82bbd03a2c
Update manpage.
continuous-integration/drone/push Build was killed Details
Highlight example URLs in DESCRIPTION, change proxy example to Tor.
2020-10-24 20:53:02 +02:00
tastytea 4a40cac16b
Add hyperlink to nginx example in readme.
continuous-integration/drone/push Build is passing Details
2020-10-24 20:36:45 +02:00
tastytea 257d6ff09b
Move nginx-example into doc/. 2020-10-24 20:33:31 +02:00
tastytea 15ee493084
Add caching to nginx example. 2020-10-24 20:30:46 +02:00
tastytea 8574da33a7
Update readme.
continuous-integration/drone/push Build is passing Details
2020-10-24 18:35:04 +02:00
tastytea 7839cd3658
CI: install catch.
continuous-integration/drone/push Build is passing Details
2020-10-24 17:34:16 +02:00
tastytea 0a1b9cfcaf
CI: Compile tests.
continuous-integration/drone/push Build is failing Details
2020-10-24 17:25:30 +02:00
tastytea d9d029b952
CI: Install GCC.
continuous-integration/drone/push Build is failing Details
2020-10-24 17:17:46 +02:00
tastytea 51f3c0b4df
Run tests in CI. 2020-10-24 17:17:09 +02:00
tastytea aec946c50f
Update tested compilers in readme. 2020-10-24 17:14:18 +02:00
tastytea 6ef00b689a
Reduce CI recipe.
continuous-integration/drone/push Build is failing Details
libcurl in Debian stretch is too old.
2020-10-24 17:13:04 +02:00
tastytea 953c1cf3e7
Replace POCO with CURL.
continuous-integration/drone/push Build is failing Details
2020-10-24 17:02:25 +02:00
tastytea 18a0edb30a
More debug flags. 2020-10-24 15:41:07 +02:00
tastytea d25fbccc9f
Set minimum CMake version to 3.6.
IMPORTED_TARGET from FindPkgConfig was introduced in 3.6.
2020-10-24 15:40:15 +02:00
tastytea 25cce227c1
CI: Install pkg-config.
continuous-integration/drone/push Build is passing Details
2020-05-01 20:37:44 +02:00
tastytea 8cee77f743
Version bump 0.5.2. 2020-05-01 20:31:45 +02:00
tastytea c67875b75c
Merge branch 'develop' 2020-05-01 20:31:06 +02:00
tastytea 5906db11da
Change jsoncpp discovery from CMake to pkg-config.
continuous-integration/drone/push Build is failing Details
CMake is deprecated by upstream.
2020-05-01 20:30:07 +02:00
tastytea 095645ba6e
Merge branch 'develop'
continuous-integration/drone/push Build is passing Details
2019-09-06 02:34:30 +02:00
tastytea d9d28dd707
Percent-decode proxy username and password.
continuous-integration/drone/push Build was killed Details
2019-08-25 05:05:36 +02:00
tastytea c19f5681a2
Use regex to extract proxy settings from environment variable.
continuous-integration/drone/push Build is passing Details
2019-08-25 04:22:32 +02:00
tastytea c7e36a7297
Fix path of jsoncpp headers.
continuous-integration/drone/push Build is passing Details
The prefix is set via CMake. By putting in it the source files too, we were
incompatible with distributions that put them somewhere else.
2019-08-12 19:52:31 +02:00
tastytea 31013f5192
Don't throw exception if environment variables are not set.
continuous-integration/drone/push Build is passing Details
2019-08-10 20:22:27 +02:00
tastytea babd67a750
Version bump 0.5.0.
continuous-integration/drone/push Build is passing Details
2019-08-09 23:25:05 +02:00
tastytea 9e8504a0f5
Updated example with proxy.
continuous-integration/drone/push Build is passing Details
2019-08-09 23:10:16 +02:00
tastytea e78d9cb346
Corrected link to manpage. 2019-08-09 23:07:45 +02:00
tastytea 76ab574e09
Updated drone config.
continuous-integration/drone/push Build is passing Details
2019-08-09 22:53:10 +02:00
tastytea 7b0920ee95
Switched from curlpp to POCO. 2019-08-09 22:38:28 +02:00
tastytea eee64c1f2d
Modernized CMake config. 2019-08-09 21:31:00 +02:00
tastytea 74b8e58bf6
Corrected Gentoo package category.
continuous-integration/drone/push Build is passing Details
2019-05-18 02:10:49 +02:00
tastytea 6fb470effa
typo 2019-04-29 10:59:24 +02:00
tastytea a3ce76cbc1
Converted drone config to new format.
continuous-integration/drone/push Build is passing Details
2019-04-28 18:40:44 +02:00
tastytea fb7c3beca8
Corrected Debian stretch dependency example.
the build was successful Details
2019-04-23 06:48:16 +02:00
tastytea 84f290cf8e
Updated example feed.
the build was successful Details
2019-04-22 13:49:25 +02:00
tastytea 820d1b8e17
Escape & in URLs.
the build was successful Details
2019-04-22 12:20:44 +02:00
tastytea 0e24f0433c
Removed useless test. 2019-04-22 11:40:02 +02:00
tastytea 4e62eb1fcc
Updated usage message.
the build was successful Details
2019-04-22 11:31:58 +02:00
tastytea 067fba7447
Rewrote escape_some_html() slightly and enhanced the test.
the build was successful Details
2019-04-22 11:16:44 +02:00
tastytea 6ff05f11ff
Added atom:link to own URL.
the build was successful Details
2019-04-22 09:59:24 +02:00
tastytea 13709efbba
Escape < and > in release descriptions.
the build was successful Details
Tiny Tiny RSS doesn't display them, even in <pre>.
2019-04-22 08:28:10 +02:00
tastytea d41b18183e
Added tests for get_http().
the build was successful Details
2019-04-21 10:54:07 +02:00
tastytea 8c21e93791
testlib for tests. 2019-04-21 10:51:14 +02:00
tastytea 79dab8bd17
Replaced checksum with commit.
the build was successful Details
2019-04-21 02:38:02 +02:00
tastytea 08690e30fa
Added tests for time.cpp.
the build was successful Details
strtime(time_point), strtime(string).
2019-04-20 13:25:45 +02:00
tastytea 97c7e20da7
Added tests for strings.cpp.
get_baseurl(), get_domain(), get_repo(), get_project().
2019-04-20 13:01:58 +02:00
32 changed files with 1154 additions and 433 deletions

131
.clang-format Normal file
View File

@ -0,0 +1,131 @@
# -*- mode: yaml -*-
# Written for clang-format 10.
# https://releases.llvm.org/10.0.0/tools/clang/docs/ClangFormatStyleOptions.html
---
DisableFormat: false
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
# AlignConsecutiveBitFields: false # clang-format 11
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: true # clang-format 11: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: false
# AllowShortEnumsOnASingleLine: false # clang-format 11
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BraceWrapping: # If BreakBeforeBraces is set to Custom.
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
# BeforeLambdaBody: true # clang-format 11
# BeforeWhile: true # clang-format 11
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ColumnLimit: 80
# CommentPragmas: 'regex'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
FixNamespaceComments: true
ForEachMacros:
- FOREACH
- RANGES_FOR
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Regroup
IncludeCategories: # stdlib headers into own group.
- Regex: '^[^\.]+$'
Priority: 4
# IndentCaseBlocks: false # clang-format 11
IndentCaseLabels: false
# IndentExternBlock: NoIndent # clang-format 11
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
# MacroBlockBegin: 'string'
# MacroBlockEnd: 'string'
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
# NamespaceMacros: 'string'
PenaltyBreakAssignment: 250
PenaltyBreakBeforeFirstCallParameter: 300
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
# RawStringFormats: # <YAML>
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 4
# TypenameMacros:
# - STACK_OF
# - LIST
UseCRLF: false
UseTab: Never
# WhitespaceSensitiveMacros: ['string', 'string'] # clang-format 11
...

View File

@ -1,192 +1,54 @@
pipeline:
gcc5:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-5
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- apt-get update -q
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- apt-get install -qy gnupg
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- apt-get update -q
- apt-get install -qy -t xenial g++-5
- apt-get install -qy cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
# -*- fill-column: 1000 -*-
kind: pipeline
name: on_push
gcc6:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-6
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- apt-get update -q
- apt-get install -qy g++-6 cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
volumes:
- name: debian-package-cache
host:
path: /var/cache/debian-package-cache
gcc7:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-7
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- apt-get update -q
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- apt-get install -qy gnupg
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- apt-get update -q
- apt-get install -qy -t xenial g++-7
- apt-get install -qy cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
trigger:
event:
exclude:
- tag
gcc8:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=g++-8
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- apt-get update -q
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" >> /etc/apt/sources.list.d/ubuntu-toolchain-r.list
- apt-get install -qy gnupg
- gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 0x60c317803a41ba51845e371a1e9377a2ba9ef27f
- gpg --armor --export 0x60c317803a41ba51845e371a1e9377a2ba9ef27f | apt-key add -
- apt-get update -q
- apt-get install -qy -t xenial g++-8
- apt-get install -qy cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
steps:
- name: GCC 8 / clang 7
image: debian:buster-slim
pull: always
environment:
CXX: g++-8
CXXFLAGS: -pipe -O2
LANG: en_US.utf-8
DEBIAN_FRONTEND: noninteractive
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- alias apt-get='rm -f /var/cache/apt/archives/lock && apt-get'
- apt-get update -q
- apt-get install -qq build-essential clang cmake pkg-config catch libcurl4-openssl-dev libjsoncpp-dev asciidoc
- rm -rf build && mkdir -p build && cd build
- cmake -DWITH_TESTS=yes ..
- cmake --build .
- cd tests && ctest -V
- cd ../../
- rm -rf build && mkdir -p build && cd build
- CXX="clang++" cmake -DWITH_TESTS=yes ..
- cmake --build .
- cd tests && ctest -V
- make install
volumes:
- name: debian-package-cache
path: /var/cache/apt/archives
clang3:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=clang++
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- apt-get update -q
- apt-get install -qy clang cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
clang5:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=clang++-5.0
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
- apt-get update -q
- apt-get install -qy -t stretch-backports clang-5.0
- apt-get install -qy cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
clang6:
image: debian:stretch-slim
pull: true
when:
event: [push, pull_request]
environment:
- LANG=C.utf8
- CXX=clang++-6.0
- CXXFLAGS=-pipe -O2
commands:
- rm /etc/apt/apt.conf.d/docker-clean
- echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
- echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
- echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list.d/stretch.list
- apt-get update -q
- apt-get install -qy -t stretch-backports clang-6.0
- apt-get install -qy cmake pkg-config
- apt-get install -qy libcurl4-openssl-dev libjsoncpp-dev asciidoc
- apt-get install -qy -t sid libcurlpp-dev
- rm -rf build && mkdir -p build && cd build
- cmake -DCMAKE_INSTALL_PREFIX=/usr ..
- make VERBOSE=1
volumes:
- /var/cache/debian-package-cache:/var/cache/apt/archives
notify:
image: drillster/drone-email
pull: true
host: cryptoparty-celle.de
secrets: [ email_username, email_password ]
- name: notify
image: drillster/drone-email
pull: always
settings:
host: mail.tzend.de
from: drone@tzend.de
when:
status: [ changed, failure ]
username:
from_secret: email_username
password:
from_secret: email_password
when:
status: [ changed, failure ]

20
.editorconfig Normal file
View File

@ -0,0 +1,20 @@
# Configuration file for EditorConfig.
# More information is available under <https://editorconfig.org/>.
root = true
[*]
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 80
[*.?pp]
indent_size = 4
tab_width = 4
[{CMakeLists.txt,*.cmake}]
indent_size = 2
tab_width = 2

View File

@ -1,51 +1,30 @@
cmake_minimum_required (VERSION 3.2)
project(gitea2rss
VERSION 0.4.2
LANGUAGES CXX
)
# IMPORTED target CURL::libcurl needs 3.12.
cmake_minimum_required(VERSION 3.12...3.18)
include(GNUInstallDirs)
find_package(PkgConfig REQUIRED)
pkg_check_modules(CURLPP REQUIRED curlpp)
pkg_check_modules(JSONCPP REQUIRED jsoncpp)
project(gitea2rss
VERSION 0.7.0
DESCRIPTION "Generates RSS feeds from Gitea releases or tags."
LANGUAGES CXX)
option(WITH_MAN "Compile and install manpage." YES)
option(WITH_TESTS "Compile tests." NO)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wpedantic -ftrapv \
-fsanitize=undefined -g -Og -fno-omit-frame-pointer")
include(cmake/debug_flags.cmake)
include_directories(${PROJECT_BINARY_DIR})
find_package(PkgConfig REQUIRED)
pkg_check_modules(jsoncpp REQUIRED IMPORTED_TARGET jsoncpp)
find_package(CURL 7.56 REQUIRED)
include_directories(${CURLPP_INCLUDE_DIRS})
include_directories(${JSONCPP_INCLUDE_DIRS})
add_subdirectory(src)
link_directories(${CURLPP_LIBRARY_DIRS})
link_directories(${JSONCPP_LIBRARY_DIRS})
# Write version in header
configure_file(
"${PROJECT_SOURCE_DIR}/src/version.hpp.in"
"${PROJECT_BINARY_DIR}/version.hpp"
)
file(GLOB sources src/*.cpp)
add_executable(${PROJECT_NAME} "${sources}")
target_link_libraries(${PROJECT_NAME} ${CURLPP_LIBRARIES} ${JSONCPP_LIBRARIES})
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
set(WITH_MAN "YES" CACHE STRING "WITH_MAN defaults to \"YES\"")
if (WITH_MAN)
add_custom_command(
OUTPUT "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.1"
WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
DEPENDS "${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.1.adoc"
COMMAND ${CMAKE_SOURCE_DIR}/build_manpage.sh
ARGS ${PROJECT_VERSION})
add_custom_target(run ALL DEPENDS "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.1")
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
add_subdirectory(man)
endif()
if(WITH_TESTS)
add_subdirectory(tests)
endif()

View File

@ -1,26 +1,28 @@
= gitea2rss
*gitea2rss* Generates RSS feeds from https://gitea.io[Gitea] releases or tags.
*gitea2rss* Generates RSS feeds from https://gitea.io[Gitea] releases, tags and
commits.
https://rss.schlomp.space/?repo=tastytea/gitea2rss[Subscribe to gitea2rss releases].
== Usage
See https://schlomp.space/tastytea/gitea2rss/src/branch/master/gitea2rss.1.adoc[manpage].
See https://schlomp.space/tastytea/gitea2rss/src/branch/master/man/gitea2rss.1.adoc[manpage].
For an example nginx configuration file, see https://schlomp.space/tastytea/gitea2rss/src/branch/master/doc/nginx-example.conf[nginx-example.conf].
== Install
[alt="Packaging status" link=https://repology.org/project/gitea2rss/versions]
image::https://repology.org/badge/vertical-allrepos/gitea2rss.svg[]
=== Gentoo
Add my https://schlomp.space/tastytea/overlay[repository] and install it from
there.
[source,shellsession]
[source,shell]
----
eselect repository enable tastytea
echo "dev-util/gitea2rss ~amd64" >> /etc/portage/package.accept_keywords/gitea2rss
emaint sync -r tastytea
emerge -a dev-util/gitea2rss
eselect repository enable guru
echo 'www-misc/gitea2rss' >> /etc/portage/package.accept_keywords/gitea2rss
emaint sync -r guru
emerge -a www-misc/gitea2rss
----
=== From source
@ -28,25 +30,19 @@ emerge -a dev-util/gitea2rss
==== Dependencies
* Tested OS: Linux
* C++ compiler (tested: https://gcc.gnu.org/[gcc] 5/6/7/8,
https://llvm.org/[clang] 3/5/6)
* https://cmake.org/[cmake] (at least: 3.6)
* https://pkgconfig.freedesktop.org/wiki/[pkgconfig] (tested: 0.29)
* http://www.curlpp.org/[curlpp] (tested: 0.8)
* C++ compiler (tested: https://gcc.gnu.org/[gcc] 8/9/10,
https://llvm.org/[clang] 7)
* https://cmake.org/[cmake] (at least: 3.12)
* https://curl.haxx.se/libcurl/[libcurl] (at least: 7.56)
* https://github.com/open-source-parsers/jsoncpp[jsoncpp] (tested: 1.8)
* Optional:
** Manpage: http://asciidoc.org/[asciidoc] (tested: 8.6)
===== Debian stretch
[source,shellsession]
[source,shell]
----
echo "APT::Default-Release \"stretch\";" >> /etc/apt/apt.conf.d/00default_release
echo "deb http://deb.debian.org/debian sid main" >> /etc/apt/sources.list.d/sid.list
apt-get update
apt-get install g++-6 cmake pkg-config libcurl4-openssl-dev libjsoncpp-dev asciidoc
apt-get install -t sid libcurlpp-dev
export CXX="g++-6"
apt install build-essential cmake libcurl4-openssl-dev libjsoncpp-dev asciidoc
----
==== Get sourcecode
@ -58,17 +54,16 @@ https://schlomp.space/tastytea/gitea2rss/releases[schlomp.space].
===== Development version
[source,shellsession]
[source,shell]
----
git clone https://schlomp.space/tastytea/gitea2rss.git
----
==== Compile
[source,shellsession]
[source,shell]
----
mkdir build
cd build/
mkdir build && cd build
cmake ..
cmake --build .
----
@ -76,14 +71,7 @@ cmake --build .
.cmake options:
* `-DCMAKE_BUILD_TYPE=Debug` for a debug build.
* `-DWITH_MAN=NO` to not compile the manpage.
* `-DWITH_TESTS=YES` to compile the tests.
Install with `make install`.
== Copyright
----
Copyright © 2019 tastytea <tastytea@tastytea.de>.
License GPLv3: GNU GPL version 3 <https://www.gnu.org/licenses/gpl-3.0.html>.
This program comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
----
You can run the tests with `ctest` inside `build/tests`. Install with `make
install`.

62
cmake/debug_flags.cmake Normal file
View File

@ -0,0 +1,62 @@
# Set compiler flags for Debug builds.
# Only has an effect on GCC/Clang >= 5.0.
set(tmp_CXXFLAGS "")
set(tmp_LDFLAGS "")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5")
list(APPEND tmp_CXXFLAGS
"-Wall"
"-Wextra"
"-Wpedantic"
"-Wuninitialized"
"-Wshadow"
"-Wnon-virtual-dtor"
"-Wconversion"
"-Wsign-conversion"
"-Wold-style-cast"
"-Wzero-as-null-pointer-constant"
"-Wmissing-declarations"
"-Wcast-align"
"-Wunused"
"-Woverloaded-virtual"
"-Wdouble-promotion"
"-Wformat=2"
"-ftrapv"
"-fsanitize=undefined"
"-Og"
"-fno-omit-frame-pointer")
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
list(APPEND tmp_CXXFLAGS
"-Wlogical-op"
"-Wuseless-cast")
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "6")
list(APPEND tmp_CXXFLAGS
"-Wmisleading-indentation"
"-Wduplicated-cond"
"-Wnull-dereference")
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "7")
list(APPEND tmp_CXXFLAGS
"-Wduplicated-branches")
endif()
endif()
endif()
add_compile_options("$<$<CONFIG:Debug>:${tmp_CXXFLAGS}>")
list(APPEND tmp_LDFLAGS
"-fsanitize=undefined")
# add_link_options was introduced in version 3.13.
if(${CMAKE_VERSION} VERSION_LESS 3.13)
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${tmp_LDFLAGS}")
else()
add_link_options("$<$<CONFIG:Debug>:${tmp_LDFLAGS}>")
endif()
else()
message(STATUS
"No additional compiler flags were set, "
"because your compiler was not anticipated.")
endif()
unset(tmp_CXXFLAGS)
unset(tmp_LDFLAGS)

View File

@ -1,24 +0,0 @@
# RSS feeds will be available at <https://rss.example.com/?repo=user/project>.
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name rss.example.com;
#access_log /var/log/nginx/rss.access_log main;
error_log /var/log/nginx/rss.error_log warn;
ssl_certificate /var/lib/dehydrated/certs/rss.example.com/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/rss.example.com/privkey.pem;
expires 1h;
location / {
include /etc/nginx/fastcgi_params;
# You may need to change fastcgi_pass.
fastcgi_pass unix:/var/run/cgi-fcgiwrap.socket-1;
fastcgi_param SCRIPT_FILENAME /usr/bin/gitea2rss;
# Base URL of your Gitea instance.
fastcgi_param GITEA2RSS_BASEURL "https://git.example.com";
}
}

34
doc/nginx-example.conf Normal file
View File

@ -0,0 +1,34 @@
# Use 100 MiB cache with a 1 MiB memory zone (enough for ~8,000 keys).
# Delete data that has not been accessed for 10 minutes.
fastcgi_cache_path /var/cache/nginx/gitea2rss levels=1:2 keys_zone=gitea2rss:1m
max_size=100m inactive=10m use_temp_path=off;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache $upstream_cache_status;
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name rss.example.com;
error_log /var/log/nginx/rss.example.com_log warn;
ssl_certificate /var/lib/dehydrated/certs/rss.example.com/fullchain.pem;
ssl_certificate_key /var/lib/dehydrated/certs/rss.example.com/privkey.pem;
# Tell clients to cache for 30 minutes.
expires 30m;
location / {
include /etc/nginx/fastcgi_params;
# You may need to change fastcgi_pass.
fastcgi_pass unix:/var/run/cgi-fcgiwrap.socket-1;
fastcgi_param SCRIPT_FILENAME /usr/bin/gitea2rss;
# Base URL of your Gitea instance.
fastcgi_param GITEA2RSS_BASEURL "https://git.example.com";
fastcgi_cache gitea2rss;
fastcgi_cache_valid 200 10m; # Cache answers for up to 10 minutes.
fastcgi_cache_lock on; # Relay only one identical request at a time.
}
}

14
man/CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
include(GNUInstallDirs)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.1"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPENDS "${PROJECT_NAME}.1.adoc"
COMMAND "${PROJECT_SOURCE_DIR}/man/build_manpage.sh"
ARGS "${PROJECT_VERSION}")
add_custom_target(man ALL
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.1")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)

View File

@ -3,7 +3,7 @@
name="gitea2rss"
if [ -n "${1}" ]; then
dir="$(dirname ${0})"
dir=$(dirname "${0}")
version=${1}
cp -vf "${dir}/${name}.1.adoc" .
sed -Ei "s/(Revision: +)[0-9]+\.[0-9]\.[0-9]/\1${version}/" "${name}.1.adoc"

View File

@ -2,7 +2,7 @@
:doctype: manpage
:Author: tastytea
:Email: tastytea@tastytea.de
:Date: 2019-04-20
:Date: 2021-04-25
:Revision: 0.0.0
:man source: gitea2rss
:man version: {revision}
@ -14,7 +14,7 @@ gitea2rss - Generates RSS feeds from Gitea releases or tags.
== SYNOPSIS
*gitea2rss* _URL of Gitea project_ [_releases_|_tags_]
*gitea2rss* _URL of Gitea project_ [_releases_|_tags_|_commits_]
== DESCRIPTION
@ -27,15 +27,13 @@ If you want to use gitea2rss as a CGI script, you have to set
*GITEA2RSS_BASEURL* to the basis URL of your instance, without the trailing
slash. For example: _https://git.example.com_. The *QUERY_STRING* must contain
_repo=user/project_. The feed-URL for alice's project, cooltool, would be:
`https://rss.example.com/?repo=alice/cooltool`. You can select the type of the
_https://rss.example.com/?repo=alice/cooltool_. You can select the type of the
feed by appending `&type=` at the end of the URL. For example:
`https://rss.example.com/?repo=alice/cooltool&type=tags`.
_https://rss.example.com/?repo=alice/cooltool&type=tags_.
The generated RSS feed contains the *channel* elements _title_, _link_,
_description_, _generator_ and _lastBuildDate_ and the *item* elements _title_,
_link_, _guid_, _pubDate_ and _description_. Since Gitea has no individual pages
for each release, _link_ elements in *item* are set to the overview page for
releases.
_link_, _guid_, _pubDate_ and _description_.
== GITEA INTEGRATION
@ -51,38 +49,41 @@ this in it:
href="https://rss.example.com/?repo={{.Repository.Owner.Name}}/{{.Repository.Name}}"/>
<link rel="alternate" type="application/rss+xml"
title="Tags of {{.Repository.Name}}"
href="https://rss.example.com/?repo={{.Repository.Owner.Name}}/{{.Repository.Name}}&type=tags"/>
href="https://rss.example.com/?repo={{.Repository.Owner.Name}}/{{.Repository.Name}}&amp;type=tags"/>
<link rel="alternate" type="application/rss+xml"
title="Commits of {{.Repository.Name}}"
href="https://rss.example.com/?repo={{.Repository.Owner.Name}}/{{.Repository.Name}}&amp;type=commits"/>
{{end}}
----
== PROXY SERVERS
Since gitea2rss is built on libcurl, it respects the same proxy environment
Since *gitea2rss* is built on libcurl, it respects the same proxy environment
variables. See *curl*(1), section _ENVIRONMENT_.
== EXAMPLES
`gitea2rss https://git.example.com/user/project tags > repo.rss`
`https_proxy="socks4a://user:pass@localhost:9050/" gitea2rss
https://git.example.com/user/project`
`ALL_PROXY="socks4a://[::1]:9050" gitea2rss https://git.example.com/user/project`
=== Example RSS feed
[source,xml]
----
<rss version="2.0">
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="https://rss.schlomp.space/?repo=tastytea/gitea2rss" rel="self" type="application/rss+xml"/>
<title>gitea2rss releases</title>
<link>https://schlomp.space/tastytea/gitea2rss</link>
<description>Releases of tastytea/gitea2rss</description>
<generator>gitea2rss 0.3.0</generator>
<lastBuildDate>Wed, 17 Apr 2019 20:31:15 +0200</lastBuildDate>
<description>List of releases of tastytea/gitea2rss</description>
<generator>gitea2rss 0.4.4</generator>
<lastBuildDate>Mon, 22 Apr 2019 11:46:53 +0000</lastBuildDate>
<item>
<title>gitea2rss: 0.1.0</title>
<link>https://schlomp.space/tastytea/gitea2rss/releases</link>
<guid isPermaLink="false">schlomp.space release 169</guid>
<pubDate>Wed, 17 Apr 2019 05:37:10 +0200</pubDate>
<pubDate>Wed, 17 Apr 2019 04:37:10 +0000</pubDate>
<description>
<![CDATA[<p><strong>Stable</strong></p>
<pre>First release. Everything works, as far as I can tell.</pre>

16
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
include(GNUInstallDirs)
# Write version in header
configure_file("version.hpp.in"
"${CMAKE_CURRENT_BINARY_DIR}/version.hpp")
file(GLOB sources *.cpp)
add_executable(${PROJECT_NAME} "${sources}" "gitea2rss.hpp")
target_include_directories(${PROJECT_NAME}
PRIVATE "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
target_link_libraries(${PROJECT_NAME}
PRIVATE PkgConfig::jsoncpp CURL::libcurl)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})

90
src/commits.cpp Normal file
View File

@ -0,0 +1,90 @@
/* This file is part of gitea2rss.
* Copyright © 2021 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <json/json.h>
#include <iostream>
#include <sstream>
namespace gitea2rss
{
using std::cerr;
using std::cout;
using std::endl;
using std::stringstream;
uint8_t write_commits(const string &url)
{
const string baseurl = get_baseurl(url);
const string repo = get_repo(url);
stringstream data(get_http(baseurl + "/api/v1/repos/" + repo + "/commits"));
if (cgi)
{
cout << endl;
}
if (data.str().empty())
{
cerr << "Error: Could not download commits.\n";
return 2;
}
write_preamble(url, "commits");
Json::Value json;
data >> json;
for (const Json::Value &commit : json)
{
const string sha = commit["sha"].asString();
string message = escape_some_html(
commit["commit"]["message"].asString());
const string title = message.substr(0, message.find('\n'));
{
size_t pos{};
while ((pos = message.find('\n')) != string::npos)
{
message.replace(pos, 1, "<br>");
}
}
const string commit_url = commit["html_url"].asString();
const string author = commit["commit"]["author"]["email"].asString()
+ " ("
+ commit["commit"]["author"]["name"].asString()
+ ")";
const string date = strtime(
commit["commit"]["author"]["date"].asString());
cout << " <item>\n";
write_line(6, "title", get_project(url) + ": " + title);
write_line(6, "link", commit_url);
write_line(6, "guid isPermaLink=\"false\"",
get_domain(url) + " commit " + sha);
write_line(6, "author", author);
write_line(6, "pubDate", date);
write_line(6, "description",
"\n <![CDATA[<p>" + message + "</p>]]>\n ");
cout << " </item>\n";
}
return 0;
}
} // namespace gitea2rss

24
src/gitea2rss.cpp Normal file
View File

@ -0,0 +1,24 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
namespace gitea2rss
{
bool cgi = false;
} // namespace gitea2rss

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019-2021 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,28 +17,34 @@
#ifndef GITEA2RSS_HPP
#define GITEA2RSS_HPP
#include <string>
#include <chrono>
#include <ctime>
#include <cstdint>
#include <ctime>
#include <string>
namespace gitea2rss
{
using std::string;
using std::chrono::system_clock;
using std::uint8_t;
using std::chrono::system_clock;
extern bool cgi;
//! Fetch HTTP document.
const string get_http(const string &url);
string get_http(const string &url);
// CURL receive function.
size_t writer_body(char *data, size_t size, size_t nmemb);
//! Convert time_point to RFC 822 compliant time string.
const string strtime(const system_clock::time_point &timepoint);
string strtime(const system_clock::time_point &timepoint);
//! Convert ISO 8601 time string to RFC 822 time string.
const string strtime(const string &time);
string strtime(const string &time);
//! Write line of XML.
void write_line(const uint8_t spaces, const string &tag, const string &value);
void write_line(uint8_t spaces, const string &tag, const string &value);
//! Write the RSS preamble and channel data.
void write_preamble(const string &url, const string &type);
@ -49,16 +55,27 @@ uint8_t write_releases(const string &url);
//! Write tags.
uint8_t write_tags(const string &url);
//! Write commits.
uint8_t write_commits(const string &url);
//! @brief Get the base URL, without trailing slash.
const string get_baseurl(const string &url);
string get_baseurl(const string &url);
//! Get the domain name.
const string get_domain(const string &url);
string get_domain(const string &url);
//! Get the full name of the repo (user/project).
const string get_repo(const string &url);
string get_repo(const string &url);
//! Get the project name.
const string get_project(const string &url);
string get_project(const string &url);
#endif // GITEA2RSS_HPP
//! Escape some characters to named HTML entities.
string escape_some_html(string html);
//! Return environment variable or "" if it is not set.
string get_env_var(const string &variable);
} // namespace gitea2rss
#endif // GITEA2RSS_HPP

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,61 +14,112 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sstream>
#include <iostream>
#include <exception>
#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>
#include <curlpp/Exception.hpp>
#include <curlpp/Infos.hpp>
#include "version.hpp"
#include "gitea2rss.hpp"
#include "version.hpp"
#include <curl/curl.h>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
namespace curlopts = curlpp::options;
using std::cout;
using std::cerr;
using std::endl;
using std::ostringstream;
using std::uint16_t;
const string get_http(const string &url)
namespace gitea2rss
{
string answer;
using std::cerr;
using std::cout;
using std::endl;
using std::runtime_error;
using std::to_string;
string buffer_body;
string get_http(const string &url)
{
try
{
ostringstream oss;
curlpp::Easy request;
request.setOpt<curlopts::UserAgent>(string("gitea2rss/")
+ global::version);
request.setOpt<curlopts::HttpHeader>({ "Connection: close" });
request.setOpt<curlopts::FollowLocation>(true);
request.setOpt<curlopts::Url>(url);
request.setOpt<curlopts::WriteStream>(&oss);
request.perform();
uint16_t ret = curlpp::infos::ResponseCode::get(request);
if (ret == 200 || ret == 302 || ret == 307
|| ret == 301 || ret == 308)
curl_global_init(CURL_GLOBAL_ALL); // NOLINT(hicpp-signed-bitwise)
CURL *connection{curl_easy_init()};
if (connection == nullptr)
{
answer = oss.str();
throw runtime_error{"Failed to initialize curl."};
}
else
char buffer_error[256];
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_setopt(connection, CURLOPT_ERRORBUFFER, buffer_error);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_setopt(connection, CURLOPT_WRITEFUNCTION, writer_body);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
CURLcode code{curl_easy_setopt(connection, CURLOPT_FOLLOWLOCATION, 1L)};
if (code != CURLE_OK)
{
if (cgi)
{
cout << "Status: " << std::to_string(ret) << endl;
}
cerr << "HTTP Error: " << std::to_string(ret) << endl;
throw runtime_error{"HTTP is not supported."};
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_setopt(connection, CURLOPT_MAXREDIRS, 5L);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
code = curl_easy_setopt(connection, CURLOPT_USERAGENT,
(string("gitea2rss/") += version).c_str());
if (code != CURLE_OK)
{
throw runtime_error{"Failed to set User-Agent."};
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_setopt(connection, CURLOPT_HTTPGET, 1L);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
code = curl_easy_setopt(connection, CURLOPT_URL, url.c_str());
if (code != CURLE_OK)
{
throw runtime_error{"Couldn't set URL: " + to_string(code)};
}
code = curl_easy_perform(connection);
if (code != CURLE_OK)
{
throw runtime_error{"libcurl error: " + to_string(code)};
}
long http_status{0}; // NOLINT(google-runtime-int)
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
curl_easy_getinfo(connection, CURLINFO_RESPONSE_CODE, &http_status);
curl_easy_cleanup(connection);
if (http_status == 200)
{
return buffer_body;
}
if (cgi)
{
cout << "Status: " << http_status << endl;
}
throw runtime_error{"HTTP error: " + to_string(http_status)};
}
catch (const std::exception &e)
catch (const runtime_error &e)
{
cerr << "Error: " << e.what() << endl;
}
return answer;
return "";
}
size_t writer_body(char *data, size_t size, size_t nmemb)
{
if (data == nullptr)
{
return 0;
}
buffer_body.append(data, size * nmemb);
return size * nmemb;
}
} // namespace gitea2rss

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019-2021 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,34 +14,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include "version.hpp"
#include <iostream>
#include <string>
#include <cstdlib>
#include <curlpp/cURLpp.hpp>
#include "version.hpp"
#include "gitea2rss.hpp"
using std::cout;
using std::cerr;
using std::endl;
using std::cout;
using std::string;
using std::chrono::system_clock;
bool cgi = false;
using namespace gitea2rss;
int main(int argc, char *argv[])
{
const char *envquery = std::getenv("QUERY_STRING");
const string query{get_env_var("QUERY_STRING")};
string url;
string type = "releases";
curlpp::initialize();
if (envquery != nullptr)
if (!query.empty())
{
const string query = envquery;
const char *envbaseurl = std::getenv("GITEA2RSS_BASEURL");
if (envbaseurl == nullptr)
const string baseurl{get_env_var("GITEA2RSS_BASEURL")};
if (baseurl.empty())
{
cout << "Status: 500 Internal Server Error\n\n";
cerr << "Error: GITEA2RSS_BASEURL not set\n";
@ -58,7 +52,7 @@ int main(int argc, char *argv[])
}
const size_t pos_repo = pos_found + 5;
const size_t pos_endrepo = query.find('&', pos_repo) - pos_repo;
url = string(envbaseurl) + "/" + query.substr(pos_repo, pos_endrepo);
url = string(baseurl) + "/" + query.substr(pos_repo, pos_endrepo);
// Look for type in QUERY_STRING.
pos_found = query.find("type=");
@ -72,14 +66,18 @@ int main(int argc, char *argv[])
}
else if (argc < 2)
{
cerr << "usage: " << argv[0] << " URL of Gitea project\n";
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
cerr << "usage: " << argv[0]
<< " URL of Gitea project [releases|tags|commits]\n";
return 1;
}
else
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
url = argv[1];
if (argc > 2)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
type = argv[2];
}
}
@ -93,6 +91,10 @@ int main(int argc, char *argv[])
{
ret = write_tags(url);
}
else if (type == "commits")
{
ret = write_commits(url);
}
if (ret != 0)
{
@ -100,9 +102,7 @@ int main(int argc, char *argv[])
}
cout << " </channel>\n"
"</rss>\n";
curlpp::terminate();
"</rss>\n";
return 0;
}

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,22 +14,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <sstream>
#include <jsoncpp/json/json.h>
#include "gitea2rss.hpp"
#include <iostream>
#include <json/json.h>
#include <sstream>
using std::cout;
using std::cerr;
using std::cout;
using std::endl;
using std::stringstream;
namespace gitea2rss
{
uint8_t write_releases(const string &url)
{
const string baseurl = get_baseurl(url);
const string repo = get_repo(url);
stringstream data(get_http(baseurl + "/api/v1/repos/"
+ repo + "/releases"));
stringstream data(
get_http(baseurl + "/api/v1/repos/" + repo + "/releases"));
if (cgi)
{
@ -50,21 +53,30 @@ uint8_t write_releases(const string &url)
{
const bool prerelease = release["prerelease"].asBool();
const string type = (prerelease ? "Pre-Release" : "Stable");
const string body = escape_some_html(release["body"].asString());
cout << " <item>\n";
write_line(6, "title", get_project(url) + ": "
+ release["name"].asString());
write_line(6, "link", baseurl + "/" + repo + "/releases");
write_line(6, "title",
get_project(url) + ": " + release["name"].asString());
write_line(6, "link",
((baseurl + "/" += repo) += "/releases/tag/") +=
release["tag_name"].asString());
write_line(6, "guid isPermaLink=\"false\"",
get_domain(url) + " release " + release["id"].asString());
write_line(6, "pubDate", strtime(release["published_at"].asString()));
write_line(6, "description",
"\n <![CDATA[<p><strong>" + type + "</strong></p>\n"
"<pre>" + release["body"].asString() + "</pre>\n"
" <p><a href=\"" + release["tarball_url"].asString()
+ "\">Download tarball</a></p>]]>\n ");
"\n <![CDATA[<p><strong>" + type
+ "</strong></p>\n"
"<pre>"
+ body
+ "</pre>\n"
" <p><a href=\""
+ release["tarball_url"].asString()
+ "\">Download tarball</a></p>]]>\n ");
cout << " </item>\n";
}
return 0;
}
} // namespace gitea2rss

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019-2021 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -16,26 +16,61 @@
#include "gitea2rss.hpp"
const string get_baseurl(const string &url)
#include <cstdlib>
#include <map>
#include <regex>
namespace gitea2rss
{
using std::getenv;
string get_baseurl(const string &url)
{
const size_t pos = url.find('/', 8);
return url.substr(0, pos);
}
const string get_domain(const string &url)
string get_domain(const string &url)
{
const string baseurl = get_baseurl(url);
return baseurl.substr(baseurl.rfind('/') + 1);
}
const string get_repo(const string &url)
string get_repo(const string &url)
{
const size_t pos = url.find('/', 8) + 1;
return url.substr(pos);
}
const string get_project(const string &url)
string get_project(const string &url)
{
const string repo = get_repo(url);
return repo.substr(repo.find('/') + 1);
}
string escape_some_html(string html)
{
const std::map<const char, const string> names = {{'<', "&#x3C;"},
{'>', "&#x3E;"}};
for (const auto &pair : names)
{
const std::regex re(string(1, pair.first));
html = std::regex_replace(html, re, pair.second);
}
return html;
}
string get_env_var(const string &variable)
{
const char *env{getenv(variable.c_str())};
if (env != nullptr)
{
return env;
}
return "";
}
} // namespace gitea2rss

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019-2021 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,13 +14,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <sstream>
#include <jsoncpp/json/json.h>
#include "gitea2rss.hpp"
using std::cout;
#include <json/json.h>
#include <iostream>
#include <sstream>
namespace gitea2rss
{
using std::cerr;
using std::cout;
using std::endl;
using std::stringstream;
@ -28,8 +33,8 @@ uint8_t write_tags(const string &url)
{
const string baseurl = get_baseurl(url);
const string repo = get_repo(url);
stringstream data(get_http(baseurl + "/api/v1/repos/"
+ repo + "/git/refs"));
stringstream data(
get_http(baseurl + "/api/v1/repos/" + repo + "/git/refs"));
if (cgi)
{
@ -42,7 +47,7 @@ uint8_t write_tags(const string &url)
return 2;
}
write_preamble(url, "releases");
write_preamble(url, "tags");
Json::Value json;
data >> json;
@ -59,18 +64,23 @@ uint8_t write_tags(const string &url)
cout << " <item>\n";
write_line(6, "title", get_project(url) + ": " + name);
write_line(6, "link", baseurl + "/" + repo + "/src/tag/" + name);
write_line(6, "link", baseurl + "/" += repo + "/src/tag/" += name);
write_line(6, "guid isPermaLink=\"false\"",
get_domain(url) + " tag " + sha);
write_line(6, "description",
"\n <![CDATA[<p><strong>" + name + "</strong> "
"with checksum " + sha + "</p>\n"
" <p><a href=\""
+ baseurl + "/" + repo + "/archive/" + name + ".tar.gz"
+ "\">Download tarball</a></p>]]>\n ");
"\n <![CDATA[<p><strong>" + name
+ "</strong> "
"on commit "
+ sha
+ "</p>\n"
" <p><a href=\""
+ baseurl + "/" + repo + "/archive/" + name + ".tar.gz"
+ "\">Download tarball</a></p>]]>\n ");
cout << " </item>\n";
}
return 0;
}
} // namespace gitea2rss

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,25 +14,49 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iomanip>
#include "gitea2rss.hpp"
const string strtime(const system_clock::time_point &timepoint)
#include <ctime>
#include <iomanip>
#include <string>
namespace gitea2rss
{
string strtime(const system_clock::time_point &timepoint)
{
constexpr uint16_t bufsize = 1024;
std::time_t time = system_clock::to_time_t(timepoint);
std::tm *tm;
tm = std::gmtime(&time);
std::tm *tm{std::gmtime(&time)};
char buffer[bufsize];
std::strftime(buffer, bufsize, "%a, %d %b %Y %T %z", tm);
return static_cast<const string>(buffer);
}
const string strtime(const string &time)
string strtime(const string &time)
{
// FIXME: Do this more elegantly.
std::tm tm = {};
tm.tm_isdst = -1; // Detect daylight saving time.
tm.tm_isdst = -1; // Detect daylight saving time.
std::stringstream ss(time);
ss >> std::get_time(&tm, "%Y-%m-%dT%T"); // Assume time is UTC.
return strtime(system_clock::from_time_t(timegm(&tm)));
ss >> std::get_time(&tm, "%Y-%m-%dT%T");
std::time_t time_tmp = timegm(&tm);
constexpr size_t zone_start = 19;
if (time[zone_start] == '+')
{
string zone = time.substr(zone_start + 1);
time_tmp -= std::stol(zone.substr(0, 2)) * 60 * 60;
time_tmp -= std::stol(zone.substr(3)) * 60;
}
else if (time[zone_start] == '+')
{
string zone = time.substr(zone_start + 1);
time_tmp += std::stol(zone.substr(0, 2)) * 60 * 60;
time_tmp += std::stol(zone.substr(3)) * 60;
}
return strtime(system_clock::from_time_t(time_tmp));
}
} // namespace gitea2rss

View File

@ -1,9 +1,11 @@
#ifndef VERSION_HPP
#define VERSION_HPP
namespace global
namespace gitea2rss
{
static constexpr char version[] = "@PROJECT_VERSION@";
}
static constexpr char version[] = "@PROJECT_VERSION@";
} // namespace gitea2rss
#endif // VERSION_HPP

View File

@ -1,5 +1,5 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,9 +14,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include "version.hpp"
#include "gitea2rss.hpp"
#include "version.hpp"
#include <cstdlib>
#include <iostream>
#include <regex>
namespace gitea2rss
{
using std::cout;
@ -41,12 +46,38 @@ void write_line(const uint8_t spaces, const string &tag, const string &value)
void write_preamble(const string &url, const string &type)
{
cout << "<rss version=\"2.0\">\n"
" <channel>\n";
const string request_uri{get_env_var("REQUEST_URI")};
const string server_name{get_env_var("SERVER_NAME")};
const string https{get_env_var("HTTPS")};
string selfurl;
if (!request_uri.empty() && !server_name.empty())
{
if (https == "on")
{
selfurl = "https://";
}
else
{
selfurl = "http://";
}
selfurl += string(server_name) + request_uri;
selfurl = std::regex_replace(selfurl, std::regex("&"), "&amp;");
}
cout << "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n"
" <channel>\n";
if (cgi)
{
cout << " <atom:link href=\"" + selfurl
+ "\" rel=\"self\" type=\"application/rss+xml\"/>\n";
}
write_line(4, "title", get_project(url) + " " + type);
write_line(4, "link", url);
write_line(4, "description", "List of " + type + " of " + get_repo(url));
write_line(4, "generator", string("gitea2rss ") + global::version);
write_line(4, "generator", string("gitea2rss ") + version);
write_line(4, "lastBuildDate", strtime(system_clock::now()));
}
} // namespace gitea2rss

38
tests/CMakeLists.txt Normal file
View File

@ -0,0 +1,38 @@
include(CTest)
file(GLOB sources_testlib ../src/*.cpp)
add_library(${PROJECT_NAME}_testlib SHARED ${sources_testlib})
target_include_directories(${PROJECT_NAME}_testlib
PUBLIC
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>"
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/src>")
target_link_libraries(${PROJECT_NAME}_testlib
PRIVATE CURL::libcurl PkgConfig::jsoncpp)
file(GLOB sources_tests test_*.cpp)
find_package(Catch2 CONFIG)
if(Catch2_FOUND) # Catch 2.x
include(Catch)
add_executable(all_tests main.cpp ${sources_tests})
target_link_libraries(all_tests
PRIVATE Catch2::Catch2 ${PROJECT_NAME}_testlib)
target_include_directories(all_tests PRIVATE "/usr/include/catch2")
catch_discover_tests(all_tests EXTRA_ARGS "${EXTRA_TEST_ARGS}")
else() # Catch 1.x
if(EXISTS "/usr/include/catch.hpp")
message(STATUS "Catch 1.x found.")
foreach(src ${sources_tests})
get_filename_component(bin ${src} NAME_WE)
add_executable(${bin} main.cpp ${src})
target_link_libraries(${bin}
PRIVATE ${PROJECT_NAME}_testlib)
add_test(${bin} ${bin} "${EXTRA_TEST_ARGS}")
endforeach()
else()
message(FATAL_ERROR
"Neither Catch 2.x nor Catch 1.x could be found.")
endif()
endif()

19
tests/main.cpp Normal file
View File

@ -0,0 +1,19 @@
/* This file is part of gitea2rss.
* Copyright © 2019 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define CATCH_CONFIG_MAIN
#include <catch.hpp>

View File

@ -0,0 +1,39 @@
/* This file is part of gitea2rss.
* Copyright © 2019-2021 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("escape_some_html() works as expected", "[strings]")
{
WHEN("String with escape-able characters")
{
const string escaped = escape_some_html("<p><small>.</small></p>");
THEN("The HTML is escaped")
{
REQUIRE(escaped
== "&#x3C;p&#x3E;&#x3C;small&#x3E;.&#x3C;/"
"small&#x3E;&#x3C;/p&#x3E;");
}
}
}

View File

@ -0,0 +1,47 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("get_baseurl() works as expected", "[strings]")
{
WHEN("HTTPS URL")
{
const string baseurl =
get_baseurl("https://git.example.com/user/project");
THEN("The base URL is correctly returned")
{
REQUIRE(baseurl == "https://git.example.com");
}
}
WHEN("HTTP URL")
{
const string baseurl =
get_baseurl("http://git.example.com/user/project");
THEN("The base URL is correctly returned")
{
REQUIRE(baseurl == "http://git.example.com");
}
}
}

36
tests/test_get_domain.cpp Normal file
View File

@ -0,0 +1,36 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("get_domain() works as expected", "[strings]")
{
WHEN("HTTPS URL is valid")
{
const string domain =
get_domain("https://git.example.com/user/project");
THEN("The domain is correctly returned")
{
REQUIRE(domain == "git.example.com");
}
}
}

45
tests/test_get_http.cpp Normal file
View File

@ -0,0 +1,45 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("get_http() works as expected", "[http]")
{
WHEN("URL is valid")
{
const string answer = get_http("https://ip.tastytea.de/");
THEN("Answer is not empty")
{
REQUIRE(!answer.empty());
}
}
WHEN("URL is invalid")
{
const string answer = get_http("https://url.invalid/");
THEN("Answer is empty")
{
REQUIRE(answer.empty());
}
}
}

View File

@ -0,0 +1,36 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("get_project() works as expected", "[strings]")
{
WHEN("HTTPS URL is valid")
{
const string project =
get_project("https://git.example.com/user/project");
THEN("The project is correctly returned")
{
REQUIRE(project == "project");
}
}
}

35
tests/test_get_repo.cpp Normal file
View File

@ -0,0 +1,35 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("get_repo() works as expected", "[strings]")
{
WHEN("HTTPS URL is valid")
{
const string repo = get_repo("https://git.example.com/user/project");
THEN("The repo is correctly returned")
{
REQUIRE(repo == "user/project");
}
}
}

47
tests/test_strtime.cpp Normal file
View File

@ -0,0 +1,47 @@
/* This file is part of gitea2rss.
* Copyright © 2019, 2020 tastytea <tastytea@tastytea.de>
*
* This program 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, version 3.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "gitea2rss.hpp"
#include <catch.hpp>
#include <chrono>
#include <string>
using std::string;
using namespace gitea2rss;
SCENARIO("strtime() works as expected", "[time]")
{
GIVEN("Time as time_point")
{
std::chrono::system_clock::time_point tp;
const string time = strtime(tp);
THEN("The time is returned in the correct format")
{
REQUIRE(time == "Thu, 01 Jan 1970 00:00:00 +0000");
}
}
GIVEN("Time as ISO 8601 string")
{
const string time = strtime("1970-01-01T00:00:00+0000");
THEN("The time is returned in the correct format")
{
REQUIRE(time == "Thu, 01 Jan 1970 00:00:00 +0000");
}
}
}