timet 1.5.7 → 1.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.deepsource.toml +13 -0
- data/CHANGELOG.md +30 -0
- data/README.md +1 -3
- data/lib/timet/application.rb +1 -2
- data/lib/timet/application_helper.rb +8 -2
- data/lib/timet/database_sync_helper.rb +4 -3
- data/lib/timet/time_helper.rb +19 -1
- data/lib/timet/time_statistics.rb +1 -1
- data/lib/timet/time_update_helper.rb +1 -19
- data/lib/timet/time_validation_helper.rb +3 -2
- data/lib/timet/validation_edit_helper.rb +1 -1
- data/lib/timet/version.rb +2 -2
- data/lib/timet/week_info.rb +8 -9
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e5079b49daa5deed838350e66235ce5301518e928a478f405423f268e431390
|
4
|
+
data.tar.gz: e7ef91dd990022437605bdfe406387e1499b9d08de5f6c233211332d9cb5ea0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6f4a1db83a82e0a0e53787a1b8847b7ceaa2694e0e4fbe318271bfc00a33c078d525d832f3be0b136d11c9b4a580ff3648ef9a1064e8921be6d7e79cb59c910
|
7
|
+
data.tar.gz: 7cd3c8513a161e3864501cec96317b833bdda14d937779b97d0feb680a894284f34d7427ba1197ad8ca0a721ede075b13b549489e5beaaa1cbfb751fa71f927f
|
data/.deepsource.toml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
## [1.5.9] - 2025-07-30
|
2
|
+
|
3
|
+
**Improvements:**
|
4
|
+
|
5
|
+
- Replaced Code Climate with DeepSource for static analysis and test coverage reporting.
|
6
|
+
- Updated the CI workflow by removing Code Climate steps and adding a .deepsource.toml configuration file.
|
7
|
+
- Updated gem dependencies, including rubocop, thor, and various aws-sdk gems.
|
8
|
+
- Refactored application.rb to use abort for more idiomatic error handling on invalid arguments.
|
9
|
+
- Updated the README to replace the old Code Climate badges with a new DeepSource badge.
|
10
|
+
|
11
|
+
**Bug fixes:**
|
12
|
+
|
13
|
+
- Fixed a shell injection vulnerability in application_helper.rb by properly escaping notification messages using Shellwords.shellescape.
|
14
|
+
- Corrected a timezone-related issue in time_validation_helper.rb by using Time.now.getlocal for future date validation.
|
15
|
+
|
16
|
+
## [1.5.8] - 2025-06-28
|
17
|
+
|
18
|
+
**Improvements:**
|
19
|
+
|
20
|
+
- Updated gem dependencies, including `aws-sdk-s3`, `rake`, `sqlite3`, and `rubocop`.
|
21
|
+
- Refactored `update_time_field` method into `TimeHelper` for better code organization.
|
22
|
+
- Simplified `TimeStatistics#average_by_tag` to use the more concise `(&:mean)` method in `TimeStatistics`.
|
23
|
+
- Improved robustness of `format_time_string` in `TimeHelper`.
|
24
|
+
- Enhanced code clarity in `DatabaseSyncHelper` and `WeekInfo`.
|
25
|
+
- Added `vendor/bundle` and a test calendar file to `.gitignore`.
|
26
|
+
|
27
|
+
**Bug Fixes:**
|
28
|
+
|
29
|
+
- Corrected time collision validation in `ValidationEditHelper` to properly handle exact time matches (`>=`).
|
30
|
+
|
1
31
|
## [1.5.7] - 2025-05-16
|
2
32
|
|
3
33
|
**Improvements:**
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
[](https://badge.fury.io/rb/timet)
|
2
2
|

|
3
|
-
[](https://codeclimate.com/github/frankvielma/timet/test_coverage)
|
5
|
-
|
3
|
+
[](https://app.deepsource.com/gh/frankvielma/timet/)
|
6
4
|
# Timet
|
7
5
|
|
8
6
|

|
data/lib/timet/application.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'shellwords'
|
4
|
+
|
3
5
|
module Timet
|
4
6
|
# Provides helper methods for the Timet application.
|
5
7
|
module ApplicationHelper
|
@@ -109,7 +111,8 @@ module Timet
|
|
109
111
|
# @param tag [String] A tag or label for the session, used in the notification message.
|
110
112
|
# @return [void]
|
111
113
|
def run_linux_session(time, tag)
|
112
|
-
|
114
|
+
escaped_message = Shellwords.shellescape(show_message(tag))
|
115
|
+
notification_command = "notify-send --icon=clock #{escaped_message}"
|
113
116
|
command = "sleep #{time} && tput bel && tt stop 0 && #{notification_command} &"
|
114
117
|
pid = Kernel.spawn(command)
|
115
118
|
Process.detach(pid)
|
@@ -121,7 +124,10 @@ module Timet
|
|
121
124
|
# @param _tag [String] A tag or label for the session, not used in the notification message on macOS.
|
122
125
|
# @return [void]
|
123
126
|
def run_mac_session(time, tag)
|
124
|
-
|
127
|
+
# Escape double quotes and backslashes for AppleScript, then shell-escape the entire AppleScript command
|
128
|
+
escaped_message_for_applescript = show_message(tag).gsub('\\', '\\\\').gsub('"', '\"')
|
129
|
+
escaped_applescript_command = Shellwords.shellescape("display notification \"#{escaped_message_for_applescript}\"")
|
130
|
+
notification_command = "osascript -e #{escaped_applescript_command}"
|
125
131
|
command = "sleep #{time} && afplay /System/Library/Sounds/Basso.aiff && tt stop 0 && #{notification_command} &"
|
126
132
|
pid = Kernel.spawn(command)
|
127
133
|
Process.detach(pid)
|
@@ -40,12 +40,13 @@ module Timet
|
|
40
40
|
# comparing it with the local database, and handling any differences found
|
41
41
|
def self.process_remote_database(local_db, remote_storage, bucket, local_db_path)
|
42
42
|
with_temp_file do |temp_file|
|
43
|
-
|
43
|
+
file_path = temp_file.path
|
44
|
+
remote_storage.download_file(bucket, 'timet.db', file_path)
|
44
45
|
|
45
|
-
if databases_are_in_sync?(
|
46
|
+
if databases_are_in_sync?(file_path, local_db_path)
|
46
47
|
puts 'Local database is up to date'
|
47
48
|
else
|
48
|
-
handle_database_differences(local_db, remote_storage, bucket, local_db_path,
|
49
|
+
handle_database_differences(local_db, remote_storage, bucket, local_db_path, file_path)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
end
|
data/lib/timet/time_helper.rb
CHANGED
@@ -115,7 +115,7 @@ module Timet
|
|
115
115
|
# TimeHelper.format_time_string('127122') # => nil
|
116
116
|
# TimeHelper.format_time_string('abc') # => nil
|
117
117
|
def self.format_time_string(input)
|
118
|
-
return nil if input.
|
118
|
+
return nil if input.to_s.empty?
|
119
119
|
|
120
120
|
digits = input.gsub(/\D/, '')[0..5]
|
121
121
|
return nil if digits.empty?
|
@@ -264,5 +264,23 @@ module Timet
|
|
264
264
|
parsed_time_component.sec
|
265
265
|
)
|
266
266
|
end
|
267
|
+
|
268
|
+
# Updates a time field (start or end) of a tracking item with a formatted date value.
|
269
|
+
#
|
270
|
+
# @param item [Array] The tracking item to be updated.
|
271
|
+
# @param field [String] The time field to be updated.
|
272
|
+
# @param new_time [String] The new time value.
|
273
|
+
#
|
274
|
+
# @return [Time] The updated time value.
|
275
|
+
#
|
276
|
+
# @example Update the 'start' field of a tracking item with a formatted date value
|
277
|
+
# update_time_field(item, 'start', '11:10:00')
|
278
|
+
def self.update_time_field(item, field, new_time)
|
279
|
+
field_index = Timet::Application::FIELD_INDEX[field]
|
280
|
+
timestamp = item[field_index]
|
281
|
+
edit_time = Time.at(timestamp || item[1]).to_s.split
|
282
|
+
edit_time[1] = new_time
|
283
|
+
DateTime.strptime(edit_time.join(' '), '%Y-%m-%d %H:%M:%S %z').to_time
|
284
|
+
end
|
267
285
|
end
|
268
286
|
end
|
@@ -72,7 +72,7 @@ module Timet
|
|
72
72
|
#
|
73
73
|
# @return [Hash<String, Float>] A hash mapping tags to their average durations.
|
74
74
|
def average_by_tag
|
75
|
-
@duration_by_tag.transform_values
|
75
|
+
@duration_by_tag.transform_values(&:mean)
|
76
76
|
end
|
77
77
|
|
78
78
|
# Returns a hash where keys are tags and values are the standard deviation of durations for each tag.
|
@@ -25,7 +25,7 @@ module Timet
|
|
25
25
|
|
26
26
|
return print_error(date_value) unless formatted_date
|
27
27
|
|
28
|
-
new_date = update_time_field(item, field, formatted_date)
|
28
|
+
new_date = TimeHelper.update_time_field(item, field, formatted_date)
|
29
29
|
new_value_epoch = new_date.to_i
|
30
30
|
|
31
31
|
if valid_time_value?(item, field, new_value_epoch, id)
|
@@ -47,24 +47,6 @@ module Timet
|
|
47
47
|
puts "Invalid date: #{message}".red
|
48
48
|
end
|
49
49
|
|
50
|
-
# Updates a time field (start or end) of a tracking item with a formatted date value.
|
51
|
-
#
|
52
|
-
# @param item [Array] The tracking item to be updated.
|
53
|
-
# @param field [String] The time field to be updated.
|
54
|
-
# @param new_time [String] The new time value.
|
55
|
-
#
|
56
|
-
# @return [Time] The updated time value.
|
57
|
-
#
|
58
|
-
# @example Update the 'start' field of a tracking item with a formatted date value
|
59
|
-
# update_time_field(item, 'start', '11:10:00')
|
60
|
-
def update_time_field(item, field, new_time)
|
61
|
-
field_index = Timet::Application::FIELD_INDEX[field]
|
62
|
-
timestamp = item[field_index]
|
63
|
-
edit_time = Time.at(timestamp || item[1]).to_s.split
|
64
|
-
edit_time[1] = new_time
|
65
|
-
DateTime.strptime(edit_time.join(' '), '%Y-%m-%d %H:%M:%S %z').to_time
|
66
|
-
end
|
67
|
-
|
68
50
|
# Validates if a new time value is valid for a specific time field (start or end).
|
69
51
|
#
|
70
52
|
# @param item [Array] The tracking item to be validated.
|
@@ -103,9 +103,10 @@ module Timet
|
|
103
103
|
#
|
104
104
|
# @raise [ArgumentError] If the new datetime is in the future.
|
105
105
|
def validate_future_date(new_datetime)
|
106
|
-
|
106
|
+
# Ensure the new datetime is not in the future relative to the current time.
|
107
|
+
return unless new_datetime > Time.now.getlocal
|
107
108
|
|
108
|
-
raise ArgumentError, "Cannot set time to a future date: #{new_datetime.strftime('%Y-%m-%d %H:%M:%S')}"
|
109
|
+
raise ArgumentError, "Cannot set time to a future date or time: #{new_datetime.strftime('%Y-%m-%d %H:%M:%S')}"
|
109
110
|
end
|
110
111
|
|
111
112
|
# Validates that the difference between two timestamps is less than 24 hours.
|
@@ -106,7 +106,7 @@ module Timet
|
|
106
106
|
def check_collision_with_next_item(field, new_epoch, next_item)
|
107
107
|
return unless next_item
|
108
108
|
|
109
|
-
if field == 'start' && new_epoch
|
109
|
+
if field == 'start' && new_epoch >= next_item[1]
|
110
110
|
raise ArgumentError,
|
111
111
|
'New start time collides with next item (starts at ' \
|
112
112
|
"#{Time.at(next_item[1]).strftime('%Y-%m-%d %H:%M:%S')})."
|
data/lib/timet/version.rb
CHANGED
data/lib/timet/week_info.rb
CHANGED
@@ -22,15 +22,14 @@ module Timet
|
|
22
22
|
@date_string = date_string_for_display # Use the passed string for display
|
23
23
|
@current_cweek = date_object.cweek
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
#
|
32
|
-
|
33
|
-
@week_display_string = if is_first_display_of_this_cweek
|
25
|
+
is_first_entry = weeks_array_ref.empty?
|
26
|
+
is_new_week = is_first_entry || @current_cweek != weeks_array_ref.last
|
27
|
+
|
28
|
+
# A separator is needed if this entry starts a new week group, but it's not the very first one.
|
29
|
+
@print_separator_before_this = is_new_week && !is_first_entry
|
30
|
+
|
31
|
+
# The week number is underlined if it's the first time this week appears.
|
32
|
+
@week_display_string = if is_new_week
|
34
33
|
format('%02d', @current_cweek).underline
|
35
34
|
else
|
36
35
|
' '
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frank Vielma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -123,6 +123,7 @@ executables:
|
|
123
123
|
extensions: []
|
124
124
|
extra_rdoc_files: []
|
125
125
|
files:
|
126
|
+
- ".deepsource.toml"
|
126
127
|
- ".reek.yml"
|
127
128
|
- ".rspec"
|
128
129
|
- ".rubocop.yml"
|