Commit graph

1783 commits

Author SHA1 Message Date
Shaun Ruffell
4798e6f26b Database: Recreate tags.data from interval data if parsing fails.
If the tags database has been corrupted for any reason we should recreate it.
This commit simplified some of the negative testing for AtomicFiles.
2020-02-23 19:03:40 +01:00
Shaun Ruffell
aa7a674ca6 Do not write tag database if it is not changed.
Database objects were unconditionally writing out the tags database
file. For commands that are not modifying any tags, this is unnecessary.
We will now track if there have been modifications so we can use it to
determine if we need to save the tags to a file.

Closes #284
2020-02-23 19:03:40 +01:00
Shaun Ruffell
4b3a907cbb Use AtomicFile for data, tags, undo, and config files
Now changes accross all of these files either happen all together or not
at all.

Related to issue #155
2020-02-23 19:03:40 +01:00
Shaun Ruffell
8e99c07d85 Introduce AtomicFiles
Introduce AtomicFile and a test of this module to the code.

AtomicFile is like File, except all writes go to temporary files until
the class method finalize_all () is called and the temporary files are
copied over the real files. If any writes fail, like when there is no
more space on the filesystem, none of the files in the database will be
modified.

Since we need version 1.00 of libfiu, I have only added it to the debian
testing container, which includes libfiu-1.00 in the default repository.

Related to #155
2020-02-23 19:03:40 +01:00
Shaun Ruffell
6db1d2b859 Do not construct File when a Path will suffice
There were places in Database, CmdReport, and CmdHelp that were using a File
object when only the Path interface was needed. This is some minor cleanup I
noticed while studying the File usage as part of preparating for converting to
AtomicFile.
2020-02-23 19:03:40 +01:00
Thomas Lauf
35a38d628c Optimize handling of implicit latest interval
- If no id is given but active time tracking (i.e. open interval) is present
  then apply the command to the open interval
2020-02-01 23:49:56 +01:00
Thomas Lauf
711848915b Test for no ids
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2020-02-01 23:49:56 +01:00
Shaun Ruffell
7261c23fa7 Database: Fix error when empty datafile is most recent / oldest
This fixes an error I introduced in the recent code to avoid loading the
entire database. It only now appeared because I happened to run the test
suite on the first of the month.

Below is the error I was seeing:

  $ test/delete.t
  1..5
  ok 1 - delete.t: Delete a single closed interval
  ok 2 - delete.t: Delete an interval which encloses a month border
  ok 3 - delete.t: Delete a mix of open/closed intervals
  not ok 4 - delete.t: Delete a single open interval
  # FAIL: AssertionError on file test/delete.t line 56 in test_delete_open:
  # 'self.assertEqual(len(j), 1)':
  #       0 != 1
  ok 5 - delete.t: Delete an open interval that spans over an exclusion

The problem is that when there was one entry in the 2020-01.data file
and one in the 2020-02.data file, when I deleted the single one in the
2020-02.data file, the interator constructor was not updating the lines
iterator when moving to a new file.
2020-02-01 23:36:18 +01:00
Shaun Ruffell
1abf6e9320 Database: firstLine -> getLatestEntry
firstLine is ambiguous (the first line that was added in time? The first line
that will be returned when iterating the database?)

See https://github.com/GothenburgBitFactory/timewarrior/pull/269#discussion_r367922757
2020-01-26 19:49:23 +01:00
Shaun Ruffell
c7c1ea632a CmdUntag: Fix copy-paste errors from recent changes 2020-01-26 19:49:23 +01:00
Shaun Ruffell
2fcca6f949 trivial:coding-style: Add curly braces around blocks modified recently
timwarrior coding standard is for there to be curly braces around all code
blocks.

See https://github.com/GothenburgBitFactory/timewarrior/pull/269#discussion_r367937920
2020-01-26 19:49:23 +01:00
Shaun Ruffell
d9480b591a CmdModify: Allow modification of synthetic intervals
This fixes an issue in the modify command since it was first added. This will
allow modify to work in the presence of synthetic intervals.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
9aac57c518 CmdSplit: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
a5493787ad CmdShorten: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
52115accb6 CmdResize: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
1b8c674771 CmdMove: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
62bde62961 CmdLenghten: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
c65c899926 CmdJoin: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
6a62d2297e CmdDelete: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
8c8f6b7c7c CmdAnnotate: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
a5785dd41a CmdUntag: Do not load entire database when untagging intervals
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
aa44df24c0 CmdModify: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
16d2c13f55 CmdTag: Do not load entire database
Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
2c1a4a146d CmdContinue: Do not load entire database
This change eliminates the call to getTracked with an empty filter,
which causes the entire database to be parsed.

Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
59ee7e47d4 Database: add assert in addInterval if start is greater than end 2020-01-17 17:48:57 +01:00
Shaun Ruffell
894f8ba5d8 Database: Add method empty 2020-01-17 17:48:57 +01:00
Shaun Ruffell
2df76a2ef0 Add helpers flattenDatabase and getIntervalsByIds
getIntervalsByIds will be used by commands that are loading complete database
currently when they really want a few intervals that the user specified by ID.

Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
610e78fede Remove getAllInclusions helper function
All locations in the code that was creating Intervals for all entries in
the database have been removed. This function can now be removed as
well.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
91e4da7a4c getUntracked helper function should not call getAllInclusions
The getUntracked, called as part of the `timew gaps` command, is
normally looking at a relatively recent interval. We do not want to take
the performance hit of loading the entire database into memory when
processing this command.

Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
b06b8cf8ae Database: add tags method for getting set of tag names
The database class now separatly tracks tag information. So for the one
place where all the inclusions were iterated over in order to build up a
tag set, we now instead ask the database for this set directly.

Related to issue #245
2020-01-17 17:48:57 +01:00
Shaun Ruffell
5dcf226d20 Database: Switch the natural order from newest inclusion to oldest
The inclusion database for the user always starts with the most recent
entry. It is now the same way in the code as well.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
623db0c8e4 Database: Remove Database::allLines()
The Database class itself can now be used in range-based for loops for iterating
over all the lines.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
bd1f7aef99 Remove unused outerRange
outerRange is no longer used, since the filter was simply started based on the
first line in the database now.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
3ec09f9be1 getOverlaps should use non-empty range filter
We can eliminate the need to parse the entire database if we only look for
overlaps based on the latest interval.

Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
9c0c27b55b getLatestInterval does not need to walk all the inclusions
This does not appear to be necessary anymore given that the database lines are
generated from intervals and are all well formed. Any open interval *should* be
at the end of the database.

Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
86bb1465e8 getTracked does not need to read in entire database
Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
e9f860d8ce Remove call to getAllInclusions when initializing tag database 2020-01-17 17:48:57 +01:00
Shaun Ruffell
cf8c35ad55 intervalSummarize should not load the entire database
intervalSummarize is called at the end of most commands. The cost of parsing
all the lines in the database can be significant as the size of the database
grows.

Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
6af1101ea2 Database: Use reverse iterator in lastLine
Now that we have the iterators, we can standardize on their use.

Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
557fd4cb34 Database: Add forward/reverse iterator
This allows the database to be treated as a single collection of strings, but
can be used to avoid loading the entire database when only interested in recent
entries.

Related to issue #245.
2020-01-17 17:48:57 +01:00
Shaun Ruffell
ea3bbd0e85 Datafile: allLines() can return const reference instead of copy.
Not only does this eliminate the need to copy the stings to the caller, it will
also eliminate the need for any iterators over the entries in the Database from
having to hold a copy of the lines from the Datafile.

Related to #245.
2020-01-17 17:48:57 +01:00
Thomas Lauf
03ffa70203 Add curly brackets
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-12-27 16:10:46 +01:00
Thomas Lauf
30740af3ba Resharpen error message for if command stop gets called with ids
- Amends #270

Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-12-27 16:10:46 +01:00
Shaun Ruffell
145af6603c Stop with id should suggest modify command
Recently I was trying to stop an interval that I had left open over the
weekend, but I had already started a new interval at the beginning of the
week. The error I was received was "The end of a date range must be after the
start." which was confusing to me.

After a few moments I realized I should have been using the modify command.
Now the stop command will suggest modify if someone attempts to use stop for
this purpose.
2019-12-27 15:47:39 +01:00
Thomas Lauf
400d02aedb Reduce upper limit for exclusion calculation to current datetime
- `Datetimee("tomorrow")` can create extra exclusion ahead of current time
  which in turn create erroneous synthetic intervals
- Fixes #260

Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-11-20 06:55:43 +01:00
Shaun Ruffell
8109c155af #220: Handle escaped quotes in tags database file.
If there are escaped quotes in the tags database file, when the file is read,
then written, additional escape characters were inserted.

For example:

When tag 'a "test"' is written, it gets stored as 'a \"test\"'. Then it's read
back in that form, but the next time it's serialized to disk, the quotes would
be escaped again resulting in 'a \\"test\\"' which has the effect of removing
the escapes for the double-quotes.
2019-11-18 06:43:21 +01:00
Shaun Ruffell
5f5cfb7b0f #254: quotes in annotations are not escaped
Escapes the quotes for the annotations in the data file, and when
converting an interval to JSON.

The quotes in the annotations were already dequoted in
IntervalFactory::fromSerialization, so we only needed to quote the strings
when serializing or dumping to JSON.
2019-11-18 06:43:21 +01:00
Thomas Lauf
e15fcd30d0 Update copyright holders
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-10-18 10:59:16 +02:00
Thomas Lauf
d64017a7a6 Update copyright dates
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-10-18 10:59:16 +02:00
Thomas Lauf
cd0d5d175e Update libshared to 0d4e31de757ea2609a82549c5b09703d3d3fbe16
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
2019-09-06 16:17:22 +02:00