From 914633235aae3ab68ca89661f5eacd7a0da49734 Mon Sep 17 00:00:00 2001 From: Barrett Ruth <62671086+barrettruth@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:26:16 -0400 Subject: [PATCH] fix(sync): add backend name prefix to all OAuth log messages (#122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(sync): add backend name prefix to all OAuth log messages (#121) Problem: four log messages in `oauth.lua` lacked the `self.name` backend prefix, producing generic notifications instead of identifying which backend (`gcal`/`gtasks`) triggered the message. Solution: prepend `self.name .. ': '` to the four unprefixed messages and drop the hardcoded "Google" from the browser prompt since `self.name` already identifies the service. * fix(sync): canonicalize all log prefixes across sync backends (#121) Problem: log messages in `oauth.lua`, `gcal.lua`, `gtasks.lua`, and `s3.lua` were inconsistent — some lacked a backend prefix, others used sentence-case or bare error strings without identifying the source. Solution: prefix all user-facing log messages with their backend name (`gcal:`, `gtasks:`, `S3:`, `Google:`). Capitalize `S3` and `Google` display names. Normalize casing and separator style (em dash) across all sync log sites. --- lua/pending/sync/gcal.lua | 10 +++---- lua/pending/sync/gtasks.lua | 10 +++---- lua/pending/sync/oauth.lua | 10 +++---- lua/pending/sync/s3.lua | 58 ++++++++++++++++++------------------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/lua/pending/sync/gcal.lua b/lua/pending/sync/gcal.lua index d316375..a0a7617 100644 --- a/lua/pending/sync/gcal.lua +++ b/lua/pending/sync/gcal.lua @@ -159,7 +159,7 @@ function M.push() oauth.with_token(oauth.google_client, 'gcal', function(access_token) local calendars, cal_err = get_all_calendars(access_token) if cal_err or not calendars then - log.error(cal_err or 'Failed to fetch calendars.') + log.error('gcal: ' .. (cal_err or 'failed to fetch calendars')) return end @@ -185,7 +185,7 @@ function M.push() local del_err = delete_event(access_token, cal_id --[[@as string]], event_id --[[@as string]]) if del_err then - log.warn('Failed to delete calendar event: ' .. del_err) + log.warn('gcal: failed to delete calendar event — ' .. del_err) failed = failed + 1 else unlink_remote(task, extra, now_ts) @@ -203,7 +203,7 @@ function M.push() if event_id and cal_id then local upd_err = update_event(access_token, cal_id, event_id, task) if upd_err then - log.warn('Failed to update calendar event: ' .. upd_err) + log.warn('gcal: failed to update calendar event — ' .. upd_err) failed = failed + 1 else updated = updated + 1 @@ -211,12 +211,12 @@ function M.push() else local lid, lid_err = find_or_create_calendar(access_token, cat, calendars) if lid_err or not lid then - log.warn('Failed to create calendar: ' .. (lid_err or 'unknown')) + log.warn('gcal: failed to create calendar — ' .. (lid_err or 'unknown')) failed = failed + 1 else local new_id, create_err = create_event(access_token, lid, task) if create_err then - log.warn('Failed to create calendar event: ' .. create_err) + log.warn('gcal: failed to create calendar event — ' .. create_err) failed = failed + 1 elseif new_id then if not task._extra then diff --git a/lua/pending/sync/gtasks.lua b/lua/pending/sync/gtasks.lua index 272bed6..89b32b6 100644 --- a/lua/pending/sync/gtasks.lua +++ b/lua/pending/sync/gtasks.lua @@ -267,7 +267,7 @@ local function push_pass(access_token, tasklists, s, now_ts, by_gtasks_id) if allow_remote_delete() then local err = delete_gtask(access_token, list_id, gtid) if err then - log.warn('Failed to delete remote task: ' .. err) + log.warn('gtasks: failed to delete remote task — ' .. err) failed = failed + 1 else unlink_remote(task, now_ts) @@ -286,7 +286,7 @@ local function push_pass(access_token, tasklists, s, now_ts, by_gtasks_id) if not synced_at or task.modified > synced_at then local err = update_gtask(access_token, list_id, gtid, task_to_gtask(task)) if err then - log.warn('Failed to update remote task: ' .. err) + log.warn('gtasks: failed to update remote task — ' .. err) failed = failed + 1 else task._extra = task._extra or {} @@ -300,7 +300,7 @@ local function push_pass(access_token, tasklists, s, now_ts, by_gtasks_id) if not err and lid then local new_id, create_err = create_gtask(access_token, lid, task_to_gtask(task)) if create_err then - log.warn('Failed to create remote task: ' .. create_err) + log.warn('gtasks: failed to create remote task — ' .. create_err) failed = failed + 1 elseif new_id then if not task._extra then @@ -339,7 +339,7 @@ local function pull_pass(access_token, tasklists, s, now_ts, by_gtasks_id) for list_name, list_id in pairs(tasklists) do local items, err = list_gtasks(access_token, list_id) if err then - log.warn('Failed to fetch task list "' .. list_name .. '": ' .. err) + log.warn('gtasks: failed to fetch task list "' .. list_name .. '" — ' .. err) failed = failed + 1 else fetched_list_ids[list_id] = true @@ -414,7 +414,7 @@ end local function sync_setup(access_token) local tasklists, tl_err = get_all_tasklists(access_token) if tl_err or not tasklists then - log.error(tl_err or 'Failed to fetch task lists.') + log.error('gtasks: ' .. (tl_err or 'failed to fetch task lists')) return nil, nil, nil end local s = require('pending').store() diff --git a/lua/pending/sync/oauth.lua b/lua/pending/sync/oauth.lua index 516a353..a64b984 100644 --- a/lua/pending/sync/oauth.lua +++ b/lua/pending/sync/oauth.lua @@ -447,12 +447,12 @@ function OAuthClient:auth(on_complete) end) vim.ui.open(auth_url) - log.info('Opening browser for Google authorization...') + log.info(self.name .. ': Opening browser for authorization...') vim.defer_fn(function() if not server_closed then close_server() - log.warn('OAuth callback timed out (120s).') + log.warn(self.name .. ': OAuth callback timed out (120s).') end end, 120000) end @@ -490,14 +490,14 @@ function OAuthClient:_exchange_code(creds, code, code_verifier, port, on_complet if result.code ~= 0 then self:clear_tokens() - log.error('Token exchange failed.') + log.error(self.name .. ': Token exchange failed.') return end local ok, decoded = pcall(vim.json.decode, result.stdout or '') if not ok or not decoded.access_token then self:clear_tokens() - log.error('Invalid token response.') + log.error(self.name .. ': Invalid token response.') return end @@ -540,7 +540,7 @@ M._BUNDLED_CLIENT_SECRET = BUNDLED_CLIENT_SECRET M.BUNDLED_CLIENT_ID = BUNDLED_CLIENT_ID M.google_client = M.new({ - name = 'google', + name = 'Google', scope = 'https://www.googleapis.com/auth/tasks' .. ' https://www.googleapis.com/auth/calendar', port = 18392, config_key = 'google', diff --git a/lua/pending/sync/s3.lua b/lua/pending/sync/s3.lua index 64c4348..0d669b3 100644 --- a/lua/pending/sync/s3.lua +++ b/lua/pending/sync/s3.lua @@ -69,7 +69,7 @@ end local function create_bucket() local name = util.input({ prompt = 'S3 bucket name (pending.nvim): ' }) if not name then - log.info('s3: bucket creation cancelled') + log.info('S3: bucket creation cancelled') return end if name == '' then @@ -108,7 +108,7 @@ local function create_bucket() .. '" } }' ) else - log.error('s3: bucket creation failed — ' .. (result.stderr or 'unknown error')) + log.error('S3: bucket creation failed — ' .. (result.stderr or 'unknown error')) end end @@ -120,13 +120,13 @@ function M.auth(args) if not input or input == '' then local s3cfg = get_config() if s3cfg and s3cfg.profile then - log.info('s3: current profile: ' .. s3cfg.profile) + log.info('S3: current profile: ' .. s3cfg.profile) else - log.info('s3: no profile configured (using default)') + log.info('S3: no profile configured (using default)') end return end - log.info('s3: set profile in your config: sync = { s3 = { profile = "' .. input .. '" } }') + log.info('S3: set profile in your config: sync = { s3 = { profile = "' .. input .. '" } }') end) return end @@ -138,9 +138,9 @@ function M.auth(args) if result.code == 0 then local ok, data = pcall(vim.json.decode, result.stdout or '') if ok and data then - log.info('s3: authenticated as ' .. (data.Arn or data.Account or 'unknown')) + log.info('S3: authenticated as ' .. (data.Arn or data.Account or 'unknown')) else - log.info('s3: credentials valid') + log.info('S3: credentials valid') end local s3cfg = get_config() if not s3cfg or not s3cfg.bucket then @@ -149,21 +149,21 @@ function M.auth(args) else local stderr = result.stderr or '' if stderr:find('SSO') or stderr:find('sso') then - log.info('s3: SSO session expired — running login...') + log.info('S3: SSO session expired — running login...') local login_cmd = base_cmd() vim.list_extend(login_cmd, { 'sso', 'login' }) local login_result = util.system(login_cmd, { text = true }) if login_result.code == 0 then - log.info('s3: SSO login successful') + log.info('S3: SSO login successful') else - log.error('s3: SSO login failed — ' .. (login_result.stderr or '')) + log.error('S3: SSO login failed — ' .. (login_result.stderr or '')) end elseif stderr:find('Unable to locate credentials') or stderr:find('NoCredentialProviders') then - log.error('s3: no AWS credentials configured. See :h pending-s3') + log.error('S3: no AWS credentials configured. See :h pending-s3') else - log.error('s3: ' .. stderr) + log.error('S3: ' .. stderr) end end end) @@ -176,10 +176,10 @@ end function M.push() util.async(function() - util.with_guard('s3', function() + util.with_guard('S3', function() local s3cfg = get_config() if not s3cfg or not s3cfg.bucket then - log.error('s3: bucket is required. Set sync.s3.bucket in config.') + log.error('S3: bucket is required. Set sync.s3.bucket in config.') return end local key = s3cfg.key or 'pending.json' @@ -198,7 +198,7 @@ function M.push() local f = io.open(s.path, 'r') if not f then - log.error('s3: failed to read store file') + log.error('S3: failed to read store file') return end local content = f:read('*a') @@ -206,7 +206,7 @@ function M.push() local tf = io.open(tmpfile, 'w') if not tf then - log.error('s3: failed to create temp file') + log.error('S3: failed to create temp file') return end tf:write(content) @@ -218,22 +218,22 @@ function M.push() os.remove(tmpfile) if result.code ~= 0 then - log.error('s3: push failed — ' .. (result.stderr or 'unknown error')) + log.error('S3: push failed — ' .. (result.stderr or 'unknown error')) return end util.finish(s) - log.info('s3: push uploaded to s3://' .. s3cfg.bucket .. '/' .. key) + log.info('S3: push uploaded to s3://' .. s3cfg.bucket .. '/' .. key) end) end) end function M.pull() util.async(function() - util.with_guard('s3', function() + util.with_guard('S3', function() local s3cfg = get_config() if not s3cfg or not s3cfg.bucket then - log.error('s3: bucket is required. Set sync.s3.bucket in config.') + log.error('S3: bucket is required. Set sync.s3.bucket in config.') return end local key = s3cfg.key or 'pending.json' @@ -245,7 +245,7 @@ function M.pull() if result.code ~= 0 then os.remove(tmpfile) - log.error('s3: pull failed — ' .. (result.stderr or 'unknown error')) + log.error('S3: pull failed — ' .. (result.stderr or 'unknown error')) return end @@ -256,7 +256,7 @@ function M.pull() end) if not load_ok then os.remove(tmpfile) - log.error('s3: pull failed — could not parse remote store') + log.error('S3: pull failed — could not parse remote store') return end @@ -318,7 +318,7 @@ function M.pull() os.remove(tmpfile) util.finish(s) - log.info('s3: pull ' .. util.fmt_counts({ + log.info('S3: pull ' .. util.fmt_counts({ { created, 'added' }, { updated, 'updated' }, { unchanged, 'unchanged' }, @@ -329,10 +329,10 @@ end function M.sync() util.async(function() - util.with_guard('s3', function() + util.with_guard('S3', function() local s3cfg = get_config() if not s3cfg or not s3cfg.bucket then - log.error('s3: bucket is required. Set sync.s3.bucket in config.') + log.error('S3: bucket is required. Set sync.s3.bucket in config.') return end local key = s3cfg.key or 'pending.json' @@ -414,7 +414,7 @@ function M.sync() local f = io.open(s.path, 'r') if not f then - log.error('s3: sync failed — could not read store file') + log.error('S3: sync failed — could not read store file') return end local content = f:read('*a') @@ -423,7 +423,7 @@ function M.sync() local push_tmpfile = vim.fn.tempname() .. '.json' local tf = io.open(push_tmpfile, 'w') if not tf then - log.error('s3: sync failed — could not create temp file') + log.error('S3: sync failed — could not create temp file') return end tf:write(content) @@ -435,13 +435,13 @@ function M.sync() os.remove(push_tmpfile) if push_result.code ~= 0 then - log.error('s3: sync push failed — ' .. (push_result.stderr or 'unknown error')) + log.error('S3: sync push failed — ' .. (push_result.stderr or 'unknown error')) util.finish(s) return end util.finish(s) - log.info('s3: sync ' .. util.fmt_counts({ + log.info('S3: sync ' .. util.fmt_counts({ { created, 'added' }, { updated, 'updated' }, }) .. ' | push uploaded')