Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82e019a4a8 | ||
|
|
9180aa6e33 | ||
|
|
32d837fb25 | ||
|
|
395b08385b | ||
|
|
9cc9e19757 | ||
|
|
c07d74574d | ||
|
|
73401664b6 | ||
|
|
d052b8752d | ||
|
|
68d9e3bb5e | ||
|
|
86837022d3 | ||
|
|
e831f85823 | ||
|
|
4b839f2c83 | ||
|
|
1e1bd32c42 | ||
|
|
880ab5d665 | ||
|
|
ef583dedea | ||
|
|
1bd26fe9ab | ||
|
|
80c01f3ffb | ||
|
|
7cd42b5d2f | ||
|
|
1b218d68f5 | ||
|
|
e6031183dd | ||
|
|
f9bcb8cfc8 | ||
|
|
2ef0214248 | ||
|
|
0a62061ca8 | ||
|
|
5d96547c07 | ||
|
|
eb3afa1fdc | ||
|
|
885ff46066 | ||
|
|
5a060802e7 | ||
|
|
acce2d5a68 | ||
|
|
adac566665 | ||
|
|
f454eecafb | ||
|
|
f83702076b | ||
|
|
83519a44c6 | ||
|
|
a2e980c6b8 | ||
|
|
e00704a375 | ||
|
|
8fb3161a02 | ||
|
|
fa528beb58 | ||
|
|
c5a2b7f759 | ||
|
|
4213afd408 | ||
|
|
8ad0c1172e | ||
|
|
f887173bf7 | ||
|
|
328b7ec260 | ||
|
|
ab41e005c9 | ||
|
|
bd785ffad5 | ||
|
|
3cce6c23f5 | ||
|
|
ec919a8677 | ||
|
|
5911286218 | ||
|
|
9e49325d6e | ||
|
|
c483c8dda9 | ||
|
|
2d2579d801 | ||
|
|
4f6c51e7ae | ||
|
|
cd6808ab15 | ||
|
|
8b648bc690 | ||
|
|
9a0a6188b1 | ||
|
|
b79453afa7 | ||
|
|
60dddffda3 | ||
|
|
e8dc5a16a1 | ||
|
|
528e72062b | ||
|
|
876820ee1a | ||
|
|
8e730f2da3 | ||
|
|
8b28c36485 | ||
|
|
04be198281 | ||
|
|
1b69ac6ad2 | ||
|
|
b1081bd510 | ||
|
|
a72322b9db | ||
|
|
82e6574d30 | ||
|
|
1f14454be7 | ||
|
|
384ca82292 | ||
|
|
066143d939 | ||
|
|
e845a25ea6 | ||
|
|
75a2b11638 | ||
|
|
6a3edc88a1 | ||
|
|
bb3555f217 | ||
|
|
5de80eedeb | ||
|
|
10c1b5f902 | ||
|
|
049ed04471 | ||
|
|
3ff42af9c7 | ||
|
|
1cfdfbae52 | ||
|
|
61291e4d1e | ||
|
|
77ec56dcd0 | ||
|
|
d0f74c4a80 | ||
|
|
4bdee56fa7 | ||
|
|
8323407242 | ||
|
|
6626207ad1 | ||
|
|
4865269630 | ||
|
|
8683574b18 | ||
|
|
5e90510530 | ||
|
|
a8bab90c34 | ||
|
|
87c2a9b5a5 | ||
|
|
cba5948a1d | ||
|
|
f4a6ec6f97 | ||
|
|
a3490966c0 | ||
|
|
855537b975 | ||
|
|
473019c1f0 | ||
|
|
d1698eab2d | ||
|
|
73b7b21b81 | ||
|
|
44f2c0c98c | ||
|
|
654159b2fd | ||
|
|
67cb30fdce | ||
|
|
7d75547f44 | ||
|
|
d68fa7ea8a | ||
|
|
db78851b40 | ||
|
|
6fdf0738a7 | ||
|
|
41003fc78b | ||
|
|
d2928dc4e4 | ||
|
|
61deb7ce7e | ||
|
|
0311ea6689 | ||
|
|
0b0ddbfbc4 | ||
|
|
cd31335742 | ||
|
|
5a3037f257 | ||
|
|
a22d173b9b | ||
|
|
134d201cb0 | ||
|
|
547d9edb55 | ||
|
|
cdde747733 | ||
|
|
588009d679 | ||
|
|
adf9f25289 | ||
|
|
ea0397f542 | ||
|
|
411fab3a27 | ||
|
|
da6a57b203 | ||
|
|
235e4ef047 | ||
|
|
1dbb0a57a8 | ||
|
|
5a7117630e | ||
|
|
e9f9f6a86e | ||
|
|
8ea1563944 | ||
|
|
e522c1980a | ||
|
|
845fe047cc | ||
|
|
5932d9f90b | ||
|
|
a8ff7655ef | ||
|
|
79cc9d8ed9 | ||
|
|
b83dc8a29e | ||
|
|
99ebf82c3a | ||
|
|
231e8ca913 | ||
|
|
9bd9a3b285 | ||
|
|
b882cd151e | ||
|
|
a3b0d5c6a6 | ||
|
|
d1664b3f55 | ||
|
|
1cac14f3f8 | ||
|
|
507e2d5807 | ||
|
|
c664d62c2f | ||
|
|
f32c4d1f73 | ||
|
|
9bf7dfda4f | ||
|
|
2a782b8f01 | ||
|
|
3c07510a43 | ||
|
|
07eff0f3c1 | ||
|
|
dad0ac0c27 | ||
|
|
2c986d6e6b | ||
|
|
1e8f83cab9 | ||
|
|
15f00452c2 | ||
|
|
6a3b13dbfc | ||
|
|
8180b94b1b | ||
|
|
6aafa9f04e | ||
|
|
fe07f62214 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@ cmake.h
|
||||
commit.h
|
||||
Makefile
|
||||
src/task
|
||||
src/taskd
|
||||
src/libtask.a
|
||||
src/commands/libcommands.a
|
||||
src/columns/libcolumns.a
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -13,6 +13,7 @@ contributions of the following people:
|
||||
Louis-Claude Canon (Contributing Author)
|
||||
Scott Kostyshak (Contributing Author)
|
||||
Renato Alves (Contributing Author)
|
||||
Tomas Babej (Contributing Author)
|
||||
|
||||
The following submitted code, packages or analysis, and deserve special thanks:
|
||||
|
||||
@@ -112,6 +113,8 @@ The following submitted code, packages or analysis, and deserve special thanks:
|
||||
Jeremy John Reeder
|
||||
Roman Inflianskas
|
||||
Łukasz Panek
|
||||
V.Krishn
|
||||
Jens Erat
|
||||
|
||||
Thanks to the following, who submitted detailed bug reports and excellent
|
||||
suggestions:
|
||||
@@ -233,10 +236,12 @@ suggestions:
|
||||
dev-zero
|
||||
Petteri
|
||||
Black Ops Testing
|
||||
Jens Erat
|
||||
Leon Feng
|
||||
Tomas Babej
|
||||
Nick Person
|
||||
Arnoud K
|
||||
Ozgur Akgun
|
||||
David Costa
|
||||
Sujeevan Vijayakumaran
|
||||
Scott Carter
|
||||
Taisuke Hachimura
|
||||
Martin
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
|
||||
if(POLICY CMP0037)
|
||||
cmake_policy(SET CMP0037 OLD)
|
||||
endif()
|
||||
|
||||
include (CheckFunctionExists)
|
||||
include (CheckStructHasMember)
|
||||
@@ -7,12 +10,17 @@ include (CheckStructHasMember)
|
||||
set (HAVE_CMAKE true)
|
||||
|
||||
project (task)
|
||||
set (PROJECT_VERSION "2.4.0")
|
||||
set (PROJECT_VERSION "2.4.1")
|
||||
|
||||
OPTION(USE_GNUTLS "Build gnutls support." ON)
|
||||
|
||||
message ("CMAKE_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set (LINUX true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set (DARWIN true)
|
||||
set (CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++")
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
|
||||
set (KFREEBSD true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
@@ -25,6 +33,9 @@ elseif (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
set (SOLARIS true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "GNU")
|
||||
set (GNUHURD true)
|
||||
elseif (${CMAKE_SYSTEM_NAME} STREQUAL "CYGWIN")
|
||||
set (CYGWIN true)
|
||||
set (CMAKE_CXX_FLAGS "-std=gnu++0x")
|
||||
else (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set (UNKNOWN true)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
@@ -65,13 +76,15 @@ set (PACKAGE_TARNAME "${PACKAGE}")
|
||||
set (PACKAGE_VERSION "${VERSION}")
|
||||
set (PACKAGE_STRING "${PACKAGE} ${VERSION}")
|
||||
|
||||
message ("-- Looking for GnuTLS")
|
||||
find_package (GnuTLS)
|
||||
if (GNUTLS_FOUND)
|
||||
set (HAVE_LIBGNUTLS true)
|
||||
set (TASK_INCLUDE_DIRS ${TASK_INCLUDE_DIRS} ${GNUTLS_INCLUDE_DIR})
|
||||
set (TASK_LIBRARIES ${TASK_LIBRARIES} ${GNUTLS_LIBRARIES})
|
||||
endif (GNUTLS_FOUND)
|
||||
if (USE_GNUTLS)
|
||||
message ("-- Looking for GnuTLS")
|
||||
find_package (GnuTLS)
|
||||
if (GNUTLS_FOUND)
|
||||
set (HAVE_LIBGNUTLS true)
|
||||
set (TASK_INCLUDE_DIRS ${TASK_INCLUDE_DIRS} ${GNUTLS_INCLUDE_DIR})
|
||||
set (TASK_LIBRARIES ${TASK_LIBRARIES} ${GNUTLS_LIBRARIES})
|
||||
endif (GNUTLS_FOUND)
|
||||
endif (USE_GNUTLS)
|
||||
|
||||
#message ("-- Looking for pthread")
|
||||
#find_path (PTHREAD_INCLUDE_DIR pthread.h)
|
||||
|
||||
58
ChangeLog
58
ChangeLog
@@ -1,10 +1,60 @@
|
||||
2.4.0 (2015-01-01) -
|
||||
2.4.1 (2015-02-16) -
|
||||
|
||||
- TW-1457 Non-existent attributes are not properly handled (thanks to Tomas
|
||||
Babej).
|
||||
- TW-1484 The 'history' and 'ghistory' reports do not obey rc.color.label.
|
||||
- TW-1486 task wait shows completed tasks which has a wait attribute (thanks to
|
||||
Sujeevan Vijayakumaran).
|
||||
- TW-1487 Task export exports some numeric attributes as strings (thanks to
|
||||
Tomas Babej).
|
||||
- TW-1491 Regression in deleting due dates (thanks to Jens Erat).
|
||||
- TW-1492 compiling v2.4.0 using musl(libc) (thanks to V.Krishn).
|
||||
- TW-1495 German translation for taskwarrior (thanks to Jens Erat).
|
||||
- TW-1498 Filtering for presence of UDA matches all tasks (thanks to Ralph
|
||||
Bean).
|
||||
- TW-1501 Calc can't handle multi-digit numbers in some expressions (thanks to
|
||||
Jeremy John Reeder).
|
||||
- TW-1502 Successful on-add hook with no output confuses TW (thanks to Tomas
|
||||
Babej).
|
||||
- TW-1504 On-modify hook does not accept correct JSON format (thanks to Tomas
|
||||
Babej).
|
||||
- TW-1505 completely ignore mis-named hook scripts (thanks to Tomas Babej,
|
||||
David Patrick).
|
||||
- TW-1509 Hooks modifications performed on sync not sycning back (thanks to
|
||||
Tomas Babej).
|
||||
- TW-1510 Task can save empty value in the data backlog (thanks to Tomas Babej).
|
||||
- TW-1517 Hook performance should be measured individually for each hook (thanks
|
||||
to Tomas Babej).
|
||||
- TW-1518 Misbehaving hooks silently break task processing (thanks to Wim
|
||||
Schuermann).
|
||||
- TW-1519 Testing suite forces taskd.trust="ignore hostname" (thanks to Renato
|
||||
Alves).
|
||||
- TW-1522 Date format doesn't like hyphens (thanks to Scott Carter).
|
||||
- TW-1524 Build Broken (thanks to Jack).
|
||||
- TW-1530 Multiple on-add hooks generating new tasks are ignored (thanks to
|
||||
Tomas Babej).
|
||||
- TW-1531 'task export' should handle recurrence (thanks to Tomas Babej).
|
||||
- TW-1532 Hooks does not execute any script on Cygwin (thanks to Taisuke
|
||||
Hachimura).
|
||||
- TW-1534 Urgency coefficient for user project disables 'info' output (thanks to
|
||||
Martin).
|
||||
- TW-1542 Large numeric UDA values get rendered in scientific notation on export
|
||||
(thanks to Ralph Bean).
|
||||
- Fixed assorted color theme problems.
|
||||
- Changed assorted reports so they do not use '.age' format for dates that are
|
||||
in the future, because those are never shown with this format (thanks to
|
||||
Sujeevan Vijayakumaran).
|
||||
- New 'recurrence' configuration setting can disable recurring task generation.
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
2.4.0 (2015-01-01) 670102842c39bdc62ef84ae4b679a8f5a2d89523
|
||||
|
||||
- TD-42 Cannot compile taskd - GNUTLS_VERSION undefined in diag.cpp (thanks
|
||||
to Michele Vetturi).
|
||||
- TD-45 Fix preprocessor define (thanks to Jochen Sprickerhof).
|
||||
- TD-55 TLSServer/Client need to include <errno.h> on Solaris (thanks to Tatjana
|
||||
Heuser). Also applied to NetBSD.
|
||||
- TD-55 TLSServer/Client need to include <errno.h> on Solaris (thanks to
|
||||
Tatjana Heuser). Also applied to NetBSD.
|
||||
- TD-56 File.cpp needs to include <string.h> on Solaris (thanks to Tatjana
|
||||
Heuѕer).
|
||||
- TD-57 taskdctl script assumes /bin/sh is /bin/bash (thanks to Tatjana Heuser).
|
||||
@@ -286,8 +336,6 @@
|
||||
- Supports 'debug.parser' configuration setting.
|
||||
- Supports 'color.label.sort' for column labels of sort columns.
|
||||
|
||||
------ current release ---------------------------
|
||||
|
||||
2.3.0 (2014-01-15) c4eb46507031b7dee839dcb932bb2a22b2f0d3a2
|
||||
|
||||
Features
|
||||
|
||||
23
DEVELOPER
23
DEVELOPER
@@ -1,9 +1,16 @@
|
||||
How to Build Taskwarrior
|
||||
|
||||
Satisfy the Requirements:
|
||||
- gcc 4.4 or later, clang 2.9 or later or equivalent. This is because 2.4.1
|
||||
marks the first step towards using modern C++11. Initially this involves
|
||||
only feature N1984.
|
||||
- libuuid
|
||||
- gnutls (optional)
|
||||
|
||||
Obtain and build code:
|
||||
$ git clone https://git.tasktools.org/scm/tm/task.git task.git
|
||||
$ cd task.git
|
||||
$ git checkout 2.4.0 # Latest dev branch
|
||||
$ git checkout 2.4.1 # Latest dev branch
|
||||
$ cmake -DCMAKE_BUILD_TYPE=debug . # debug or release. Default: neither.
|
||||
$ make VERBOSE=1 # Shows details
|
||||
|
||||
@@ -18,8 +25,9 @@ How to Build Taskwarrior
|
||||
current development branch. The source tarballs do not reflect HEAD, and do
|
||||
not contain the test suite.
|
||||
|
||||
If you send us a patch, make sure that patch is made against git HEAD. We
|
||||
cannot apply patches made against the tarball source.
|
||||
If you send a patch (support@taskwarrior.org), make sure that patch is made
|
||||
against git HEAD on the development branch. We cannot apply patches made
|
||||
against the tarball source, or master.
|
||||
|
||||
General Statement
|
||||
This file is intended to convey the current efforts, priorities and needs of
|
||||
@@ -181,12 +189,11 @@ Work in Progress
|
||||
Current Codebase Condition
|
||||
|
||||
'master' branch:
|
||||
- 2.3.0 Current release, locked.
|
||||
- 2.4.1 Current release, locked.
|
||||
|
||||
'2.4.0' branch:
|
||||
- Current development branch with new command line parser, expressions,
|
||||
and heading for beta soon.
|
||||
'2.4.2' branch:
|
||||
- Current development branch no plans yet.
|
||||
|
||||
---
|
||||
|
||||
2014-10-12 Updated for 2.4.0
|
||||
2015-02-14 Updated for 2.4.1
|
||||
|
||||
@@ -24,7 +24,7 @@ Command Line Parsing
|
||||
determines whether subsequent arguments are interpreted as part of a filter or
|
||||
set of modifications.
|
||||
|
||||
The Parser object is fed command line arguments, then through a succession of
|
||||
The CLI object is fed command line arguments, then through a succession of
|
||||
calls builds and annotates a parse tree. To help with this, the Lexer is
|
||||
used to break up strings into tokens.
|
||||
|
||||
|
||||
15
INSTALL
15
INSTALL
@@ -10,6 +10,13 @@ Pre-requisites
|
||||
You will need the CMake build system installed in order to build taskwarrior
|
||||
from source.
|
||||
|
||||
You will need a C++ compiler that support C++11 N1984, which includes:
|
||||
|
||||
- gcc 4.4 (released 2009-04-21)
|
||||
- clang 2.9 (released 2011-04-06)
|
||||
- uuid lib
|
||||
- gnutls (optional)
|
||||
|
||||
More information on cmake can be obtained at http://cmake.org
|
||||
|
||||
It is HIGHLY RECOMMENDED that you build with a library that provides uuid_*
|
||||
@@ -92,10 +99,12 @@ Currently the defined languages are:
|
||||
|
||||
eng_USA 1
|
||||
esp_ESP 2
|
||||
deu_DEU 3
|
||||
fra_FRA 4
|
||||
ita_ITA 5
|
||||
por_PRT 6
|
||||
|
||||
epo_RUS 7
|
||||
pol_POL 8
|
||||
|
||||
Uninstallation
|
||||
--------------
|
||||
@@ -131,9 +140,7 @@ Cygwin
|
||||
|
||||
|
||||
Darwin, 32bit
|
||||
The taskwarrior packages will not work on a 32-bit OSX installation on Core
|
||||
Duo hardware. You will need to build Taskwarrior from source, and use this
|
||||
configure command:
|
||||
Taskwarrior needs to be built from source, and use this configure command:
|
||||
|
||||
cmake -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_EXE_LINKER_FLAGS=-m32 .
|
||||
|
||||
|
||||
100
NEWS
100
NEWS
@@ -1,92 +1,46 @@
|
||||
|
||||
New Features in taskwarrior 2.4.0
|
||||
New Features in taskwarrior 2.4.1
|
||||
|
||||
- The 'show' command displays default configuration values, when appropriate.
|
||||
- Removed deprecated commands 'push', 'pull' and 'merge'.
|
||||
- Portuguese (por-PRT), French (fra-FRA), Esperanto (epo-RUS) and Polish
|
||||
(pol-POL) localizations.
|
||||
- Better handling for deletion of recurring tasks.
|
||||
- New virtual tags: YESTERDAY, TOMORROW, READY, PENDING, COMPLETED, DELETED,
|
||||
TAGGED.
|
||||
- The '_get' command properly uses exit codes.
|
||||
- Regular expressions are now enabled by default.
|
||||
- The 'filter' verbosity token shows the complete filter used for the last
|
||||
command.
|
||||
- The 'new-uuid' verbosity token shows the UUID of newly created tasks.
|
||||
- The 'info' report now breaks down urgency values.
|
||||
- New 'color.until' color rule.
|
||||
- Using a non-zero 'urgency.inherit.coefficient' value means a task inherits
|
||||
the urgency values of the dependency chain.
|
||||
- Listing breaks now supported. See 'man taskrc'.
|
||||
- New fish shell completion script.
|
||||
- The filter form 'name:value' now maps to the partial match operator '=',
|
||||
rather than the exact match operator, '=='. This means that dates now
|
||||
match on the day by default, not the time also.
|
||||
- UDA indicator format.
|
||||
- Hooks.
|
||||
- New and updated holidays.rc files.
|
||||
- New German translation.
|
||||
- Hook scripts are now under much stricter control.
|
||||
|
||||
New commands in taskwarrior 2.4.0
|
||||
New commands in taskwarrior 2.4.1
|
||||
|
||||
- New 'calc' command (and standalone utility) for quick command line
|
||||
calculations.
|
||||
- None
|
||||
|
||||
New configuration options in taskwarrior 2.4.0
|
||||
New configuration options in taskwarrior 2.4.1
|
||||
|
||||
- The 'taskd.trust' setting is now a tri-state, supporting values 'strict',
|
||||
'ignore hostname' and 'allow all', for server certificate validation.
|
||||
- New theme: dark-gray-blue-256.theme
|
||||
- The 'allow.empty.filter' setting can be set to 'no' to disallow the
|
||||
potentially dangerous combination of write commands and empty filters.
|
||||
- New truncated_count column style for the description field which as the
|
||||
name says is a combination of the existing truncated and count styles.
|
||||
- New 'hooks' setting is a master control switch for hook processing.
|
||||
- New 'debug.hooks' for debugging hook scripts.
|
||||
- New 'debug.parser' for debugging parser issues scripts.
|
||||
- New 'color.label.sort' is used to color the column label of sort columns.
|
||||
- New 'urgency.uda.<name>.<value>' allows specific UDA values to affect
|
||||
urgency.
|
||||
- New 'recurrence.confirmation' which allows bypassing confirmation for
|
||||
changes to recurring tasks, by accepting, rejecting or prompting.
|
||||
- New 'uda.<name>.indicator' to override the UDA indicator.
|
||||
- The 'date.iso' setting allows you to enable (default) or disable support
|
||||
for ISO-8601 dates. This is because some of you have 'dateformat' settings
|
||||
that conflict.
|
||||
- The 'recurrence' setting enables (default) or disables recurring task
|
||||
instance generation.
|
||||
|
||||
Newly deprecated features in taskwarrior 2.4.0
|
||||
Newly deprecated features in taskwarrior 2.4.1
|
||||
|
||||
- The alias '_query' is deprecated.
|
||||
- Bare word search terms are deprecated, so 'task pattern list' will not
|
||||
be supported in future releases, instead requiring 'task /pattern/ list'.
|
||||
- The 'limit' pseudo attribute will change to 'rc.limit' in a future release.
|
||||
- None
|
||||
|
||||
Removed features in 2.4.0
|
||||
Removed features in 2.4.1
|
||||
|
||||
- Version 1.x column names no longer supported.
|
||||
- Version 1.x sort columns no longer supported.
|
||||
- Old-style color names including underscores are no longer supported.
|
||||
- Removed priority counts from the 'projects' commands.
|
||||
- Removed the unused 'locale' configuration variable.
|
||||
- Removed the unused 'patterns' confguration variable.
|
||||
- Removed the obsolete 'task-faq.5' man page.
|
||||
- Removed the obsolete 'task-tutorial.5' man page.
|
||||
- Removed the obsolete 'tasksh.1' man page.
|
||||
- Removed the 'tasksh' program from the Taskwarrior distribution. It is now
|
||||
a separate project.
|
||||
- Removed the 'complete.all.projects' setting that was not used.
|
||||
- Removed support for 'report.X.limit', which can now be set in the report
|
||||
filter 'limit:N'.
|
||||
- The 'total active time' information is removed from the 'info' report.
|
||||
This was being misinterpreted as support for time tracking.
|
||||
- The 'shadow file' feature is removed, but replaced with an example hook
|
||||
script that performs the same function..
|
||||
- None
|
||||
|
||||
Known Issues
|
||||
|
||||
- On Cygwin, case-insensitive regex searches are broken. The default is
|
||||
now case-sensitive for Cygwin only.
|
||||
- https://bug.tasktools.org
|
||||
- If you upgraded from Taskwarrior 2.3.0, you will need one of the following
|
||||
settings to allow continued syncing to a Taskserver:
|
||||
|
||||
$ task config taskd.trust strict
|
||||
$ task config taskd.trust 'ignore hostname'
|
||||
$ task config taskd.trust 'allow all'
|
||||
|
||||
These are presented in order of preference from most to least secure, and
|
||||
depend on how your certs were generated.
|
||||
|
||||
- https://bug.tasktools.org/
|
||||
|
||||
Taskwarrior has been built and tested on the following configurations:
|
||||
|
||||
* OS X 10.10 Yosemite, 10.9 Mavericks
|
||||
* OS X 10.10 Yosemite
|
||||
* Fedora 20 Heisenbug
|
||||
* Ubuntu 14.04 Trusty Tahr
|
||||
* Debian 7.0 Wheezy (stable)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task-color 5 2015-01-01 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task-color 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-color \- A color tutorial for the taskwarrior command line todo manager.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task-sync 5 2015-01-01 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task-sync 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task-sync \- A discussion and tutorial for the various task(1) data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH task 1 2015-01-01 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH task 1 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
task \- A command line todo manager.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH taskrc 5 2015-01-01 "${PACKAGE_STRING}" "User Manuals"
|
||||
.TH taskrc 5 2015-02-16 "${PACKAGE_STRING}" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
taskrc \- Configuration details for the task(1) command
|
||||
@@ -282,9 +282,8 @@ and project. The others are sent to standard output.
|
||||
.TP
|
||||
.B confirmation=yes
|
||||
May be "yes" or "no", and determines whether taskwarrior will ask for
|
||||
confirmation before deleting a task, performing bulk changes, or the undo
|
||||
command. The default value is "yes". Consider leaving this setting as "yes",
|
||||
for safety.
|
||||
confirmation before deleting a task or performing the undo command. The default
|
||||
value is "yes". Consider leaving this setting as "yes", for safety.
|
||||
|
||||
.TP
|
||||
.B allow.empty.filter=yes
|
||||
@@ -313,9 +312,9 @@ Controls padding between columns of the report output. Default is "1".
|
||||
.TP
|
||||
.B bulk=3
|
||||
Is a number, defaulting to 3. When this number or greater of tasks are modified
|
||||
in a single command, confirmation will be required, unless the
|
||||
in a single command, confirmation will be required, regardless of the value of
|
||||
.B confirmation
|
||||
variable is "no".
|
||||
variable.
|
||||
|
||||
This is useful for preventing large-scale unintended changes.
|
||||
|
||||
@@ -412,6 +411,11 @@ The character or string to show in the depends.indicator column. Defaults to +.
|
||||
.B uda.<name>.indicator=U
|
||||
The character or string to show in the <uda>.indicator column. Defaults to U.
|
||||
|
||||
.TP
|
||||
.B recurrence=yes
|
||||
Controls whether recurrence is enable, and whether recurring tasks continue to
|
||||
generate new task instances. Defaults to 'yes'.
|
||||
|
||||
.TP
|
||||
.B recurrence.confirmation=prompt
|
||||
Controls whether changes to recurring tasks propagates to other child tasks with
|
||||
@@ -616,6 +620,10 @@ field that is set. Otherwise, they are set to the corresponding values of
|
||||
.RE
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B date.iso=yes
|
||||
Enables ISO-8601 date support. The default value is "yes".
|
||||
|
||||
.TP
|
||||
.B weekstart=Sunday
|
||||
Determines the day a week starts. Valid values are Sunday or Monday only. The
|
||||
|
||||
@@ -44,7 +44,7 @@ color.recurring=rgb013
|
||||
color.scheduled=on rgb001
|
||||
color.until=
|
||||
color.blocked=white on color8
|
||||
color.blocking=white on color15
|
||||
color.blocking=black on color15
|
||||
|
||||
# Project
|
||||
color.project.none=
|
||||
|
||||
@@ -44,7 +44,7 @@ color.recurring=
|
||||
color.scheduled=
|
||||
color.until=
|
||||
color.blocked=bold gray10 on gray4
|
||||
color.blocking=bold gray18 on gray6
|
||||
color.blocking=gray18 on gray6
|
||||
|
||||
# Project
|
||||
color.project.none=
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,20 +1,19 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# The on-add event is triggered separately for each task added
|
||||
# The on-add event is triggered separately for each task added. This hook
|
||||
# script can accept/reject the addition. Processing will continue.
|
||||
|
||||
# Input:
|
||||
# - line of JSON for the task added
|
||||
|
||||
# Output:
|
||||
# - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
# zero, otherwise ignored.
|
||||
# - minimal new task: {"description":"Buy milk"}
|
||||
# - to modify a task include complete JSON
|
||||
# - all emitted non-JSON lines are considered feedback messages if the exit
|
||||
# code is zero, otherwise they are considered errors.
|
||||
|
||||
# - Line of JSON for proposed new task.
|
||||
read new_task
|
||||
|
||||
# Output:
|
||||
# - JSON, modified or unmodified.
|
||||
# - Optional feedback/error.
|
||||
echo $new_task
|
||||
echo 'on-add'
|
||||
|
||||
# Status:
|
||||
# - 0: JSON accepted, non-JSON is feedback.
|
||||
# - non-0: JSON ignored, non-JSON is error.
|
||||
exit 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
read new_task
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# The on-exit event is triggered once, after all processing is complete, i.e.
|
||||
# last
|
||||
# The on-exit event is triggered once, after all processing is complete.
|
||||
# This hooks script has no effect on processing.
|
||||
|
||||
# Input:
|
||||
# - read-only line of JSON for each task added/modified
|
||||
|
||||
# Output:
|
||||
# - any emitted JSON is ignored
|
||||
# - all emitted non-JSON lines are considered feedback messages if the exit
|
||||
# code is zero, otherwise they are considered errors.
|
||||
|
||||
while read -t 1 modified_task
|
||||
# - Read-only line of JSON for each task added/modified
|
||||
while read modified_task
|
||||
do
|
||||
# Scan task
|
||||
echo $modified_task
|
||||
done
|
||||
|
||||
# Output:
|
||||
# - Optional feedback/error.
|
||||
echo 'on-exit'
|
||||
|
||||
# Status:
|
||||
# - 0: JSON ignored, non-JSON is feedback.
|
||||
# - non-0: JSON ignored, non-JSON is error.
|
||||
exit 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This hook script replaces the shadow file feature, found in Taskwarrior
|
||||
# prior to version 2.4.0.
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# The on-launch event is triggered once, after initialization, before any
|
||||
# processing occurs, i.e first
|
||||
# processing occurs. This hooks script has no effect on processing.
|
||||
|
||||
# Input:
|
||||
# - none
|
||||
# - None
|
||||
|
||||
# Output:
|
||||
# - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
# zero, otherwise ignored.
|
||||
# - minimal new task: {"description":"Buy milk"}
|
||||
# - to modify a task include complete JSON
|
||||
# - all emitted non-JSON lines are considered feedback messages if the exit
|
||||
# code is zero, otherwise they are considered errors.
|
||||
|
||||
# - Optional feedback/error.
|
||||
echo 'on-launch'
|
||||
|
||||
# Status:
|
||||
# - 0: JSON ignored, non-JSON is feedback.
|
||||
# - non-0: JSON ignored, non-JSON is error.
|
||||
exit 0
|
||||
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
# The on-modify event is triggered separately for each task added or modified
|
||||
# The on-modify event is triggered separately for each task modified. This hook
|
||||
# script can accept/reject the modification. Processing will continue.
|
||||
|
||||
# Input:
|
||||
# - line of JSON for the original task
|
||||
# - line of JSON for the modified task, the diff being the modification
|
||||
|
||||
# Output:
|
||||
# - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
# zero, otherwise ignored.
|
||||
# - minimal new task: {"description":"Buy milk"}
|
||||
# - to modify a task include complete JSON
|
||||
# - all emitted non-JSON lines are considered feedback messages if the exit
|
||||
# code is zero, otherwise they are considered errors.
|
||||
|
||||
read original_task
|
||||
read modified_task
|
||||
|
||||
# Output:
|
||||
# - JSON, modified or unmodified.
|
||||
# - Optional feedback/error.
|
||||
echo $modified_task
|
||||
echo 'on-modify'
|
||||
|
||||
# Status:
|
||||
# - 0: JSON accepted, non-JSON is feedback.
|
||||
# - non-0: JSON ignored, non-JSON is error.
|
||||
exit 0
|
||||
|
||||
@@ -82,6 +82,7 @@ std::string Config::_defaults =
|
||||
"# # Comma-separated list. May contain any subset of:\n"
|
||||
"#verbose=blank,header,footnote,label,new-id,new-uuid,affected,edit,special,project,sync,filter\n"
|
||||
"confirmation=yes # Confirmation on delete, big changes\n"
|
||||
"recurrence=yes # Enable recurrence\n"
|
||||
"recurrence.confirmation=prompt # Confirmation for propagating changes among recurring tasks (yes/no/prompt)\n"
|
||||
"allow.empty.filter=yes # An empty filter gets a warning and requires confirmation\n"
|
||||
"indent.annotation=2 # Indent spaces for annotations\n"
|
||||
@@ -116,6 +117,7 @@ std::string Config::_defaults =
|
||||
"dateformat.info=Y-M-D H:N:S # Preferred display date format for information\n"
|
||||
"dateformat.report= # Preferred display date format for reports\n"
|
||||
"dateformat.annotation= # Preferred display date format for annotations\n"
|
||||
"date.iso=yes # Enable ISO date support\n"
|
||||
"weekstart="
|
||||
STRING_DATE_SUNDAY_LONG
|
||||
" # Sunday or Monday only\n"
|
||||
@@ -358,19 +360,19 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"report.long.description=All details of tasks\n"
|
||||
"report.long.labels=ID,A,Created,Mod,Deps,P,Project,Tags,Recur,Wait,Sched,Due,Until,Description\n"
|
||||
"report.long.columns=id,start.active,entry,modified.age,depends,priority,project,tags,recur,wait.age,scheduled,due,until,description\n"
|
||||
"report.long.columns=id,start.active,entry,modified.age,depends,priority,project,tags,recur,wait.remaining,scheduled,due,until,description\n"
|
||||
"report.long.filter=status:pending\n"
|
||||
"report.long.sort=modified-\n"
|
||||
"\n"
|
||||
"report.list.description=Most details of tasks\n"
|
||||
"report.list.labels=ID,Active,Age,D,P,Project,Tags,R,Sch,Due,Until,Description,Urg\n"
|
||||
"report.list.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due,until.age,description.count,urgency\n"
|
||||
"report.list.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due,until.remaining,description.count,urgency\n"
|
||||
"report.list.filter=status:pending\n"
|
||||
"report.list.sort=start-,due+,project+/,urgency-\n"
|
||||
"\n"
|
||||
"report.ls.description=Few details of tasks\n"
|
||||
"report.ls.labels=ID,A,D,Project,Tags,R,Wait,S,Due,Until,Description\n"
|
||||
"report.ls.columns=id,start.active,depends.indicator,project,tags,recur.indicator,wait.age,scheduled.countdown,due.countdown,until.countdown,description.count\n"
|
||||
"report.ls.columns=id,start.active,depends.indicator,project,tags,recur.indicator,wait.remaining,scheduled.countdown,due.countdown,until.countdown,description.count\n"
|
||||
"report.ls.filter=status:pending\n"
|
||||
"report.ls.sort=start-,description+\n"
|
||||
"\n"
|
||||
@@ -382,13 +384,13 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"report.newest.description=Newest tasks\n"
|
||||
"report.newest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description\n"
|
||||
"report.newest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.age,scheduled.countdown,due,until.age,description\n"
|
||||
"report.newest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.remaining,scheduled.countdown,due,until.age,description\n"
|
||||
"report.newest.filter=(status:pending or status:waiting) and recur.none:\n"
|
||||
"report.newest.sort=entry-\n"
|
||||
"\n"
|
||||
"report.oldest.description=Oldest tasks\n"
|
||||
"report.oldest.labels=ID,Active,Created,Age,Mod,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description\n"
|
||||
"report.oldest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.age,scheduled.countdown,due,until.age,description\n"
|
||||
"report.oldest.columns=id,start.age,entry,entry.age,modified.age,depends.indicator,priority,project,tags,recur.indicator,wait.remaining,scheduled.countdown,due,until.age,description\n"
|
||||
"report.oldest.filter=(status:pending or status:waiting)\n"
|
||||
"report.oldest.sort=entry+\n"
|
||||
"\n"
|
||||
@@ -400,7 +402,7 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"report.active.description=Active tasks\n"
|
||||
"report.active.labels=ID,Started,Active,Age,D,P,Project,Tags,Recur,W,Sch,Due,Until,Description\n"
|
||||
"report.active.columns=id,start,start.age,entry.age,depends.indicator,priority,project,tags,recur,wait.indicator,scheduled.age,due,until,description\n"
|
||||
"report.active.columns=id,start,start.age,entry.age,depends.indicator,priority,project,tags,recur,wait.indicator,scheduled.remaining,due,until,description\n"
|
||||
"report.active.filter=status:pending and +ACTIVE\n"
|
||||
"report.active.sort=project+,start+\n"
|
||||
"\n"
|
||||
@@ -412,30 +414,30 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"report.recurring.description=Recurring Tasks\n"
|
||||
"report.recurring.labels=ID,Active,Age,D,P,Project,Tags,Recur,Sch,Due,Until,Description,Urg\n"
|
||||
"report.recurring.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur,scheduled.countdown,due,until.age,description,urgency\n"
|
||||
"report.recurring.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur,scheduled.countdown,due,until.remaining,description,urgency\n"
|
||||
"report.recurring.filter=(status:pending or status:waiting) and (+PARENT or +CHILD)\n"
|
||||
"report.recurring.sort=due+,urgency-,entry+\n"
|
||||
"\n"
|
||||
"report.waiting.description=Waiting (hidden) tasks\n"
|
||||
"report.waiting.labels=ID,A,Age,D,P,Project,Tags,R,Wait,for,Sched,Due,Until,Description\n"
|
||||
"report.waiting.columns=id,start.active,entry.age,depends.indicator,priority,project,tags,recur.indicator,wait,wait.age,scheduled,due,until,description\n"
|
||||
"report.waiting.columns=id,start.active,entry.age,depends.indicator,priority,project,tags,recur.indicator,wait,wait.remaining,scheduled,due,until,description\n"
|
||||
"report.waiting.filter=+WAITING\n"
|
||||
"report.waiting.sort=due+,wait+,entry+\n"
|
||||
"\n"
|
||||
"report.all.description=All tasks\n"
|
||||
"report.all.labels=ID,St,UUID,A,Age,Done,D,P,Project,Tags,R,Wait,Sch,Due,Until,Description\n"
|
||||
"report.all.columns=id,status.short,uuid.short,start.active,entry.age,end.age,depends.indicator,priority,project.parent,tags.count,recur.indicator,wait.age,scheduled.age,due,until.age,description\n"
|
||||
"report.all.columns=id,status.short,uuid.short,start.active,entry.age,end.age,depends.indicator,priority,project.parent,tags.count,recur.indicator,wait.remaining,scheduled.remaining,due,until.remaining,description\n"
|
||||
"report.all.sort=entry-\n"
|
||||
"\n"
|
||||
"report.next.description=Most urgent tasks\n"
|
||||
"report.next.labels=ID,Active,Age,Deps,P,Project,Tag,Recur,S,Due,Until,Description,Urg\n"
|
||||
"report.next.columns=id,start.age,entry.age,depends,priority,project,tags,recur,scheduled.countdown,due.age,until.age,description,urgency\n"
|
||||
"report.next.columns=id,start.age,entry.age,depends,priority,project,tags,recur,scheduled.countdown,due.remaining,until.remaining,description,urgency\n"
|
||||
"report.next.filter=status:pending limit:page\n"
|
||||
"report.next.sort=start-,urgency-\n"
|
||||
"\n"
|
||||
"report.ready.description=Most urgent actionable tasks\n"
|
||||
"report.ready.labels=ID,Active,Age,D,P,Project,Tags,R,S,Due,Until,Description,Urg\n"
|
||||
"report.ready.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due.countdown,until.age,description,urgency\n"
|
||||
"report.ready.columns=id,start.age,entry.age,depends.indicator,priority,project,tags,recur.indicator,scheduled.countdown,due.countdown,until.remaining,description,urgency\n"
|
||||
"report.ready.filter=+READY\n"
|
||||
"report.ready.sort=start-,urgency-\n"
|
||||
"\n"
|
||||
@@ -453,7 +455,7 @@ std::string Config::_defaults =
|
||||
"\n"
|
||||
"report.blocking.description=Blocking tasks\n"
|
||||
"report.blocking.labels=ID,UUID,A,Deps,Project,Tags,R,W,Sch,Due,Until,Description,Urg\n"
|
||||
"report.blocking.columns=id,uuid.short,start.active,depends,project,tags,recur,wait.indicator,scheduled.age,due.age,until.age,description.count,urgency\n"
|
||||
"report.blocking.columns=id,uuid.short,start.active,depends,project,tags,recur,wait.indicator,scheduled.remaining,due.remaining,until.remaining,description.count,urgency\n"
|
||||
"report.blocking.sort=urgency-,due+,entry+\n"
|
||||
"report.blocking.filter= status:pending +BLOCKING\n"
|
||||
"\n";
|
||||
|
||||
@@ -504,7 +504,7 @@ bool Context::color ()
|
||||
use_color = config.getBoolean ("color");
|
||||
|
||||
// Only tty's support color.
|
||||
if (! isatty (fileno (stdout)))
|
||||
if (! isatty (STDOUT_FILENO))
|
||||
{
|
||||
// No ioctl.
|
||||
config.set ("detection", "off");
|
||||
@@ -658,6 +658,7 @@ void Context::staticInitialization ()
|
||||
Task::searchCaseSensitive = Variant::searchCaseSensitive = config.getBoolean ("search.case.sensitive");
|
||||
Task::regex = Variant::searchUsingRegex = config.getBoolean ("regex");
|
||||
Lexer::dateFormat = Variant::dateFormat = config.get ("dateformat");
|
||||
Lexer::isoEnabled = Variant::isoEnabled = config.getBoolean ("date.iso");
|
||||
|
||||
std::map <std::string, Column*>::iterator i;
|
||||
for (i = columns.begin (); i != columns.end (); ++i)
|
||||
@@ -770,7 +771,7 @@ void Context::clear ()
|
||||
// this output?'.
|
||||
void Context::updateXtermTitle ()
|
||||
{
|
||||
if (config.getBoolean ("xterm.title") && isatty (fileno (stdout)))
|
||||
if (config.getBoolean ("xterm.title") && isatty (STDOUT_FILENO))
|
||||
{
|
||||
std::string command = cli.getCommand ();
|
||||
std::string title;
|
||||
|
||||
12
src/DOM.cpp
12
src/DOM.cpp
@@ -240,6 +240,12 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
|
||||
Column* column = context.columns[canonical];
|
||||
if (column)
|
||||
{
|
||||
if (column->is_uda () && ! task.has (canonical))
|
||||
{
|
||||
value = Variant ("''");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (column->type () == "date")
|
||||
value = Variant (task.get_date (canonical), Variant::type_date);
|
||||
else if (column->type () == "duration" || canonical == "recur")
|
||||
@@ -307,6 +313,12 @@ bool DOM::get (const std::string& name, const Task& task, Variant& value)
|
||||
Column* column = context.columns[canonical];
|
||||
if (column)
|
||||
{
|
||||
if (column->is_uda () && ! task.has (canonical))
|
||||
{
|
||||
value = Variant ("''");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (column->type () == "date")
|
||||
value = Variant (ref.get_date (canonical), Variant::type_date);
|
||||
else if (column->type () == "duration")
|
||||
|
||||
398
src/Hooks.cpp
398
src/Hooks.cpp
@@ -38,8 +38,10 @@
|
||||
#include <Context.h>
|
||||
#include <JSON.h>
|
||||
#include <Hooks.h>
|
||||
#include <Timer.h>
|
||||
#include <text.h>
|
||||
#include <util.h>
|
||||
#include <i18n.h>
|
||||
|
||||
extern Context context;
|
||||
|
||||
@@ -73,7 +75,17 @@ void Hooks::initialize ()
|
||||
{
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = _scripts.begin (); i != _scripts.end (); ++i)
|
||||
context.debug ("Found hook script " + *i);
|
||||
{
|
||||
Path p (*i);
|
||||
std::string name = p.name ();
|
||||
if (name.substr (0, 6) == "on-add" ||
|
||||
name.substr (0, 9) == "on-modify" ||
|
||||
name.substr (0, 9) == "on-launch" ||
|
||||
name.substr (0, 7) == "on-exit")
|
||||
context.debug ("Found hook script " + *i);
|
||||
else
|
||||
context.debug ("Found misnamed hook script " + *i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (_debug >= 1)
|
||||
@@ -98,8 +110,7 @@ bool Hooks::enable (bool value)
|
||||
// - none
|
||||
//
|
||||
// Output:
|
||||
// - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
// zero, otherwise ignored.
|
||||
// - JSON not allowed.
|
||||
// - all emitted non-JSON lines are considered feedback or error messages
|
||||
// depending on the status code.
|
||||
//
|
||||
@@ -120,29 +131,28 @@ void Hooks::onLaunch ()
|
||||
std::vector <std::string> output;
|
||||
int status = callHookScript (*script, input, output);
|
||||
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = output.begin (); line != output.end (); ++line)
|
||||
{
|
||||
if (isJSON (*line))
|
||||
{
|
||||
if (status == 0)
|
||||
{
|
||||
// Only 'add' is possible.
|
||||
Task newTask (*line);
|
||||
context.tdb2.add (newTask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status == 0)
|
||||
context.header (*line);
|
||||
else
|
||||
context.error (*line);
|
||||
}
|
||||
}
|
||||
std::vector <std::string> outputJSON;
|
||||
std::vector <std::string> outputFeedback;
|
||||
separateOutput (output, outputJSON, outputFeedback);
|
||||
|
||||
assertNTasks (outputJSON, 0);
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFeedback (outputFeedback);
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.error (*message);
|
||||
|
||||
if (status)
|
||||
throw 0; // This is how hooks silently terminate processing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +167,7 @@ void Hooks::onLaunch ()
|
||||
// - read-only line of JSON for each task added/modified
|
||||
//
|
||||
// Output:
|
||||
// - any emitted JSON is ignored
|
||||
// - all emitted JSON is ignored
|
||||
// - all emitted non-JSON lines are considered feedback or error messages
|
||||
// depending on the status code.
|
||||
//
|
||||
@@ -188,24 +198,28 @@ void Hooks::onExit ()
|
||||
std::vector <std::string> output;
|
||||
int status = callHookScript (*script, input, output);
|
||||
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = output.begin (); line != output.end (); ++line)
|
||||
{
|
||||
if (isJSON (*line))
|
||||
{
|
||||
context.error ("JSON output ignored: {1}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status == 0)
|
||||
context.footnote (*line);
|
||||
else
|
||||
context.error (*line);
|
||||
}
|
||||
}
|
||||
std::vector <std::string> outputJSON;
|
||||
std::vector <std::string> outputFeedback;
|
||||
separateOutput (output, outputJSON, outputFeedback);
|
||||
|
||||
assertNTasks (outputJSON, 0);
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFeedback (outputFeedback);
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.error (*message);
|
||||
|
||||
if (status)
|
||||
throw 0; // This is how hooks silently terminate processing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,14 +233,14 @@ void Hooks::onExit ()
|
||||
// - line of JSON for the task added
|
||||
//
|
||||
// Output:
|
||||
// - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
// zero, otherwise ignored.
|
||||
// - emitted JSON for the input task is added, if the exit code is zero,
|
||||
// otherwise ignored.
|
||||
// - all emitted non-JSON lines are considered feedback or error messages
|
||||
// depending on the status code.
|
||||
//
|
||||
void Hooks::onAdd (std::vector <Task>& tasks)
|
||||
void Hooks::onAdd (Task& task)
|
||||
{
|
||||
if (! _enabled || tasks.size () < 1)
|
||||
if (! _enabled)
|
||||
return;
|
||||
|
||||
context.timer_hooks.start ();
|
||||
@@ -234,9 +248,9 @@ void Hooks::onAdd (std::vector <Task>& tasks)
|
||||
std::vector <std::string> matchingScripts = scripts ("on-add");
|
||||
if (matchingScripts.size ())
|
||||
{
|
||||
// Convert vector of tasks to a vector of strings.
|
||||
// Convert task to a vector of strings.
|
||||
std::vector <std::string> input;
|
||||
input.push_back (tasks[0].composeJSON ());
|
||||
input.push_back (task.composeJSON ());
|
||||
|
||||
// Call the hook scripts.
|
||||
std::vector <std::string>::iterator script;
|
||||
@@ -245,33 +259,37 @@ void Hooks::onAdd (std::vector <Task>& tasks)
|
||||
std::vector <std::string> output;
|
||||
int status = callHookScript (*script, input, output);
|
||||
|
||||
input.clear ();
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = output.begin (); line != output.end (); ++line)
|
||||
{
|
||||
if (isJSON (*line))
|
||||
{
|
||||
if (status == 0)
|
||||
input.push_back (*line);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status == 0)
|
||||
context.footnote (*line);
|
||||
else
|
||||
context.error (*line);
|
||||
}
|
||||
}
|
||||
std::vector <std::string> outputJSON;
|
||||
std::vector <std::string> outputFeedback;
|
||||
separateOutput (output, outputJSON, outputFeedback);
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
assertNTasks (outputJSON, 1);
|
||||
assertValidJSON (outputJSON);
|
||||
assertSameTask (outputJSON, task);
|
||||
|
||||
// Propagate forward to the next script.
|
||||
input[0] = outputJSON[0];
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFeedback (outputFeedback);
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.error (*message);
|
||||
|
||||
if (status)
|
||||
throw 0; // This is how hooks silently terminate processing.
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer the modified task lines back to the original task list.
|
||||
tasks.clear ();
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = input.begin (); i != input.end (); ++i)
|
||||
tasks.push_back (Task (*i));
|
||||
// Transfer the modified task back to the original task.
|
||||
task = Task (input[0]);
|
||||
}
|
||||
|
||||
context.timer_hooks.stop ();
|
||||
@@ -285,14 +303,14 @@ void Hooks::onAdd (std::vector <Task>& tasks)
|
||||
// - line of JSON for the modified task, the diff being the modification
|
||||
//
|
||||
// Output:
|
||||
// - all emitted JSON lines are added/modified as tasks, if the exit code is
|
||||
// zero, otherwise ignored.
|
||||
// - emitted JSON for the input task is saved, if the exit code is zero,
|
||||
// otherwise ignored.
|
||||
// - all emitted non-JSON lines are considered feedback or error messages
|
||||
// depending on the status code.
|
||||
//
|
||||
void Hooks::onModify (const Task& before, std::vector <Task>& tasks)
|
||||
void Hooks::onModify (const Task& before, Task& after)
|
||||
{
|
||||
if (! _enabled || tasks.size () < 1)
|
||||
if (! _enabled)
|
||||
return;
|
||||
|
||||
context.timer_hooks.start ();
|
||||
@@ -300,61 +318,46 @@ void Hooks::onModify (const Task& before, std::vector <Task>& tasks)
|
||||
std::vector <std::string> matchingScripts = scripts ("on-modify");
|
||||
if (matchingScripts.size ())
|
||||
{
|
||||
// Prepare invariants.
|
||||
std::string beforeJSON = before.composeJSON ();
|
||||
std::string uuidPattern = "\"uuid\":\"" + before.get ("uuid") + "\"";
|
||||
|
||||
// Convert vector of tasks to a vector of strings.
|
||||
std::vector <std::string> input;
|
||||
input.push_back (beforeJSON); // [0] original, never changes
|
||||
input.push_back (tasks[0].composeJSON ()); // [1] original'
|
||||
input.push_back (before.composeJSON ()); // [line 0] original, never changes
|
||||
input.push_back (after.composeJSON ()); // [line 1] modified
|
||||
|
||||
// Call the hook scripts.
|
||||
std::vector <std::string>::iterator script;
|
||||
for (script = matchingScripts.begin (); script != matchingScripts.end (); ++script)
|
||||
{
|
||||
std::vector <std::string> firstTwoOnly;
|
||||
firstTwoOnly.push_back (input[0]);
|
||||
firstTwoOnly.push_back (input[1]);
|
||||
|
||||
std::vector <std::string> output;
|
||||
int status = callHookScript (*script, firstTwoOnly, output);
|
||||
int status = callHookScript (*script, input, output);
|
||||
|
||||
// Start from scratch.
|
||||
input[1] = ""; // [1] placeholder for original'
|
||||
std::vector <std::string> outputJSON;
|
||||
std::vector <std::string> outputFeedback;
|
||||
separateOutput (output, outputJSON, outputFeedback);
|
||||
|
||||
std::vector <std::string>::iterator line;
|
||||
for (line = output.begin (); line != output.end (); ++line)
|
||||
if (status == 0)
|
||||
{
|
||||
if (isJSON (*line))
|
||||
{
|
||||
if (status == 0)
|
||||
{
|
||||
if (line->find (uuidPattern) != std::string::npos)
|
||||
input[1] = *line; // [1] original'
|
||||
else
|
||||
input.push_back (*line); // [n > 1] extras
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status == 0)
|
||||
context.footnote (*line);
|
||||
else
|
||||
context.error (*line);
|
||||
}
|
||||
assertNTasks (outputJSON, 1);
|
||||
assertValidJSON (outputJSON);
|
||||
assertSameTask (outputJSON, before);
|
||||
|
||||
// Propagate accepted changes forward to the next script.
|
||||
input[1] = outputJSON[0];
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.debug (*message);
|
||||
}
|
||||
else
|
||||
{
|
||||
assertFeedback (outputFeedback);
|
||||
|
||||
std::vector <std::string>::iterator message;
|
||||
for (message = outputFeedback.begin (); message != outputFeedback.end (); ++message)
|
||||
context.error (*message);
|
||||
|
||||
if (status)
|
||||
throw 0; // This is how hooks silently terminate processing.
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer the modified task lines back to the original task list.
|
||||
tasks.clear ();
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = input.begin (); i != input.end (); ++i)
|
||||
if (i != input.begin ())
|
||||
tasks.push_back (Task (*i));
|
||||
}
|
||||
|
||||
context.timer_hooks.stop ();
|
||||
@@ -384,65 +387,135 @@ std::vector <std::string> Hooks::scripts (const std::string& event)
|
||||
return matching;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Hooks::separateOutput (
|
||||
const std::vector <std::string>& output,
|
||||
std::vector <std::string>& json,
|
||||
std::vector <std::string>& feedback) const
|
||||
{
|
||||
std::vector <std::string>::const_iterator i;
|
||||
for (i = output.begin (); i != output.end (); ++i)
|
||||
{
|
||||
if (isJSON (*i))
|
||||
json.push_back (*i);
|
||||
else
|
||||
feedback.push_back (*i);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Hooks::isJSON (const std::string& input) const
|
||||
{
|
||||
// Does it even look like JSON? {...}
|
||||
if (input.length () > 2 &&
|
||||
input[0] == '{' &&
|
||||
input[input.length () - 1] == '}')
|
||||
return input.length () > 2 &&
|
||||
input[0] == '{' &&
|
||||
input[input.length () - 1] == '}';
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Hooks::assertValidJSON (const std::vector <std::string>& input) const
|
||||
{
|
||||
std::vector <std::string>::const_iterator i;
|
||||
for (i = input.begin (); i != input.end (); i++)
|
||||
{
|
||||
if (i->length () < 3 ||
|
||||
(*i)[0] != '{' ||
|
||||
(*i)[i->length () - 1] != '}')
|
||||
{
|
||||
context.error (STRING_HOOK_ERROR_OBJECT);
|
||||
throw 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// The absolute minimum a task needs is:
|
||||
bool foundDescription = false;
|
||||
|
||||
// Parse the whole thing.
|
||||
json::value* root = json::parse (input);
|
||||
if (root->type () == json::j_object)
|
||||
json::value* root = json::parse (*i);
|
||||
if (root->type () != json::j_object)
|
||||
{
|
||||
json::object* root_obj = (json::object*)root;
|
||||
|
||||
// For each object element...
|
||||
json_object_iter i;
|
||||
for (i = root_obj->_data.begin ();
|
||||
i != root_obj->_data.end ();
|
||||
++i)
|
||||
{
|
||||
// If the attribute is a recognized column.
|
||||
std::string type = Task::attributes[i->first];
|
||||
if (type == "string" && i->first == "description")
|
||||
foundDescription = true;
|
||||
}
|
||||
context.error (STRING_HOOK_ERROR_OBJECT);
|
||||
throw 0;
|
||||
}
|
||||
else
|
||||
throw std::string ("Object expected.");
|
||||
|
||||
// It's JSON, but is it a task?
|
||||
if (! foundDescription)
|
||||
throw std::string ("Missing 'description' attribute, of type 'string'.");
|
||||
if (((json::object*)root)->_data.find ("description") == ((json::object*)root)->_data.end ())
|
||||
{
|
||||
context.error (STRING_HOOK_ERROR_NODESC);
|
||||
throw 0;
|
||||
}
|
||||
|
||||
// Yep, looks like a JSON task.
|
||||
return true;
|
||||
if (((json::object*)root)->_data.find ("uuid") == ((json::object*)root)->_data.end ())
|
||||
{
|
||||
context.error (STRING_HOOK_ERROR_NOUUID);
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
|
||||
catch (const std::string& e)
|
||||
{
|
||||
if (_debug >= 1)
|
||||
context.error ("Hook output looks like JSON, but is not a valid task.");
|
||||
|
||||
if (_debug >= 2)
|
||||
context.error ("JSON " + e);
|
||||
context.error (format (STRING_HOOK_ERROR_SYNTAX, *i));
|
||||
if (_debug)
|
||||
context.error (STRING_HOOK_ERROR_JSON + e);
|
||||
throw 0;
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
if (_debug >= 1)
|
||||
context.error ("Hook output looks like JSON, but fails to parse.");
|
||||
context.error (STRING_HOOK_ERROR_NOPARSE + *i);
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Hooks::assertNTasks (const std::vector <std::string>& input, int n) const
|
||||
{
|
||||
if (input.size () != n)
|
||||
{
|
||||
context.error (format (STRING_HOOK_ERROR_BAD_NUM, n, (int) input.size ()));
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Hooks::assertSameTask (const std::vector <std::string>& input, const Task& task) const
|
||||
{
|
||||
std::string uuid = task.get ("uuid");
|
||||
|
||||
std::vector <std::string>::const_iterator i;
|
||||
for (i = input.begin (); i != input.end (); i++)
|
||||
{
|
||||
json::object* root_obj = (json::object*)json::parse (*i);
|
||||
|
||||
// If there is no UUID at all.
|
||||
json_object_iter u = root_obj->_data.find ("uuid");
|
||||
if (u == root_obj->_data.end () ||
|
||||
u->second->type () != json::j_string)
|
||||
{
|
||||
context.error (format (STRING_HOOK_ERROR_SAME1, uuid));
|
||||
throw 0;
|
||||
}
|
||||
|
||||
json::string* up = (json::string*) u->second;
|
||||
std::string json_uuid = json::decode (unquoteText (up->dump ()));
|
||||
if (json_uuid != uuid)
|
||||
{
|
||||
context.error (format (STRING_HOOK_ERROR_SAME2, uuid, json_uuid));
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Hooks::assertFeedback (const std::vector <std::string>& input) const
|
||||
{
|
||||
bool foundSomething = false;
|
||||
std::vector <std::string>::const_iterator i;
|
||||
for (i = input.begin (); i != input.end (); ++i)
|
||||
if (nontrivial (*i))
|
||||
foundSomething = true;
|
||||
|
||||
if (! foundSomething)
|
||||
{
|
||||
context.error (STRING_HOOK_ERROR_NOFEEDBACK);
|
||||
throw 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -452,11 +525,11 @@ int Hooks::callHookScript (
|
||||
std::vector <std::string>& output)
|
||||
{
|
||||
if (_debug >= 1)
|
||||
context.debug ("Hooks: Calling " + script);
|
||||
context.debug ("Hook: Calling " + script);
|
||||
|
||||
if (_debug >= 2)
|
||||
{
|
||||
context.debug ("Hooks: input");
|
||||
context.debug ("Hook: input");
|
||||
std::vector <std::string>::const_iterator i;
|
||||
for (i = input.begin (); i != input.end (); ++i)
|
||||
context.debug (" " + *i);
|
||||
@@ -469,19 +542,30 @@ int Hooks::callHookScript (
|
||||
|
||||
std::string outputStr;
|
||||
std::vector <std::string> args;
|
||||
int status = execute (script, args, inputStr, outputStr);
|
||||
int status;
|
||||
|
||||
// Measure time for each hook if running in debug
|
||||
if (_debug >= 2)
|
||||
{
|
||||
Timer timer_per_hook("Hooks::execute (" + script + ")");
|
||||
timer_per_hook.start();
|
||||
|
||||
status = execute (script, args, inputStr, outputStr);
|
||||
}
|
||||
else
|
||||
status = execute (script, args, inputStr, outputStr);
|
||||
|
||||
split (output, outputStr, '\n');
|
||||
|
||||
if (_debug >= 2)
|
||||
{
|
||||
context.debug ("Hooks: output");
|
||||
context.debug ("Hook: output");
|
||||
std::vector <std::string>::iterator i;
|
||||
for (i = output.begin (); i != output.end (); ++i)
|
||||
if (*i != "")
|
||||
context.debug (" " + *i);
|
||||
|
||||
context.debug (format ("Hooks: Completed with status {1}", status));
|
||||
context.debug (format ("Hook: Completed with status {1}", status));
|
||||
context.debug (" "); // Blank line
|
||||
}
|
||||
|
||||
|
||||
@@ -44,14 +44,19 @@ public:
|
||||
|
||||
void onLaunch ();
|
||||
void onExit ();
|
||||
void onAdd (std::vector <Task>&);
|
||||
void onModify (const Task&, std::vector <Task>&);
|
||||
void onAdd (Task&);
|
||||
void onModify (const Task&, Task&);
|
||||
|
||||
std::vector <std::string> list ();
|
||||
|
||||
private:
|
||||
std::vector <std::string> scripts (const std::string&);
|
||||
void separateOutput (const std::vector <std::string>&, std::vector <std::string>&, std::vector <std::string>&) const;
|
||||
bool isJSON (const std::string&) const;
|
||||
void assertValidJSON (const std::vector <std::string>&) const;
|
||||
void assertNTasks (const std::vector <std::string>&, int) const;
|
||||
void assertSameTask (const std::vector <std::string>&, const Task&) const;
|
||||
void assertFeedback (const std::vector <std::string>&) const;
|
||||
int callHookScript (const std::string&, const std::vector <std::string>&, std::vector <std::string>&);
|
||||
|
||||
private:
|
||||
|
||||
@@ -702,7 +702,7 @@ void ISO8601d::resolve ()
|
||||
t.tm_min = (seconds % 3600) / 60;
|
||||
t.tm_sec = seconds % 60;
|
||||
|
||||
_value = utc ? timegm (&t) : timelocal (&t);
|
||||
_value = utc ? timegm (&t) : mktime (&t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <i18n.h>
|
||||
|
||||
std::string Lexer::dateFormat = "";
|
||||
bool Lexer::isoEnabled = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Lexer::Lexer (const std::string& input)
|
||||
@@ -732,15 +733,18 @@ void Lexer::dequote (std::string& input)
|
||||
bool Lexer::is_date (std::string& result)
|
||||
{
|
||||
// Try an ISO date parse.
|
||||
std::string::size_type iso_i = 0;
|
||||
std::string iso_result;
|
||||
ISO8601d iso;
|
||||
iso.ambiguity (_ambiguity);
|
||||
if (iso.parse (_input.substr (_shift_counter), iso_i))
|
||||
if (isoEnabled)
|
||||
{
|
||||
result = _input.substr (_shift_counter, iso_i);
|
||||
while (iso_i--) shift ();
|
||||
return true;
|
||||
std::string::size_type iso_i = 0;
|
||||
std::string iso_result;
|
||||
ISO8601d iso;
|
||||
iso.ambiguity (_ambiguity);
|
||||
if (iso.parse (_input.substr (_shift_counter), iso_i))
|
||||
{
|
||||
result = _input.substr (_shift_counter, iso_i);
|
||||
while (iso_i--) shift ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try a legacy rc.dateformat parse here.
|
||||
|
||||
@@ -34,6 +34,7 @@ class Lexer
|
||||
{
|
||||
public:
|
||||
static std::string dateFormat;
|
||||
static bool isoEnabled;
|
||||
|
||||
enum Type
|
||||
{
|
||||
|
||||
120
src/TDB2.cpp
120
src/TDB2.cpp
@@ -567,12 +567,12 @@ void TDB2::add (Task& task, bool add_to_backlog /* = true */)
|
||||
if (!verifyUniqueUUID (uuid))
|
||||
throw format (STRING_TDB2_UUID_NOT_UNIQUE, uuid);
|
||||
|
||||
// Create a vector tasks, as hooks can cause them to multiply.
|
||||
std::vector <Task> changes;
|
||||
changes.push_back (task);
|
||||
context.hooks.onAdd (changes);
|
||||
// Only locally-added tasks trigger hooks. This means that tasks introduced
|
||||
// via 'sync' do not trigger hooks.
|
||||
if (add_to_backlog)
|
||||
context.hooks.onAdd (task);
|
||||
|
||||
update (uuid, task, add_to_backlog, changes);
|
||||
update (uuid, task, add_to_backlog);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -584,77 +584,64 @@ void TDB2::modify (Task& task, bool add_to_backlog /* = true */)
|
||||
std::string uuid = task.get ("uuid");
|
||||
|
||||
// Get the unmodified task as reference, so the hook can compare.
|
||||
Task original;
|
||||
get (uuid, original);
|
||||
if (add_to_backlog)
|
||||
{
|
||||
Task original;
|
||||
get (uuid, original);
|
||||
context.hooks.onModify (original, task);
|
||||
}
|
||||
|
||||
// Create a vector tasks, as hooks can cause them to multiply.
|
||||
std::vector <Task> changes;
|
||||
changes.push_back (task);
|
||||
context.hooks.onModify (original, changes);
|
||||
|
||||
update (uuid, task, add_to_backlog, changes);
|
||||
update (uuid, task, add_to_backlog);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB2::update (
|
||||
const std::string& uuid,
|
||||
Task& task,
|
||||
const bool add_to_backlog,
|
||||
std::vector <Task>& changes)
|
||||
const bool add_to_backlog)
|
||||
{
|
||||
std::vector <Task>::iterator i;
|
||||
for (i = changes.begin (); i != changes.end (); ++i)
|
||||
// Validate to add metadata.
|
||||
task.validate (false);
|
||||
|
||||
// If the task already exists, it is a modification, else addition.
|
||||
Task original;
|
||||
if (get (task.get ("uuid"), original))
|
||||
{
|
||||
// Validate to add metadata.
|
||||
i->validate (false);
|
||||
// Update the task, wherever it is.
|
||||
if (!pending.modify_task (task))
|
||||
completed.modify_task (task);
|
||||
|
||||
// If the task already exists, it is a modification, else addition.
|
||||
Task original;
|
||||
if (get (i->get ("uuid"), original))
|
||||
{
|
||||
// Update the task, wherever it is.
|
||||
if (!pending.modify_task (*i))
|
||||
completed.modify_task (*i);
|
||||
|
||||
// time <time>
|
||||
// old <task>
|
||||
// new <task>
|
||||
// ---
|
||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||
undo.add_line ("old " + original.composeF4 () + "\n");
|
||||
undo.add_line ("new " + i->composeF4 () + "\n");
|
||||
undo.add_line ("---\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Re-validate to add default values.
|
||||
i->validate ();
|
||||
|
||||
// Add new task to either pending or completed.
|
||||
std::string status = i->get ("status");
|
||||
if (status == "completed" ||
|
||||
status == "deleted")
|
||||
completed.add_task (*i);
|
||||
else
|
||||
pending.add_task (*i);
|
||||
|
||||
// Add undo data lines:
|
||||
// time <time>
|
||||
// new <task>
|
||||
// ---
|
||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||
undo.add_line ("new " + i->composeF4 () + "\n");
|
||||
undo.add_line ("---\n");
|
||||
}
|
||||
|
||||
// Add task to backlog.
|
||||
if (add_to_backlog)
|
||||
backlog.add_line (i->composeJSON () + "\n");
|
||||
|
||||
// The original task may be further referenced by the caller.
|
||||
if (i->get ("uuid") == uuid)
|
||||
task = *i;
|
||||
// time <time>
|
||||
// old <task>
|
||||
// new <task>
|
||||
// ---
|
||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||
undo.add_line ("old " + original.composeF4 () + "\n");
|
||||
undo.add_line ("new " + task.composeF4 () + "\n");
|
||||
undo.add_line ("---\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add new task to either pending or completed.
|
||||
std::string status = task.get ("status");
|
||||
if (status == "completed" ||
|
||||
status == "deleted")
|
||||
completed.add_task (task);
|
||||
else
|
||||
pending.add_task (task);
|
||||
|
||||
// Add undo data lines:
|
||||
// time <time>
|
||||
// new <task>
|
||||
// ---
|
||||
undo.add_line ("time " + Date ().toEpochString () + "\n");
|
||||
undo.add_line ("new " + task.composeF4 () + "\n");
|
||||
undo.add_line ("---\n");
|
||||
}
|
||||
|
||||
// Add task to backlog.
|
||||
if (add_to_backlog)
|
||||
backlog.add_line (task.composeJSON () + "\n");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -979,6 +966,9 @@ void TDB2::show_diff (
|
||||
view.add (Column::factory ("string", STRING_TDB2_UNDO_PRIOR));
|
||||
view.add (Column::factory ("string", STRING_TDB2_UNDO_CURRENT));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
Task after (current);
|
||||
|
||||
if (prior != "")
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
|
||||
private:
|
||||
void gather_changes ();
|
||||
void update (const std::string&, Task&, const bool, std::vector <Task>&);
|
||||
void update (const std::string&, Task&, const bool);
|
||||
bool verifyUniqueUUID (const std::string&);
|
||||
void show_diff (const std::string&, const std::string&, const std::string&);
|
||||
void revert_undo (std::vector <std::string>&, std::string&, std::string&, std::string&, std::string&);
|
||||
|
||||
47
src/Task.cpp
47
src/Task.cpp
@@ -636,8 +636,9 @@ void Task::parseJSON (const std::string& line)
|
||||
// Dates are converted from ISO to epoch.
|
||||
else if (type == "date")
|
||||
{
|
||||
Date d (unquoteText (i->second->dump ()));
|
||||
set (i->first, d.toEpochString ());
|
||||
std::string text = unquoteText (i->second->dump ());
|
||||
Date d (text);
|
||||
set (i->first, text == "" ? "" : d.toEpochString ());
|
||||
}
|
||||
|
||||
// Tags are an array of JSON strings.
|
||||
@@ -804,6 +805,10 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||
if (i->first.substr (0, 11) == "annotation_")
|
||||
continue;
|
||||
|
||||
// If value is an empty string, do not ever output it
|
||||
if (i->second == "")
|
||||
continue;
|
||||
|
||||
if (attributes_written)
|
||||
out << ",";
|
||||
|
||||
@@ -815,16 +820,22 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||
if (type == "date")
|
||||
{
|
||||
Date d (i->second);
|
||||
if (i->first == "modification")
|
||||
out << "\"modified\":\""
|
||||
<< d.toISO ()
|
||||
<< "\"";
|
||||
else
|
||||
out << "\""
|
||||
<< i->first
|
||||
<< "\":\""
|
||||
<< d.toISO ()
|
||||
<< "\"";
|
||||
out << "\""
|
||||
<< (i->first == "modification" ? "modified" : i->first)
|
||||
<< "\":\""
|
||||
// Date was deleted, do not export parsed empty string
|
||||
<< (i->second == "" ? "" : d.toISO ())
|
||||
<< "\"";
|
||||
|
||||
++attributes_written;
|
||||
}
|
||||
|
||||
else if (type == "numeric")
|
||||
{
|
||||
out << "\""
|
||||
<< i->first
|
||||
<< "\":"
|
||||
<< i->second;
|
||||
|
||||
++attributes_written;
|
||||
}
|
||||
@@ -847,6 +858,8 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||
}
|
||||
|
||||
out << "]";
|
||||
|
||||
++attributes_written;
|
||||
}
|
||||
|
||||
// Everything else is a quoted value.
|
||||
@@ -894,9 +907,8 @@ std::string Task::composeJSON (bool decorate /*= false*/) const
|
||||
// Include urgency.
|
||||
if (decorate)
|
||||
out << ","
|
||||
<< "\"urgency\":\""
|
||||
<< urgency_c ()
|
||||
<<"\"";
|
||||
<< "\"urgency\":"
|
||||
<< urgency_c ();
|
||||
#endif
|
||||
|
||||
out << "}";
|
||||
@@ -1112,10 +1124,10 @@ bool Task::hasTag (const std::string& tag) const
|
||||
if (tag == "SCHEDULED") return has ("scheduled");
|
||||
if (tag == "CHILD") return has ("parent");
|
||||
if (tag == "UNTIL") return has ("until");
|
||||
if (tag == "WAITING") return has ("wait");
|
||||
if (tag == "ANNOTATED") return hasAnnotations ();
|
||||
if (tag == "TAGGED") return has ("tags");
|
||||
if (tag == "PARENT") return has ("mask");
|
||||
if (tag == "WAITING") return get ("status") == "waiting";
|
||||
if (tag == "PENDING") return get ("status") == "pending";
|
||||
if (tag == "COMPLETED") return get ("status") == "completed";
|
||||
if (tag == "DELETED") return get ("status") == "deleted";
|
||||
@@ -2068,9 +2080,6 @@ void Task::modify (modType type, bool text_required /* = false */)
|
||||
if (v.type () == Variant::type_string)
|
||||
throw format (STRING_UDA_NUMERIC, v.get_string ());
|
||||
|
||||
v.cast (Variant::type_real);
|
||||
v.cast (Variant::type_string);
|
||||
|
||||
set (name, v);
|
||||
++modCount;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
std::string Variant::dateFormat = "";
|
||||
bool Variant::searchCaseSensitive = true;
|
||||
bool Variant::searchUsingRegex = true;
|
||||
bool Variant::isoEnabled = true;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Variant::Variant ()
|
||||
@@ -2065,7 +2066,8 @@ void Variant::cast (const enum type new_type)
|
||||
|
||||
ISO8601d iso;
|
||||
std::string::size_type pos = 0;
|
||||
if (iso.parse (_string, pos) &&
|
||||
if (isoEnabled &&
|
||||
iso.parse (_string, pos) &&
|
||||
pos == _string.length ())
|
||||
{
|
||||
_date = (time_t) iso;
|
||||
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
static std::string dateFormat;
|
||||
static bool searchCaseSensitive;
|
||||
static bool searchUsingRegex;
|
||||
static bool isoEnabled;
|
||||
|
||||
enum type {type_unknown, type_boolean, type_integer, type_real, type_string,
|
||||
type_date, type_duration};
|
||||
|
||||
@@ -57,7 +57,7 @@ int main (int argc, char** argv)
|
||||
try
|
||||
{
|
||||
bool infix = true;
|
||||
bool ambiguous = true;
|
||||
bool ambiguous = false;
|
||||
|
||||
// Add a source for constants.
|
||||
Eval e;
|
||||
@@ -77,8 +77,8 @@ int main (int argc, char** argv)
|
||||
<< " -d|--debug Debug mode\n"
|
||||
<< " -i|--infix Infix expression (default)\n"
|
||||
<< " -p|--postfix Postfix expression\n"
|
||||
<< " -a|--ambiguous Choose dates over numbers when ambiguous (default)\n"
|
||||
<< " -n|--noambiguous Choose numbers over dates when ambiguous\n"
|
||||
<< " -a|--ambiguous Choose dates over numbers when ambiguous\n"
|
||||
<< " -n|--noambiguous Choose numbers over dates when ambiguous (default)\n"
|
||||
<< "\n";
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class ColumnDate : public Column
|
||||
{
|
||||
public:
|
||||
ColumnDate ();
|
||||
~ColumnDate ();
|
||||
virtual ~ColumnDate ();
|
||||
|
||||
virtual bool validate (std::string&);
|
||||
virtual void measure (Task&, unsigned int&, unsigned int&);
|
||||
|
||||
@@ -284,6 +284,7 @@ int CmdCalendar::execute (std::string& output)
|
||||
Color color_weekend (context.config.get ("color.calendar.weekend"));
|
||||
Color color_holiday (context.config.get ("color.calendar.holiday"));
|
||||
Color color_weeknumber (context.config.get ("color.calendar.weeknumber"));
|
||||
Color color_label (context.config.get ("color.label"));
|
||||
|
||||
if (context.color () && context.config.getBoolean ("calendar.legend"))
|
||||
out << "Legend: "
|
||||
@@ -342,7 +343,6 @@ int CmdCalendar::execute (std::string& output)
|
||||
executable = executable.substr (0, cal) + PACKAGE;
|
||||
|
||||
std::vector <std::string> args;
|
||||
args.push_back (executable);
|
||||
args.push_back ("rc:" + context.rc_file._data);
|
||||
args.push_back ("rc.due:0");
|
||||
args.push_back ("rc.verbose:label,affected,blank");
|
||||
@@ -363,6 +363,7 @@ int CmdCalendar::execute (std::string& output)
|
||||
holTable.width (context.getWidth ());
|
||||
holTable.add (Column::factory ("string", STRING_CMD_CAL_LABEL_DATE));
|
||||
holTable.add (Column::factory ("string", STRING_CMD_CAL_LABEL_HOL));
|
||||
holTable.colorHeader (color_label);
|
||||
|
||||
Config::const_iterator it;
|
||||
std::map <time_t, std::vector<std::string> > hm; // we need to store multiple holidays per day
|
||||
@@ -426,7 +427,10 @@ std::string CmdCalendar::renderMonths (
|
||||
throw std::string (STRING_CMD_CAL_SUN_MON);
|
||||
|
||||
// Build table for the number of months to be displayed.
|
||||
Color label (context.config.get ("color.label"));
|
||||
|
||||
ViewText view;
|
||||
view.colorHeader (label);
|
||||
view.width (context.getWidth ());
|
||||
for (int i = 0 ; i < (monthsPerLine * 8); i += 8)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,9 @@ int CmdColumns::execute (std::string& output)
|
||||
formats.add (Column::factory ("string", STRING_COLUMN_LABEL_STYLES));
|
||||
formats.add (Column::factory ("string", STRING_COLUMN_LABEL_EXAMPLES));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
formats.colorHeader (label);
|
||||
|
||||
Color alternate (context.config.get ("color.alternate"));
|
||||
formats.colorOdd (alternate);
|
||||
formats.intraColorOdd (alternate);
|
||||
|
||||
@@ -312,7 +312,7 @@ int CmdDiagnostics::execute (std::string& output)
|
||||
out << bold.colorize (STRING_CMD_DIAG_HOOKS)
|
||||
<< "\n"
|
||||
<< " Scripts: "
|
||||
<< (context.config.getBoolean ("hooks") ? "Enabled" : "Disabled")
|
||||
<< (context.config.getBoolean ("hooks") ? STRING_CMD_DIAG_HOOK_ENABLE : STRING_CMD_DIAG_HOOK_DISABLE)
|
||||
<< "\n";
|
||||
|
||||
std::vector <std::string> hooks = context.hooks.list ();
|
||||
@@ -322,15 +322,20 @@ int CmdDiagnostics::execute (std::string& output)
|
||||
for (h = hooks.begin (); h != hooks.end (); ++h)
|
||||
{
|
||||
Path p (*h);
|
||||
std::string name = p.name ();
|
||||
out << " "
|
||||
<< *h
|
||||
<< (p.executable () ? " (executable)" : " (not executable)")
|
||||
<< (p.is_link () ? " (symlink)" : "")
|
||||
<< (p.executable () ? format (" ({1})", STRING_CMD_DIAG_HOOK_EXEC) : format (" ({1})", STRING_CMD_DIAG_HOOK_NO_EXEC))
|
||||
<< (p.is_link () ? format (" ({1})", STRING_CMD_DIAG_HOOK_SYMLINK) : "")
|
||||
<< ((name.substr (0, 6) == "on-add" ||
|
||||
name.substr (0, 9) == "on-modify" ||
|
||||
name.substr (0, 9) == "on-launch" ||
|
||||
name.substr (0, 7) == "on-exit") ? "" : format (" ({1})", STRING_CMD_DIAG_HOOK_NAME))
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
out << " (none)\n";
|
||||
out << format (" ({1})\n", STRING_CMD_DIAG_NONE);
|
||||
|
||||
out << "\n";
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ int CmdExport::execute (std::string& output)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
// Make sure reccurent tasks are generated.
|
||||
handleRecurrence ();
|
||||
|
||||
// Apply filter.
|
||||
Filter filter;
|
||||
std::vector <Task> filtered;
|
||||
|
||||
@@ -104,6 +104,9 @@ int CmdHistoryMonthly::execute (std::string& output)
|
||||
view.add (Column::factory ("string.right", STRING_CMD_HISTORY_DEL));
|
||||
view.add (Column::factory ("string.right", STRING_CMD_HISTORY_NET));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
int totalAdded = 0;
|
||||
int totalCompleted = 0;
|
||||
int totalDeleted = 0;
|
||||
@@ -257,6 +260,9 @@ int CmdHistoryAnnual::execute (std::string& output)
|
||||
view.add (Column::factory ("string.right", STRING_CMD_HISTORY_DEL));
|
||||
view.add (Column::factory ("string.right", STRING_CMD_HISTORY_NET));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
int totalAdded = 0;
|
||||
int totalCompleted = 0;
|
||||
int totalDeleted = 0;
|
||||
@@ -411,6 +417,9 @@ int CmdGHistoryMonthly::execute (std::string& output)
|
||||
Color color_add (context.config.get ("color.history.add"));
|
||||
Color color_done (context.config.get ("color.history.done"));
|
||||
Color color_delete (context.config.get ("color.history.delete"));
|
||||
Color label (context.config.get ("color.label"));
|
||||
|
||||
view.colorHeader (label);
|
||||
|
||||
// Determine the longest line, and the longest "added" line.
|
||||
int maxAddedLine = 0;
|
||||
@@ -603,6 +612,9 @@ int CmdGHistoryAnnual::execute (std::string& output)
|
||||
Color color_add (context.config.get ("color.history.add"));
|
||||
Color color_done (context.config.get ("color.history.done"));
|
||||
Color color_delete (context.config.get ("color.history.delete"));
|
||||
Color label (context.config.get ("color.label"));
|
||||
|
||||
view.colorHeader (label);
|
||||
|
||||
// Determine the longest line, and the longest "added" line.
|
||||
int maxAddedLine = 0;
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <Filter.h>
|
||||
#include <Date.h>
|
||||
#include <Duration.h>
|
||||
#include <ViewText.h>
|
||||
#include <main.h>
|
||||
#include <text.h>
|
||||
#include <i18n.h>
|
||||
@@ -106,6 +105,9 @@ int CmdInfo::execute (std::string& output)
|
||||
Color alternate (context.config.get ("color.alternate"));
|
||||
view.colorOdd (alternate);
|
||||
view.intraColorOdd (alternate);
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
}
|
||||
|
||||
Date now;
|
||||
@@ -321,62 +323,7 @@ int CmdInfo::execute (std::string& output)
|
||||
// Task::urgency
|
||||
row = view.addRow ();
|
||||
view.set (row, 0, STRING_COLUMN_LABEL_URGENCY);
|
||||
|
||||
std::string urgency =
|
||||
trimLeft (format (task->urgency (), 4, 4)) + "\n" +
|
||||
urgencyTerm ("project", task->urgency_project (), Task::urgencyProjectCoefficient) +
|
||||
urgencyTerm ("priority", task->urgency_priority (), Task::urgencyPriorityCoefficient) +
|
||||
urgencyTerm ("active", task->urgency_active (), Task::urgencyActiveCoefficient) +
|
||||
urgencyTerm ("scheduled", task->urgency_scheduled (), Task::urgencyScheduledCoefficient) +
|
||||
urgencyTerm ("waiting", task->urgency_waiting (), Task::urgencyWaitingCoefficient) +
|
||||
urgencyTerm ("blocked", task->urgency_blocked (), Task::urgencyBlockedCoefficient) +
|
||||
urgencyTerm ("blocking", task->urgency_blocking (), Task::urgencyBlockingCoefficient) +
|
||||
urgencyTerm ("annotations", task->urgency_annotations (), Task::urgencyAnnotationsCoefficient) +
|
||||
urgencyTerm ("tags", task->urgency_tags (), Task::urgencyTagsCoefficient) +
|
||||
urgencyTerm ("next", task->urgency_next (), Task::urgencyNextCoefficient) +
|
||||
urgencyTerm ("due", task->urgency_due (), Task::urgencyDueCoefficient) +
|
||||
urgencyTerm ("age", task->urgency_age (), Task::urgencyAgeCoefficient);
|
||||
|
||||
// Tag, Project- and UDA-specific coefficients.
|
||||
std::map <std::string, float>::iterator var;
|
||||
for (var = Task::coefficients.begin (); var != Task::coefficients.end (); ++var)
|
||||
{
|
||||
if (var->first.substr (0, 13) == "urgency.user.")
|
||||
{
|
||||
// urgency.user.project.<project>.coefficient
|
||||
std::string::size_type end = std::string::npos;
|
||||
if (var->first.substr (13, 8) == "project." &&
|
||||
(end = var->first.find (".coefficient")) != std::string::npos)
|
||||
{
|
||||
std::string project = var->first.substr (21, end - 21);
|
||||
if (task->get ("project").find (project) == 0)
|
||||
urgency += urgencyTerm ("PROJECT " + project, 1.0, var->second);
|
||||
}
|
||||
|
||||
// urgency.user.tag.<tag>.coefficient
|
||||
if (var->first.substr (13, 4) == "tag." &&
|
||||
(end = var->first.find (".coefficient")) != std::string::npos)
|
||||
{
|
||||
std::string name = var->first.substr (17, end - 17);
|
||||
if (task->hasTag (name))
|
||||
urgency += urgencyTerm ("TAG " + name, 1.0, var->second);
|
||||
}
|
||||
}
|
||||
|
||||
// urgency.uda.<name>.coefficient
|
||||
else if (var->first.substr (0, 12) == "urgency.uda.")
|
||||
{
|
||||
std::string::size_type end = var->first.find (".coefficient");
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
std::string name = var->first.substr (12, end - 12);
|
||||
if (task->has (name))
|
||||
urgency += urgencyTerm ("UDA " + name, 1.0, var->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view.set (row, 1, urgency);
|
||||
view.set (row, 1, format (task->urgency (), 4, 4));
|
||||
|
||||
// Show any UDAs
|
||||
std::vector <std::string> all = task->all ();
|
||||
@@ -410,6 +357,7 @@ int CmdInfo::execute (std::string& output)
|
||||
// Show any orphaned UDAs, which are identified by not being represented in
|
||||
// the context.columns map.
|
||||
for (att = all.begin (); att != all.end (); ++att)
|
||||
{
|
||||
if (att->substr (0, 11) != "annotation_" &&
|
||||
context.columns.find (*att) == context.columns.end ())
|
||||
{
|
||||
@@ -417,8 +365,86 @@ int CmdInfo::execute (std::string& output)
|
||||
view.set (row, 0, "[" + *att);
|
||||
view.set (row, 1, task->get (*att) + "]");
|
||||
}
|
||||
}
|
||||
|
||||
// Create a second table, containing undo log change details.
|
||||
// Create a second table, containing urgency details.
|
||||
ViewText urgencyDetails;
|
||||
if (context.color ())
|
||||
{
|
||||
Color alternate (context.config.get ("color.alternate"));
|
||||
urgencyDetails.colorOdd (alternate);
|
||||
urgencyDetails.intraColorOdd (alternate);
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
urgencyDetails.colorHeader (label);
|
||||
}
|
||||
|
||||
urgencyDetails.width (context.getWidth ());
|
||||
urgencyDetails.add (Column::factory ("string", "")); // Attribute
|
||||
urgencyDetails.add (Column::factory ("string", "")); // Value
|
||||
urgencyDetails.add (Column::factory ("string", "")); // *
|
||||
urgencyDetails.add (Column::factory ("string", "")); // Coefficient
|
||||
urgencyDetails.add (Column::factory ("string", "")); // =
|
||||
urgencyDetails.add (Column::factory ("string", "")); // Result
|
||||
|
||||
urgencyTerm (urgencyDetails, "project", task->urgency_project (), Task::urgencyProjectCoefficient);
|
||||
urgencyTerm (urgencyDetails, "priority", task->urgency_priority (), Task::urgencyPriorityCoefficient);
|
||||
urgencyTerm (urgencyDetails, "active", task->urgency_active (), Task::urgencyActiveCoefficient);
|
||||
urgencyTerm (urgencyDetails, "scheduled", task->urgency_scheduled (), Task::urgencyScheduledCoefficient);
|
||||
urgencyTerm (urgencyDetails, "waiting", task->urgency_waiting (), Task::urgencyWaitingCoefficient);
|
||||
urgencyTerm (urgencyDetails, "blocked", task->urgency_blocked (), Task::urgencyBlockedCoefficient);
|
||||
urgencyTerm (urgencyDetails, "blocking", task->urgency_blocking (), Task::urgencyBlockingCoefficient);
|
||||
urgencyTerm (urgencyDetails, "annotations", task->urgency_annotations (), Task::urgencyAnnotationsCoefficient);
|
||||
urgencyTerm (urgencyDetails, "tags", task->urgency_tags (), Task::urgencyTagsCoefficient);
|
||||
urgencyTerm (urgencyDetails, "next", task->urgency_next (), Task::urgencyNextCoefficient);
|
||||
urgencyTerm (urgencyDetails, "due", task->urgency_due (), Task::urgencyDueCoefficient);
|
||||
urgencyTerm (urgencyDetails, "age", task->urgency_age (), Task::urgencyAgeCoefficient);
|
||||
|
||||
// Tag, Project- and UDA-specific coefficients.
|
||||
std::map <std::string, float>::iterator var;
|
||||
for (var = Task::coefficients.begin (); var != Task::coefficients.end (); ++var)
|
||||
{
|
||||
if (var->first.substr (0, 13) == "urgency.user.")
|
||||
{
|
||||
// urgency.user.project.<project>.coefficient
|
||||
std::string::size_type end = std::string::npos;
|
||||
if (var->first.substr (13, 8) == "project." &&
|
||||
(end = var->first.find (".coefficient")) != std::string::npos)
|
||||
{
|
||||
std::string project = var->first.substr (21, end - 21);
|
||||
if (task->get ("project").find (project) == 0)
|
||||
urgencyTerm (urgencyDetails, "PROJECT " + project, 1.0, var->second);
|
||||
}
|
||||
|
||||
// urgency.user.tag.<tag>.coefficient
|
||||
if (var->first.substr (13, 4) == "tag." &&
|
||||
(end = var->first.find (".coefficient")) != std::string::npos)
|
||||
{
|
||||
std::string name = var->first.substr (17, end - 17);
|
||||
if (task->hasTag (name))
|
||||
urgencyTerm (urgencyDetails, "TAG " + name, 1.0, var->second);
|
||||
}
|
||||
}
|
||||
|
||||
// urgency.uda.<name>.coefficient
|
||||
else if (var->first.substr (0, 12) == "urgency.uda.")
|
||||
{
|
||||
std::string::size_type end = var->first.find (".coefficient");
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
std::string name = var->first.substr (12, end - 12);
|
||||
if (task->has (name))
|
||||
urgencyTerm (urgencyDetails, "UDA " + name, 1.0, var->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
row = urgencyDetails.addRow ();
|
||||
urgencyDetails.set (row, 5, rightJustify ("------", 6));
|
||||
row = urgencyDetails.addRow ();
|
||||
urgencyDetails.set (row, 5, rightJustify (format (task->urgency (), 4, 4), 6));
|
||||
|
||||
// Create a third table, containing undo log change details.
|
||||
ViewText journal;
|
||||
|
||||
// If an alternating row color is specified, notify the table.
|
||||
@@ -427,6 +453,9 @@ int CmdInfo::execute (std::string& output)
|
||||
Color alternate (context.config.get ("color.alternate"));
|
||||
journal.colorOdd (alternate);
|
||||
journal.intraColorOdd (alternate);
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
journal.colorHeader (label);
|
||||
}
|
||||
|
||||
journal.width (context.getWidth ());
|
||||
@@ -473,6 +502,10 @@ int CmdInfo::execute (std::string& output)
|
||||
<< view.render ()
|
||||
<< "\n";
|
||||
|
||||
if (urgencyDetails.rows () > 0)
|
||||
out << urgencyDetails.render ()
|
||||
<< "\n";
|
||||
|
||||
if (journal.rows () > 0)
|
||||
out << journal.render ()
|
||||
<< "\n";
|
||||
@@ -483,24 +516,23 @@ int CmdInfo::execute (std::string& output)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string CmdInfo::urgencyTerm (
|
||||
void CmdInfo::urgencyTerm (
|
||||
ViewText& view,
|
||||
const std::string& label,
|
||||
float measure,
|
||||
float coefficient) const
|
||||
{
|
||||
float value = measure * coefficient;
|
||||
if (fabsf (value) > epsilon)
|
||||
return std::string (
|
||||
rightJustify (label, 20) +
|
||||
" " +
|
||||
leftJustify (format (measure, 5, 3), 6) +
|
||||
" * " +
|
||||
leftJustify (format (coefficient, 4, 2), 4) +
|
||||
" = " +
|
||||
leftJustify (format (value, 5, 3), 5) +
|
||||
"\n");
|
||||
|
||||
return "";
|
||||
if (value != 0.0)
|
||||
{
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, " " + label);
|
||||
view.set (row, 1, rightJustify (format (measure, 5, 3), 6));
|
||||
view.set (row, 2, "+");
|
||||
view.set (row, 3, rightJustify (format (coefficient, 4, 2), 4));
|
||||
view.set (row, 4, "=");
|
||||
view.set (row, 5, rightJustify (format (value, 5, 3), 6));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <Command.h>
|
||||
#include <ViewText.h>
|
||||
|
||||
class CmdInfo : public Command
|
||||
{
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
int execute (std::string&);
|
||||
|
||||
private:
|
||||
std::string urgencyTerm (const std::string&, float, float) const;
|
||||
void urgencyTerm (ViewText&, const std::string&, float, float) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,9 @@ int CmdProjects::execute (std::string& output)
|
||||
view.add (Column::factory ("string", STRING_COLUMN_LABEL_PROJECT));
|
||||
view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_TASKS));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
std::vector <std::string> processed;
|
||||
std::map <std::string, int>::iterator project;
|
||||
for (project = unique.begin (); project != unique.end (); ++project)
|
||||
|
||||
@@ -85,6 +85,9 @@ int CmdReports::execute (std::string& output)
|
||||
view.add (Column::factory ("string", STRING_CMD_REPORTS_REPORT));
|
||||
view.add (Column::factory ("string", STRING_CMD_REPORTS_DESC));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
// If an alternating row color is specified, notify the table.
|
||||
if (context.color ())
|
||||
{
|
||||
|
||||
@@ -134,6 +134,7 @@ int CmdShow::execute (std::string& output)
|
||||
" dateformat.holiday"
|
||||
" dateformat.info"
|
||||
" dateformat.report"
|
||||
" date.iso"
|
||||
" debug"
|
||||
" debug.hooks"
|
||||
" debug.parser"
|
||||
@@ -171,6 +172,7 @@ int CmdShow::execute (std::string& output)
|
||||
" monthsperline"
|
||||
" nag"
|
||||
" print.empty.columns"
|
||||
" recurrence"
|
||||
" recurrence.confirmation"
|
||||
" recurrence.indicator"
|
||||
" recurrence.limit"
|
||||
@@ -260,6 +262,9 @@ int CmdShow::execute (std::string& output)
|
||||
|
||||
Color error (context.config.get ("color.error"));
|
||||
Color warning (context.config.get ("color.warning"));
|
||||
Color label (context.config.get ("color.label"));
|
||||
|
||||
view.colorHeader (label);
|
||||
|
||||
bool issue_error = false;
|
||||
bool issue_warning = false;
|
||||
|
||||
@@ -160,6 +160,9 @@ int CmdStats::execute (std::string& output)
|
||||
view.add (Column::factory ("string", STRING_CMD_STATS_CATEGORY));
|
||||
view.add (Column::factory ("string", STRING_CMD_STATS_DATA));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
int row = view.addRow ();
|
||||
view.set (row, 0, STRING_COLUMN_LABEL_STAT_PE);
|
||||
view.set (row, 1, pendingT);
|
||||
|
||||
@@ -127,7 +127,7 @@ int CmdSummary::execute (std::string& output)
|
||||
|
||||
Color bar_color (context.config.get ("color.summary.bar"));
|
||||
Color bg_color (context.config.get ("color.summary.background"));
|
||||
Color label (context.config.get ("color.label"));
|
||||
Color label (context.config.get ("color.label"));
|
||||
|
||||
view.colorHeader (label);
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@ int CmdTags::execute (std::string& output)
|
||||
view.add (Column::factory ("string", STRING_COLUMN_LABEL_TAG));
|
||||
view.add (Column::factory ("string.right", STRING_COLUMN_LABEL_COUNT));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
Color bold ("bold");
|
||||
bool special = false;
|
||||
std::map <std::string, int>::iterator i;
|
||||
|
||||
@@ -99,6 +99,9 @@ int CmdTimesheet::execute (std::string& output)
|
||||
completed.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
|
||||
completed.add (Column::factory ("string", STRING_COLUMN_LABEL_DESC));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
completed.colorHeader (label);
|
||||
|
||||
std::vector <Task>::iterator task;
|
||||
for (task = all.begin (); task != all.end (); ++task)
|
||||
{
|
||||
@@ -155,6 +158,7 @@ int CmdTimesheet::execute (std::string& output)
|
||||
started.add (Column::factory ("string", STRING_COLUMN_LABEL_PROJECT));
|
||||
started.add (Column::factory ("string.right", STRING_COLUMN_LABEL_DUE));
|
||||
started.add (Column::factory ("string", STRING_COLUMN_LABEL_DESC));
|
||||
started.colorHeader (label);
|
||||
|
||||
for (task = all.begin (); task != all.end (); ++task)
|
||||
{
|
||||
|
||||
@@ -87,6 +87,9 @@ int CmdUDAs::execute (std::string& output)
|
||||
view.add (Column::factory ("string", STRING_COLUMN_LABEL_DEFAULT));
|
||||
view.add (Column::factory ("string", STRING_COLUMN_LABEL_UDACOUNT));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
view.colorHeader (label);
|
||||
|
||||
std::vector <std::string>::iterator uda;
|
||||
for (uda = udas.begin (); uda != udas.end (); ++uda)
|
||||
{
|
||||
@@ -147,6 +150,9 @@ int CmdUDAs::execute (std::string& output)
|
||||
orphanView.add (Column::factory ("string", STRING_COLUMN_LABEL_ORPHAN));
|
||||
orphanView.add (Column::factory ("string", STRING_COLUMN_LABEL_UDACOUNT));
|
||||
|
||||
Color label (context.config.get ("color.label"));
|
||||
orphanView.colorHeader (label);
|
||||
|
||||
std::map <std::string, int>::iterator o;
|
||||
for (o = orphans.begin (); o != orphans.end (); ++o)
|
||||
{
|
||||
|
||||
@@ -163,29 +163,27 @@ void Command::factory (std::map <std::string, Command*>& all)
|
||||
|
||||
// Instantiate a command object for each custom report.
|
||||
std::vector <std::string> reports;
|
||||
Config::const_iterator i;
|
||||
for (i = context.config.begin (); i != context.config.end (); ++i)
|
||||
for (auto &i : context.config)
|
||||
{
|
||||
if (i->first.substr (0, 7) == "report.")
|
||||
if (i.first.substr (0, 7) == "report.")
|
||||
{
|
||||
std::string report = i->first.substr (7);
|
||||
std::string report = i.first.substr (7);
|
||||
std::string::size_type columns = report.find (".columns");
|
||||
if (columns != std::string::npos)
|
||||
reports.push_back (report.substr (0, columns));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector <std::string>::iterator report;
|
||||
for (report = reports.begin (); report != reports.end (); ++report)
|
||||
for (auto &report : reports)
|
||||
{
|
||||
// Make sure a custom report does not clash with a built-in command.
|
||||
if (all.find (*report) != all.end ())
|
||||
throw format (STRING_CMD_CONFLICT, *report);
|
||||
if (all.find (report) != all.end ())
|
||||
throw format (STRING_CMD_CONFLICT, report);
|
||||
|
||||
c = new CmdCustom (
|
||||
*report,
|
||||
"task <filter> " + *report,
|
||||
context.config.get ("report." + *report + ".description"));
|
||||
report,
|
||||
"task <filter> " + report,
|
||||
context.config.get ("report." + report + ".description"));
|
||||
|
||||
all[c->keyword ()] = c;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <cmake.h>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <Context.h>
|
||||
#include <main.h>
|
||||
@@ -53,7 +54,7 @@ int Context::getWidth ()
|
||||
terminal_height == 0)
|
||||
{
|
||||
unsigned short buff[4];
|
||||
if (ioctl (fileno(stdout), TIOCGWINSZ, &buff) != -1)
|
||||
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1)
|
||||
{
|
||||
terminal_height = buff[0];
|
||||
terminal_width = buff[1];
|
||||
@@ -88,7 +89,7 @@ int Context::getHeight ()
|
||||
terminal_height == 0)
|
||||
{
|
||||
unsigned short buff[4];
|
||||
if (ioctl (fileno(stdout), TIOCGWINSZ, &buff) != -1)
|
||||
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &buff) != -1)
|
||||
{
|
||||
terminal_height = buff[0];
|
||||
terminal_width = buff[1];
|
||||
|
||||
1016
src/l10n/deu-DEU.h
Normal file
1016
src/l10n/deu-DEU.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -489,6 +489,8 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "Handshake failed. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "You should either provide a CA certificate or override verification, but not both."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Platform, build and environment details"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Platform"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<unknown>"
|
||||
@@ -510,6 +512,13 @@
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "No duplicates found"
|
||||
#define STRING_CMD_DIAG_NONE "-none-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Hooks"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
@@ -788,6 +797,18 @@
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Error: missing value after ',' at position {1}"
|
||||
#define STRING_JSON_MISSING_VALUE2 "Error: missing value at position {1}"
|
||||
@@ -970,7 +991,7 @@
|
||||
|
||||
/*
|
||||
To be included later, before the 'precendence' line.
|
||||
|
||||
|
||||
" + - Addition, subtraction\n" \
|
||||
" ! Inversion\n" \
|
||||
" ~ !~ Match, no match\n" \
|
||||
@@ -990,4 +1011,3 @@
|
||||
#define STRING_UTIL_BYTES "B"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -489,64 +489,73 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "Handshake failed. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "You should either provide a CA certificate or override verification, but not both."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
#define STRING_CMD_DIAG_USAGE "Operaciuma, kompila, kaj media detaloj"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Operaciumo"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<nekonata>"
|
||||
#define STRING_CMD_DIAG_COMPILER "Kompililo"
|
||||
#define STRING_CMD_DIAG_VERSION "Versio"
|
||||
#define STRING_CMD_DIAG_CAPS "Eblecoj"
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Platform, build and environment details"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Platform"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<unknown>"
|
||||
#define STRING_CMD_DIAG_COMPILER "Compiler"
|
||||
#define STRING_CMD_DIAG_VERSION "Version"
|
||||
#define STRING_CMD_DIAG_CAPS "Caps"
|
||||
#define STRING_CMD_DIAG_COMPLIANCE "Compliance"
|
||||
#define STRING_CMD_DIAG_FEATURES "Trajtoj de la Kompilo"
|
||||
#define STRING_CMD_DIAG_BUILT "Kompilita"
|
||||
#define STRING_CMD_DIAG_COMMIT "Ŝanĝaro"
|
||||
#define STRING_CMD_DIAG_FOUND "(trovita)"
|
||||
#define STRING_CMD_DIAG_MISSING "(mankanta)"
|
||||
#define STRING_CMD_DIAG_ENABLED "Ebligita"
|
||||
#define STRING_CMD_DIAG_DISABLED "Malebligita"
|
||||
#define STRING_CMD_DIAG_CONFIG "Agordo"
|
||||
#define STRING_CMD_DIAG_TESTS "Testoj"
|
||||
#define STRING_CMD_DIAG_UUID_SCAN "Skanis {1} taskojn por trovi identajn UUID-identigilojn:"
|
||||
#define STRING_CMD_DIAG_UUID_DUP "Trovis ĝemelan taskon {1}"
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "Ne trovis nenian ĝemelan taskon"
|
||||
#define STRING_CMD_DIAG_NONE "-nenio-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Hokoj"
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Produktas liston de ĉia komando, por motivo memkompletada"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Produktas liston de ĉia komando, por motivo memkompletada en zsh"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Produktas liston de ĉia komando, por motivo memkompletada en zsh"
|
||||
#define STRING_CMD_ALIASES_USAGE "Produktas liston de ĉia alinomo, por motivo memkompletada"
|
||||
#define STRING_CMD_INSTALL_USAGE "Instalas kromprogramojn kaj eksternajn skribojn"
|
||||
#define STRING_CMD_DIAG_FEATURES "Build Features"
|
||||
#define STRING_CMD_DIAG_BUILT "Built"
|
||||
#define STRING_CMD_DIAG_COMMIT "Commit"
|
||||
#define STRING_CMD_DIAG_FOUND "(found)"
|
||||
#define STRING_CMD_DIAG_MISSING "(missing)"
|
||||
#define STRING_CMD_DIAG_ENABLED "Enabled"
|
||||
#define STRING_CMD_DIAG_DISABLED "Disabled"
|
||||
#define STRING_CMD_DIAG_CONFIG "Configuration"
|
||||
#define STRING_CMD_DIAG_TESTS "Tests"
|
||||
#define STRING_CMD_DIAG_UUID_SCAN "Scanned {1} tasks for duplicate UUIDs:"
|
||||
#define STRING_CMD_DIAG_UUID_DUP "Found duplicate {1}"
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "No duplicates found"
|
||||
#define STRING_CMD_DIAG_NONE "-none-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Hooks"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_MODIFY_USAGE1 "Modifas ekzistantan taskon kun argumentoj provizataj."
|
||||
#define STRING_CMD_MODIFY_NO_DUE "Oni ne povas specifi reokazantan taskon sen datlimo."
|
||||
#define STRING_CMD_MODIFY_REM_DUE "Oni ne povas viŝi la datlimon de reokazanta tasko."
|
||||
#define STRING_CMD_MODIFY_REC_ALWAYS "Oni ne povas viŝi la reokazon de reokazanta tasko."
|
||||
#define STRING_CMD_MODIFY_TASK "Modifanta taskon {1} '{2}'."
|
||||
#define STRING_CMD_MODIFY_TASK_R "Modifanta reokazantan taskon {1} '{2}'."
|
||||
#define STRING_CMD_MODIFY_1 "Modifis {1} taskon."
|
||||
#define STRING_CMD_MODIFY_N "Modifis {1} taskojn."
|
||||
#define STRING_CMD_MODIFY_NO "Ne modifis taskon."
|
||||
#define STRING_CMD_MODIFY_CONFIRM "Modifi taskon {1} '{2}'?"
|
||||
#define STRING_CMD_MODIFY_RECUR "Tio estas reokazanta tasko. Ĉu vi volas modifi ĉian pendantan okazon?"
|
||||
#define STRING_CMD_MODIFY_NEED_TEXT "Oni devas provizi plu de teksto."
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
#define STRING_CMD_ALIASES_USAGE "Generates a list of all aliases, for autocompletion purposes"
|
||||
#define STRING_CMD_INSTALL_USAGE "Installs extensions and external scripts"
|
||||
|
||||
#define STRING_CMD_COLOR_USAGE "Ĉia koloro, ekzemplero, aŭ gamo"
|
||||
#define STRING_CMD_COLOR_HERE "Jen la koloroj ke estas aktuale uzataj:"
|
||||
#define STRING_CMD_COLOR_COLOR "Koloro"
|
||||
#define STRING_CMD_COLOR_DEFINITION "Difino"
|
||||
#define STRING_CMD_COLOR_EXPLANATION "Uzu tiun komandon por vidi, kiel koloroj aspektas ĉe via terminalo."
|
||||
#define STRING_CMD_COLOR_16 "Uzo 16-koloraj (subtenas substrekon, grasan tekston, brilan fonon):"
|
||||
#define STRING_CMD_COLOR_256 "Uzo 256-koloraj (subtenas substrekon):"
|
||||
#define STRING_CMD_COLOR_YOURS "Via ekzemplero:"
|
||||
#define STRING_CMD_COLOR_BASIC "Principaj koloroj"
|
||||
#define STRING_CMD_COLOR_EFFECTS "Efektoj"
|
||||
#define STRING_CMD_COLOR_CUBE "Kolorkubo rgb"
|
||||
#define STRING_CMD_COLOR_RAMP "Grizramplo"
|
||||
#define STRING_CMD_COLOR_TRY "Provu lanĉi '{1}'."
|
||||
#define STRING_CMD_COLOR_OFF "Koloroj estas aktuale malebligita ĉe via dosiero .taskrc. Por ebligi kolorojn, viŝi la vicon 'color=off', aŭ ŝanĝu 'off' al 'on'."
|
||||
#define STRING_CMD_CONFIG_USAGE "Ŝanĝas agordoj de task"
|
||||
#define STRING_CMD_CONFIG_CONFIRM "Ĉu vi estas certa, ke vi volas ŝanĝi la valoron de '{1}', de '{2}' al '{3}'?"
|
||||
#define STRING_CMD_CONFIG_CONFIRM2 "Ĉu vi estas certa, ke vi volas aldoni '{1}' kun valoro '{2}'?"
|
||||
#define STRING_CMD_CONFIG_CONFIRM3 "Ĉu vi estas certa, ke vi volas viŝi '{1}'?"
|
||||
#define STRING_CMD_MODIFY_USAGE1 "Modifies the existing task with provided arguments."
|
||||
#define STRING_CMD_MODIFY_NO_DUE "You cannot specify a recurring task without a due date."
|
||||
#define STRING_CMD_MODIFY_REM_DUE "You cannot remove the due date from a recurring task."
|
||||
#define STRING_CMD_MODIFY_REC_ALWAYS "You cannot remove the recurrence from a recurring task."
|
||||
#define STRING_CMD_MODIFY_TASK "Modifying task {1} '{2}'."
|
||||
#define STRING_CMD_MODIFY_TASK_R "Modifying recurring task {1} '{2}'."
|
||||
#define STRING_CMD_MODIFY_1 "Modified {1} task."
|
||||
#define STRING_CMD_MODIFY_N "Modified {1} tasks."
|
||||
#define STRING_CMD_MODIFY_NO "Task not modified."
|
||||
#define STRING_CMD_MODIFY_CONFIRM "Modify task {1} '{2}'?"
|
||||
#define STRING_CMD_MODIFY_RECUR "This is a recurring task. Do you want to modify all pending recurrences of this same task?"
|
||||
#define STRING_CMD_MODIFY_NEED_TEXT "Additional text must be provided."
|
||||
|
||||
#define STRING_CMD_COLOR_USAGE "All colors, a sample, or a legend"
|
||||
#define STRING_CMD_COLOR_HERE "Here are the colors currently in use:"
|
||||
#define STRING_CMD_COLOR_COLOR "Color"
|
||||
#define STRING_CMD_COLOR_DEFINITION "Definition"
|
||||
#define STRING_CMD_COLOR_EXPLANATION "Use this command to see how colors are displayed by your terminal."
|
||||
#define STRING_CMD_COLOR_16 "16-color usage (supports underline, bold text, bright background):"
|
||||
#define STRING_CMD_COLOR_256 "256-color usage (supports underline):"
|
||||
#define STRING_CMD_COLOR_YOURS "Your sample:"
|
||||
#define STRING_CMD_COLOR_BASIC "Basic colors"
|
||||
#define STRING_CMD_COLOR_EFFECTS "Effects"
|
||||
#define STRING_CMD_COLOR_CUBE "Color cube rgb"
|
||||
#define STRING_CMD_COLOR_RAMP "Gray ramp"
|
||||
#define STRING_CMD_COLOR_TRY "Try running '{1}'."
|
||||
#define STRING_CMD_COLOR_OFF "Color is currently turned off in your .taskrc file. To enable color, remove the line 'color=off', or change the 'off' to 'on'."
|
||||
#define STRING_CMD_CONFIG_USAGE "Change settings in the task configuration"
|
||||
#define STRING_CMD_CONFIG_CONFIRM "Are you sure you want to change the value of '{1}' from '{2}' to '{3}'?"
|
||||
#define STRING_CMD_CONFIG_CONFIRM2 "Are you sure you want to add '{1}' with a value of '{2}'?"
|
||||
#define STRING_CMD_CONFIG_CONFIRM3 "Are you sure you want to remove '{1}'?"
|
||||
#define STRING_CMD_CONFIG_NO_ENTRY "No entry named '{1}' found."
|
||||
#define STRING_CMD_CONFIG_FILE_MOD "Agorda dosiero {1} modifita."
|
||||
#define STRING_CMD_CONFIG_NO_CHANGE "Ne ŝanĝis nenion."
|
||||
@@ -783,10 +792,22 @@
|
||||
#define STRING_FILE_PERMS "Taskwarrior ne havas la bezonatan permeson por '{1}'."
|
||||
|
||||
// helpers
|
||||
#define STRING_HELPER_PROJECT_CHANGE "Projekto '{1}' ŝanĝis."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Projekto '{1}' estas {2}% kompleta"
|
||||
#define STRING_HELPER_PROJECT_REM "(Restas {1} de {2} taskoj)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "(Restas {1} tasko)."
|
||||
#define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete"
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Eraro: mankas valoro post ',' ĉe pozicio {1}"
|
||||
@@ -970,7 +991,7 @@
|
||||
|
||||
/*
|
||||
To be included later, before the 'precendence' line.
|
||||
|
||||
|
||||
" + - Addition, subtraction\n" \
|
||||
" ! Inversion\n" \
|
||||
" ~ !~ Match, no match\n" \
|
||||
@@ -990,4 +1011,3 @@
|
||||
#define STRING_UTIL_BYTES "B"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
// 1. Copy this file (eng-USA.h) to a new file with the target locale as the
|
||||
// file name. Using German as an example, do this:
|
||||
//
|
||||
// cp eng-USA.h de-DE.h
|
||||
// cp eng-USA.h deu-DEU.h
|
||||
//
|
||||
// 2. Modify all the strings below.
|
||||
// i.e. change "Unknown error." to "Unbekannter Fehler.".
|
||||
@@ -67,7 +67,7 @@
|
||||
// by inserting:
|
||||
//
|
||||
// #elif PACKAGE_LANGUAGE == LANGUAGE_DEU_DEU
|
||||
// #include <de-DE.h>
|
||||
// #include <deu-DEU.h>
|
||||
//
|
||||
// 4. Add your new language to task.git/CMakeLists.txt, making sure that
|
||||
// number is unique:
|
||||
@@ -471,6 +471,7 @@
|
||||
#define STRING_TASK_NO_DESC "La anotación carece de descripción: {1}"
|
||||
#define STRING_TASK_NO_ENTRY "La anotación carece de fecha de entrada: {1}"
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_SYNC_USAGE "Sincroniza datos con el Servidor Task"
|
||||
#define STRING_CMD_SYNC_NO_SERVER "El Servidor Task no está configurado."
|
||||
#define STRING_CMD_SYNC_BAD_CRED "Credenciales del Servidor Task incorrectas."
|
||||
@@ -521,6 +522,11 @@
|
||||
#define STRING_CMD_DIAG_HOOKS "Hooks" // |esp-ESP|==|eng-USA|
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Genera una lista de todos los comandos, con fines de auto-completado"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Genera una lista de todos los comandos, con fines de auto-completado zsh"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
#define STRING_CMD_ALIASES_USAGE "Genera una lista de todos los alias, con fines de auto-completado"
|
||||
#define STRING_CMD_INSTALL_USAGE "Instala extensiones y scripts externos"
|
||||
@@ -795,10 +801,22 @@
|
||||
#define STRING_FILE_PERMS "Taskwarrior no tiene los permisos adecuados para '{1}'."
|
||||
|
||||
// helpers
|
||||
#define STRING_HELPER_PROJECT_CHANGE "El proyecto '{1}' ha cambiado."
|
||||
#define STRING_HELPER_PROJECT_COMPL "El proyecto '{1}' se ha completado en un {2}%"
|
||||
#define STRING_HELPER_PROJECT_REM "(quedan {1} de {2} tareas)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "(quada {1} tasko)."
|
||||
#define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete"
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Error: falta valor después de ',' en posición {1}"
|
||||
@@ -1018,4 +1036,3 @@
|
||||
#define STRING_UTIL_BYTES "B" // |esp-ESP|==|eng-USA|
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
// 1. Copy this file (eng-USA.h) to a new file with the target locale as the
|
||||
// file name. Using German as an example, do this:
|
||||
//
|
||||
// cp eng-USA.h de-DE.h
|
||||
// cp eng-USA.h deu-DEU.h
|
||||
//
|
||||
// 2. Modify all the strings below.
|
||||
// i.e. change "Unknown error." to "Unbekannter Fehler.".
|
||||
@@ -67,7 +67,7 @@
|
||||
// by inserting:
|
||||
//
|
||||
// #elif PACKAGE_LANGUAGE == LANGUAGE_DEU_DEU
|
||||
// #include <de-DE.h>
|
||||
// #include <deu-DEU.h>
|
||||
//
|
||||
// 4. Add your new language to task.git/CMakeLists.txt, making sure that
|
||||
// number is unique:
|
||||
@@ -261,6 +261,7 @@
|
||||
#define STRING_COLUMN_EXAMPLES_ANNO4 "If you're not getting your hair cut"
|
||||
|
||||
// commands/Cmd*
|
||||
// USAGE strings are visible in 'task help'
|
||||
#define STRING_CMD_CONFLICT "Le rapport personnalisé '{1}' entre en conflit avec une commande prédéfinie de task."
|
||||
#define STRING_CMD_VERSION_USAGE "Affiche le numéro de version de taskwarrior"
|
||||
#define STRING_CMD_VERSION_USAGE2 "Affiche uniquement le numéro de version de taskwarrior"
|
||||
@@ -488,6 +489,8 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "Handshake failed. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "You should either provide a CA certificate or override verification, but not both."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Platform, build and environment details"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Platform"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<unknown>"
|
||||
@@ -509,6 +512,13 @@
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "No duplicates found"
|
||||
#define STRING_CMD_DIAG_NONE "-none-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Hooks"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Generates a list of all commands, for autocompletion purposes"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Generates a list of all commands, for zsh autocompletion purposes"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
@@ -787,6 +797,18 @@
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Erreur : valeur manquante après ',' à la position {1}"
|
||||
#define STRING_JSON_MISSING_VALUE2 "Erreur : valeur manquante à la position {1}"
|
||||
@@ -989,4 +1011,3 @@
|
||||
#define STRING_UTIL_BYTES "o"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
// 1. Copy this file (eng-USA.h) to a new file with the target locale as the
|
||||
// file name. Using German as an example, do this:
|
||||
//
|
||||
// cp eng-USA.h de-DE.h
|
||||
// cp eng-USA.h deu-DEU.h
|
||||
//
|
||||
// 2. Modify all the strings below.
|
||||
// i.e. change "Unknown error." to "Unbekannter Fehler.".
|
||||
@@ -67,7 +67,7 @@
|
||||
// by inserting:
|
||||
//
|
||||
// #elif PACKAGE_LANGUAGE == LANGUAGE_DEU_DEU
|
||||
// #include <de-DE.h>
|
||||
// #include <deu-DEU.h>
|
||||
//
|
||||
// 4. Add your new language to task.git/CMakeLists.txt, making sure that
|
||||
// number is unique:
|
||||
@@ -91,7 +91,6 @@
|
||||
|
||||
#ifndef INCLUDED_STRINGS
|
||||
#define INCLUDED_STRINGS
|
||||
#define L10N // Localization complete.
|
||||
|
||||
// Note that for English, the following two lines are not displayed. For all
|
||||
// other localizations, these lines will appear in the output of the 'version'
|
||||
@@ -141,9 +140,9 @@
|
||||
#define STRING_VARIANT_MUL_STR_DUR "Cannot multiply strings by durations"
|
||||
#define STRING_VARIANT_MUL_DUR_STR "Cannot multiply durations by strings"
|
||||
#define STRING_VARIANT_MUL_DUR_DATE "Cannot multiply durations by dates"
|
||||
#define STRING_VARIANT_MUL_DUR_DUR "Cannot multiply durations by duraitons"
|
||||
#define STRING_VARIANT_MUL_DUR_DUR "Cannot multiply durations by durations"
|
||||
#define STRING_VARIANT_DIV_UNKNOWN "Cannot divide unknown type"
|
||||
#define STRING_VARIANT_DIV_BOOL "Cannot divide Boolean"
|
||||
#define STRING_VARIANT_DIV_BOOL "Cannot divide Boolean values"
|
||||
#define STRING_VARIANT_DIV_INT_BOOL "Cannot divide integers by Boolean values"
|
||||
#define STRING_VARIANT_DIV_ZERO "Cannot divide by zero"
|
||||
#define STRING_VARIANT_DIV_INT_STR "Cannot divide integer by string"
|
||||
@@ -155,7 +154,7 @@
|
||||
#define STRING_VARIANT_DIV_DUR_STR "Cannot divide durations by strings"
|
||||
#define STRING_VARIANT_DIV_DUR_DATE "Cannot divide durations by dates"
|
||||
#define STRING_VARIANT_DIV_DUR_DUR "Cannot divide durations by durations"
|
||||
#define STRING_VARIANT_MOD_BOOL "Cannot modulo Boolean"
|
||||
#define STRING_VARIANT_MOD_BOOL "Cannot modulo Booleans"
|
||||
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
|
||||
#define STRING_VARIANT_MOD_DUR "Cannot modulo duration values"
|
||||
#define STRING_VARIANT_MOD_INT_BOOL "Cannot modulo integer by Boolean"
|
||||
@@ -178,13 +177,13 @@
|
||||
// These are errors generated at the lowest level of input analysis,
|
||||
// at the character level.
|
||||
#define STRING_LEX_IMMEDIATE_UNK "Lexer start failure, unknown characters found immediately."
|
||||
#define STRING_LEX_TYPE_UNK "Lexer cannot process and unknown token type."
|
||||
#define STRING_LEX_TYPE_UNK "Lexer cannot process an unknown token type."
|
||||
|
||||
// Dates
|
||||
//
|
||||
// These are errors generated when parsing date values.
|
||||
#define STRING_DATES_MONTH_31 "Error: no month has more than 31 days."
|
||||
#define STRING_DATES_ORD_MISMATCH "Error: number and ordinal don't match (ie '1st', not '1nd')."
|
||||
#define STRING_DATES_ORD_MISMATCH "Error: number and ordinal don't match (e.g., '1st', not '1nd')."
|
||||
|
||||
// Color
|
||||
#define STRING_COLOR_UNRECOGNIZED "Il colore '{1}' non è riconosciuto."
|
||||
@@ -489,6 +488,8 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "Handshake failed. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "You should either provide a CA certificate or override verification, but not both."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Dettagli su piattaforma, build e ambiente"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Piattaforma"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<sconoscito>"
|
||||
@@ -510,6 +511,13 @@
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "Nessun duplicato trovato"
|
||||
#define STRING_CMD_DIAG_NONE "-nessuno-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Hooks"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Genera la lista di tutti i comandi, per autocompletamento"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Genera la lista di tutti i comandi, per autocompletamento in zsh"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
@@ -788,6 +796,18 @@
|
||||
#define STRING_HELPER_PROJECT_REM "({1} di {2} task rimanenti)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Errore: mancato valore dopo ',' alla posizione {1}"
|
||||
#define STRING_JSON_MISSING_VALUE2 "Errore: mancato valore alla posizione {1}"
|
||||
@@ -990,4 +1010,3 @@
|
||||
#define STRING_UTIL_BYTES "B"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -489,6 +489,8 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "Nieudany handshake. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "Powinieneś udostępnić certyfikat CA lub nadpisać weryfikację. Wybierz jedną z opcji."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Szczegóły platformy i środowiska budowania"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Platforma"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<nieznane>"
|
||||
@@ -510,6 +512,13 @@
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "Nie znaleziono duplikatów"
|
||||
#define STRING_CMD_DIAG_NONE "-brak-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Haki"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Generuje listę wszystkich poleceń dla funkcji autouzupełniania"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Generuje listę wszystkich poleceń dla funkcji autouzupełniania w powłoce zsh"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Generates a list of all attributes, for zsh autocompletion purposes"
|
||||
@@ -783,10 +792,22 @@
|
||||
#define STRING_FILE_PERMS "Taskwarrior nie posiada praw dostępu do '{1}'."
|
||||
|
||||
// helpers
|
||||
#define STRING_HELPER_PROJECT_CHANGE "Projekt '{1}' uległ zmianie."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Projekt '{1}' w {2}% ukończony"
|
||||
#define STRING_HELPER_PROJECT_REM "({1} z {2} zadań pozostało)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} zadań pozostało)."
|
||||
#define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete"
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Błąd: brak wartości po ',' na pozycji {1}"
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
// 1. Copy this file (eng-USA.h) to a new file with the target locale as the
|
||||
// file name. Using German as an example, do this:
|
||||
//
|
||||
// cp eng-USA.h de-DE.h
|
||||
// cp eng-USA.h deu-DEU.h
|
||||
//
|
||||
// 2. Modify all the strings below.
|
||||
// i.e. change "Unknown error." to "Unbekannter Fehler.".
|
||||
@@ -67,7 +67,7 @@
|
||||
// by inserting:
|
||||
//
|
||||
// #elif PACKAGE_LANGUAGE == LANGUAGE_DEU_DEU
|
||||
// #include <de-DE.h>
|
||||
// #include <deu-DEU.h>
|
||||
//
|
||||
// 4. Add your new language to task.git/CMakeLists.txt, making sure that
|
||||
// number is unique:
|
||||
@@ -489,6 +489,8 @@
|
||||
#define STRING_CMD_SYNC_HANDSHAKE "'Handshake' falhou. {1}"
|
||||
#define STRING_CMD_SYNC_TRUST_CA "Deve fornecer um certificado CA ou desactivar a verificação, mas não ambos."
|
||||
#define STRING_CMD_SYNC_TRUST_OBS "The 'taskd.trust' settings may now only contain a value of 'strict', 'ignore hostname' or 'allow all'."
|
||||
|
||||
// STRING_CMD_DIAG_* strings all appear on the 'diag' command output.
|
||||
#define STRING_CMD_DIAG_USAGE "Plataforma, versão e detalhes de ambiente"
|
||||
#define STRING_CMD_DIAG_PLATFORM "Plataforma"
|
||||
#define STRING_CMD_DIAG_UNKNOWN "<desconhecido>"
|
||||
@@ -510,6 +512,13 @@
|
||||
#define STRING_CMD_DIAG_UUID_NO_DUP "Nenhum duplicado encontrado"
|
||||
#define STRING_CMD_DIAG_NONE "-nenhum-"
|
||||
#define STRING_CMD_DIAG_HOOKS "Âncoras"
|
||||
#define STRING_CMD_DIAG_HOOK_NAME "unrecognized hook name"
|
||||
#define STRING_CMD_DIAG_HOOK_SYMLINK "symlink"
|
||||
#define STRING_CMD_DIAG_HOOK_EXEC "executable"
|
||||
#define STRING_CMD_DIAG_HOOK_NO_EXEC "not executable"
|
||||
#define STRING_CMD_DIAG_HOOK_ENABLE "Enabled"
|
||||
#define STRING_CMD_DIAG_HOOK_DISABLE "Disabled"
|
||||
|
||||
#define STRING_CMD_HCOMMANDS_USAGE "Gera uma lista com todos os comandos, para fins de terminação automática"
|
||||
#define STRING_CMD_ZSHCOMMANDS_USAGE "Gera uma lista com todos os comandos, para terminação automática em zsh"
|
||||
#define STRING_CMD_ZSHATTS_USAGE "Gera uma lista de todos os atributos, para terminação automática em zsh"
|
||||
@@ -783,10 +792,22 @@
|
||||
#define STRING_FILE_PERMS "O taskwarrior não encontrou as permissões corretas em '{1}'."
|
||||
|
||||
// helpers
|
||||
#define STRING_HELPER_PROJECT_CHANGE "O projeto '{1}' foi alterado."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Projeto '{1}' está {2}% concluído"
|
||||
#define STRING_HELPER_PROJECT_REM "(Restam {1} de {2} tarefas)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} tarefas em falta)."
|
||||
#define STRING_HELPER_PROJECT_CHANGE "The project '{1}' has changed."
|
||||
#define STRING_HELPER_PROJECT_COMPL "Project '{1}' is {2}% complete"
|
||||
#define STRING_HELPER_PROJECT_REM "({1} of {2} tasks remaining)."
|
||||
#define STRING_HELPER_PROJECT_REM1 "({1} task remaining)."
|
||||
|
||||
// Hooks
|
||||
#define STRING_HOOK_ERROR_OBJECT "Hook Error: JSON Object '{...}' expected."
|
||||
#define STRING_HOOK_ERROR_NODESC "Hook Error: JSON Object missing 'description' attribute."
|
||||
#define STRING_HOOK_ERROR_NOUUID "Hook Error: JSON Object missing 'uuid' attribute."
|
||||
#define STRING_HOOK_ERROR_SYNTAX "Hook Error: JSON syntax error in: {1}"
|
||||
#define STRING_HOOK_ERROR_JSON "Hook Error: JSON "
|
||||
#define STRING_HOOK_ERROR_NOPARSE "Hook Error: JSON failed to parse: "
|
||||
#define STRING_HOOK_ERROR_BAD_NUM "Hook Error: Expected {1} JSON task(s), found {2}"
|
||||
#define STRING_HOOK_ERROR_SAME1 "Hook Error: JSON must be for the same task: {1}"
|
||||
#define STRING_HOOK_ERROR_SAME2 "Hook Error: JSON must be for the same task: {1} != {2}"
|
||||
#define STRING_HOOK_ERROR_NOFEEDBACK "Hook Error: Expected feedback from a failing hook script."
|
||||
|
||||
// JSON
|
||||
#define STRING_JSON_MISSING_VALUE "Erro: valor em falta após ',' na posição {1}"
|
||||
@@ -990,4 +1011,3 @@
|
||||
#define STRING_UTIL_BYTES "B" // |por-PRT|==|eng-USA|
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -54,6 +54,11 @@ extern Context context;
|
||||
// child tasks need to be generated to fill gaps.
|
||||
void handleRecurrence ()
|
||||
{
|
||||
// Recurrence can be disabled.
|
||||
// Note: This is currently a workaround for TD-44, TW-1520.
|
||||
if (! context.config.getBoolean ("recurrence"))
|
||||
return;
|
||||
|
||||
std::vector <Task> tasks = context.tdb2.pending.get_tasks ();
|
||||
Date now;
|
||||
|
||||
|
||||
@@ -985,7 +985,11 @@ std::string rightJustify (const int input, const int width)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string rightJustify (const std::string& input, const int width)
|
||||
{
|
||||
return std::string (width - utf8_text_width (input), ' ') + input;
|
||||
unsigned int len = utf8_text_width (input);
|
||||
return ((width > len)
|
||||
? std::string (width - len, ' ')
|
||||
: "")
|
||||
+ input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
36
src/util.cpp
36
src/util.cpp
@@ -153,7 +153,7 @@ int autoComplete (
|
||||
{
|
||||
matches.clear ();
|
||||
|
||||
// Handle trivial case.
|
||||
// Handle trivial case.
|
||||
unsigned int length = partial.length ();
|
||||
if (length)
|
||||
{
|
||||
@@ -276,7 +276,7 @@ int execute (
|
||||
struct timeval tv;
|
||||
int select_retval, read_retval, write_retval;
|
||||
char buf[16384];
|
||||
int written;
|
||||
unsigned int written;
|
||||
const char* input_cstr = input.c_str ();
|
||||
|
||||
if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) // Handled locally with EPIPE.
|
||||
@@ -294,27 +294,37 @@ int execute (
|
||||
if (pid == 0)
|
||||
{
|
||||
// This is only reached in the child
|
||||
close (pin[1]); // Close the write end of the input pipe.
|
||||
close (pout[0]); // Close the read end of the output pipe.
|
||||
|
||||
if (dup2 (pin[0], STDIN_FILENO) == -1)
|
||||
throw std::string (std::strerror (errno));
|
||||
|
||||
if (dup2 (pout[1], STDOUT_FILENO) == -1)
|
||||
throw std::string (std::strerror (errno));
|
||||
|
||||
char** argv = new char* [args.size () + 1];
|
||||
char** argv = new char* [args.size () + 2];
|
||||
argv[0] = (char*) executable.c_str ();
|
||||
for (unsigned int i = 0; i < args.size (); ++i)
|
||||
argv[i] = (char*) args[i].c_str ();
|
||||
argv[i+1] = (char*) args[i].c_str ();
|
||||
|
||||
argv[args.size ()] = NULL;
|
||||
argv[args.size () + 1] = NULL;
|
||||
_exit (execvp (executable.c_str (), argv));
|
||||
}
|
||||
|
||||
// This is only reached in the parent
|
||||
close (pin[0]); // Close the read end of the input pipe.
|
||||
close (pout[1]); // Close the write end if the output pipe.
|
||||
close (pout[1]); // Close the write end of the output pipe.
|
||||
|
||||
if (input.size () == 0)
|
||||
{
|
||||
// Nothing to send to the child, close the pipe early.
|
||||
close (pin[1]);
|
||||
}
|
||||
|
||||
read_retval = -1;
|
||||
written = 0;
|
||||
while (read_retval != 0 || input.size () - written != 0)
|
||||
while (read_retval != 0 || input.size () != written)
|
||||
{
|
||||
FD_ZERO (&rfds);
|
||||
if (read_retval != 0)
|
||||
@@ -323,7 +333,7 @@ int execute (
|
||||
}
|
||||
|
||||
FD_ZERO (&wfds);
|
||||
if (input.size () - written != 0)
|
||||
if (input.size () != written)
|
||||
{
|
||||
FD_SET (pin[1], &wfds);
|
||||
}
|
||||
@@ -353,6 +363,12 @@ int execute (
|
||||
}
|
||||
}
|
||||
written += write_retval;
|
||||
|
||||
if (written == input.size ())
|
||||
{
|
||||
// Let the child know that no more input is coming by closing the pipe.
|
||||
close (pin[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET (pout[0], &rfds))
|
||||
@@ -366,7 +382,6 @@ int execute (
|
||||
}
|
||||
}
|
||||
|
||||
close (pin[1]); // Close the write end of the input pipe.
|
||||
close (pout[0]); // Close the read end of the output pipe.
|
||||
|
||||
int status = -1;
|
||||
@@ -382,6 +397,9 @@ int execute (
|
||||
throw std::string ("Error: Could not get Hook exit status!");
|
||||
}
|
||||
|
||||
if (signal (SIGPIPE, SIG_DFL) == SIG_ERR) // We're done, return to default.
|
||||
throw std::string (std::strerror (errno));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
110
test/README
Normal file
110
test/README
Normal file
@@ -0,0 +1,110 @@
|
||||
README
|
||||
======
|
||||
|
||||
This is the task.git/test/README file, and contains notes about the Taskwarrior
|
||||
test suite.
|
||||
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
|
||||
TL;DR cd test && make && ./run_all && ./problems
|
||||
|
||||
All unit tests produce TAP (Test Anything Protocol) output, and are run by the
|
||||
'run_all' test harness.
|
||||
|
||||
The 'run_all' script produces an 'all.log' file which is the accumulated output
|
||||
of all tests. Before executing 'run_all' you need to compile the C++ unit
|
||||
tests, by running 'make' on the 'test' directory.
|
||||
|
||||
The script 'problems' will list all the tests that fail, with a count of the
|
||||
failing tests.
|
||||
|
||||
Any TAP harness may be used.
|
||||
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
There are three varieties of tests:
|
||||
|
||||
* Perl unit tests that use Test::More and the JSON module. We are phasing
|
||||
these out, and will accept no new Perl tests. These tests are high level
|
||||
and exercise Taskwarrior at the command line level.
|
||||
|
||||
* C++ unit tests that test low-level object interfaces. These are typically
|
||||
very fast tests, and are exhaustive in nature.
|
||||
|
||||
* Python unit tests that are at the highest level, exercising the command
|
||||
line, hooks and syncing. There is an example, 'template.t', that shows how
|
||||
to perform various high level tests.
|
||||
|
||||
All tests are named with the pattern '*.t', and any other forms are not run by
|
||||
the test harness. Additionally a test must be set executable (chmod +x) for it
|
||||
to be run. In the case of Perl and Python tests one can still run them manually
|
||||
by launching them with 'perl/python test.t'. It also allows us to keep tests
|
||||
submitted for bugs that are not scheduled to be fixed in the upcoming release,
|
||||
and we don't want the failing tests to prevent us from seeing 100% pass rate
|
||||
for the bugs we *have* fixed.
|
||||
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
The test suite is evolving, and becoming a better tool for determining whether
|
||||
code is ready for release. There are goals that shape these changes, and they
|
||||
are:
|
||||
|
||||
* Migrate test suite to Python and C++, eliminating all Perl. The Python
|
||||
test suite is more expressive and high level. Migrating reduces
|
||||
dependencies.
|
||||
|
||||
* Increase test coverage by testing more features, more thoroughly.
|
||||
|
||||
* Write fewer bug regression tests. Over time, bug regression tests are less
|
||||
useful than feature tests, and more likely to contain overlapping coverage.
|
||||
|
||||
* The Python test suite provides test isolation, such that each test is run
|
||||
in a separate directory. This will allow eventual parallelization, but not
|
||||
until the Perl tests are eliminated.
|
||||
|
||||
* Eliminate obsolete tests, which are tests that have overlapping coverage.
|
||||
This means migrate bug-specific tests to feature tests.
|
||||
|
||||
* Categorize the tests, restructure the directories.
|
||||
|
||||
|
||||
What Makes a Good Test
|
||||
----------------------
|
||||
|
||||
A good test ensures that a feature is functioning as expected, and contains
|
||||
both positive and negative aspects, or in other words looks for expected
|
||||
behavior as well as looking for the absence of unexpected behavior.
|
||||
|
||||
|
||||
How to Submit a Test Change/Addition
|
||||
------------------------------------
|
||||
|
||||
Mail it to support@taskwarrior.org, or attach it to an open bug.
|
||||
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
For anyone looking for test-related tasks to take on, here are some suggestions:
|
||||
|
||||
* Take tw-285.t and improve it to test more (if not all) virtual tags, then
|
||||
rename it virtual-tags.t.
|
||||
|
||||
* Select a bug.*.t Perl test and convert it to Python using the template.
|
||||
|
||||
* Look at the latest todo.txt file format spec, and make sure that
|
||||
import.todo.sh.t is testing the current format.
|
||||
|
||||
* Select a feature.*.t Perl test, convert it to Python using the template,
|
||||
then rename it to <feature>.t
|
||||
|
||||
* Find and eliminate individual test that do the same thing.
|
||||
|
||||
|
||||
---
|
||||
131
test/TAP.py
131
test/TAP.py
@@ -1,131 +0,0 @@
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import re
|
||||
|
||||
class TAP:
|
||||
"""TAP-compliant unit test class."""
|
||||
|
||||
def __init__(self, planned = 0):
|
||||
self.planned = planned
|
||||
self.counter = 0
|
||||
self.passed = 0
|
||||
self.failed = 0
|
||||
self.skipped = 0
|
||||
print "1..%d " % self.planned
|
||||
|
||||
def __del__(self):
|
||||
percentPassed = 0.0
|
||||
if self.planned > 0:
|
||||
percentPassed = (100.0 * self.passed) / max (self.planned, self.passed + self.failed + self.skipped)
|
||||
|
||||
if self.counter < self.planned:
|
||||
print "# Only %d tests, out of a planned %d were run." % (self.counter, self.planned)
|
||||
self.skipped += self.planned - self.counter
|
||||
elif self.counter > self.planned:
|
||||
print "# %d tests were run, but only %d were planned." % (self.counter, self.planned)
|
||||
|
||||
print "# %d passed, %d failed, %d skipped. %.2f%% passed." % (self.passed, self.failed, self.skipped, percentPassed)
|
||||
|
||||
def plan(self, planned):
|
||||
self.planned = planned
|
||||
print "1..%d " % self.planned
|
||||
|
||||
def planMore(self, extra):
|
||||
self.planned += extra
|
||||
print "1..%d" % self.planned
|
||||
|
||||
def ok(self, expression, description):
|
||||
self.counter += 1
|
||||
if bool(expression):
|
||||
self.passed += 1
|
||||
print "ok %d - %s" % (self.counter, description)
|
||||
else:
|
||||
self.failed += 1
|
||||
print "not ok %d - %s" % (self.counter, description)
|
||||
|
||||
def notok(self, expression, description):
|
||||
self.counter += 1
|
||||
if not bool(expression):
|
||||
self.passed += 1
|
||||
print "ok %d - %s" % (self.counter, description)
|
||||
else:
|
||||
self.failed += 1
|
||||
print "not ok %d - %s" % (self.counter, description)
|
||||
|
||||
def equals(self, actual, expected, description):
|
||||
self.counter += 1
|
||||
if actual == expected:
|
||||
self.passed += 1
|
||||
print "ok %d - %s" % (self.counter, description)
|
||||
else:
|
||||
self.failed += 1
|
||||
print "not ok %d - %s" % (self.counter, description)
|
||||
print "# expected:", expected, "\n# got:", actual
|
||||
|
||||
def like(self, actual, pattern, description):
|
||||
self.counter += 1
|
||||
if re.search(pattern, actual):
|
||||
self.passed += 1
|
||||
print "ok %d - %s" % (self.counter, description)
|
||||
else:
|
||||
self.failed += 1
|
||||
print "not ok %d - %s" % (self.counter, description)
|
||||
|
||||
def unlike(self, actual, pattern, description):
|
||||
self.counter += 1
|
||||
if re.search(pattern, actual):
|
||||
self.failed += 1
|
||||
print "not ok %d - %s" % (self.counter, description)
|
||||
else:
|
||||
self.passed += 1
|
||||
print "ok %d - %s" % (self.counter, description)
|
||||
|
||||
def diag(self, stuff):
|
||||
for line in stuff.strip().split("\n"):
|
||||
print "#", line.strip()
|
||||
|
||||
def skip(self, message):
|
||||
self.counter += 1
|
||||
self.skipped += 1
|
||||
print "skip %d %s" % (self.counter, message)
|
||||
|
||||
def passed(self, message):
|
||||
self.counter += 1
|
||||
self.passed += 1
|
||||
print "ok %d %s" % (self.counter, message)
|
||||
|
||||
def fail(self, message):
|
||||
self.counter += 1
|
||||
self.failed += 1
|
||||
print "not ok %d %s" % (self.counter, message)
|
||||
|
||||
def skip(self, message):
|
||||
self.counter += 1
|
||||
self.skipped += 1
|
||||
print "skip %d %s" % (self.counter, message)
|
||||
|
||||
################################################################################
|
||||
@@ -1,101 +1,94 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 19;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase, Taskd, ServerTestCase # noqa
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"abbreviation.minimum=1\n";
|
||||
close $fh;
|
||||
}
|
||||
class TestAbbreviation(TestCase):
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
self.t.config("abbreviation.minimum", "1")
|
||||
|
||||
# Test the priority attribute abbrevations.
|
||||
qx{../src/task rc:$rc add priority:H with 2>&1};
|
||||
qx{../src/task rc:$rc add without 2>&1};
|
||||
self.t(("add", "project:home", "priority:H", "hasattributes"))
|
||||
self.t(("add", "noattributes"))
|
||||
|
||||
my $output = qx{../src/task rc:$rc list priority:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: priority:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: priority:H without");
|
||||
def verify_attibute(self, expr):
|
||||
code, out, err = self.t(("list", expr))
|
||||
|
||||
$output = qx{../src/task rc:$rc list priorit:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: priorit:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: priorit:H without");
|
||||
self.assertIn("hasattributes", out, msg=expr + " hasattributes")
|
||||
self.assertNotIn("noattributes", out, msg=expr + " noattributes")
|
||||
|
||||
$output = qx{../src/task rc:$rc list priori:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: priori:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: priori:H without");
|
||||
def test_attribute_abbreviations(self):
|
||||
"Test project attribute abbrevations"
|
||||
|
||||
$output = qx{../src/task rc:$rc list prior:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: prior:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: prior:H without");
|
||||
self.verify_attibute("project:home")
|
||||
self.verify_attibute("projec:home")
|
||||
self.verify_attibute("proje:home")
|
||||
self.verify_attibute("proj:home")
|
||||
self.verify_attibute("pro:home")
|
||||
|
||||
$output = qx{../src/task rc:$rc list prio:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: prio:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: prio:H without");
|
||||
def test_uda_abbreviations(self):
|
||||
"Test uda attribute abbrevations"
|
||||
# NOTE This will be an UDA when TW-1541 is closed, for now it's just
|
||||
# one more attribute
|
||||
|
||||
$output = qx{../src/task rc:$rc list pri:H 2>&1};
|
||||
like ($output, qr/\bwith\b/, "$ut: pri:H with");
|
||||
unlike ($output, qr/\bwithout\b/, "$ut: pri:H without");
|
||||
self.verify_attibute("priority:H")
|
||||
self.verify_attibute("priorit:H")
|
||||
self.verify_attibute("priori:H")
|
||||
self.verify_attibute("prior:H")
|
||||
self.verify_attibute("prio:H")
|
||||
self.verify_attibute("pri:H")
|
||||
|
||||
# Test the version command abbreviations.
|
||||
$output = qx{../src/task rc:$rc version 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: version");
|
||||
def verify_command(self, cmd):
|
||||
code, out, err = self.t((cmd,))
|
||||
|
||||
$output = qx{../src/task rc:$rc versio 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: versio");
|
||||
self.assertIn("MIT license", out, msg=cmd)
|
||||
|
||||
$output = qx{../src/task rc:$rc versi 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: versi");
|
||||
def test_command_abbreviations(self):
|
||||
"Test version command abbrevations"
|
||||
|
||||
$output = qx{../src/task rc:$rc vers 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: vers");
|
||||
self.verify_command("version")
|
||||
self.verify_command("versio")
|
||||
self.verify_command("versi")
|
||||
self.verify_command("vers")
|
||||
self.verify_command("ver")
|
||||
self.verify_command("ve")
|
||||
self.verify_command("v")
|
||||
|
||||
$output = qx{../src/task rc:$rc ver 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: ver");
|
||||
|
||||
$output = qx{../src/task rc:$rc ve 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: ve");
|
||||
|
||||
$output = qx{../src/task rc:$rc v 2>&1};
|
||||
like ($output, qr/MIT\s+license/, "$ut: v");
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
124
test/add.t
124
test/add.t
@@ -1,68 +1,72 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 7;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
from basetest.utils import UUID_regex
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
class TestAdd(TestCase):
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
self.t(("add", "This is a test"))
|
||||
|
||||
# Test the add command.
|
||||
qx{../src/task rc:$rc add This is a test 2>&1};
|
||||
my $output = qx{../src/task rc:$rc info 1 2>&1};
|
||||
like ($output, qr/ID\s+1\n/, "$ut: add ID");
|
||||
like ($output, qr/Description\s+This is a test\n/, "$ut: add ID");
|
||||
like ($output, qr/Status\s+Pending\n/, "$ut: add Pending");
|
||||
like ($output, qr/UUID\s+[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\n/,
|
||||
"$ut: add UUID");
|
||||
def test_add(self):
|
||||
"Testing add command"
|
||||
|
||||
# Test the /// modifier.
|
||||
qx{../src/task rc:$rc 1 modify /test/TEST/ 2>&1};
|
||||
qx{../src/task rc:$rc 1 modify "/is //" 2>&1};
|
||||
$output = qx{../src/task rc:$rc info 1 2>&1};
|
||||
like ($output, qr/ID\s+1\n/, "$ut: add ID");
|
||||
like ($output, qr/Status\s+Pending\n/, "$ut: add Pending");
|
||||
like ($output, qr/Description\s+This a TEST\n/, "$ut: add Description");
|
||||
code, out, err = self.t(("info", "1"))
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
self.assertRegexpMatches(out, "ID\s+1\n")
|
||||
self.assertRegexpMatches(out, "Description\s+This is a test\n")
|
||||
self.assertRegexpMatches(out, "Status\s+Pending\n")
|
||||
self.assertRegexpMatches(out, "UUID\s+" + UUID_regex + "\n")
|
||||
|
||||
def test_modify_slash(self):
|
||||
"Test the /// modifier"
|
||||
|
||||
self.t(("1", "modify", "/test/TEST/"))
|
||||
self.t(("1", "modify", "/is //"))
|
||||
|
||||
code, out, err = self.t(("info", "1"))
|
||||
|
||||
self.assertRegexpMatches(out, "ID\s+1\n")
|
||||
self.assertRegexpMatches(out, "Status\s+Pending\n")
|
||||
self.assertRegexpMatches(out, "Description\s+This a TEST\n")
|
||||
self.assertRegexpMatches(out, "UUID\s+" + UUID_regex + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import signal
|
||||
|
||||
sig_names = dict((k, v) for v, k in reversed(sorted(signal.__dict__.items()))
|
||||
if v.startswith('SIG') and not v.startswith('SIG_'))
|
||||
|
||||
|
||||
class CommandError(Exception):
|
||||
def __init__(self, cmd, code, out, err=None, msg=None):
|
||||
DEFAULT = ("Command '{{0}}' was {signal}'ed. "
|
||||
"SIGABRT usually means task timed out.\n")
|
||||
if msg is None:
|
||||
msg_suffix = "\n*** Start STDOUT ***\n{2}\n*** End STDOUT ***\n"
|
||||
if err is not None:
|
||||
msg_suffix += (
|
||||
"\n*** Start STDERR ***\n{3}\n*** End STDERR ***\n"
|
||||
)
|
||||
if code == -signal.SIGABRT:
|
||||
self.msg = ("Command '{0}' was aborted, likely due to not "
|
||||
"finishing in due time. The exit code was '{1}'.\n"
|
||||
) + msg_suffix
|
||||
|
||||
if code < 0:
|
||||
self.msg = DEFAULT.format(signal=sig_names[abs(code)])
|
||||
else:
|
||||
self.msg = ("Command '{0}' finished with unexpected exit "
|
||||
"code '{1}'.\n"
|
||||
) + msg_suffix
|
||||
"code '{1}'.\n")
|
||||
|
||||
self.msg += msg_suffix
|
||||
else:
|
||||
self.msg = msg
|
||||
|
||||
@@ -34,12 +39,13 @@ class HookError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TimeoutWaitingForStream(object):
|
||||
class TimeoutWaitingFor(object):
|
||||
def __init__(self, name):
|
||||
self.stream = name
|
||||
self.name = name
|
||||
|
||||
def __repr__(self):
|
||||
return "*** Timeout reached while waiting for %s ***".format(self.name)
|
||||
return "*** Timeout reached while waiting for {0} ***".format(
|
||||
self.name)
|
||||
|
||||
|
||||
class StreamsAreMerged(object):
|
||||
|
||||
@@ -16,6 +16,26 @@ from .utils import DEFAULT_HOOK_PATH
|
||||
from .exceptions import HookError
|
||||
|
||||
|
||||
class InvalidJSON(object):
|
||||
"""Object representing the original unparsed JSON string and the JSON error
|
||||
"""
|
||||
def __init__(self, original, error):
|
||||
self.original = original
|
||||
self.error = error
|
||||
|
||||
|
||||
def json_decoder(string):
|
||||
"""Attempt to decode a JSON string and in case of error return an
|
||||
InvalidJSON object
|
||||
"""
|
||||
decoder = json.JSONDecoder().decode
|
||||
|
||||
try:
|
||||
return decoder(string)
|
||||
except ValueError as e:
|
||||
return InvalidJSON(string, str(e))
|
||||
|
||||
|
||||
class Hooks(object):
|
||||
"""Abstraction to help interact with hooks (add, remove) during tests and
|
||||
keep track of which are active.
|
||||
@@ -51,10 +71,10 @@ class Hooks(object):
|
||||
def __getitem__(self, name):
|
||||
return self._hooks[name]
|
||||
|
||||
def __setitem(self, key, value):
|
||||
def __setitem__(self, key, value):
|
||||
self._hooks[key] = value
|
||||
|
||||
def __delitem(self, key):
|
||||
def __delitem__(self, key):
|
||||
del self._hooks[key]
|
||||
|
||||
def __iter__(self):
|
||||
@@ -81,6 +101,8 @@ class Hooks(object):
|
||||
else:
|
||||
self[hookname] = Hook(hookname, self.hookdir, content)
|
||||
|
||||
self[hookname].enable()
|
||||
|
||||
def add_default(self, hookname, log=False):
|
||||
"""Register a pre-built hook that exists in the folder containing hooks
|
||||
used for testing.
|
||||
@@ -94,6 +116,9 @@ class Hooks(object):
|
||||
else:
|
||||
self[hookname] = Hook(hookname, self.hookdir, default=True)
|
||||
|
||||
# Finally enable this hook
|
||||
self[hookname].enable()
|
||||
|
||||
def remove(self, hook):
|
||||
"""Remove the hook matching given hookname"""
|
||||
try:
|
||||
@@ -178,9 +203,6 @@ class Hook(object):
|
||||
with open(self.hookfile, 'w') as fh:
|
||||
fh.write(content)
|
||||
|
||||
# Finally enable the hook
|
||||
self.enable()
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
if self.hookname == other.hookname:
|
||||
@@ -292,9 +314,6 @@ class LoggedHook(Hook):
|
||||
# Setup wrapper pointing to the correct hook name
|
||||
self._setup_wrapper()
|
||||
|
||||
# Finally enable all hooks
|
||||
self.enable()
|
||||
|
||||
def __repr__(self):
|
||||
return "<LoggedHook '{0}'>".format(self.hookname)
|
||||
|
||||
@@ -349,8 +368,30 @@ class LoggedHook(Hook):
|
||||
# Cache is up to date
|
||||
return True
|
||||
|
||||
def _parse_log(self):
|
||||
"""Parse the logs generated by the hook
|
||||
def enable(self):
|
||||
"""Make hookfile executable to allow triggering
|
||||
"""
|
||||
super(LoggedHook, self).enable()
|
||||
os.chmod(self.wrappedfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
|
||||
|
||||
def disable(self):
|
||||
"""Remove hookfile executable bit to deny triggering
|
||||
"""
|
||||
super(LoggedHook, self).disable()
|
||||
os.chmod(self.wrappedfile, stat.S_IREAD | stat.S_IWRITE)
|
||||
|
||||
def is_active(self):
|
||||
"""Check if hook is active by verifying the execute bit
|
||||
"""
|
||||
parent_is_active = super(LoggedHook, self).disable()
|
||||
return parent_is_active and os.access(self.wrappedfile, os.X_OK)
|
||||
|
||||
def get_logs(self):
|
||||
"""Parse the logs generated by the hook and return a dictionary
|
||||
containing the logs collected with the wrapper in a python friendly
|
||||
format:
|
||||
* JSON is parsed as python dictionaries
|
||||
* timestamps are parsed as datetime objects
|
||||
|
||||
It should look something like this:
|
||||
|
||||
@@ -381,111 +422,91 @@ class LoggedHook(Hook):
|
||||
|
||||
with open(self.hooklog_in) as fh:
|
||||
for i, line in enumerate(fh):
|
||||
line = line.rstrip("\n")
|
||||
if line.startswith("%"):
|
||||
# Timestamp includes nanosecond resolution
|
||||
timestamp = line.split(" ")[-1]
|
||||
log["calls"].append(timestamp)
|
||||
# convert timestamp to python datetime object
|
||||
log["calls"].append(
|
||||
datetime.fromtimestamp(float(timestamp))
|
||||
)
|
||||
elif line.startswith("{"):
|
||||
log["input"]["json"].append(line)
|
||||
# Decode json input (to hook)
|
||||
log["input"]["json"].append(json_decoder(line))
|
||||
else:
|
||||
raise IOError("Unexpected content on STDIN line {0}: {1}"
|
||||
.format(i, line))
|
||||
|
||||
with open(self.hooklog_out) as fh:
|
||||
for line in fh:
|
||||
line = line.rstrip("\n")
|
||||
if line.startswith("!"):
|
||||
exitcode = int(line.split(" ")[-1])
|
||||
log["exitcode"] = exitcode
|
||||
elif line.startswith("{"):
|
||||
log["output"]["json"].append(line)
|
||||
# Decode json output (from hook)
|
||||
log["output"]["json"].append(json_decoder(line))
|
||||
else:
|
||||
log["output"]["msgs"].append(line)
|
||||
|
||||
# NOTE convert all lists to tuples to prevent tampering?
|
||||
|
||||
self._cache["log"] = log
|
||||
|
||||
# Update last modification timestamp in cache
|
||||
self._cache["last_change"] = self._get_log_stat()
|
||||
|
||||
def enable(self):
|
||||
"""Make hookfile executable to allow triggering
|
||||
"""
|
||||
super(LoggedHook, self).enable()
|
||||
os.chmod(self.wrappedfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
|
||||
return self._cache["log"]
|
||||
|
||||
def disable(self):
|
||||
"""Remove hookfile executable bit to deny triggering
|
||||
"""
|
||||
super(LoggedHook, self).disable()
|
||||
os.chmod(self.wrappedfile, stat.S_IREAD | stat.S_IWRITE)
|
||||
|
||||
def is_active(self):
|
||||
"""Check if hook is active by verifying the execute bit
|
||||
"""
|
||||
parent_is_active = super(LoggedHook, self).disable()
|
||||
return parent_is_active and os.access(self.wrappedfile, os.X_OK)
|
||||
|
||||
def get_logs(self):
|
||||
"""Return a dictionary containing the logs collected with the wrapper
|
||||
in a python friendly format:
|
||||
* JSON is parsed as python dictionaries
|
||||
* timestamps are parsed as datetime objects
|
||||
"""
|
||||
log = self._parse_log()
|
||||
newlog = {}
|
||||
|
||||
json_decoder = json.JSONDecoder().decode
|
||||
|
||||
for k1 in log:
|
||||
# Timestamps
|
||||
if k1 == "calls":
|
||||
timestamp = lambda x: datetime.fromtimestamp(int(x) / 1e9)
|
||||
newlog[k1] = map(timestamp, log[k1])
|
||||
|
||||
elif k1 in ("input", "output"):
|
||||
newlog[k1] = {}
|
||||
|
||||
for k2 in log[k1]:
|
||||
if k2 == "json":
|
||||
# JSON replies
|
||||
newlog[k1][k2] = map(json_decoder, log[k1][k2])
|
||||
else:
|
||||
# Messages and future fields
|
||||
newlog[k1][k2] = deepcopy(log[k1][k2])
|
||||
else:
|
||||
# exitcode and future fields
|
||||
newlog[k1] = deepcopy(log[k1])
|
||||
|
||||
return newlog
|
||||
|
||||
def assert_triggered(self):
|
||||
"""Check if current hook file was triggered/used by taskwarrior
|
||||
"""
|
||||
log = self._parse_log()
|
||||
|
||||
if log["calls"]:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def assert_triggered_count(self, count):
|
||||
def assertTriggeredCount(self, count):
|
||||
"""Check if current hook file was triggered/used by taskwarrior and
|
||||
how many times.
|
||||
"""
|
||||
log = self._parse_log()
|
||||
log = self.get_logs()
|
||||
|
||||
if len(log["calls"]) == count:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
assert len(log["calls"]) == count, ("{0} calls expected for {1} but "
|
||||
"found {2}".format(
|
||||
count,
|
||||
self.hookname,
|
||||
log["calls"]
|
||||
))
|
||||
|
||||
def assert_exitcode(self, exitcode):
|
||||
def assertExitcode(self, exitcode):
|
||||
"""Check if current hook finished with the expected exit code
|
||||
"""
|
||||
log = self._parse_log()
|
||||
log = self.get_logs()
|
||||
|
||||
if log["exitcode"] == exitcode:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
assert log["exitcode"] == exitcode, ("Expected exit code {0} for {1} "
|
||||
"but found {2}".format(
|
||||
exitcode,
|
||||
self.hookname,
|
||||
log["exitcode"]
|
||||
))
|
||||
|
||||
def assertValidJSONOutput(self):
|
||||
"""Check if current hook output is valid JSON in all expected replies
|
||||
"""
|
||||
log = self.get_logs()
|
||||
|
||||
for i, out in enumerate(log["output"]["json"]):
|
||||
assert not isinstance(out, InvalidJSON), ("Invalid JSON found at "
|
||||
"reply number {0} with "
|
||||
"content {1}".format(
|
||||
i + 1,
|
||||
out.original
|
||||
))
|
||||
|
||||
def assertInvalidJSONOutput(self):
|
||||
"""Check if current hook output is invalid JSON in any expected reply
|
||||
"""
|
||||
log = self.get_logs()
|
||||
|
||||
for i, out in enumerate(log["output"]["json"]):
|
||||
assert isinstance(out, InvalidJSON), ("Valid JSON found at reply "
|
||||
"number {0} with content "
|
||||
"{1}".format(
|
||||
i + 1,
|
||||
out.original
|
||||
))
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
@@ -33,7 +33,7 @@ class Taskd(object):
|
||||
DEFAULT_TASKD = binary_location("taskd")
|
||||
|
||||
def __init__(self, taskd=DEFAULT_TASKD, certpath=None,
|
||||
address="127.0.0.1"):
|
||||
address="localhost"):
|
||||
"""Initialize a Task server that runs in the background and stores data
|
||||
in a temporary folder
|
||||
|
||||
@@ -60,7 +60,7 @@ class Taskd(object):
|
||||
self.certpath = certpath
|
||||
|
||||
self.address = address
|
||||
self.port = find_unused_port()
|
||||
self.port = find_unused_port(self.address)
|
||||
|
||||
# Keep all certificate paths public for access by TaskClients
|
||||
self.client_cert = os.path.join(self.certpath, "client.cert.pem")
|
||||
@@ -182,7 +182,7 @@ class Taskd(object):
|
||||
if self.proc.poll() is not None:
|
||||
return False
|
||||
|
||||
if not port_used(port=self.port):
|
||||
if not port_used(addr=self.address, port=self.port):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@@ -13,7 +13,7 @@ try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
from .exceptions import CommandError, TimeoutWaitingForStream
|
||||
from .exceptions import CommandError, TimeoutWaitingFor
|
||||
|
||||
USED_PORTS = set()
|
||||
ON_POSIX = 'posix' in sys.builtin_module_names
|
||||
@@ -43,6 +43,8 @@ TASKD_SKIP = os.environ.get("TASKD_SKIP", False)
|
||||
# Environment flags to control use of PATH or in-tree binaries
|
||||
USE_PATH = os.environ.get("USE_PATH", False)
|
||||
|
||||
UUID_regex = ("[0-9A-Fa-f]{8}-" + ("[0-9A-Fa-f]{4}-" * 3) + "[0-9A-Fa-f]{12}")
|
||||
|
||||
|
||||
def binary_location(cmd):
|
||||
"""If USE_PATH is set rely on PATH to look for task/taskd binaries.
|
||||
@@ -54,76 +56,142 @@ def binary_location(cmd):
|
||||
return os.path.join(BIN_PREFIX, cmd)
|
||||
|
||||
|
||||
def wait_process(proc, timeout=1):
|
||||
"""Wait for process to finish
|
||||
def wait_condition(cond, timeout=1):
|
||||
"""Wait for condition to return anything other than None
|
||||
"""
|
||||
if timeout is None:
|
||||
timeout = 1
|
||||
|
||||
sleeptime = .1
|
||||
# NOTE Increasing sleeptime can dramatically increase testsuite runtime
|
||||
# It also reduces CPU load significantly
|
||||
sleeptime = .01
|
||||
|
||||
if timeout < sleeptime:
|
||||
print("Warning, timeout cannot be smaller than", sleeptime)
|
||||
timeout = sleeptime
|
||||
|
||||
# Max number of attempts until giving up
|
||||
tries = int(timeout / sleeptime)
|
||||
|
||||
# Wait for up to a second for the process to finish and avoid zombies
|
||||
for i in range(tries):
|
||||
exit = proc.poll()
|
||||
val = cond()
|
||||
|
||||
if exit is not None:
|
||||
if val is not None:
|
||||
break
|
||||
|
||||
sleep(sleeptime)
|
||||
|
||||
return exit
|
||||
return val
|
||||
|
||||
|
||||
def _get_output(proc, input, timeout=None):
|
||||
def wait_process(pid, timeout=None):
|
||||
"""Wait for process to finish
|
||||
"""
|
||||
def process():
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError:
|
||||
# Process is dead
|
||||
return True
|
||||
else:
|
||||
# Process is still ticking
|
||||
return None
|
||||
|
||||
return wait_condition(process, timeout)
|
||||
|
||||
|
||||
def _queue_output(arguments, pidq, outputq):
|
||||
"""Read/Write output/input of given process.
|
||||
This function is meant to be executed in a thread as it may block
|
||||
"""
|
||||
kwargs = arguments["process"]
|
||||
input = arguments["input"]
|
||||
|
||||
proc = Popen(**kwargs)
|
||||
|
||||
# NOTE If for whatever reason pid is None at the time of access, use the
|
||||
# following line instead
|
||||
# pid = wait_condition(lambda: proc.pid)
|
||||
pid = proc.pid
|
||||
# Put the PID in the queue for main process to know
|
||||
pidq.put(pid)
|
||||
|
||||
# Send input and wait for finish
|
||||
out, err = proc.communicate(input)
|
||||
|
||||
# Give the output back to the caller
|
||||
outputq.put((out, err, proc.returncode))
|
||||
|
||||
|
||||
def _retrieve_output(thread, timeout, queue, thread_error):
|
||||
"""Fetch output from taskw subprocess queues
|
||||
"""
|
||||
# Try to join the thread on failure abort
|
||||
thread.join(timeout)
|
||||
if thread.isAlive():
|
||||
# Join should have killed the thread. This is unexpected
|
||||
raise TimeoutWaitingFor(thread_error + ". Unexpected error")
|
||||
|
||||
# Thread died so we should have output
|
||||
try:
|
||||
# data = (stdout, stderr, exitcode)
|
||||
data = queue.get(timeout=timeout)
|
||||
except Empty:
|
||||
data = TimeoutWaitingFor("streams from TaskWarrior")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def _get_output(arguments, timeout=None):
|
||||
"""Collect output from the subprocess without blocking the main process if
|
||||
subprocess hangs.
|
||||
"""
|
||||
def queue_output(proc, input, outq, errq):
|
||||
"""Read/Write output/input of given process.
|
||||
This function is meant to be executed in a thread as it may block
|
||||
"""
|
||||
# Send input and wait for finish
|
||||
out, err = proc.communicate(input)
|
||||
# Give the output back to the caller
|
||||
outq.put(out)
|
||||
errq.put(err)
|
||||
# NOTE Increase this value if tests fail with None being received as
|
||||
# stdout/stderr instead of the expected content
|
||||
output_timeout = 0.1 # seconds
|
||||
|
||||
outq = Queue()
|
||||
errq = Queue()
|
||||
pidq = Queue()
|
||||
outputq = Queue()
|
||||
|
||||
t = Thread(target=queue_output, args=(proc, input, outq, errq))
|
||||
t = Thread(target=_queue_output, args=(arguments, pidq, outputq))
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
# A task process shouldn't take longer than 1 second to finish
|
||||
exit = wait_process(proc, timeout)
|
||||
try:
|
||||
pid = pidq.get(timeout=timeout)
|
||||
except Empty:
|
||||
return _retrieve_output(t, output_timeout, outputq,
|
||||
"TaskWarrior to start")
|
||||
|
||||
# If it does take longer than 1 second, abort it
|
||||
if exit is None:
|
||||
# Wait for process to finish (normal execution)
|
||||
state = wait_process(pid, timeout)
|
||||
|
||||
if state:
|
||||
# Process finished
|
||||
return _retrieve_output(t, output_timeout, outputq,
|
||||
"TaskWarrior thread to join")
|
||||
|
||||
# If we reach this point we assume the process got stuck or timed out
|
||||
for sig in (signal.SIGABRT, signal.SIGTERM, signal.SIGKILL):
|
||||
# Start with lower signals and escalate if process ignores them
|
||||
try:
|
||||
proc.send_signal(signal.SIGABRT)
|
||||
os.kill(pid, signal.SIGABRT)
|
||||
except OSError as e:
|
||||
# 3 means the process finished/died between last check and now
|
||||
if e.errno != 3:
|
||||
raise
|
||||
exit = wait_process(proc)
|
||||
|
||||
# NOTE Increase this value if tests fail with None being received as
|
||||
# stdout/stderr instead of the expected content
|
||||
timeout = 0.1 # seconds
|
||||
# Wait for process to finish (should die/exit after signal)
|
||||
state = wait_process(pid, timeout)
|
||||
|
||||
try:
|
||||
out = outq.get(timeout=timeout)
|
||||
except Empty:
|
||||
out = TimeoutWaitingForStream("stdout")
|
||||
try:
|
||||
err = errq.get(timeout=timeout)
|
||||
except Empty:
|
||||
err = TimeoutWaitingForStream("stderr")
|
||||
if state:
|
||||
# Process finished
|
||||
return _retrieve_output(t, output_timeout, outputq,
|
||||
"TaskWarrior to die")
|
||||
|
||||
return out, err, exit
|
||||
# This should never happen but in case something goes really bad
|
||||
raise OSError("TaskWarrior stopped responding and couldn't be killed")
|
||||
|
||||
|
||||
def run_cmd_wait(cmd, input=None, stdout=PIPE, stderr=PIPE,
|
||||
@@ -140,9 +208,19 @@ def run_cmd_wait(cmd, input=None, stdout=PIPE, stderr=PIPE,
|
||||
else:
|
||||
stderr = PIPE
|
||||
|
||||
p = Popen(cmd, stdin=stdin, stdout=stdout, stderr=stderr, bufsize=1,
|
||||
close_fds=ON_POSIX, env=env)
|
||||
out, err, exit = _get_output(p, input, timeout)
|
||||
arguments = {
|
||||
"process": {
|
||||
"args": cmd,
|
||||
"stdin": stdin,
|
||||
"stdout": stdout,
|
||||
"stderr": stderr,
|
||||
"bufsize": 1,
|
||||
"close_fds": ON_POSIX,
|
||||
"env": env,
|
||||
},
|
||||
"input": input,
|
||||
}
|
||||
out, err, exit = _get_output(arguments, timeout)
|
||||
|
||||
if merge_streams:
|
||||
if exit != 0:
|
||||
@@ -164,16 +242,40 @@ def run_cmd_wait_nofail(*args, **kwargs):
|
||||
return e.code, e.out, e.err
|
||||
|
||||
|
||||
def get_IPs(hostname):
|
||||
output = {}
|
||||
addrs = socket.getaddrinfo(hostname, 0, 0, 0, socket.IPPROTO_TCP)
|
||||
|
||||
for family, socktype, proto, canonname, sockaddr in addrs:
|
||||
addr = sockaddr[0]
|
||||
output[family] = addr
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def port_used(addr="localhost", port=None):
|
||||
"Return True if port is in use, False otherwise"
|
||||
if port is None:
|
||||
raise TypeError("Argument 'port' may not be None")
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
result = s.connect_ex((addr, port))
|
||||
s.close()
|
||||
# result == 0 if connection was successful
|
||||
return result == 0
|
||||
# If we got an address name, resolve it both to IPv6 and IPv4.
|
||||
IPs = get_IPs(addr)
|
||||
|
||||
# Taskd seems to prefer IPv6 so we do it first
|
||||
for family in (socket.AF_INET6, socket.AF_INET):
|
||||
try:
|
||||
addr = IPs[family]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
s = socket.socket(family, socket.SOCK_STREAM)
|
||||
result = s.connect_ex((addr, port))
|
||||
s.close()
|
||||
if result == 0:
|
||||
# connection was successful
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def find_unused_port(addr="localhost", start=53589, track=True):
|
||||
@@ -248,8 +350,8 @@ except ImportError:
|
||||
# Additionally check that `file` is not a directory, as on Windows
|
||||
# directories pass the os.access check.
|
||||
def _access_check(fn, mode):
|
||||
return (os.path.exists(fn) and os.access(fn, mode)
|
||||
and not os.path.isdir(fn))
|
||||
return (os.path.exists(fn) and os.access(fn, mode) and
|
||||
not os.path.isdir(fn))
|
||||
|
||||
# If we're given a path with a directory part, look it up directly
|
||||
# rather than referring to PATH directories. This includes checking
|
||||
|
||||
139
test/bug.1006.t
139
test/bug.1006.t
@@ -1,70 +1,87 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 4;
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
from basetest import Task, TestCase
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"verbose=affected\n";
|
||||
close $fh;
|
||||
}
|
||||
class TestBug1006(TestCase):
|
||||
"""Bug with completion of "des" in task descriptions and annotations. It
|
||||
happens for all the shortcuts for column attributes that are automatically
|
||||
completed. This is because DOM elements are checked before standard words
|
||||
when strings are tokenized.
|
||||
"""
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
self.t.config("verbose", "affected")
|
||||
|
||||
# Bug with completion of "des" in task descriptions and annotations. It happens
|
||||
# for all the shortcuts for column attributes that are automatically completed.
|
||||
# This is because DOM elements are checked before standard words when strings
|
||||
# are tokenized.
|
||||
def initial_tasks(self):
|
||||
self.t(("add", "des"))
|
||||
self.t(("1", "annotate", "des"))
|
||||
|
||||
# Check that the completion is inactive in task descriptions
|
||||
qx{../src/task rc:$rc add des 2>&1};
|
||||
qx{../src/task rc:$rc 1 annotate des 2>&1};
|
||||
my $output = qx{../src/task rc:$rc 1 info 2>&1};
|
||||
like ($output, qr/^Description\s+des$/ms, "$ut: Attribute not completed in description");
|
||||
unlike ($output, qr/description/ms, "$ut: Attribute not completed in description");
|
||||
def test_completion_of_des_inactive(self):
|
||||
"Check that the completion is inactive in task descriptions"
|
||||
|
||||
# Check that the completion works when needed
|
||||
$output = qx{../src/task rc:$rc des:des 2>&1};
|
||||
like ($output, qr/^1 task$/ms, "$ut: Task found using its description");
|
||||
self.initial_tasks()
|
||||
code, out, err = self.t(("1", "info"))
|
||||
|
||||
qx{../src/task rc:$rc add entrée interdite 2>&1};
|
||||
$output = qx{../src/task rc:$rc list interdite 2>&1};
|
||||
like ($output, qr/entrée interdite/, "$ut: 'entrée' left intact");
|
||||
expected = "Description +des\n"
|
||||
errormsg = "Attribute not completed in description"
|
||||
self.assertRegexpMatches(out, expected, msg=errormsg)
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
notexpected = "description"
|
||||
self.assertNotIn(notexpected, out, msg=errormsg)
|
||||
|
||||
def test_completion_as_expected(self):
|
||||
"Check that the completion works when needed"
|
||||
|
||||
self.initial_tasks()
|
||||
code, out, err = self.t(("des:des",))
|
||||
|
||||
errormsg = "Task found using its description"
|
||||
self.assertIn("1 task", out, msg=errormsg)
|
||||
|
||||
def test_accented_chars(self):
|
||||
"Check that é in entrée remains untouched"
|
||||
|
||||
self.t(("add", "entrée interdite"))
|
||||
code, out, err = self.t(("list", "interdite"))
|
||||
|
||||
errormsg = "'entrée' left intact"
|
||||
self.assertIn("entrée interdite", out, msg=errormsg)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
|
||||
@@ -46,10 +46,9 @@ if (open my $fh, '>', $rc)
|
||||
}
|
||||
|
||||
# Bug 982: Missing words when adding a description with NUMBER-SOMETHING
|
||||
|
||||
qx{../src/task rc:$rc add 1-test 1+tag 2>&1};
|
||||
my $output = qx{../src/task rc:$rc 1 info 2>&1};
|
||||
like ($output, qr/^Description 1-test 1\+tag$/ms, 'Description contains plus and minus signs');
|
||||
like ($output, qr/^Description\s+1-test 1\+tag$/ms, "$ut: Description contains plus and minus signs");
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
121
test/bug.987.x
121
test/bug.987.x
@@ -1,121 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 7;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
delete $ENV{'TASKRC'};
|
||||
|
||||
use File::Basename;
|
||||
my $ut = basename ($0);
|
||||
my $rc = $ut . '.rc';
|
||||
|
||||
# Create the rc file.
|
||||
if (open my $fh, '>', $rc)
|
||||
{
|
||||
print $fh "data.location=.\n",
|
||||
"confirmation=off\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
# Bug 987 - 'Total active time' is still increasing when a task is done
|
||||
|
||||
# Test all cases for which the active duration must be close to zero and
|
||||
# constant:
|
||||
# - start (a), stop (o), done (d) and none (n)
|
||||
# (none disallows the name of each task to be the prefix of any other)
|
||||
qx{../src/task rc:$rc add test_aodn};
|
||||
qx{../src/task rc:$rc test_aodn start};
|
||||
qx{faketime -f '+1s' ../src/task rc:$rc test_aodn stop};
|
||||
qx{faketime -f '+2s' ../src/task rc:$rc test_aodn done};
|
||||
check_constant_close_zero("test_aodn");
|
||||
|
||||
# - start and done
|
||||
qx{../src/task rc:$rc add test_adn};
|
||||
qx{../src/task rc:$rc test_adn start};
|
||||
qx{faketime -f '+1s' ../src/task rc:$rc test_adn done};
|
||||
check_constant_close_zero("test_adn");
|
||||
|
||||
# - start, done and stop
|
||||
qx{../src/task rc:$rc add test_adon};
|
||||
qx{../src/task rc:$rc test_adon start};
|
||||
qx{faketime -f '+1s' ../src/task rc:$rc test_adon done};
|
||||
qx{faketime -f '+2s' ../src/task rc:$rc test_adon stop};
|
||||
check_constant_close_zero("test_adon");
|
||||
|
||||
# - done, start and stop (XXX whether this should be allowed is questionable)
|
||||
qx{../src/task rc:$rc add test_daon};
|
||||
qx{../src/task rc:$rc test_daon done};
|
||||
qx{faketime -f '+1s' ../src/task rc:$rc test_daon start};
|
||||
qx{faketime -f '+2s' ../src/task rc:$rc test_daon stop};
|
||||
check_constant_close_zero("test_daon");
|
||||
|
||||
# Test all cases for which the active duration must not be shown:
|
||||
# - done
|
||||
qx{../src/task rc:$rc add test_dn};
|
||||
qx{../src/task rc:$rc test_dn done};
|
||||
check_no_summary("test_dn");
|
||||
|
||||
# Test all case for which the active duration must be close to zero and
|
||||
# increasing:
|
||||
# - start
|
||||
qx{../src/task rc:$rc add test_sn};
|
||||
qx{../src/task rc:$rc test_sn start};
|
||||
check_running_close_zero("test_sn");
|
||||
|
||||
# - done and start (XXX whether this should be allowed is questionable)
|
||||
qx{../src/task rc:$rc add test_dsn};
|
||||
qx{../src/task rc:$rc test_dsn start};
|
||||
check_running_close_zero("test_dsn");
|
||||
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
|
||||
################################################################################
|
||||
# Check that the active time is not above one minute after waiting for one minute
|
||||
sub check_constant_close_zero {
|
||||
my ($task) = @_;
|
||||
my $output = qx{faketime -f '+60s' ../src/task rc:$rc $task info};
|
||||
like ($output, qr/Total active time 0:00:/ms, 'Total active duration is not increasing and is close to zeo');
|
||||
}
|
||||
|
||||
# Check that there is no active time summary
|
||||
sub check_no_summary {
|
||||
my ($task) = @_;
|
||||
my $output = qx{faketime -f '+10s' ../src/task rc:$rc $task info};
|
||||
unlike ($output, qr/Total active time/ms, 'No total active duration summary');
|
||||
}
|
||||
|
||||
# Check that the active time is above one minute after waiting for one minute
|
||||
sub check_running_close_zero {
|
||||
my ($task) = @_;
|
||||
my $output = qx{faketime -f '+60s' ../src/task rc:$rc $task info};
|
||||
like ($output, qr/Total active time 0:01:/ms, 'Total active duration is increasing and is close to zero');
|
||||
}
|
||||
16
test/cal.t
16
test/cal.t
@@ -29,7 +29,7 @@
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Test::More tests => 81;
|
||||
use Test::More tests => 78;
|
||||
|
||||
# Ensure environment has no influence.
|
||||
delete $ENV{'TASKDATA'};
|
||||
@@ -51,7 +51,8 @@ if (open my $fh, '>', $rc)
|
||||
"color.calendar.overdue=black on red\n",
|
||||
"color.calendar.weekend=white on bright black\n",
|
||||
"confirmation=off\n",
|
||||
"bulk=10\n";
|
||||
"bulk=10\n",
|
||||
"verbose=none\n";
|
||||
close $fh;
|
||||
}
|
||||
|
||||
@@ -181,6 +182,7 @@ if (open my $fh, '>', $rc)
|
||||
"calendar.details.report=list\n",
|
||||
"calendar.holidays=full\n",
|
||||
"color=on\n",
|
||||
"_forcecolor=on\n",
|
||||
"color.alternate=\n",
|
||||
"color.calendar.weekend=\n",
|
||||
"color.calendar.holiday=black on bright yellow\n",
|
||||
@@ -240,9 +242,7 @@ qx{../src/task rc:$rc add due:$duedate nine 2>&1};
|
||||
$output = qx{../src/task rc:$rc calendar rc.monthsperline:1 2>&1};
|
||||
like ($output, qr/$month\S*?\s+?$year/, "$ut: Current month and year are displayed");
|
||||
like ($output, qr/$duedate/, "$ut: Due date on current day is displayed");
|
||||
|
||||
# TODO: This test fails on 2015-01-01.
|
||||
like ($output, qr/[12] task/, "$ut: 1/2 due task(s) are displayed");
|
||||
like ($output, qr/[123] task/, "$ut: 1/2/3 due task(s) are displayed");
|
||||
|
||||
$output = qx{../src/task rc:$rc calendar rc.monthsperline:1 1 2015 2>&1};
|
||||
like ($output, qr/Date/, "$ut: Word Date is displayed");
|
||||
@@ -258,12 +258,6 @@ $output = qx{../src/task rc:$rc calendar rc._forcecolor:on rc.monthsperline:1 rc
|
||||
unlike ($output, qr/Date/, "$ut: Word Date is not displayed");
|
||||
unlike ($output, qr/Holiday/, "$ut: Word Holiday is not displayed");
|
||||
|
||||
# TODO: This test fails on 2015-01-01.
|
||||
like ($output, qr/30;103m 1/, "$ut: Holiday AAAA is color-coded");
|
||||
|
||||
like ($output, qr/30;103m15/, "$ut: Holiday BBBBBB is color-coded"); # 80
|
||||
like ($output, qr/30;103m25/, "$ut: Holiday åäö is color-coded");
|
||||
|
||||
# Cleanup.
|
||||
unlink qw(pending.data completed.data undo.data backlog.data), $rc;
|
||||
exit 0;
|
||||
|
||||
11
test/conversion
Executable file
11
test/conversion
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
printf "C++: %5d\n" $(ls *.t.cpp | wc -l)
|
||||
printf "Python: %5d\n" $(head -n1 *.t | grep -a '\bpython' | wc -l)
|
||||
printf "Perl: %5d\n" $(head -n1 *.t | grep -a '\bperl\b' | wc -l)
|
||||
if [ "$1" = "-v" ]; then
|
||||
echo -n "Perl left: "; echo $(grep -l '^#\! \?/usr/bin/env perl\b' *.t)
|
||||
fi
|
||||
echo
|
||||
printf "Feature %5d\n" $(ls feature.*.t | wc -l)
|
||||
printf "Bug %5d\n" $(ls {tw-,bug.}*.t | wc -l)
|
||||
511
test/datetime-negative.t
Executable file
511
test/datetime-negative.t
Executable file
@@ -0,0 +1,511 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class BaseDateTimeNegativeTest(TestCase):
|
||||
"""
|
||||
Base class for Datetime negative tests.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
|
||||
def assertInvalidDatetimeFormat(self, value):
|
||||
self.t.runError(('add', 'due:%s' % value, 'test1'))
|
||||
self.t.runError(('add', 'scheduled:%s' % value, 'test2'))
|
||||
self.t.runError(('add', 'wait:%s' % value, 'test3'))
|
||||
self.t.runError(('add', 'until:%s' % value, 'test4'))
|
||||
|
||||
|
||||
class TestIncorrectDate(BaseDateTimeNegativeTest):
|
||||
"""
|
||||
This test case makes sure various formats
|
||||
of incorrect datetimes do not get interpreted
|
||||
as valid timetamps. Covers TW-1499.
|
||||
"""
|
||||
|
||||
def test_set_incorrect_datetime_randomstring(self):
|
||||
self.assertInvalidDatetimeFormat('random')
|
||||
|
||||
def test_set_incorrect_datetime_negative_in_YYYY_MM_DD(self):
|
||||
self.assertInvalidDatetimeFormat('-2014-07-07')
|
||||
|
||||
def test_set_incorrect_datetime_missing_day_in_YYYY_MM_DD(self):
|
||||
self.assertInvalidDatetimeFormat('2014-07-')
|
||||
|
||||
# def test_set_incorrect_datetime_month_zero_in_YYYY_MM_DD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-0-12')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_characters_in_YYYY_MM_DD(self):
|
||||
self.assertInvalidDatetimeFormat('abcd-ab-ab')
|
||||
|
||||
# def test_set_incorrect_datetime_day_as_zeros_in_YYYY_DDD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-000')
|
||||
|
||||
# def test_set_incorrect_datetime_overlap_day_in_nonoverlap_year_in_YYYY_DDD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-366')
|
||||
|
||||
# def test_set_incorrect_datetime_medium_overlap_day_in_YYYY_DDD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-999')
|
||||
|
||||
def test_set_incorrect_datetime_huge_overlap_day_in_YYYY_DDD(self):
|
||||
self.assertInvalidDatetimeFormat('2014-999999999')
|
||||
|
||||
# def test_set_incorrect_datetime_week_with_the_number_zero_in_YYYY_Www(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-W00')
|
||||
|
||||
def test_set_incorrect_datetime_overflow_in_week_in_YYYY_Www(self):
|
||||
self.assertInvalidDatetimeFormat('2014-W54')
|
||||
|
||||
def test_set_incorrect_datetime_day_zero_in_YYYY_WwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014-W240')
|
||||
|
||||
def test_set_incorrect_datetime_day_eight_in_YYYY_WwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014-W248')
|
||||
|
||||
def test_set_incorrect_datetime_day_two_hundred_in_YYYY_WwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014-W24200')
|
||||
|
||||
# def test_set_incorrect_datetime_week_with_the_number_zero_in_YYYYWww(self):
|
||||
# self.assertInvalidDatetimeFormat('2014W00')
|
||||
|
||||
def test_set_incorrect_datetime_overflow_in_week_in_YYYYWww(self):
|
||||
self.assertInvalidDatetimeFormat('2014W54')
|
||||
|
||||
# def test_set_incorrect_datetime_week_zero_in_YYYYWwwD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014W001')
|
||||
|
||||
# def test_set_incorrect_datetime_fifth_day_of_week_zero_in_YYYYWwwD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014W005')
|
||||
|
||||
def test_set_incorrect_datetime_overflow_week_in_YYYYWwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014W541')
|
||||
|
||||
def test_set_incorrect_datetime_huge_overflow_week_in_YYYYWwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014W991')
|
||||
|
||||
# def test_set_incorrect_datetime_day_zero_in_YYYYWwwD(self):
|
||||
# self.assertInvalidDatetimeFormat('2014W240')
|
||||
|
||||
def test_set_incorrect_datetime_day_eight_in_YYYYWwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014W248')
|
||||
|
||||
def test_set_incorrect_datetime_day_two_hundred_in_YYYYWwwD(self):
|
||||
self.assertInvalidDatetimeFormat('2014W24200')
|
||||
|
||||
# def test_set_incorrect_datetime_month_zero_in_YYYY_MM(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-00')
|
||||
|
||||
# def test_set_incorrect_datetime_overflow_month_in_YYYY_MM(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-13')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_overflow_month_in_YYYY_MM(self):
|
||||
# self.assertInvalidDatetimeFormat('2014-99')
|
||||
|
||||
|
||||
class TestIncorrectTime(BaseDateTimeNegativeTest):
|
||||
"""
|
||||
This test class makes sure invalid time formats are not getting
|
||||
accepted by TaskWarrior parser.
|
||||
"""
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mmZ(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00Z')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('99:00Z')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mmZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60Z')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mmZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99Z')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:abZ')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12Z')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cdZ')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12Z')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mmZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12Z')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('99:00+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('99:00-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('99:00:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_second_overflow_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:60')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_second_overflow_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_seconds_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:ab')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd:ef')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12:12')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12:12')
|
||||
|
||||
# def test_set_incorrect_datetime_negative_seconds_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:-12')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_ssZ(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00:00Z')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('99:00:00Z')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_ssZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60:00Z')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_ssZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99:00Z')
|
||||
|
||||
# def test_set_incorrect_datetime_second_overflow_in_hh_mm_ssZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:60Z')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_second_overflow_in_hh_mm_ssZ(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:99Z')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab:00Z')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12:00Z')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_seconds_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:abZ')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd:efZ')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12:12Z')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12:12Z')
|
||||
|
||||
def test_set_incorrect_datetime_negative_seconds_in_hh_mm_ssZ(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:-12Z')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00:00+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('95:00:00+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60:00+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99:00+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_second_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:60+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_second_overflow_in_hh_mm_ss_plus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:99+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab:00+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12:00+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_seconds_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:ab+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd:ef+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12:12+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12:12+01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_seconds_in_hh_mm_ss_plus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:-12+01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_hour_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('24:00:00-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_huge_hour_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('95:00:00-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_minute_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:60:00-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_minute_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:99:00-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_second_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:60-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_huge_second_overflow_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:99-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minutes_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:ab:00-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hours_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:12:00-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_seconds_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:ab-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_time_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('ab:cd:ef-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_hours_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('-12:12:12-01:00')
|
||||
|
||||
def test_set_incorrect_datetime_negative_minutes_in_hh_mm_ss_minus_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:-12:12-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_negative_seconds_in_hh_mm_ss_minus_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:-12-01:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_hour_positive_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12+13:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_medium_hour_positive_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12+24:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_huge_hour_positive_offset_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12+99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_minute_positive_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12+03:60')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_huge_minute_positive_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12+03:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hour_positive_offset_length_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12+3:20')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minute_positive_offset_lentgh_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12+03:2')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_positive_offset_length_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12+3:2')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_hour_negative_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12-13:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_medium_hour_negative_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12-24:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_huge_hour_negative_offset_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12-99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_minute_negative_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12-03:60')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_huge_minute_negative_offset_in_hh_mm_ss(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12:12-03:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hour_negative_offset_length_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12-3:20')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minute_negative_offset_lentgh_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12-03:2')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_negative_offset_length_in_hh_mm_ss(self):
|
||||
self.assertInvalidDatetimeFormat('12:12:12-3:2')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_hour_positive_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12+13:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_medium_hour_positive_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12+24:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_huge_hour_positive_offset_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12+99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_minute_positive_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12+03:60')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_huge_minute_positive_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12+03:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hour_positive_offset_length_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12+3:20')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minute_positive_offset_lentgh_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12+03:2')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_positive_offset_length_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12+3:2')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_hour_negative_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12-13:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_medium_hour_negative_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12-24:00')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_huge_hour_negative_offset_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12-99:00')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_minute_negative_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12-03:60')
|
||||
|
||||
# def test_set_incorrect_datetime_invalid_huge_minute_negative_offset_in_hh_mm(self):
|
||||
# self.assertInvalidDatetimeFormat('12:12-03:99')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_hour_negative_offset_length_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12-3:20')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_minute_negative_offset_lentgh_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12-03:2')
|
||||
|
||||
def test_set_incorrect_datetime_invalid_negative_offset_length_in_hh_mm(self):
|
||||
self.assertInvalidDatetimeFormat('12:12-3:2')
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
185
test/export.t
Executable file
185
test/export.t
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import numbers
|
||||
import os
|
||||
import re
|
||||
import unittest
|
||||
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
# TODO: Move to common file with all regexpes
|
||||
UUID_REGEXP = r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'
|
||||
DATETIME_FORMAT = "%Y%m%dT%H%M%SZ"
|
||||
|
||||
|
||||
class TestExportCommand(TestCase):
|
||||
def setUp(self):
|
||||
self.t = Task()
|
||||
self.t(('add', 'test'))
|
||||
|
||||
def export(self, identifier):
|
||||
return json.loads(self.t((str(identifier), 'export'))[1].strip())
|
||||
|
||||
def assertType(self, value, type):
|
||||
self.assertEqual(isinstance(value, type), True)
|
||||
|
||||
def assertTimestamp(self, value):
|
||||
"""
|
||||
Asserts that timestamp is exported as string in the correct format.
|
||||
"""
|
||||
|
||||
# Timestamps should be exported as strings
|
||||
self.assertType(value, unicode)
|
||||
# And they should follow the %Y%m%dT%H%M%SZ format
|
||||
datetime.datetime.strptime(value, DATETIME_FORMAT)
|
||||
|
||||
def assertString(self, value, expected_value=None, regexp=False):
|
||||
"""
|
||||
Checks the type of value to be string, and that content is as passed in
|
||||
the expected_value argument. This can be either a string, or a compiled
|
||||
regular expression object.
|
||||
"""
|
||||
|
||||
self.assertType(value, unicode)
|
||||
|
||||
if expected_value is not None:
|
||||
if regexp:
|
||||
# Match to pattern if checking with regexp
|
||||
self.assertRegexpMatches(value, expected_value)
|
||||
else:
|
||||
# Equality match if checking with string
|
||||
self.assertEqual(value, expected_value)
|
||||
|
||||
def assertNumeric(self, value, expected_value=None):
|
||||
"""
|
||||
Checks the type of the value to be int, and that the expected value
|
||||
matches the actual value produced.
|
||||
"""
|
||||
self.assertType(value, numbers.Real)
|
||||
if expected_value is not None:
|
||||
self.assertEqual(value, expected_value)
|
||||
|
||||
def test_export_status(self):
|
||||
self.assertString(self.export(1)['status'], "pending")
|
||||
|
||||
def test_export_uuid(self):
|
||||
self.assertString(self.export(1)['uuid'], UUID_REGEXP, regexp=True)
|
||||
|
||||
def test_export_entry(self):
|
||||
self.assertTimestamp(self.export(1)['entry'])
|
||||
|
||||
def test_export_description(self):
|
||||
self.assertString(self.export(1)['description'], "test")
|
||||
|
||||
def test_export_start(self):
|
||||
self.t(('1', 'start'))
|
||||
self.assertTimestamp(self.export(1)['start'])
|
||||
|
||||
def test_export_end(self):
|
||||
self.t(('1', 'start'))
|
||||
time.sleep(2)
|
||||
self.t(('1', 'done'))
|
||||
self.assertTimestamp(self.export(1)['end'])
|
||||
|
||||
def test_export_due(self):
|
||||
self.t(('1', 'modify', 'due:today'))
|
||||
self.assertTimestamp(self.export(1)['due'])
|
||||
|
||||
def test_export_wait(self):
|
||||
self.t(('1', 'modify', 'wait:tomorrow'))
|
||||
self.assertTimestamp(self.export(1)['wait'])
|
||||
|
||||
def test_export_modified(self):
|
||||
self.assertTimestamp(self.export(1)['modified'])
|
||||
|
||||
def test_export_scheduled(self):
|
||||
self.t(('1', 'modify', 'schedule:tomorrow'))
|
||||
self.assertTimestamp(self.export(1)['scheduled'])
|
||||
|
||||
def test_export_recur(self):
|
||||
self.t(('1', 'modify', 'recur:daily', 'due:today'))
|
||||
self.assertString(self.export(1)['recur'], "daily")
|
||||
|
||||
def test_export_project(self):
|
||||
self.t(('1', 'modify', 'project:Home'))
|
||||
self.assertString(self.export(1)['project'], "Home")
|
||||
|
||||
def test_export_priority(self):
|
||||
self.t(('1', 'modify', 'priority:H'))
|
||||
self.assertString(self.export(1)['priority'], "H")
|
||||
|
||||
def test_export_depends(self):
|
||||
self.t(('add', 'everything depends on me task'))
|
||||
self.t(('add', 'wrong, everything depends on me task'))
|
||||
self.t(('1', 'modify', 'depends:2,3'))
|
||||
|
||||
values = self.export(1)['depends']
|
||||
self.assertString(values)
|
||||
|
||||
for uuid in values.split(','):
|
||||
self.assertString(uuid, UUID_REGEXP, regexp=True)
|
||||
|
||||
def test_export_urgency(self):
|
||||
self.t(('add', 'urgent task', '+urgent'))
|
||||
|
||||
# Urgency can be either integer or float
|
||||
self.assertNumeric(self.export(1)['urgency'])
|
||||
|
||||
def test_export_numeric_uda(self):
|
||||
self.t.config('uda.estimate.type', 'numeric')
|
||||
self.t(('add', 'estimate:42', 'test numeric uda'))
|
||||
self.assertNumeric(self.export('2')['estimate'], 42)
|
||||
|
||||
def test_export_string_uda(self):
|
||||
self.t.config('uda.estimate.type', 'string')
|
||||
self.t(('add', 'estimate:big', 'test string uda'))
|
||||
self.assertString(self.export('2')['estimate'], 'big')
|
||||
|
||||
def test_export_datetime_uda(self):
|
||||
self.t.config('uda.estimate.type', 'date')
|
||||
self.t(('add', 'estimate:eom', 'test date uda'))
|
||||
self.assertTimestamp(self.export('2')['estimate'])
|
||||
|
||||
def test_export_duration_uda(self):
|
||||
self.t.config('uda.estimate.type', 'duration')
|
||||
self.t(('add', 'estimate:month', 'test duration uda'))
|
||||
self.assertString(self.export('2')['estimate'], 'month')
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
161
test/hooks.on-add.t
Executable file
161
test/hooks.on-add.t
Executable file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class TestHooksOnAdd(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t.activate_hooks()
|
||||
|
||||
def test_onadd_builtin_accept(self):
|
||||
"""on-add-accept - a well-behaved, successful, on-add hook."""
|
||||
hookname = 'on-add-accept'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onadd_builtin_reject(self):
|
||||
"""on-add-reject - a well-behaved, failing, on-add hook."""
|
||||
hookname = 'on-add-reject'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onadd_builtin_misbehave1(self):
|
||||
"""on-add-misbehave1 - does not consume input."""
|
||||
hookname = 'on-add-misbehave1'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onadd_builtin_misbehave2(self):
|
||||
"""on-add-misbehave2 - does not emit JSON."""
|
||||
hookname = 'on-add-misbehave2'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
self.assertIn("Hook Error: Expected 1 JSON task(s), found 0", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
def test_onadd_builtin_misbehave3(self):
|
||||
"""on-add-misbehave3 - emits additional JSON."""
|
||||
hookname = 'on-add-misbehave3'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
self.assertIn("Hook Error: Expected 1 JSON task(s), found 2", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
def test_onadd_builtin_misbehave4(self):
|
||||
"""on-add-misbehave4 - emits different task JSON."""
|
||||
hookname = 'on-add-misbehave4'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
self.assertIn("Hook Error: JSON must be for the same task:", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onadd_builtin_misbehave5(self):
|
||||
"""on-add-misbehave5 - emits syntactically wrong JSON."""
|
||||
hookname = 'on-add-misbehave5'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
self.assertIn("Hook Error: JSON syntax error in: {\"}", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
hook.assertInvalidJSONOutput()
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onadd_builtin_misbehave6(self):
|
||||
"""on-add-misbehave6 - emits incomplete JSON."""
|
||||
hookname = 'on-add-misbehave6'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t.runError(("add", "foo"))
|
||||
self.assertIn("Hook Error: JSON Object missing 'uuid' attribute.", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
112
test/hooks.on-exit.t
Executable file
112
test/hooks.on-exit.t
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class TestHooksOnExit(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t.activate_hooks()
|
||||
|
||||
def test_onexit_builtin_good(self):
|
||||
"""on-exit-good - a well-behaved, successful, on-exit hook."""
|
||||
hookname = 'on-exit-good'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("version",))
|
||||
self.assertIn("Taskwarrior", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onexit_builtin_bad(self):
|
||||
"""on-exit-bad - a well-behaved, failing, on-exit hook."""
|
||||
hookname = 'on-exit-bad'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t.runError(("version",))
|
||||
self.assertIn("Taskwarrior", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onexit_builtin_misbehave1(self):
|
||||
"""on-exit-misbehave1 - Does not consume input."""
|
||||
hookname = 'on-exit-misbehave1'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t(("version",))
|
||||
self.assertIn("Taskwarrior", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onexit_builtin_misbehave2(self):
|
||||
"""on-exit-misbehave2 - Emits unexpected JSON."""
|
||||
hookname = 'on-exit-misbehave2'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t.runError(("version",))
|
||||
self.assertIn("Hook Error: Expected 0 JSON task(s), found 1", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
112
test/hooks.on-launch.t
Executable file
112
test/hooks.on-launch.t
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class TestHooksOnLaunch(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t.activate_hooks()
|
||||
|
||||
def test_onlaunch_builtin_good(self):
|
||||
"""on-launch-good - a well-behaved, successful, on-launch hook."""
|
||||
hookname = 'on-launch-good'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("version",))
|
||||
self.assertIn("Taskwarrior", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onlaunch_builtin_bad(self):
|
||||
"""on-launch-bad - a well-behaved, failing, on-launch hook."""
|
||||
hookname = 'on-launch-bad'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t.runError(("version",))
|
||||
self.assertNotIn("Taskwarrior", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onlaunch_builtin_misbehave1(self):
|
||||
"""on-launch-misbehave1 - Hook kills itself."""
|
||||
hookname = 'on-launch-misbehave1'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t.runError(("version",))
|
||||
self.assertNotIn("Could not get Hook exit status!", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(137)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onlaunch_builtin_misbehave2(self):
|
||||
"""on-launch-misbehave2 - Hook emits unexpected JSON."""
|
||||
hookname = 'on-launch-misbehave2'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
# Failing hook should prevent processing.
|
||||
code, out, err = self.t.runError(("version",))
|
||||
self.assertIn("Hook Error: Expected 0 JSON task(s), found 1", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
159
test/hooks.on-modify.t
Executable file
159
test/hooks.on-modify.t
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class TestHooksOnModify(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t.activate_hooks()
|
||||
|
||||
def test_onmodify_builtin_accept(self):
|
||||
"""on-modify-accept - a well-behaved, successful, on-modify hook."""
|
||||
hookname = 'on-modify-accept'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t(("1", "modify", "+tag"))
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_reject(self):
|
||||
"""on-modify-reject - a well-behaved, failing, on-modify hook."""
|
||||
hookname = 'on-modify-reject'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_misbehave2(self):
|
||||
"""on-modify-misbehave2 - does not emit JSON."""
|
||||
hookname = 'on-modify-misbehave2'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
self.assertIn("Hook Error: Expected 1 JSON task(s), found 0", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_misbehave3(self):
|
||||
"""on-modify-misbehave3 - emits additional JSON."""
|
||||
hookname = 'on-modify-misbehave3'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
self.assertIn("Hook Error: Expected 1 JSON task(s), found 2", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_misbehave4(self):
|
||||
"""on-modify-misbehave4 - emits different task JSON."""
|
||||
hookname = 'on-modify-misbehave4'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
self.assertIn("Hook Error: JSON must be for the same task:", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_misbehave5(self):
|
||||
"""on-modify-misbehave5 - emits syntactically wrong JSON."""
|
||||
hookname = 'on-modify-misbehave5'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
self.assertIn("Hook Error: JSON syntax error in: {\"}", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
def test_onmodify_builtin_misbehave6(self):
|
||||
"""on-modify-misbehave6 - emits incomplete JSON."""
|
||||
hookname = 'on-modify-misbehave6'
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
code, out, err = self.t(("add", "foo"))
|
||||
code, out, err = self.t.runError(("1", "modify", "+tag"))
|
||||
self.assertIn("Hook Error: JSON Object missing 'uuid' attribute.", err)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
logs = hook.get_logs()
|
||||
self.assertEqual(logs["output"]["msgs"][0], "FEEDBACK")
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
@@ -45,6 +45,8 @@ const char *positive_tests[] =
|
||||
|
||||
"{\n\"one\"\n:\n1\n}\n",
|
||||
|
||||
" { \"one\" : 1 } ",
|
||||
|
||||
"{\"name\":123, \"array\":[1,2,3.4], \"object\":{\"m1\":\"v1\", \"m2\":\"v2\"}}",
|
||||
|
||||
"{\"name\":\"value\",\"array\":[\"one\",\"two\"],\"object\":{\"name2\":123,\"literal\":false}}",
|
||||
|
||||
25
test/math.t
25
test/math.t
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
63
test/recur.disabled.t
Executable file
63
test/recur.disabled.t
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
##
|
||||
## Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
##
|
||||
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
## of this software and associated documentation files (the "Software"), to deal
|
||||
## in the Software without restriction, including without limitation the rights
|
||||
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
## copies of the Software, and to permit persons to whom the Software is
|
||||
## furnished to do so, subject to the following conditions:
|
||||
##
|
||||
## The above copyright notice and this permission notice shall be included
|
||||
## in all copies or substantial portions of the Software.
|
||||
##
|
||||
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
## OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
## SOFTWARE.
|
||||
##
|
||||
## http://www.opensource.org/licenses/mit-license.php
|
||||
##
|
||||
################################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
import unittest
|
||||
# Ensure python finds the local simpletap module
|
||||
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from basetest import Task, TestCase
|
||||
|
||||
|
||||
class TestRecurrenceDisabled(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
|
||||
def test_reccurence_disabled(self):
|
||||
"""
|
||||
Test that recurrent tasks are not being generated when recurrence is
|
||||
disabled.
|
||||
"""
|
||||
|
||||
self.t.config("recurrence", "no")
|
||||
self.t(("add", "due:today", "recur:daily", "Recurrent task."))
|
||||
|
||||
# Trigger GC, expect no match and therefore non-zero code
|
||||
self.t.runError(("list",))
|
||||
|
||||
# Check that no task has been generated.
|
||||
code, out, err = self.t(("task", "count"))
|
||||
self.assertEqual("0", out.strip())
|
||||
|
||||
if __name__ == "__main__":
|
||||
from simpletap import TAPTestRunner
|
||||
unittest.main(testRunner=TAPTestRunner())
|
||||
|
||||
# vim: ai sts=4 et sw=4
|
||||
@@ -28,7 +28,7 @@ else
|
||||
# because 'date +%s' isn't supported on Solaris.
|
||||
STARTEPOCH=`perl -e 'print time'`
|
||||
|
||||
VRAMSTEG=`which vramsteg`
|
||||
VRAMSTEG=`which vramsteg 2>/dev/null`
|
||||
BAR=0
|
||||
if [ -x "$VRAMSTEG" ]; then
|
||||
BAR=1
|
||||
|
||||
124
test/template.t
124
test/template.t
@@ -1,5 +1,30 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
###############################################################################
|
||||
#
|
||||
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# http://www.opensource.org/licenses/mit-license.php
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
import sys
|
||||
import os
|
||||
@@ -70,6 +95,105 @@ class TestBugNumber(TestCase):
|
||||
"""Executed once after all tests in the class"""
|
||||
|
||||
|
||||
class TestHooksBugNumber(TestCase):
|
||||
def setUp(self):
|
||||
"""Executed before each test in the class"""
|
||||
self.t = Task()
|
||||
self.t.activate_hooks()
|
||||
|
||||
def test_onmodify_custom(self):
|
||||
"""Testing a custom made hook"""
|
||||
hookname = "on-modify-example-raw"
|
||||
|
||||
content = """#!/usr/bin/env python
|
||||
import sys
|
||||
import json
|
||||
|
||||
original_task = sys.stdin.readline()
|
||||
modified_task = sys.stdin.readline()
|
||||
|
||||
task = json.loads(modified_task)
|
||||
task["description"] = "The hook did its magic"
|
||||
|
||||
sys.stdout.write(json.dumps(task, separators=(',', ':')) + '\\n')
|
||||
sys.exit(0)
|
||||
"""
|
||||
|
||||
self.t.hooks.add(hookname, content)
|
||||
|
||||
self.t(("add", "Hello hooks"))
|
||||
self.t(("1", "mod", "/Hello/Greetings/"))
|
||||
code, out, err = self.t()
|
||||
self.assertIn("The hook did its magic", out)
|
||||
|
||||
self.t.hooks[hookname].disable()
|
||||
self.assertFalse(self.t.hooks[hookname].is_active())
|
||||
|
||||
self.t(("1", "mod", "/magic/thing/"))
|
||||
code, out, err = self.t()
|
||||
self.assertIn("The hook did its thing", out)
|
||||
|
||||
def test_onmodify_builtin_with_log(self):
|
||||
"""Testing a builtin hook and keeping track of its input/output
|
||||
|
||||
The builtin hook in found in test/test_hooks
|
||||
"""
|
||||
hookname = "on-modify-for-template.py"
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
self.t(("add", "Hello hooks"))
|
||||
self.t(("1", "mod", "/Hello/Greetings/"))
|
||||
code, out, err = self.t()
|
||||
self.assertIn("This is an example modify hook", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
logs = hook.get_logs()
|
||||
|
||||
# Hook was called once
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(0)
|
||||
|
||||
# Ensure output from hook is valid JSON
|
||||
# (according to python's JSON parser)
|
||||
hook.assertValidJSONOutput()
|
||||
|
||||
# Some message output from the hook
|
||||
self.assertEqual(logs["output"]["msgs"][0],
|
||||
"Hello from the template hook")
|
||||
|
||||
# This is what taskwarrior received
|
||||
self.assertEqual(logs["output"]["json"][0]["description"],
|
||||
"This is an example modify hook")
|
||||
|
||||
def test_onmodify_bad_builtin_with_log(self):
|
||||
"""Testing a builtin hook and keeping track of its input/output
|
||||
|
||||
The builtin hook in found in test/test_hooks
|
||||
"""
|
||||
hookname = "on-modify-for-template-badexit.py"
|
||||
self.t.hooks.add_default(hookname, log=True)
|
||||
|
||||
self.t(("add", "Hello hooks"))
|
||||
self.t.runError(("1", "mod", "/Hello/Greetings/"))
|
||||
code, out, err = self.t()
|
||||
self.assertNotIn("This is an example modify hook", out)
|
||||
|
||||
hook = self.t.hooks[hookname]
|
||||
logs = hook.get_logs()
|
||||
|
||||
# Hook was called once
|
||||
hook.assertTriggeredCount(1)
|
||||
hook.assertExitcode(1)
|
||||
|
||||
# Some message output from the hook
|
||||
self.assertEqual(logs["output"]["msgs"][0],
|
||||
"Hello from the template hook")
|
||||
|
||||
# This is what taskwarrior would have used if hook finished cleanly
|
||||
self.assertEqual(logs["output"]["json"][0]["description"],
|
||||
"This is an example modify hook")
|
||||
|
||||
|
||||
class ServerTestBugNumber(ServerTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,32 +1,247 @@
|
||||
Public Key Info:
|
||||
Public Key Algorithm: RSA
|
||||
Key Security Level: High (4096 bits)
|
||||
|
||||
modulus:
|
||||
00:b4:20:a9:9b:6b:47:87:f1:e7:e8:5f:2c:df:d1:
|
||||
14:3b:46:69:12:8b:39:bd:be:1b:58:1c:59:86:82:
|
||||
64:ca:22:b1:59:5a:87:96:e1:ce:44:a0:c0:e0:20:
|
||||
96:e3:08:ff:e5:4c:ec:6b:e6:00:22:21:91:6e:29:
|
||||
80:c6:d8:3b:c0:0d:1f:f0:5f:aa:67:d7:da:13:09:
|
||||
f8:81:45:8f:06:1a:5f:75:6c:90:ca:cf:f1:c8:4f:
|
||||
2b:f7:a7:09:38:99:5e:50:e0:be:b6:16:5b:18:6f:
|
||||
62:8b:9a:5a:c5:a0:df:7c:6e:4c:df:e2:19:61:c6:
|
||||
45:48:81:40:f1:5d:17:67:e3:4b:10:59:1d:35:24:
|
||||
3e:3d:b0:51:fb:55:bd:7e:0e:fb:34:31:44:0d:cd:
|
||||
7d:7f:50:f6:b7:91:22:e9:d8:03:a1:43:d5:4e:0f:
|
||||
ae:4f:ca:4c:92:b2:95:dc:b9:e9:86:1b:a9:3d:73:
|
||||
9f:61:39:5c:07:6e:bc:2a:50:3f:7b:89:03:16:d6:
|
||||
ff:c0:68:bc:dd:f2:9f:2c:ab:44:14:96:3c:1d:d1:
|
||||
1e:48:51:48:e5:cf:53:1e:aa:0b:07:22:bc:04:af:
|
||||
1e:34:b4:e9:17:47:d9:37:1e:eb:69:22:8c:5f:41:
|
||||
86:fb:3d:18:43:f9:4b:9b:45:0a:63:0e:60:06:b9:
|
||||
49:0b:1d:ee:03:a9:1d:ea:8a:31:39:bb:ec:9f:a7:
|
||||
05:c0:11:97:56:1d:3d:6e:a2:43:89:f5:03:d0:f6:
|
||||
ae:86:0e:f3:dd:89:17:12:ef:0f:25:9f:59:dd:af:
|
||||
45:8e:e4:b6:5e:0d:06:d1:82:22:08:74:e9:25:12:
|
||||
79:88:15:fe:f8:f9:5d:e7:84:47:0e:d8:fb:0f:ba:
|
||||
f4:a6:38:1c:53:50:d9:0b:a9:9d:ed:43:d3:2c:14:
|
||||
30:8d:ff:e2:8e:5d:6c:a1:83:4e:4d:a7:ac:d0:06:
|
||||
54:a5:74:cd:64:39:89:11:2d:85:8e:83:4f:02:70:
|
||||
d5:fa:86:c2:3e:1b:08:5c:cf:d5:d7:aa:11:34:88:
|
||||
ab:22:0b:85:ad:ef:73:25:98:0f:24:04:2a:e5:fc:
|
||||
3e:96:bf:11:af:0a:02:38:e2:ca:17:2a:c1:97:1e:
|
||||
ac:d2:be:a2:c0:14:51:ca:07:2c:31:60:c0:31:b3:
|
||||
52:a2:54:fd:7b:c7:a5:69:3c:44:38:2e:23:cb:b5:
|
||||
60:fe:3d:43:8f:c2:60:f4:f2:b4:99:95:11:8b:6f:
|
||||
2f:6a:9b:bd:76:9a:13:51:ea:62:d2:c4:c7:a6:f4:
|
||||
86:5d:7f:f2:f4:cc:2b:30:75:e9:32:52:19:fe:da:
|
||||
50:73:99:27:58:38:08:a8:ec:6f:b1:e5:60:8b:24:
|
||||
b2:63:fd:
|
||||
|
||||
public exponent:
|
||||
01:00:01:
|
||||
|
||||
private exponent:
|
||||
00:b1:64:91:64:4c:6c:af:c7:5e:da:8c:10:c7:83:
|
||||
42:e7:75:5a:39:36:ff:f0:8b:6e:a6:81:94:f1:51:
|
||||
2d:2d:9c:a9:08:14:8d:ff:db:f5:a5:c4:a2:ee:97:
|
||||
69:c1:c1:b5:31:ff:65:be:85:4e:90:4e:7a:c9:00:
|
||||
fa:9f:d9:88:4e:85:1e:75:3d:e1:b6:4e:ef:a7:5c:
|
||||
64:6d:fb:30:f5:93:b7:7b:0f:26:31:76:44:e9:3e:
|
||||
7f:50:70:22:36:a9:64:27:46:8e:cb:08:8d:42:2d:
|
||||
3f:e1:b8:6b:b8:c1:cc:16:e1:11:b8:53:15:28:23:
|
||||
79:4c:04:6f:0e:c4:dd:2e:24:bc:62:27:41:0a:7a:
|
||||
dd:09:27:c2:35:41:a5:52:a6:32:62:9e:3a:25:55:
|
||||
c0:48:48:56:11:46:50:19:f7:f0:eb:3a:c0:b1:15:
|
||||
e4:57:14:26:01:3a:fb:37:db:a7:cd:b9:24:1d:2e:
|
||||
e7:41:7a:99:d5:80:0a:b3:a9:40:3b:cb:1d:4d:bb:
|
||||
03:38:5c:6d:d4:2f:02:ef:9c:e3:79:5a:d3:6d:91:
|
||||
ea:be:d1:be:77:04:8d:19:5f:e1:68:6f:9e:b7:06:
|
||||
37:3b:35:07:71:34:03:09:b3:db:a7:38:ad:01:8a:
|
||||
a9:02:78:92:93:2e:ca:74:e9:b3:67:06:5b:2f:83:
|
||||
fe:17:db:8a:2d:9f:09:08:9f:ce:58:1f:38:72:2c:
|
||||
36:ac:d1:0c:11:3a:84:4c:40:3d:ad:20:de:39:7a:
|
||||
2a:b0:d2:e6:a9:c8:5e:78:e7:a0:6d:33:2a:fd:2d:
|
||||
67:cb:98:ed:b9:01:bb:e6:fc:1e:e2:01:c8:0b:59:
|
||||
1c:fc:c4:82:2f:d0:95:cf:f4:aa:2d:0d:dc:00:42:
|
||||
9e:5f:4c:cb:c6:14:ed:9a:4b:d5:95:ad:97:0a:9d:
|
||||
33:5f:72:ab:ec:e6:4a:4d:61:b4:0c:33:f1:d9:f5:
|
||||
07:bc:c2:2f:59:4e:8a:59:3e:4d:e2:6d:20:f0:60:
|
||||
42:44:2a:88:f5:f9:fa:68:97:3d:aa:4b:87:2a:47:
|
||||
01:9b:be:9d:85:e8:18:3c:ad:bb:5c:0e:6e:d9:88:
|
||||
bd:23:1e:56:4e:33:13:8a:27:84:6d:b3:d8:bc:be:
|
||||
70:43:4c:f8:7e:5d:09:5e:35:d3:1e:c7:80:04:1d:
|
||||
af:81:f2:85:52:3e:3c:98:b2:30:03:29:18:c5:da:
|
||||
4f:be:58:6d:43:5d:7e:26:bc:9d:23:55:0c:61:cb:
|
||||
ed:a7:57:c7:50:9a:fc:77:d0:55:c1:a7:a3:ff:3e:
|
||||
7a:de:9a:0b:42:6c:51:ba:2f:39:a4:01:d1:90:3f:
|
||||
2c:ff:57:89:65:9e:ad:b8:c2:f6:f5:b8:65:aa:dd:
|
||||
a2:4a:49:
|
||||
|
||||
prime1:
|
||||
00:dc:e3:cf:71:5a:2f:ef:8a:de:63:6d:c3:3a:1d:
|
||||
77:12:97:b6:8b:97:4a:c0:5a:21:b0:04:39:67:f8:
|
||||
c7:8f:21:2a:39:f5:ed:9b:0a:fb:11:3a:68:44:5f:
|
||||
54:2e:5f:5b:db:db:57:c7:a2:c9:ce:77:32:b2:fd:
|
||||
b5:8f:12:c6:36:2c:b6:f0:9c:8b:9c:3f:09:b0:4a:
|
||||
a0:b3:3c:37:2f:46:b3:2f:e6:e6:fe:91:55:c3:aa:
|
||||
e6:9d:4a:34:4d:6b:c4:c9:24:41:a5:eb:06:4f:11:
|
||||
39:a1:b0:7a:67:c5:7c:03:f1:e5:de:74:ba:9c:75:
|
||||
38:46:23:99:87:a6:db:72:9f:93:51:5b:b0:f9:58:
|
||||
ad:77:ed:a9:48:97:62:8e:f2:43:c3:49:9e:09:70:
|
||||
08:2f:ec:59:e4:ef:77:c4:2d:72:b3:c7:96:04:47:
|
||||
e9:9e:1f:ed:eb:09:e8:f5:78:4c:33:ec:37:62:79:
|
||||
32:ed:7a:4e:9a:05:6e:2c:df:61:40:c1:7e:63:ee:
|
||||
7c:87:fa:35:87:0a:da:aa:9e:00:74:fa:37:8e:f6:
|
||||
c4:06:d9:f2:10:e9:19:4d:4a:b0:e3:98:c8:bd:4f:
|
||||
2d:81:31:07:a6:6a:d7:b0:2e:d3:a8:f9:d7:57:8e:
|
||||
05:97:39:2e:5e:50:ae:9b:9f:09:98:e6:3c:b8:4c:
|
||||
6a:bb:
|
||||
|
||||
prime2:
|
||||
00:d0:c2:33:7b:b2:d9:67:66:65:10:ab:67:fe:29:
|
||||
6e:ec:8b:14:c8:2e:59:ff:7e:57:2e:19:53:20:9e:
|
||||
1b:bc:3f:d6:62:49:45:dc:3b:bd:83:22:9b:4b:93:
|
||||
a3:04:9d:9e:6c:54:45:69:56:3f:56:73:4a:76:5c:
|
||||
50:4d:cb:6d:31:4b:10:80:a6:8c:1f:32:47:14:93:
|
||||
e1:a2:5f:92:29:28:1c:c4:71:4c:04:e7:3e:5a:3d:
|
||||
66:2f:64:29:da:9a:50:e3:2f:e6:d5:6d:9c:fa:ad:
|
||||
7b:db:71:25:63:2a:7e:f8:c2:fd:b2:14:45:7e:1b:
|
||||
23:81:6f:2d:c5:24:55:46:5f:54:3f:41:38:34:90:
|
||||
2b:73:6f:e4:53:ba:d8:74:4f:0f:51:d6:37:03:76:
|
||||
8f:05:77:52:f7:3b:04:38:16:fc:47:ab:e3:33:1b:
|
||||
dd:c5:2e:69:13:ba:76:bb:a0:58:aa:a3:af:2f:6e:
|
||||
0c:d0:ae:41:af:b2:2e:cd:84:57:e7:0f:d2:1b:f7:
|
||||
40:79:d4:e4:3e:74:b2:d9:b8:2e:94:34:76:27:00:
|
||||
05:6d:ba:d0:1a:46:95:f2:b0:eb:21:33:ca:71:f9:
|
||||
38:4e:1c:2d:1a:80:84:6e:4b:0d:33:5f:5e:e7:18:
|
||||
c6:c1:ff:2e:c6:c5:0f:ad:11:21:f5:81:38:00:08:
|
||||
0c:a7:
|
||||
|
||||
coefficient:
|
||||
00:d4:c5:a5:62:ea:96:09:ba:3d:a8:94:23:81:6e:
|
||||
f9:94:cd:12:54:8f:24:51:be:ea:cc:4d:b2:77:5e:
|
||||
75:d5:b6:79:fd:f4:bb:e9:92:94:90:8f:4c:e2:4d:
|
||||
40:c1:d0:ce:e9:a9:6f:3e:13:f3:b0:48:3d:99:78:
|
||||
ef:4b:a7:f7:7e:2b:2f:82:63:c6:81:05:9e:86:64:
|
||||
bc:c8:de:96:d3:54:12:b9:eb:17:65:58:52:8b:ef:
|
||||
d8:ed:52:fc:e4:19:41:9b:15:81:ac:06:10:6c:e8:
|
||||
2a:6c:83:44:ee:52:b8:e7:8b:aa:46:33:31:b1:bf:
|
||||
17:eb:67:a6:9d:99:d2:74:1d:4e:54:dd:50:05:b3:
|
||||
4e:5f:49:41:9b:29:71:67:19:bd:a1:1e:2b:9c:be:
|
||||
ea:a0:4f:ae:01:25:aa:0a:f3:00:9a:c9:93:ac:86:
|
||||
26:f0:14:54:31:c8:1e:b3:3b:e0:a2:fb:f2:df:8a:
|
||||
35:f5:db:39:08:78:dc:79:fd:97:72:23:ff:b2:f0:
|
||||
54:ca:17:e2:01:b6:bc:17:4e:60:da:30:16:e0:a1:
|
||||
02:79:2c:7b:23:00:10:84:66:e8:7c:87:13:64:4f:
|
||||
17:20:ea:a6:07:ed:ab:d9:7e:1c:1e:d1:f7:20:f4:
|
||||
a6:a8:d7:46:52:a9:a3:4b:8a:90:e9:83:51:fb:0c:
|
||||
a7:b7:
|
||||
|
||||
exp1:
|
||||
40:c6:05:04:c6:5f:9c:2c:ea:bd:d9:68:10:58:a7:
|
||||
9c:2a:24:fb:96:27:f3:73:fa:c0:f4:dc:28:a3:09:
|
||||
51:ed:75:c6:7d:59:69:c7:b4:8b:fe:c6:a8:96:13:
|
||||
c7:6d:6b:30:73:87:b0:21:0a:70:a2:ff:99:01:51:
|
||||
06:5d:89:06:45:e2:77:78:50:70:47:03:fe:50:44:
|
||||
03:8b:3a:db:80:2d:f7:74:0c:74:c6:05:92:55:41:
|
||||
3f:0a:8d:7f:ce:84:6c:3f:57:88:e1:fc:7d:9f:1d:
|
||||
79:4e:98:f6:69:30:ce:af:56:aa:ff:2b:e1:c9:75:
|
||||
f1:0b:6b:70:1d:fb:e8:06:e7:5a:4a:3b:01:43:81:
|
||||
ca:d3:44:7a:e6:f9:9d:d5:69:0d:91:3e:e8:a1:93:
|
||||
a5:09:f7:ea:6c:56:80:8e:9b:3e:20:de:da:ee:83:
|
||||
91:3c:e7:b5:ae:b8:43:93:3d:35:54:a5:81:18:ed:
|
||||
58:3a:2f:66:77:05:31:df:67:53:67:ea:3a:3f:ab:
|
||||
00:ec:dc:59:77:53:5c:08:ed:35:60:52:7e:77:da:
|
||||
4f:f0:05:4d:f4:2c:d9:3f:77:d3:a5:ef:e7:a3:9a:
|
||||
42:72:30:3e:1a:c2:99:05:82:47:e0:cb:c6:fe:fc:
|
||||
a0:b5:c1:e5:22:5f:b1:7e:d7:7f:a0:b4:59:8e:ff:
|
||||
15:
|
||||
|
||||
exp2:
|
||||
1c:bb:5d:d2:9c:9f:07:78:34:58:c2:fe:a1:20:9a:
|
||||
bf:bb:b4:b4:88:8c:a2:79:85:0e:37:36:15:bb:2d:
|
||||
1e:0f:bb:35:f3:d7:c5:a4:03:45:55:32:02:88:e3:
|
||||
5a:f3:46:a6:aa:42:93:68:e7:76:c2:8f:71:12:eb:
|
||||
8a:89:81:11:d3:bf:05:b5:e6:7b:34:b4:4b:c4:be:
|
||||
bd:56:62:0b:80:15:d5:83:b2:6e:ca:54:ee:9e:9c:
|
||||
bd:d1:0f:61:a2:f3:97:11:34:b8:13:4a:13:c6:64:
|
||||
d1:a3:14:fe:3d:0f:14:b5:e1:ac:ec:d5:53:b1:f0:
|
||||
85:14:04:3c:a9:ef:82:ac:04:30:60:8d:97:ce:6f:
|
||||
ec:87:6d:e9:88:41:da:60:37:3f:90:38:2a:25:db:
|
||||
31:69:66:e5:d8:1d:90:8a:b9:56:33:f6:25:46:a4:
|
||||
93:4a:fb:f3:57:2a:98:50:4d:63:ce:fb:81:8f:a7:
|
||||
fb:e0:bf:f1:aa:98:7e:78:c4:90:6c:c1:02:50:59:
|
||||
73:6b:35:ae:d2:e8:fa:c6:3a:c2:f3:25:7f:e0:a4:
|
||||
de:a1:63:9a:fa:34:11:1f:00:7d:a5:5f:2b:a8:9d:
|
||||
73:42:b5:82:7c:45:bd:d8:5e:8c:bf:87:94:4e:f8:
|
||||
ac:22:af:11:74:75:df:e0:07:c8:7e:6c:72:b4:a8:
|
||||
e9:
|
||||
|
||||
|
||||
Public Key ID: EA:D5:94:E7:05:6F:CC:9B:3A:C4:D8:FA:BC:3F:BD:51:39:3F:7E:47
|
||||
Public key's random art:
|
||||
+--[ RSA 4096]----+
|
||||
| |
|
||||
| |
|
||||
| . |
|
||||
| . = .|
|
||||
| S o+. *o.|
|
||||
| . o.o+o oE|
|
||||
| . . .o. o=.|
|
||||
| . . ....o *|
|
||||
| . .=+.++|
|
||||
+-----------------+
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
PiYowq/WR28SzglSbdL1
|
||||
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
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,32 +1,247 @@
|
||||
Public Key Info:
|
||||
Public Key Algorithm: RSA
|
||||
Key Security Level: High (4096 bits)
|
||||
|
||||
modulus:
|
||||
00:f0:6e:0c:8d:82:c9:98:2d:73:18:4a:ed:8a:d1:
|
||||
1f:68:4c:d3:15:e0:aa:84:88:5c:ad:7b:7d:55:2d:
|
||||
91:75:d9:ed:38:f2:09:31:89:30:5d:42:f0:5d:b5:
|
||||
a4:b1:bf:c7:d0:8a:33:e9:ce:3b:28:5d:0d:43:b4:
|
||||
cc:7f:7a:eb:36:4f:17:01:39:13:b5:c1:9f:5c:be:
|
||||
a6:bc:64:4e:ea:64:1d:40:10:c2:db:62:53:cf:0a:
|
||||
61:a1:ea:b2:a7:b4:0e:18:d1:f0:0d:61:62:a5:0e:
|
||||
4e:64:a8:57:21:e0:ef:78:f3:65:43:ed:4f:47:5b:
|
||||
fd:47:fc:81:dc:81:d4:1a:75:13:0b:30:57:90:af:
|
||||
73:b0:47:1d:68:57:80:04:b9:95:5a:83:d5:df:a2:
|
||||
55:25:44:f1:e2:76:93:49:8b:a5:00:04:bc:b8:56:
|
||||
91:ee:bc:b8:67:29:cd:cf:d9:28:d6:25:7e:fd:93:
|
||||
eb:e6:e6:7c:af:56:f6:ae:25:64:fa:d6:d1:81:8c:
|
||||
cf:6e:47:96:9b:9c:b6:33:44:74:e1:80:65:02:39:
|
||||
1f:a5:2c:26:c4:9f:fc:32:c1:bc:b3:d2:c2:f9:ab:
|
||||
b2:4e:6a:1f:be:58:84:4b:70:7e:31:a0:e4:e3:27:
|
||||
4a:34:0f:62:ea:ee:0d:4f:5b:24:83:e1:f7:d1:9d:
|
||||
92:e3:6e:38:80:c4:5d:77:28:94:2f:f3:a9:f2:59:
|
||||
ba:39:6b:7d:d4:1a:c6:74:34:f6:42:a5:3b:a9:ae:
|
||||
d7:00:0d:c8:5e:a6:ad:c9:69:0c:86:96:d9:b9:8d:
|
||||
63:80:35:f5:35:05:51:05:a4:04:cd:d9:54:a1:cb:
|
||||
fd:0a:4d:6f:d9:a2:b7:2b:e3:f6:18:ac:5e:de:37:
|
||||
e7:3d:ff:87:89:23:d6:3a:ac:94:ae:09:6b:92:5f:
|
||||
c9:7d:68:38:1f:89:f8:fe:e3:bc:2b:5f:c6:30:6c:
|
||||
ae:89:98:88:3f:0f:49:83:d6:1f:18:c6:ba:95:e7:
|
||||
4c:34:ef:3f:e5:ef:61:8f:02:18:fd:6f:59:8b:5a:
|
||||
d3:e7:5f:1e:45:a4:e3:82:86:0f:c4:dc:dd:5e:4b:
|
||||
67:62:70:c3:bb:61:64:78:19:e3:1d:7e:a7:7e:d2:
|
||||
7f:b3:d2:06:57:05:1c:ee:f6:d5:a6:f8:71:71:71:
|
||||
ae:43:72:65:63:55:1f:df:97:53:ea:78:6a:45:e3:
|
||||
df:08:74:8a:f9:a2:4a:7f:60:30:bc:6b:d0:97:77:
|
||||
d5:4a:b9:28:89:b9:09:36:bc:e5:4f:3f:21:b9:5e:
|
||||
a3:c1:4d:95:02:19:3b:f8:64:41:8e:8c:3c:d5:80:
|
||||
09:f0:2b:87:e5:fb:5d:b2:e6:52:48:11:36:e4:12:
|
||||
c8:41:db:
|
||||
|
||||
public exponent:
|
||||
01:00:01:
|
||||
|
||||
private exponent:
|
||||
20:05:07:f6:f0:ac:18:70:35:1b:cf:1e:c3:96:06:
|
||||
30:c5:ca:76:e7:6c:ce:29:ba:ed:ff:bc:39:53:d0:
|
||||
43:79:ba:76:13:05:d6:6b:06:dd:e4:c4:4e:36:9a:
|
||||
b0:71:72:12:fb:d4:de:16:71:1a:77:0a:05:32:56:
|
||||
e9:c3:5c:ff:e6:98:91:b9:20:3e:dc:82:74:bf:8f:
|
||||
45:17:b6:ca:d0:7a:74:c5:c6:ad:a0:f2:b8:68:11:
|
||||
88:96:d1:24:34:7e:8c:1f:a9:70:9e:bf:9c:6b:c3:
|
||||
54:f4:76:66:34:a6:af:dc:fa:67:89:7b:3d:6d:aa:
|
||||
d5:a3:73:48:02:a2:54:c3:b2:bd:92:ba:96:b2:47:
|
||||
1d:fa:da:97:c2:cf:71:d1:a5:6a:60:94:63:2c:23:
|
||||
5a:cb:4b:cb:75:2f:38:64:38:9d:40:04:42:28:85:
|
||||
56:de:1b:50:e1:e8:5e:fd:f4:ca:50:44:11:51:59:
|
||||
e1:6e:60:bc:99:40:51:00:f9:e9:ce:22:28:b6:b0:
|
||||
09:67:cf:4e:fa:17:e9:cb:fc:24:ec:0c:87:b7:43:
|
||||
d7:a3:81:a6:3e:08:40:5a:3c:df:55:fa:51:75:e4:
|
||||
51:3d:20:ed:20:ac:bd:bf:45:8f:26:76:55:2a:2e:
|
||||
5f:b0:8c:e3:ec:c0:29:09:62:5b:8e:04:8b:0e:09:
|
||||
39:ae:a6:e8:6f:2f:25:34:01:e7:53:f2:fb:50:08:
|
||||
23:3f:5f:45:e6:71:68:27:55:00:59:3e:37:53:df:
|
||||
3b:bd:a3:1a:3b:a1:06:f0:ff:90:b5:30:cf:14:a8:
|
||||
59:86:c4:25:df:38:b1:29:ff:47:53:94:6b:b1:62:
|
||||
03:c8:23:8e:97:da:b2:6b:c9:15:15:f0:5d:50:c2:
|
||||
d9:01:ef:52:65:2f:c4:c2:bc:3a:e6:32:a0:54:54:
|
||||
f9:0c:96:da:15:5a:b3:4d:77:04:7d:73:11:48:06:
|
||||
e9:8f:9f:6c:61:0e:64:21:6e:14:2d:23:70:ad:c1:
|
||||
86:2b:23:12:08:7f:09:1d:07:24:9b:84:9c:ef:e6:
|
||||
bd:ae:77:6b:01:2c:60:bf:0a:56:2e:29:07:4e:c5:
|
||||
24:72:71:ba:eb:82:9e:7f:6c:0e:dd:a8:2d:f9:78:
|
||||
f6:d6:5c:05:39:4b:e2:ba:3f:c8:32:3b:4d:3b:16:
|
||||
dc:b2:30:f2:12:99:87:6c:e7:c5:66:2c:74:34:d0:
|
||||
30:81:8e:e9:6f:df:9f:9c:d6:2f:fe:82:e5:d9:d9:
|
||||
3d:0b:2f:9b:85:d6:2b:0c:2f:98:6a:e1:b3:34:d0:
|
||||
3b:84:ce:5a:f9:04:81:29:f4:02:97:5b:9a:12:de:
|
||||
4b:64:48:94:f6:ee:3f:be:55:77:73:18:c4:f3:0e:
|
||||
8b:c1:
|
||||
|
||||
prime1:
|
||||
00:f9:d7:c4:3c:dc:91:90:0c:08:e2:67:e1:9b:4e:
|
||||
6d:8a:3f:6a:dc:84:67:b7:30:97:e6:40:30:42:56:
|
||||
06:23:80:a3:60:a0:34:11:d7:e0:5c:80:1e:5c:7c:
|
||||
80:9d:32:bd:3f:0e:df:dc:4f:a1:0b:a9:be:48:40:
|
||||
2b:09:35:d2:37:58:89:90:7c:7c:31:03:71:9e:84:
|
||||
f9:be:b0:a2:0e:f7:d8:4f:4b:6c:37:67:c0:a7:80:
|
||||
9b:7b:c1:bf:be:89:55:46:ff:d7:88:7a:3b:d1:63:
|
||||
80:c3:04:1c:05:8c:dc:68:19:32:e7:db:4d:dd:0f:
|
||||
59:41:5b:2d:8d:a8:f5:dc:90:c8:31:45:05:b3:d7:
|
||||
63:ea:ba:fe:9b:9e:02:2a:d3:3e:c0:40:35:99:f9:
|
||||
cb:c4:f9:42:c2:bc:73:f7:2c:f7:78:65:92:9a:ab:
|
||||
e4:be:85:59:f9:e7:84:5e:c3:a6:36:98:70:d7:6a:
|
||||
97:21:17:4e:ee:cd:29:23:02:68:fa:4c:8c:7f:22:
|
||||
f8:0e:8b:18:09:3b:17:6f:6f:36:f7:2a:50:dd:15:
|
||||
b6:13:e7:e2:7d:2e:13:b8:87:74:af:c3:12:2d:aa:
|
||||
92:d7:64:7a:5d:40:d0:08:f5:a7:c8:91:c3:b4:59:
|
||||
e7:5b:63:dc:fd:11:9f:24:d2:4c:93:37:d8:88:f6:
|
||||
14:b7:
|
||||
|
||||
prime2:
|
||||
00:f6:5a:e5:a6:05:1b:f1:05:1f:27:03:33:9e:2c:
|
||||
58:72:a6:ac:a7:66:75:d3:80:74:98:12:b0:09:0e:
|
||||
3e:c2:30:81:5a:5f:2a:48:3b:67:70:0a:2b:92:c4:
|
||||
52:ec:20:a8:f3:96:5f:e4:ca:7d:34:19:31:b7:6d:
|
||||
68:f0:f2:43:9f:a8:7b:2f:3c:93:d4:20:e6:d1:39:
|
||||
9e:eb:e3:36:42:8f:b8:68:0d:05:ad:f3:ab:f8:e4:
|
||||
4b:b4:26:66:01:bb:e7:51:d0:af:38:ec:41:b6:f9:
|
||||
cc:ce:ae:b9:aa:db:b5:bf:9d:8c:d8:50:35:ef:e4:
|
||||
84:04:e9:42:f4:1c:0a:98:bc:7c:7f:46:b9:24:6a:
|
||||
2a:22:d0:d0:85:a7:0e:eb:ec:5b:28:22:83:45:d4:
|
||||
45:06:a7:1d:e4:6b:2f:04:21:e6:da:a4:22:23:71:
|
||||
b7:a1:9d:be:b4:d3:73:54:a7:2a:b3:32:6b:2d:f8:
|
||||
d3:b5:19:64:c7:98:94:01:d5:8b:68:79:66:c2:b2:
|
||||
fd:cf:5f:87:87:6e:37:f1:0e:1b:f6:17:03:5b:2f:
|
||||
8a:30:f7:3f:20:1e:38:4d:07:9a:6d:c0:ca:aa:a7:
|
||||
83:b9:b6:85:2b:ec:4f:96:82:ac:f1:3e:26:b9:5f:
|
||||
d6:0d:bc:84:e6:bc:fb:37:d8:0a:42:27:a3:3e:29:
|
||||
7f:fd:
|
||||
|
||||
coefficient:
|
||||
00:88:e9:77:eb:66:73:61:1e:dd:97:27:e8:ef:9b:
|
||||
16:75:8c:a6:74:6a:fd:af:92:0b:cb:80:f3:08:c9:
|
||||
48:0a:eb:38:42:64:42:f7:e3:49:d6:a4:67:3e:67:
|
||||
8f:84:5f:7d:3a:7b:fa:57:22:83:57:f4:b9:fc:88:
|
||||
03:01:d1:df:52:33:b0:e8:08:cb:02:ed:c1:5e:04:
|
||||
b4:9c:12:0d:c3:37:0a:db:b8:5f:93:32:58:4f:0a:
|
||||
d4:32:dd:89:7e:f3:41:3b:42:31:da:31:1e:41:eb:
|
||||
df:7a:10:af:e9:be:47:cd:59:02:73:b4:ea:be:44:
|
||||
6a:b6:27:08:25:be:d0:52:48:09:01:16:10:01:d2:
|
||||
7c:d6:88:50:3c:94:31:4c:a7:dd:31:a8:b9:4d:b4:
|
||||
de:08:72:8a:42:b2:93:c3:a1:b7:e7:63:0c:b4:7a:
|
||||
8e:9d:dd:dd:cb:e7:01:3b:1f:fc:d3:10:38:9c:ca:
|
||||
db:42:f2:87:6b:e6:71:6e:c1:41:bc:0f:ef:87:a9:
|
||||
78:98:19:ea:71:8d:c8:2a:54:64:86:d5:34:6a:c7:
|
||||
41:66:4d:18:1e:b1:ec:3e:b0:31:79:6c:20:24:d8:
|
||||
e1:7b:3d:a4:3e:b1:81:50:18:4a:ae:7f:6d:a7:c2:
|
||||
98:0e:be:ca:99:27:b8:79:44:46:89:07:94:b5:e0:
|
||||
92:f5:
|
||||
|
||||
exp1:
|
||||
5a:58:a7:12:e7:24:10:35:f9:e4:7d:72:3c:ea:20:
|
||||
7c:74:b0:5c:eb:d8:61:8b:45:f2:b2:55:81:37:80:
|
||||
62:c8:3a:cc:4f:42:65:0d:6e:89:a4:9e:d6:0d:03:
|
||||
a9:54:d6:d0:7d:bd:7f:fa:9f:9f:0b:13:cf:26:bd:
|
||||
29:48:78:2b:21:6e:25:7c:8e:a0:5e:c1:70:74:5f:
|
||||
a7:90:52:1a:1d:8f:f0:24:b3:0e:5a:0b:75:c6:f0:
|
||||
f2:d0:be:58:d5:6a:ac:11:0a:4c:c4:fe:ea:9a:13:
|
||||
ce:f1:a6:7c:6f:52:a8:a6:2c:1d:61:d5:87:51:ec:
|
||||
91:d0:b9:e9:57:27:09:4a:a5:ca:03:4e:ab:99:00:
|
||||
fd:b9:ff:26:20:fe:61:a4:20:35:ff:42:22:db:0c:
|
||||
cf:be:df:60:72:2b:71:3f:a6:81:b8:21:4a:a3:4c:
|
||||
45:85:0d:63:6c:50:16:c0:a3:53:6c:ce:a9:67:57:
|
||||
1d:55:43:6a:e1:6f:b5:c4:42:57:f8:e4:79:79:18:
|
||||
c0:91:95:f0:88:98:d1:e8:22:b5:40:6d:1b:75:a5:
|
||||
71:0f:52:7c:b7:f3:d3:af:d0:07:5b:00:30:d9:54:
|
||||
de:64:ec:46:da:90:20:1d:4d:3e:1f:4f:e8:e0:f5:
|
||||
e3:bb:7a:07:5d:9e:f1:fe:c6:48:1a:52:c8:3c:4c:
|
||||
83:
|
||||
|
||||
exp2:
|
||||
00:a2:ae:d7:e4:50:8f:69:14:26:c4:4e:7a:f1:c2:
|
||||
fb:0d:8b:3f:8c:b4:3e:ae:d2:af:2c:15:7b:26:1f:
|
||||
c0:15:e0:8e:2b:2d:98:f0:66:3a:22:64:b4:ed:90:
|
||||
b3:e9:b6:8f:9b:7b:fc:0b:4c:24:6e:19:0d:19:c2:
|
||||
28:80:a4:9b:3f:7d:b5:0b:36:87:b0:97:a1:95:1c:
|
||||
e5:f3:83:f1:ba:f6:c9:a1:fc:a7:79:7d:e6:5c:cf:
|
||||
f5:a6:1b:8d:55:2b:ce:cf:da:6d:3b:bb:d8:91:8a:
|
||||
58:53:4c:52:d3:9f:8f:5f:e0:1c:b8:64:0f:9a:41:
|
||||
5f:65:16:dc:dd:f2:fe:94:6a:34:14:a0:91:76:98:
|
||||
9d:06:ac:ba:66:e8:31:14:5e:da:bb:a0:3e:ec:08:
|
||||
07:25:23:8a:bb:e2:84:03:c8:97:78:5e:d7:24:6c:
|
||||
de:04:dd:f4:a7:d8:d2:da:5e:21:f6:80:1f:03:16:
|
||||
c4:47:5d:63:8d:e3:16:2a:37:e8:7d:af:5d:ca:c9:
|
||||
04:8e:c2:d8:ee:f8:3b:fc:f5:82:45:7a:60:ff:00:
|
||||
5f:d3:82:12:af:95:05:3c:e8:fe:73:e7:d2:6d:eb:
|
||||
7d:33:50:72:94:d4:d2:a1:e3:dd:6c:d9:cc:1c:b2:
|
||||
4a:da:7b:59:90:3d:cf:ef:ca:bc:cb:7e:fd:6f:f9:
|
||||
5b:c9:
|
||||
|
||||
|
||||
Public Key ID: 74:D8:EC:2A:C5:84:BC:65:11:5B:BF:61:1A:6C:B7:BD:68:5A:4C:6F
|
||||
Public key's random art:
|
||||
+--[ RSA 4096]----+
|
||||
| o.. |
|
||||
| . . O . |
|
||||
| o B B = |
|
||||
| B + = = |
|
||||
| . S o + . |
|
||||
| . . o o . |
|
||||
| . . = E |
|
||||
| . + . |
|
||||
| . |
|
||||
+-----------------+
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIFfQIBAAKCATEAvoi36do6MWZbBiRAxcuKtg+sa+8ammOXVFLIGleecwR1a14n
|
||||
xCyLZyMXnd7VbhZIkweXlo/Ts+wqle8IejsXVspffyBGaRLCkHP0KyKvvTx4wvuX
|
||||
4cGMjd05ZwpApPlWIJ73/QZokgAShVtwkSF3zOUsqB/Aa82KqmBv9iSGM+8lj5N2
|
||||
ZqO+pnG2tAJOB6m2N0u0+NzZD7B47wfreQ2UAiJS4SLKlW5jG79YaeMQ/jDfgNn3
|
||||
kMOVraPbVAZhRd9MVafT+mV70W0lVCvwcGNORWOi+J33Tz0Kkh2X/0SfmSb3uOjo
|
||||
WQsdXqCfLQXjjb3UbfOpbKBQhtrL0eJ/ZDl/wHjRC3S6dyEY0tnvqoR/HsCwVkbM
|
||||
vQUvxU0NISPjdvH0CHj7NNhiMimuyNdP8y7tvwIDAQABAoIBMQC3Nqp68YChvgXr
|
||||
KvMp/6Z7mSi4hSw0p21+BTgrtHNFsFTkkJ52kkreOy1bfkoHWOAimdtXSShOS9tL
|
||||
X5XsS2QO7fzUNoneQc7brtRsoicRNdP90oZi7IWmaMLo5T/yI1yBc7uNEBt/wRgO
|
||||
KjZdKCyV1w2RAS87umMLoD4pF0gBKoYYwLjKy8vpK1F/WPQFhFkWZPM5lswWu3VF
|
||||
tvIwBk91HoL6eueIZ3vO8z7+T1pQvComeELG5sZ3HALte39YfTEwQaTRBSGyPolf
|
||||
sB2098b1bhzsXLJAjkdmD2SKP0g9eVBFDn/t+2XXsEtFiqq5JB2INdu8pseOHuBR
|
||||
V1w7FL7jPT2z/lx3BflhVWLijKVfU5F5/DnDMmiCFY0/aIZxZJU+PO/zyIWHYpPb
|
||||
mxBTdB7xAoGZAPPzAiWMVFVs10p8oMwXnHwdMVLZsAd49qXSTKgTCdyF30BxVVCV
|
||||
drg4aGyoUT7T676IgG1aqF7YmpFkMjTaDIiYIRTLhsQrRHmsZpKKsrYclU77m80Q
|
||||
5V6S4IbW0rdM0pZ2PjtmZMwk2NkpH1Yl/ANNd2tkM9f9e9ZMRAiKxkyC8cj0pLRm
|
||||
Rnuu5e9RiUsVq/g92/2OyE83AoGZAMfyOCuGs6o+YpTTQPgnMShViz9Xu4GqaVcH
|
||||
dg6dtaOiSLW053ShCOKTOpCtBW++IQzZE9iAd+dyIIQCAZXwOKDdVxH3x3uUvwaY
|
||||
rbdX2gsObbB4K9UgZ774n0FNTT8OlI7XOKAY+qW5H+GV22iDANrp2HvqL0s4pcUj
|
||||
+2oqpgWSOG5XHnlcOUsgGtKn4U9wZpwmTHtuYUm5AoGZAOgTN+iWrqgyCkKPe72N
|
||||
fM5KS2EhPShuuF6aSVjf+9Kx/OhmqR4ngrDQ4O711YzquOwjGeJui5znfWxxoJ3N
|
||||
Dn1oFJie4s9+xf7mtxIUJt2/JX/lN5wHxd2J51X/yqicyf5f8OY7jAr1xuIZD/m5
|
||||
2x0dNk2RHw0M1iHRnituMiYZsIFX09TXM5h4k8Bvlig7LsXTu5RloERTAoGYMmQ8
|
||||
fdPMEhr483Mui5wtCnJMzuEIk8xkEhgCS/q5XY037/uw3bb8K0ZZ2z6QATKU180Z
|
||||
8FWoYn9j7IEo7yYEz54ZJKEi+GVro3j1RyDwBhtTz8bpnSQ2oW29jVKzJjJBhKJ/
|
||||
VfIVsZCvlUYUbwmdPI71DX3e/4E+XioMYhxvjTXl3QE93+47TlDAEdlXspKseaw5
|
||||
WF5gTJkCgZkA8Hi24HicbqzxpQ8WeiG8Vl/Qkm7kANqDTwO6ZhcuWrO5rTqFlmMl
|
||||
Q5IpyYVVmSRo+Sd+2MRXskie6/tmaAgXlNUIBL0cDupIwk66z3loiKUSaocTpeia
|
||||
Pt8HJcpTk/JWlqJ78mfVS9KKaBdC/TSVs9N9EO/KHAJDl8UsbLh2q3T8Wjc2+ROZ
|
||||
XnwlBhqrbULWIEcvGWW4FzQ=
|
||||
MIIJKQIBAAKCAgEA8G4MjYLJmC1zGErtitEfaEzTFeCqhIhcrXt9VS2RddntOPIJ
|
||||
MYkwXULwXbWksb/H0Ioz6c47KF0NQ7TMf3rrNk8XATkTtcGfXL6mvGRO6mQdQBDC
|
||||
22JTzwphoeqyp7QOGNHwDWFipQ5OZKhXIeDvePNlQ+1PR1v9R/yB3IHUGnUTCzBX
|
||||
kK9zsEcdaFeABLmVWoPV36JVJUTx4naTSYulAAS8uFaR7ry4ZynNz9ko1iV+/ZPr
|
||||
5uZ8r1b2riVk+tbRgYzPbkeWm5y2M0R04YBlAjkfpSwmxJ/8MsG8s9LC+auyTmof
|
||||
vliES3B+MaDk4ydKNA9i6u4NT1skg+H30Z2S4244gMRddyiUL/Op8lm6OWt91BrG
|
||||
dDT2QqU7qa7XAA3IXqatyWkMhpbZuY1jgDX1NQVRBaQEzdlUocv9Ck1v2aK3K+P2
|
||||
GKxe3jfnPf+HiSPWOqyUrglrkl/JfWg4H4n4/uO8K1/GMGyuiZiIPw9Jg9YfGMa6
|
||||
ledMNO8/5e9hjwIY/W9Zi1rT518eRaTjgoYPxNzdXktnYnDDu2FkeBnjHX6nftJ/
|
||||
s9IGVwUc7vbVpvhxcXGuQ3JlY1Uf35dT6nhqRePfCHSK+aJKf2AwvGvQl3fVSrko
|
||||
ibkJNrzlTz8huV6jwU2VAhk7+GRBjow81YAJ8CuH5ftdsuZSSBE25BLIQdsCAwEA
|
||||
AQKCAgAgBQf28KwYcDUbzx7DlgYwxcp252zOKbrt/7w5U9BDebp2EwXWawbd5MRO
|
||||
NpqwcXIS+9TeFnEadwoFMlbpw1z/5piRuSA+3IJ0v49FF7bK0Hp0xcatoPK4aBGI
|
||||
ltEkNH6MH6lwnr+ca8NU9HZmNKav3PpniXs9barVo3NIAqJUw7K9krqWskcd+tqX
|
||||
ws9x0aVqYJRjLCNay0vLdS84ZDidQARCKIVW3htQ4ehe/fTKUEQRUVnhbmC8mUBR
|
||||
APnpziIotrAJZ89O+hfpy/wk7AyHt0PXo4GmPghAWjzfVfpRdeRRPSDtIKy9v0WP
|
||||
JnZVKi5fsIzj7MApCWJbjgSLDgk5rqboby8lNAHnU/L7UAgjP19F5nFoJ1UAWT43
|
||||
U987vaMaO6EG8P+QtTDPFKhZhsQl3zixKf9HU5RrsWIDyCOOl9qya8kVFfBdUMLZ
|
||||
Ae9SZS/Ewrw65jKgVFT5DJbaFVqzTXcEfXMRSAbpj59sYQ5kIW4ULSNwrcGGKyMS
|
||||
CH8JHQckm4Sc7+a9rndrASxgvwpWLikHTsUkcnG664Kef2wO3agt+Xj21lwFOUvi
|
||||
uj/IMjtNOxbcsjDyEpmHbOfFZix0NNAwgY7pb9+fnNYv/oLl2dk9Cy+bhdYrDC+Y
|
||||
auGzNNA7hM5a+QSBKfQCl1uaEt5LZEiU9u4/vlV3cxjE8w6LwQKCAQEA+dfEPNyR
|
||||
kAwI4mfhm05tij9q3IRntzCX5kAwQlYGI4CjYKA0EdfgXIAeXHyAnTK9Pw7f3E+h
|
||||
C6m+SEArCTXSN1iJkHx8MQNxnoT5vrCiDvfYT0tsN2fAp4Cbe8G/volVRv/XiHo7
|
||||
0WOAwwQcBYzcaBky59tN3Q9ZQVstjaj13JDIMUUFs9dj6rr+m54CKtM+wEA1mfnL
|
||||
xPlCwrxz9yz3eGWSmqvkvoVZ+eeEXsOmNphw12qXIRdO7s0pIwJo+kyMfyL4DosY
|
||||
CTsXb2829ypQ3RW2E+fifS4TuId0r8MSLaqS12R6XUDQCPWnyJHDtFnnW2Pc/RGf
|
||||
JNJMkzfYiPYUtwKCAQEA9lrlpgUb8QUfJwMznixYcqasp2Z104B0mBKwCQ4+wjCB
|
||||
Wl8qSDtncAorksRS7CCo85Zf5Mp9NBkxt21o8PJDn6h7LzyT1CDm0Tme6+M2Qo+4
|
||||
aA0FrfOr+ORLtCZmAbvnUdCvOOxBtvnMzq65qtu1v52M2FA17+SEBOlC9BwKmLx8
|
||||
f0a5JGoqItDQhacO6+xbKCKDRdRFBqcd5GsvBCHm2qQiI3G3oZ2+tNNzVKcqszJr
|
||||
LfjTtRlkx5iUAdWLaHlmwrL9z1+Hh2438Q4b9hcDWy+KMPc/IB44TQeabcDKqqeD
|
||||
ubaFK+xPloKs8T4muV/WDbyE5rz7N9gKQiejPil//QKCAQBaWKcS5yQQNfnkfXI8
|
||||
6iB8dLBc69hhi0XyslWBN4BiyDrMT0JlDW6JpJ7WDQOpVNbQfb1/+p+fCxPPJr0p
|
||||
SHgrIW4lfI6gXsFwdF+nkFIaHY/wJLMOWgt1xvDy0L5Y1WqsEQpMxP7qmhPO8aZ8
|
||||
b1KopiwdYdWHUeyR0LnpVycJSqXKA06rmQD9uf8mIP5hpCA1/0Ii2wzPvt9gcitx
|
||||
P6aBuCFKo0xFhQ1jbFAWwKNTbM6pZ1cdVUNq4W+1xEJX+OR5eRjAkZXwiJjR6CK1
|
||||
QG0bdaVxD1J8t/PTr9AHWwAw2VTeZOxG2pAgHU0+H0/o4PXju3oHXZ7x/sZIGlLI
|
||||
PEyDAoIBAQCirtfkUI9pFCbETnrxwvsNiz+MtD6u0q8sFXsmH8AV4I4rLZjwZjoi
|
||||
ZLTtkLPpto+be/wLTCRuGQ0ZwiiApJs/fbULNoewl6GVHOXzg/G69smh/Kd5feZc
|
||||
z/WmG41VK87P2m07u9iRilhTTFLTn49f4By4ZA+aQV9lFtzd8v6UajQUoJF2mJ0G
|
||||
rLpm6DEUXtq7oD7sCAclI4q74oQDyJd4XtckbN4E3fSn2NLaXiH2gB8DFsRHXWON
|
||||
4xYqN+h9r13KyQSOwtju+Dv89YJFemD/AF/TghKvlQU86P5z59Jt630zUHKU1NKh
|
||||
491s2cwcskrae1mQPc/vyrzLfv1v+VvJAoIBAQCI6XfrZnNhHt2XJ+jvmxZ1jKZ0
|
||||
av2vkgvLgPMIyUgK6zhCZEL340nWpGc+Z4+EX306e/pXIoNX9Ln8iAMB0d9SM7Do
|
||||
CMsC7cFeBLScEg3DNwrbuF+TMlhPCtQy3Yl+80E7QjHaMR5B6996EK/pvkfNWQJz
|
||||
tOq+RGq2JwglvtBSSAkBFhAB0nzWiFA8lDFMp90xqLlNtN4IcopCspPDobfnYwy0
|
||||
eo6d3d3L5wE7H/zTEDicyttC8odr5nFuwUG8D++HqXiYGepxjcgqVGSG1TRqx0Fm
|
||||
TRgesew+sDF5bCAk2OF7PaQ+sYFQGEquf22nwpgOvsqZJ7h5REaJB5S14JL1
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEMzCCAuugAwIBAgIEU7iVFjANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJT
|
||||
RTEeMBwGA1UECgwVR8O2dGVib3JnIEJpdCBGYWN0b3J5MRIwEAYDVQQHDAlHw7Z0
|
||||
ZWJvcmcxGjAYBgNVBAgMEVbDpHN0cmEgR8O2dGFsYW5kMR4wHAYDVQQDDBVHw7Z0
|
||||
ZWJvcmcgQml0IEZhY3RvcnkwHhcNMTQwNzA2MDAxNTE4WhcNMTUwNzA2MDAxNTE4
|
||||
WjBAMR4wHAYDVQQKDBVHw7Z0ZWJvcmcgQml0IEZhY3RvcnkxHjAcBgNVBAMMFUfD
|
||||
tnRlYm9yZyBCaXQgRmFjdG9yeTCCAVIwDQYJKoZIhvcNAQEBBQADggE/ADCCAToC
|
||||
ggExAKsv5Nau53tmC8n3UH+FmraZPNr7glF0sDe0ofGz7YL2omKgE4QXIumiJ6ab
|
||||
5jXWaFwubhiy6WEdSPtOkdB1VelNzfm0jPSXsDJhowfaUBP5F4iw7UUfapJ3feXf
|
||||
Y5ieJj+Dd1jsOIWwnOFvl+qvMC+KtjH4v+4nTRJ0QdI5/EheEJECmtxAS4XtmNJV
|
||||
qQ2lRquGOxHz4tAzH1dl2WDKZm6/Jn9gKxH66iGIKMrkbRuaVTbZI838SK2GJRLp
|
||||
3FAIEps87kOitfZkQeMh15nsTW1e+HCitsyDiCY+cW7D5uTSn07c4pMYo0VXU5BH
|
||||
Gwj+gaNYZPP0G088g9hRg4c1oufYGhkO0G4P583+/7Nc2eZWOve3o/tJwEfGT8pk
|
||||
FTgAOc+ZBSQUgqyoswiWyTsZhqcCAwEAAaOBlzCBlDAMBgNVHRMBAf8EAjAAMB4G
|
||||
A1UdEQQXMBWCDXRhc2t0b29scy5vcmeHBGFrjWswEwYDVR0lBAwwCgYIKwYBBQUH
|
||||
AwEwDwYDVR0PAQH/BAUDAwegADAdBgNVHQ4EFgQURXMgYOwqEdOjh4T6gXCNph1i
|
||||
W+kwHwYDVR0jBBgwFoAUV6hrNd+llELYw9FhchM/2QvO37UwDQYJKoZIhvcNAQEL
|
||||
BQADggExAG/0Fr2FYjtxnQNqQukODgLhE0nuR78G4aLbO3UYEP7vAaclUKlF2IsE
|
||||
aTSnvOqIF4pwrrA08D0fu5ZlHwJ//JQhxyrJAHmmYol3zX48iVAau8KD4FvEsLV7
|
||||
d2SERbtl02yZ/e2J50pyEikwgke4I+V/Wjphg28tOZVRPFZy+N8J+j7Dn/faTlJF
|
||||
mp121KuyR098YV6EDNSnUMDsaVCO8y/OfQXewDMJdVTeYapH91S6RU5b1q16mIHQ
|
||||
bFBJhWcOXTJdCpxq8nSAXYOIk5EKFIJqrlzA6ZcoiOtva5m1isSjyhQ/fotLAduX
|
||||
YJ1qbTghXCTWuUxX+GjUDqnNK3pHfTCUYJALaT95IunyB/YJGGgFmUoc3hqP+rcQ
|
||||
2EyLepPryOLhqXsETgYnMKyBhXRhzAM=
|
||||
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
|
||||
Kt6t5W0w1V6RBnCUtQEf
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIICKTCB4gIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJTRTEeMBwGA1UE
|
||||
CgwVR8O2dGVib3JnIEJpdCBGYWN0b3J5MRIwEAYDVQQHDAlHw7Z0ZWJvcmcxGjAY
|
||||
BgNVBAgMEVbDpHN0cmEgR8O2dGFsYW5kMR4wHAYDVQQDDBVHw7Z0ZWJvcmcgQml0
|
||||
IEZhY3RvcnkXDTE0MDcwNjAwMTUxOFoXDTE1MDcwNjAwMTUxOFowAKAvMC0wHwYD
|
||||
VR0jBBgwFoAUV6hrNd+llELYw9FhchM/2QvO37UwCgYDVR0UBAMCAQAwDQYJKoZI
|
||||
hvcNAQEFBQADggExAFoR5SJ/D0SWE9kGgvgotRFFeXfkgel9im/sQdHdUrKn/MGG
|
||||
imT4upSBU1hTgDqy252DRUPrs3DXON/T4L8sWq7t7PfzlDbO6fV2Wkmsd43/yCPt
|
||||
tK6dsrcnAhWFCamkBNVGi/RZt6da3y72Y7fo7cfzkK8UeF6UWgGBt4+raR3pmRIw
|
||||
+FpDEYuUOXajvtIxMD0CMdeFo+w8/5RGxXyqR4sftnRrD2hX6aFljrejxP/Pa7M9
|
||||
TvgKtUMxsOSauSWN7vg59+FE92PNqNa3KEquO7h5CI5yjr/+85K7o/6FGHOV4iD2
|
||||
h/RQHI2l8AEpqDqJLZu5GvjN6mblhIYlo+uMTZOXHWxoIDDQLsOXJyCpHSNWjGRs
|
||||
dP4OMD0/0ykppjogdOdUMEN/8smqtPumPzP/ykg=
|
||||
MIIDCDCB8QIBATANBgkqhkiG9w0BAQsFADB9MR4wHAYDVQQDDBVHw7Z0ZWJvcmcg
|
||||
Qml0IEZhY3RvcnkxHjAcBgNVBAoMFUfDtnRlYm9yZyBCaXQgRmFjdG9yeTESMBAG
|
||||
A1UEBwwJR8O2dGVib3JnMRowGAYDVQQIDBFWw6RzdHJhIEfDtnRhbGFuZDELMAkG
|
||||
A1UEBhMCU0UYDzIwMTUwMTE5MjMxODA5WhgPMjAxNjAxMTkyMzE4MDlaMACgOjA4
|
||||
MB8GA1UdIwQYMBaAFOrVlOcFb8ybOsTY+rw/vVE5P35HMBUGA1UdFAQOAgxUvZCx
|
||||
D9YrMF6sqNkwDQYJKoZIhvcNAQELBQADggIBALBQaaSdZDHi5MsnIRHsbz3J0FGb
|
||||
NU7oI8wLXMWTNNF4rv9h5kVQCOwCYBOhIGTXkunM9HCZ22gTYVXus1uOBVoJR+1g
|
||||
qvraZU1bhtziE3DRHCZDRhq3l8SV9/VZDWP/DryPuBgJgxE8Gaq8UGJ1u2QhWmaj
|
||||
ZFET3bNiQwV8omI8Bi+D+aKpICt0+WixPAYhdf5pAb6dtGwh9Qy9J7hlH9FYyXMm
|
||||
E5bNWjPjfJeluant0V2yXqaDFL2UnryeD03+YagkZ9ixkCxWgBXOjMCfZ0Bmpej9
|
||||
jrJ4W/ki6W28eWrNbgIMJl4EDJyof2pOIGXkvSW+QjO7laxNevIZ9ofOHz8eMeXA
|
||||
FOwJvLBjl4Jp03HyTh1jhCnr1y0PVYtvwv88ThBGbYGCKcVQlKCOa+C3dBQ9thIY
|
||||
SU8yWhBWt6Bdrxf92GMJxpTqUbzyL8HoqwK4SI+gfua3J5YeBTErYKhD2an3Ra7T
|
||||
UeisZJM7nGi1astGLE8V5rYtb74hNJbrR8I3CyE/Odsnk1Jq2kKMc5wQQeJLEsoX
|
||||
lRtSdmYSXZ13IoKj0sJvm3jydSX42u1mtwZwHrKmcVVG5XqLKn/2x6Z8+5vjM9JK
|
||||
AsuGlpGIiZDMg2wnY8q0yo0q+yPE5xi9NlOeCSRtY0DfpNLqWi8exrIwwplT26V8
|
||||
cbzBujcnnznK9J6F
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -1,32 +1,247 @@
|
||||
Public Key Info:
|
||||
Public Key Algorithm: RSA
|
||||
Key Security Level: High (4096 bits)
|
||||
|
||||
modulus:
|
||||
00:c8:b5:8c:80:84:05:5d:4e:e7:6b:34:4a:e9:4a:
|
||||
4f:d5:2f:39:3e:ef:50:6a:d0:a9:21:4f:56:4c:0c:
|
||||
1d:c5:b0:33:19:ad:fe:84:40:c0:f8:a3:c2:97:4b:
|
||||
9e:b0:6d:dc:f6:14:da:c6:43:f2:07:e6:6c:19:6e:
|
||||
aa:be:f6:18:e5:15:88:20:50:7a:6c:23:d1:15:7a:
|
||||
ef:b6:78:ce:3c:af:0e:88:f9:e3:09:b3:00:be:0f:
|
||||
91:68:02:3d:9d:93:ea:1d:e9:19:91:1d:ab:da:92:
|
||||
b5:7b:cc:26:a9:34:8a:b2:2c:43:8e:24:68:bd:f2:
|
||||
d5:09:b8:6b:28:73:b7:44:13:f8:14:df:40:89:14:
|
||||
21:5f:c0:41:53:39:5d:76:75:be:8d:44:94:bf:a6:
|
||||
ef:de:cb:3a:2c:8f:26:ed:60:0d:06:43:ce:2f:76:
|
||||
a0:72:54:c6:be:24:bc:fa:ed:22:87:7a:7f:0a:8f:
|
||||
29:28:c2:71:63:d3:ea:e4:a1:6b:eb:f0:dc:93:16:
|
||||
e2:88:98:1f:00:0d:26:70:a9:57:a7:43:15:eb:fa:
|
||||
9a:6f:9d:e5:4c:f6:e5:af:af:f9:ac:33:77:5a:8d:
|
||||
06:b5:f7:ca:0d:38:8d:8f:06:29:d6:2f:e3:7f:89:
|
||||
19:5c:ef:85:f9:24:a8:d0:08:a7:bd:4d:e2:30:28:
|
||||
4c:19:a9:9a:c1:43:ce:7e:0d:ee:70:62:fc:87:d4:
|
||||
9c:28:fb:c3:39:db:90:ae:de:26:b0:b1:fa:17:37:
|
||||
73:fc:f1:52:53:fb:38:1a:89:b1:4d:06:6e:a4:b4:
|
||||
e9:2d:06:bf:db:52:8a:f8:7a:d7:f1:fb:18:3a:4d:
|
||||
50:fa:1b:4c:63:ec:15:65:9a:2d:7b:d8:ab:22:0f:
|
||||
0f:d3:de:fd:f7:9e:b1:69:e9:68:f5:1c:d0:3b:55:
|
||||
a7:6d:4f:4d:3f:af:e4:4c:1e:07:f6:5b:01:e2:89:
|
||||
83:58:d0:86:be:66:2d:aa:e4:96:d1:58:d4:d7:97:
|
||||
af:97:58:87:6b:56:b9:85:62:1d:7e:c2:f9:c8:f1:
|
||||
38:f9:16:9a:ee:f4:a5:9e:47:1f:3c:81:42:4a:0f:
|
||||
fe:8b:d5:b9:0e:d4:a3:3e:5a:72:ae:4d:62:59:40:
|
||||
cb:9a:7e:fd:a4:11:6c:93:79:a5:10:9d:e1:42:3f:
|
||||
e2:b3:2a:d5:7a:cd:c2:2a:5a:3c:b7:f7:0d:6c:f3:
|
||||
d2:d3:86:0e:c4:00:48:37:05:3d:f3:1d:e1:52:a9:
|
||||
6f:85:93:c9:f6:b4:b6:77:25:44:51:83:bf:30:97:
|
||||
6e:5b:32:a9:52:da:ca:8e:86:73:00:31:44:79:1e:
|
||||
b7:7f:5a:da:d6:c4:ca:13:a3:46:a9:db:4b:4f:d6:
|
||||
ba:44:65:
|
||||
|
||||
public exponent:
|
||||
01:00:01:
|
||||
|
||||
private exponent:
|
||||
00:ab:b6:8f:07:20:6c:0a:81:48:01:f2:d2:28:36:
|
||||
f8:87:f6:07:ee:ed:05:8a:ed:0b:d5:c0:af:9f:0e:
|
||||
3a:a6:77:f1:b0:05:a9:1b:72:de:e5:9a:0d:10:2d:
|
||||
95:0d:72:60:b9:73:ec:1b:f5:e3:6a:98:db:61:02:
|
||||
ca:37:e8:0a:32:6b:b2:73:9b:06:b1:e0:0e:b0:66:
|
||||
e6:10:e1:d7:e8:19:08:c1:6d:b0:ad:0a:a5:16:f5:
|
||||
f0:bb:e0:36:e0:ca:bc:60:6c:9e:00:06:37:92:1f:
|
||||
33:ff:3f:10:d0:70:70:3c:b1:1b:f6:ce:f5:81:94:
|
||||
f0:68:89:8b:bc:27:0b:e2:c5:86:d8:2c:8c:64:fa:
|
||||
80:f7:0f:5f:94:19:1e:fa:0b:10:44:82:29:14:b2:
|
||||
78:c3:ce:70:ed:d0:67:48:6c:85:98:17:88:9e:18:
|
||||
ca:7a:26:47:86:43:9e:1e:bb:a4:6f:ee:00:24:83:
|
||||
88:7e:23:a4:a8:f8:94:1c:98:71:e1:80:c6:e5:5c:
|
||||
8d:e0:b8:ec:c4:b9:7b:6a:a5:a6:a5:26:02:ea:4a:
|
||||
13:b8:6c:88:d1:c8:e5:86:e2:72:23:be:40:5d:8b:
|
||||
0b:f3:c0:93:ef:ad:b3:86:6a:8a:7e:81:a8:0b:e3:
|
||||
ba:7c:45:3c:04:84:35:9d:0d:da:9c:5d:b6:a6:e6:
|
||||
c2:fb:28:d8:db:6d:8e:27:aa:42:d7:91:37:d9:6b:
|
||||
51:d2:54:c2:b3:9a:be:a7:5b:20:5c:59:b7:69:0c:
|
||||
17:27:34:26:4d:7e:68:95:28:8d:db:bb:88:07:12:
|
||||
68:94:7f:e1:a9:91:e3:fe:8f:21:fb:3a:43:40:ff:
|
||||
81:cf:ae:a6:7d:2d:67:4c:fc:82:d1:dc:84:e2:1b:
|
||||
dc:07:5a:2c:ab:6b:68:8c:b2:8d:1b:97:b0:22:6d:
|
||||
2a:5e:72:bc:b5:b8:93:a8:e5:8a:0e:a2:4b:b0:76:
|
||||
55:a1:14:ae:6e:68:25:89:9c:68:cf:cc:6c:f3:bc:
|
||||
4a:96:bc:b2:1a:01:db:3c:da:37:a2:81:ff:55:dd:
|
||||
b9:a4:90:79:55:94:bb:be:ca:d7:86:89:ae:68:a5:
|
||||
9f:f4:5a:2c:d9:33:ed:fa:22:f7:1d:b2:43:ce:e6:
|
||||
61:37:e6:eb:25:44:89:bd:43:4a:3c:10:a8:0a:2f:
|
||||
40:c3:a8:75:73:17:42:22:a9:73:73:95:e8:7e:26:
|
||||
9c:30:c9:13:04:0f:e3:78:7f:75:8d:30:9a:d9:1b:
|
||||
6d:48:2b:09:d8:80:53:27:82:a3:97:e1:d8:2d:35:
|
||||
59:7d:60:da:e8:27:5e:a7:ee:ff:6b:90:ca:74:9a:
|
||||
27:67:89:08:17:88:6c:b2:12:18:ba:ac:e2:72:ae:
|
||||
a5:ea:9d:
|
||||
|
||||
prime1:
|
||||
00:d3:b9:bb:17:8e:2c:2c:e9:f2:45:6b:41:e5:2e:
|
||||
63:9e:8c:cc:d3:06:c7:b5:49:60:2f:78:98:80:73:
|
||||
09:e3:17:5f:44:89:7c:74:8d:52:6f:de:b7:56:a3:
|
||||
f1:6c:fb:59:be:4c:df:79:22:df:4f:21:6f:f2:b2:
|
||||
54:3b:6d:83:26:e6:5b:8f:93:25:dc:c2:98:5d:3b:
|
||||
57:b3:b7:e1:d5:85:03:f9:b8:ca:26:cb:b4:35:41:
|
||||
50:df:96:05:75:c2:f1:98:06:26:52:bd:87:e4:ec:
|
||||
88:40:1d:c3:b4:de:b2:e8:21:1d:38:dd:7a:0a:b6:
|
||||
f9:fc:ce:7a:1d:33:0a:cb:ea:14:95:8b:9a:50:7e:
|
||||
b4:34:01:42:ee:5b:14:34:45:36:c3:b9:2e:16:e1:
|
||||
a0:f0:e2:11:7a:6c:1e:d5:b2:84:03:d8:07:49:27:
|
||||
e5:fc:fe:4f:01:66:fe:7d:40:fa:4c:f4:86:06:dc:
|
||||
31:33:bb:30:b1:52:f6:9a:ee:6f:22:a8:68:66:52:
|
||||
3a:58:35:15:27:6a:70:67:2b:2c:8b:7c:b0:e0:87:
|
||||
85:49:c7:51:6e:5d:4c:a1:6b:69:2b:b2:9f:a7:9a:
|
||||
2e:08:8a:ec:e4:36:ad:83:46:55:92:f9:ef:05:14:
|
||||
ac:24:28:7d:e5:72:b9:49:ce:1b:d3:40:4b:fe:16:
|
||||
7a:03:
|
||||
|
||||
prime2:
|
||||
00:f2:ae:15:0a:b2:f6:29:ee:5c:eb:fd:76:27:68:
|
||||
b4:5a:95:21:f8:32:4d:92:53:a3:c0:ce:ab:fc:b0:
|
||||
cd:f7:58:1c:35:88:90:42:e2:9f:65:ec:7f:01:98:
|
||||
69:bc:69:84:4c:3a:68:0d:c8:09:a2:88:8f:c7:c7:
|
||||
a1:35:f0:95:c1:2d:67:23:95:50:fc:cb:97:a6:1f:
|
||||
67:82:02:9e:3a:dc:b0:1b:77:49:50:bd:ce:be:8f:
|
||||
28:cf:29:c2:2e:82:32:5a:45:7e:cb:c1:44:33:af:
|
||||
7e:db:8e:68:c9:01:57:8e:cb:e0:ac:1d:5e:d5:21:
|
||||
d6:d4:d1:40:81:68:7f:1e:55:24:c2:bb:9d:3d:1b:
|
||||
cd:6c:ca:11:b9:13:cf:ad:37:26:3d:22:e5:d0:3a:
|
||||
5f:24:aa:0b:f6:c7:cb:7b:0c:12:bd:5b:d5:c2:25:
|
||||
5f:64:38:10:eb:5f:40:2d:0d:0f:b4:90:54:24:d9:
|
||||
70:65:1f:d5:9d:ae:9d:ef:a1:36:87:3d:c6:41:a7:
|
||||
56:5e:fe:33:1d:43:a0:c5:98:3e:ac:b1:23:4c:0e:
|
||||
a2:5d:50:82:22:b6:ba:b0:b9:5e:84:c4:2b:a9:0d:
|
||||
15:f9:26:32:57:49:6b:1f:fc:d6:4d:8e:fc:f9:13:
|
||||
c7:a5:80:53:82:83:49:92:34:dc:fe:82:52:49:4b:
|
||||
2f:77:
|
||||
|
||||
coefficient:
|
||||
00:99:7f:81:87:b0:27:9e:72:29:8d:76:a7:25:72:
|
||||
e5:60:9e:86:80:fe:2a:d3:c4:07:96:d4:de:e4:a0:
|
||||
c6:dc:89:11:4a:ba:0e:06:1e:7e:bb:bc:69:2e:40:
|
||||
fd:4a:cd:65:34:37:d0:0c:9e:f9:b3:01:05:b3:6d:
|
||||
8e:9f:7d:72:36:56:7f:b1:ca:e4:e8:76:fd:99:12:
|
||||
9d:ef:3c:f6:1b:4a:80:7b:92:c5:26:c1:50:f2:6d:
|
||||
a8:86:4e:3b:5c:10:14:cd:21:db:c8:38:d1:56:c9:
|
||||
72:a8:00:45:8c:71:d3:35:20:0c:a6:83:5e:33:9c:
|
||||
b2:f7:96:1c:35:30:8d:47:1b:e8:f8:84:df:9e:e4:
|
||||
32:d2:c0:da:1b:ed:27:db:a4:6b:0d:61:bb:67:6a:
|
||||
24:fc:93:9d:46:1f:91:34:21:61:cc:95:7c:0e:d6:
|
||||
64:96:4e:2e:06:40:57:df:b5:e2:57:30:c5:ff:d5:
|
||||
f5:89:08:ce:98:4e:01:81:30:dc:29:f6:05:98:7f:
|
||||
02:1c:ea:f5:a7:13:47:7c:98:81:13:a9:5d:9b:80:
|
||||
a8:2e:c9:5e:ae:b3:df:c6:02:81:19:84:1c:21:df:
|
||||
88:b0:96:7a:84:e8:ef:91:f2:69:50:f1:93:3c:31:
|
||||
94:38:10:01:6c:3d:fa:ca:94:5f:c5:9a:d6:43:77:
|
||||
fd:36:
|
||||
|
||||
exp1:
|
||||
5a:1a:26:66:a5:d8:62:dc:c4:7f:8a:5f:a6:9a:91:
|
||||
46:7e:01:04:a5:54:03:f0:50:00:a3:bf:b2:9a:42:
|
||||
50:e4:37:64:c1:65:b7:6c:14:f3:0a:c2:d7:1a:39:
|
||||
b9:f9:55:7d:c8:d5:29:86:0f:a6:6b:42:6a:f4:3d:
|
||||
28:75:38:65:2b:8f:37:90:95:82:57:45:e4:17:47:
|
||||
01:72:75:a7:1a:4e:50:cd:b5:29:c1:72:d5:5f:10:
|
||||
7d:b6:28:68:af:27:85:5c:c8:9e:59:8e:25:7c:0b:
|
||||
97:cd:92:e5:bc:08:43:05:24:9c:78:94:61:4e:f1:
|
||||
20:06:f6:ac:ca:76:03:c5:80:31:0c:12:05:c3:86:
|
||||
08:c3:a8:aa:2b:14:74:12:28:76:2e:ae:50:8a:80:
|
||||
a5:42:6f:d1:bb:85:7b:c7:d6:aa:94:1a:b5:a5:47:
|
||||
18:dd:58:dd:ed:e8:cb:81:05:84:0e:63:a3:33:bd:
|
||||
b4:98:2a:e6:ab:b9:ca:c1:41:86:6c:48:d1:92:98:
|
||||
c5:c5:01:55:9e:d4:6a:f3:52:a7:a1:ce:dc:1e:90:
|
||||
38:8f:9c:35:ed:7a:99:0f:4e:d8:8b:d1:a9:cf:d1:
|
||||
5b:4d:53:f6:e2:d6:00:91:c4:05:22:5b:f7:bb:8e:
|
||||
6e:6c:d4:f6:fa:55:a3:f5:14:9e:58:34:7e:d3:2d:
|
||||
e5:
|
||||
|
||||
exp2:
|
||||
00:d4:73:ee:5b:e5:7c:78:0d:03:30:5e:3e:b8:15:
|
||||
83:fe:e1:1c:52:0a:c7:ba:58:9a:bd:4a:b1:6a:90:
|
||||
e6:5f:a9:b5:58:70:6b:cb:02:57:05:85:db:52:6c:
|
||||
39:f5:06:73:19:c0:f0:23:50:82:8e:d5:fa:f9:ad:
|
||||
1c:c6:fa:0e:40:86:1d:0b:1b:c7:40:e8:83:a4:9d:
|
||||
4d:a2:95:e4:2c:27:d3:cc:d7:cb:49:72:41:b2:b5:
|
||||
e5:c6:27:0a:a6:68:b8:e8:2a:7a:ec:aa:0f:a9:27:
|
||||
f4:69:05:ed:5a:3b:60:89:d4:96:a6:57:38:14:62:
|
||||
81:8e:e2:7a:14:50:85:28:ea:e5:39:cd:c1:c4:23:
|
||||
b8:dd:8a:b1:a5:53:60:b6:85:d7:66:22:4d:0a:d4:
|
||||
6f:42:cb:d3:99:82:23:f3:5f:08:70:da:1a:f2:d2:
|
||||
81:06:5d:c7:02:27:eb:29:05:8c:40:49:32:40:e8:
|
||||
52:eb:54:c9:50:37:f4:70:3a:b4:60:05:86:b1:27:
|
||||
6c:07:d1:86:b2:11:e8:87:d3:d6:da:9c:61:08:4e:
|
||||
af:79:fd:e7:4f:b8:a5:0b:dd:dc:8f:62:a5:ce:63:
|
||||
74:5f:20:3f:66:07:12:4f:78:ab:ac:4e:87:cd:0e:
|
||||
b1:f3:83:ba:98:41:93:80:f9:e2:96:b5:44:90:81:
|
||||
cf:d5:
|
||||
|
||||
|
||||
Public Key ID: 83:6E:01:66:0D:60:8D:AA:36:49:B1:EF:72:61:30:8A:E8:3F:58:5A
|
||||
Public key's random art:
|
||||
+--[ RSA 4096]----+
|
||||
| o+. |
|
||||
| o. .o |
|
||||
| .o + . |
|
||||
|.= o . . |
|
||||
|* = o S |
|
||||
|=+ E . . . |
|
||||
|o O . o |
|
||||
| = + . |
|
||||
| +.. |
|
||||
+-----------------+
|
||||
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
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
|
||||
FGx/3NV/ZgtZ3UVTxXM=
|
||||
MIIJKgIBAAKCAgEAyLWMgIQFXU7nazRK6UpP1S85Pu9QatCpIU9WTAwdxbAzGa3+
|
||||
hEDA+KPCl0uesG3c9hTaxkPyB+ZsGW6qvvYY5RWIIFB6bCPRFXrvtnjOPK8OiPnj
|
||||
CbMAvg+RaAI9nZPqHekZkR2r2pK1e8wmqTSKsixDjiRovfLVCbhrKHO3RBP4FN9A
|
||||
iRQhX8BBUzlddnW+jUSUv6bv3ss6LI8m7WANBkPOL3agclTGviS8+u0ih3p/Co8p
|
||||
KMJxY9Pq5KFr6/DckxbiiJgfAA0mcKlXp0MV6/qab53lTPblr6/5rDN3Wo0GtffK
|
||||
DTiNjwYp1i/jf4kZXO+F+SSo0AinvU3iMChMGamawUPOfg3ucGL8h9ScKPvDOduQ
|
||||
rt4msLH6Fzdz/PFSU/s4GomxTQZupLTpLQa/21KK+HrX8fsYOk1Q+htMY+wVZZot
|
||||
e9irIg8P0979956xaelo9RzQO1WnbU9NP6/kTB4H9lsB4omDWNCGvmYtquSW0VjU
|
||||
15evl1iHa1a5hWIdfsL5yPE4+Raa7vSlnkcfPIFCSg/+i9W5DtSjPlpyrk1iWUDL
|
||||
mn79pBFsk3mlEJ3hQj/isyrVes3CKlo8t/cNbPPS04YOxABINwU98x3hUqlvhZPJ
|
||||
9rS2dyVEUYO/MJduWzKpUtrKjoZzADFEeR63f1ra1sTKE6NGqdtLT9a6RGUCAwEA
|
||||
AQKCAgEAq7aPByBsCoFIAfLSKDb4h/YH7u0Fiu0L1cCvnw46pnfxsAWpG3Le5ZoN
|
||||
EC2VDXJguXPsG/XjapjbYQLKN+gKMmuyc5sGseAOsGbmEOHX6BkIwW2wrQqlFvXw
|
||||
u+A24Mq8YGyeAAY3kh8z/z8Q0HBwPLEb9s71gZTwaImLvCcL4sWG2CyMZPqA9w9f
|
||||
lBke+gsQRIIpFLJ4w85w7dBnSGyFmBeInhjKeiZHhkOeHrukb+4AJIOIfiOkqPiU
|
||||
HJhx4YDG5VyN4LjsxLl7aqWmpSYC6koTuGyI0cjlhuJyI75AXYsL88CT762zhmqK
|
||||
foGoC+O6fEU8BIQ1nQ3anF22pubC+yjY222OJ6pC15E32WtR0lTCs5q+p1sgXFm3
|
||||
aQwXJzQmTX5olSiN27uIBxJolH/hqZHj/o8h+zpDQP+Bz66mfS1nTPyC0dyE4hvc
|
||||
B1osq2tojLKNG5ewIm0qXnK8tbiTqOWKDqJLsHZVoRSubmgliZxoz8xs87xKlryy
|
||||
GgHbPNo3ooH/Vd25pJB5VZS7vsrXhomuaKWf9Fos2TPt+iL3HbJDzuZhN+brJUSJ
|
||||
vUNKPBCoCi9Aw6h1cxdCIqlzc5XofiacMMkTBA/jeH91jTCa2RttSCsJ2IBTJ4Kj
|
||||
l+HYLTVZfWDa6Cdep+7/a5DKdJonZ4kIF4hsshIYuqzicq6l6p0CggEBANO5uxeO
|
||||
LCzp8kVrQeUuY56MzNMGx7VJYC94mIBzCeMXX0SJfHSNUm/et1aj8Wz7Wb5M33ki
|
||||
308hb/KyVDttgybmW4+TJdzCmF07V7O34dWFA/m4yibLtDVBUN+WBXXC8ZgGJlK9
|
||||
h+TsiEAdw7TesughHTjdegq2+fzOeh0zCsvqFJWLmlB+tDQBQu5bFDRFNsO5Lhbh
|
||||
oPDiEXpsHtWyhAPYB0kn5fz+TwFm/n1A+kz0hgbcMTO7MLFS9prubyKoaGZSOlg1
|
||||
FSdqcGcrLIt8sOCHhUnHUW5dTKFraSuyn6eaLgiK7OQ2rYNGVZL57wUUrCQofeVy
|
||||
uUnOG9NAS/4WegMCggEBAPKuFQqy9inuXOv9didotFqVIfgyTZJTo8DOq/ywzfdY
|
||||
HDWIkELin2XsfwGYabxphEw6aA3ICaKIj8fHoTXwlcEtZyOVUPzLl6YfZ4ICnjrc
|
||||
sBt3SVC9zr6PKM8pwi6CMlpFfsvBRDOvftuOaMkBV47L4KwdXtUh1tTRQIFofx5V
|
||||
JMK7nT0bzWzKEbkTz603Jj0i5dA6XySqC/bHy3sMEr1b1cIlX2Q4EOtfQC0ND7SQ
|
||||
VCTZcGUf1Z2une+hNoc9xkGnVl7+Mx1DoMWYPqyxI0wOol1QgiK2urC5XoTEK6kN
|
||||
FfkmMldJax/81k2O/PkTx6WAU4KDSZI03P6CUklLL3cCggEAWhomZqXYYtzEf4pf
|
||||
ppqRRn4BBKVUA/BQAKO/sppCUOQ3ZMFlt2wU8wrC1xo5uflVfcjVKYYPpmtCavQ9
|
||||
KHU4ZSuPN5CVgldF5BdHAXJ1pxpOUM21KcFy1V8QfbYoaK8nhVzInlmOJXwLl82S
|
||||
5bwIQwUknHiUYU7xIAb2rMp2A8WAMQwSBcOGCMOoqisUdBIodi6uUIqApUJv0buF
|
||||
e8fWqpQataVHGN1Y3e3oy4EFhA5jozO9tJgq5qu5ysFBhmxI0ZKYxcUBVZ7UavNS
|
||||
p6HO3B6QOI+cNe16mQ9O2IvRqc/RW01T9uLWAJHEBSJb97uObmzU9vpVo/UUnlg0
|
||||
ftMt5QKCAQEA1HPuW+V8eA0DMF4+uBWD/uEcUgrHuliavUqxapDmX6m1WHBrywJX
|
||||
BYXbUmw59QZzGcDwI1CCjtX6+a0cxvoOQIYdCxvHQOiDpJ1NopXkLCfTzNfLSXJB
|
||||
srXlxicKpmi46Cp67KoPqSf0aQXtWjtgidSWplc4FGKBjuJ6FFCFKOrlOc3BxCO4
|
||||
3YqxpVNgtoXXZiJNCtRvQsvTmYIj818IcNoa8tKBBl3HAifrKQWMQEkyQOhS61TJ
|
||||
UDf0cDq0YAWGsSdsB9GGshHoh9PW2pxhCE6vef3nT7ilC93cj2KlzmN0XyA/ZgcS
|
||||
T3irrE6HzQ6x84O6mEGTgPnilrVEkIHP1QKCAQEAmX+Bh7AnnnIpjXanJXLlYJ6G
|
||||
gP4q08QHltTe5KDG3IkRSroOBh5+u7xpLkD9Ss1lNDfQDJ75swEFs22On31yNlZ/
|
||||
scrk6Hb9mRKd7zz2G0qAe5LFJsFQ8m2ohk47XBAUzSHbyDjRVslyqABFjHHTNSAM
|
||||
poNeM5yy95YcNTCNRxvo+ITfnuQy0sDaG+0n26RrDWG7Z2ok/JOdRh+RNCFhzJV8
|
||||
DtZklk4uBkBX37XiVzDF/9X1iQjOmE4BgTDcKfYFmH8CHOr1pxNHfJiBE6ldm4Co
|
||||
LslerrPfxgKBGYQcId+IsJZ6hOjvkfJpUPGTPDGUOBABbD36ypRfxZrWQ3f9Ng==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user