timet 1.6.3 → 1.6.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84fa974afe30946a8b292569e74917c3992097e0ae652339320981f2951f298d
4
- data.tar.gz: dc6cf2d3f5bd30feebb93db4aa07c436203e53bf1d9d0dbba5166695b622b021
3
+ metadata.gz: cd119a6557987c9bdf16530865c16c60b3aca4cf30ed5424a04649f55bb6f430
4
+ data.tar.gz: 6a0e25787dce7bc903e3b2fa6374631db80045ae3dbf353b9cb8b2fd6cbbcf95
5
5
  SHA512:
6
- metadata.gz: 49cf7cc38f9e44687d27bee93a8de5678963fd92a9589241e38635afcdf4b86f8229d1c401483d2d6e955ee83e5423ca10f832f4beb0101873e60f5d0ff34821
7
- data.tar.gz: 2098f1a3c297277bd07425961b3e84425a1189ae5984e21c35649a3a2c517a5a175dfd5b477abb59ba49f78925a9c4ec872006d3be025ddc4ee363bf86ff7004
6
+ metadata.gz: 74c3b445e264432d4412afef6bdc53e6f2c1f8a1b8d64c430a4c638d70f58190654faa2d7b550ebcc97fb2068d0091fcb7d4f4ce5d365179c7828db4e0076830
7
+ data.tar.gz: 9563a33fff69df1b70375f7528174cd5ff064f77b2d78a2f8609d861e095d7f50312e065e21c587786c442ed10b6c7de2803e96e2d556db4626e729cfa04e0e2
data/.rubocop.yml CHANGED
@@ -6,9 +6,14 @@ AllCops:
6
6
  - timet.gemspec
7
7
  - "vendor/**/*" # Exclude vendor/bundle gems
8
8
 
9
+ Naming/PredicateMethod:
10
+ Exclude:
11
+ - 'lib/timet/database_syncer.rb'
12
+
9
13
  Metrics/ModuleLength:
10
14
  Exclude:
11
15
  - 'lib/timet/tag_distribution.rb'
16
+ - 'lib/timet/database_syncer.rb'
12
17
 
13
18
  Metrics/MethodLength:
14
19
  Max: 15
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## [1.6.4] - 2026-03-26
2
+
3
+ **Improvements:**
4
+
5
+ - **Database Synchronization:** Refactored sync logic to use bidirectional comparison with timestamp-based conflict resolution, improving reliability during database merges.
6
+ - **Dependencies:** Updated `icalendar` to `~> 2.12.2` and `json` to `~> 2.19`, removing unused gems.
7
+ - **Code Quality:** Added RuboCop exclusions for predicate methods in `DatabaseSyncer` and module length for `database_syncer.rb`.
8
+ - **Test Coverage:** Expanded test suite for bidirectional sync scenarios, including conflict resolution and remote item handling.
9
+
10
+ **Bug Fixes:**
11
+
12
+ - **Sync Logic:** Fixed item synchronization to properly handle local-only and remote-only items with timestamp-based decision making.
13
+ - **Database Updates:** Corrected `update_item_from_hash` method to properly bind ID parameter in SQL queries.
14
+ - **Conflict Resolution:** Simplified remote wins logic to compare timestamps directly, removing redundant deleted flag checks.
15
+ - **Sync Flagging:** Fixed return values in sync methods to accurately track whether local changes occurred during synchronization.
16
+
1
17
  ## [1.6.3] - 2026-02-28
2
18
 
3
19
  **Improvements:**
@@ -55,35 +55,65 @@ module Timet
55
55
 
56
56
  def sync_databases(*args)
57
57
  local_db, remote_db, remote_storage, bucket, local_db_path = args
58
- process_database_items(local_db, remote_db)
59
- remote_storage.upload_file(bucket, local_db_path, 'timet.db')
58
+ local_items = local_db.execute_sql('SELECT * FROM items ORDER BY updated_at DESC')
59
+ remote_items = remote_db.execute('SELECT * FROM items ORDER BY updated_at DESC')
60
+
61
+ local_by_id = items_to_hash(local_items)
62
+ remote_by_id = items_to_hash(remote_items)
63
+
64
+ local_changes = process_bidirectional_sync(local_db, local_by_id, remote_by_id)
65
+
66
+ if local_changes
67
+ remote_storage.upload_file(bucket, local_db_path, 'timet.db')
68
+ puts 'Changes uploaded to remote'
69
+ else
70
+ puts 'No local changes to upload'
71
+ end
72
+
60
73
  puts 'Database sync completed'
61
74
  end
62
75
 
63
- def process_database_items(local_db, remote_db)
64
- remote_items = remote_db.execute('SELECT * FROM items ORDER BY updated_at DESC')
65
- local_items = local_db.execute_sql('SELECT * FROM items ORDER BY updated_at DESC')
76
+ def process_bidirectional_sync(local_db, local_items_by_id, remote_items_by_id)
77
+ all_ids = (remote_items_by_id.keys + local_items_by_id.keys).uniq
78
+ local_has_changes = false
79
+
80
+ all_ids.each do |id|
81
+ remote_item = remote_items_by_id[id]
82
+ local_item = local_items_by_id[id]
66
83
 
67
- sync_items_by_id(local_db, items_to_hash(local_items), items_to_hash(remote_items))
84
+ changed = sync_single_item_and_flag(local_db, id, local_item, remote_item)
85
+ local_has_changes = true if changed
86
+ end
87
+
88
+ local_has_changes
68
89
  end
69
90
 
70
- def sync_items_by_id(local_db, local_items_by_id, remote_items_by_id)
71
- all_item_ids = (remote_items_by_id.keys + local_items_by_id.keys).uniq
72
- all_item_ids.each { |id| sync_single_item(local_db, id, local_items_by_id, remote_items_by_id) }
91
+ def sync_single_item_and_flag(local_db, id, local_item, remote_item)
92
+ if !remote_item && local_item
93
+ puts "Local item #{id} will be uploaded"
94
+ true
95
+ elsif !local_item && remote_item
96
+ puts "Adding remote item #{id} to local"
97
+ insert_item_from_hash(local_db, remote_item)
98
+ false
99
+ elsif local_item && remote_item
100
+ merge_and_track_changes?(local_db, id, local_item, remote_item)
101
+ else
102
+ false
103
+ end
73
104
  end
74
105
 
75
- def sync_single_item(*args)
76
- local_db, id, local_items_by_id, remote_items_by_id = args
77
- remote_item = remote_items_by_id[id]
78
- local_item = local_items_by_id[id]
106
+ def merge_and_track_changes?(local_db, id, local_item, remote_item)
107
+ local_time = extract_timestamp(local_item)
108
+ remote_time = extract_timestamp(remote_item)
79
109
 
80
- if !remote_item
81
- log_local_only(id)
82
- elsif !local_item
83
- add_remote_item(local_db, id, remote_item)
84
- else
85
- merge_item(local_db, id, local_item, remote_item)
110
+ if remote_time > local_time
111
+ puts "Remote item #{id} is newer - updating local"
112
+ update_item_from_hash(local_db, remote_item)
113
+ elsif local_time > remote_time
114
+ puts "Local item #{id} is newer - will be uploaded"
86
115
  end
116
+ true
87
117
  end
88
118
 
89
119
  def log_local_only(id)
@@ -132,9 +162,11 @@ module Timet
132
162
 
133
163
  def update_item_from_hash(db, item)
134
164
  fields = "#{ITEM_FIELDS.join(' = ?, ')} = ?"
165
+ values = get_update_values(item)
166
+ values << item['id']
135
167
  db.execute_sql(
136
168
  "UPDATE items SET #{fields} WHERE id = ?",
137
- get_update_values(item)
169
+ values
138
170
  )
139
171
  end
140
172
 
@@ -147,9 +179,8 @@ module Timet
147
179
  items.to_h { |item| [item['id'], item] }
148
180
  end
149
181
 
150
- def remote_wins?(remote_item, remote_time, local_time)
151
- time_diff = remote_time > local_time
152
- time_diff && (remote_item['deleted'].to_i == 1 || time_diff)
182
+ def remote_wins?(_remote_item, remote_time, local_time)
183
+ remote_time > local_time
153
184
  end
154
185
 
155
186
  def format_status_message(id, item, source)
data/lib/timet/version.rb CHANGED
@@ -6,6 +6,6 @@ module Timet
6
6
  # @return [String] The version number in the format 'major.minor.patch'.
7
7
  #
8
8
  # @example Get the version of the Timet application
9
- # Timet::VERSION # => '1.6.3'
10
- VERSION = '1.6.3'
9
+ # Timet::VERSION # => '1.6.4'
10
+ VERSION = '1.6.4'
11
11
  end
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.6.3
4
+ version: 1.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Vielma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-28 00:00:00.000000000 Z
11
+ date: 2026-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor