Commit b4f7263
feat(git-id-switcher): Identity Management UX Overhaul (Phase 5.5) - v0.16.0 (#242)
* feat(i18n): add 16 new keys for Phase 5.5 UX improvements
Add new i18n keys across all 17 languages:
- Profile management: selectProfile, searchProfiles, manageProfiles, newProfile
- Form labels: required, optional, notSet, save
- SSH/GPG fields: sshKeyPath, sshHost, gpgKeyId
- Validation: invalidPath, pathNotInSshDir, fileNotFound
- UI feedback: saved, cannotChange
Also fix OS-specific path message to use neutral wording
("home .ssh folder" instead of "~/.ssh/")
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(identity): add FieldMetadata and FIELD_METADATA for edit UI
- Add FieldMetadata interface for field definition
- Add EDITABLE_FIELDS constant with all 9 fields
- Add FIELD_METADATA array with validators and UI hints
- Add getFieldMetadata() helper function
- Add validateSshKeyPathForField() using validators/common
- Add "ID" i18n key to all 17 locale files
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(identityManager): add SSH/GPG field validation and UI support
- Add validateSshKeyPathInput(), validateGpgKeyIdInput(), validateSshHostInput()
- Extend OPTIONAL_FIELDS with sshKeyPath, sshHost, gpgKeyId
- Extend validateFieldInput() to handle new field types
- Extend buildFieldItems() with SSH Key Path, SSH Host, GPG Key ID items
- Extend getPlaceholderForField() with new field placeholders
- Export validateSshKeyPathFormat, validateGpgKeyId, validateSshHost from inputValidator.ts
- Add 7 new i18n keys to all 17 languages
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(ui): add title bar buttons and unify Profile terminology
- showIdentityQuickPick(): add gear button to title bar for quick access to manage
- showManageIdentitiesQuickPick(): add plus button to title bar for quick add
- Unify UI labels: "Select Profile", "Search profiles...", "Manage Profiles", "New Profile"
- Fix potential double-resolve issue by adding resolved flag
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(i18n): unify Japanese terminology for SSH/GPG key
Japanese translations inconsistently used katakana vs kanji for "key".
Standardize all occurrences to use the kanji form.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(ui): redesign add identity wizard to property list form
Replace the 3-step wizard with a property list form for creating new identities.
Changes:
- Add icon property to FieldMetadata interface
- Add Codicon icons to all FIELD_METADATA entries (lock, person, mail, etc.)
- Implement showAddIdentityForm() with QuickPick-based property list UI
- Show all fields at once with required/optional indicators
- Disable save button until required fields (id, name, email) are filled
- Add back button to title bar for navigation
- After save, navigate to edit screen for optional field entry
- Add 4 new i18n keys to all 17 languages
- Fix memory leak in event listener cleanup using Disposable pattern
- Keep showAddIdentityWizard() as deprecated compatibility wrapper
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(ui): change QuickPick placeholder to "Filter..." for better UX
The VS Code QuickPick API does not support hiding the search box
(GitHub Issue #90402). Changed placeholder from "Select a field to edit"
to "Filter..." to match the actual search box behavior.
Updated all 17 i18n files with appropriate translations.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(ui): improve edit identity screen with back button and visual feedback
- Add showFieldSelectionQuickPick() with createQuickPick API for back button
- Set placeholder to "Filter..." for consistency with add form
- Display all fields with Codicons from FIELD_METADATA
- Show ID field as locked (non-editable) with $(lock) icon
- Add visual feedback "$(check) Saved" after field update
- Refactor executeFieldEditLoop() to continue loop after edit
- Extract waitForQuickPickSelection<T>() as generic helper
- Update test mocks for createQuickPick and QuickInputButtons
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(ui): add back button and file picker to InputBox
- Add showFieldInputBox() with createInputBox API for back button support
- Add waitForInputBoxValue() helper with onCustomButton callback
- Add file picker button for sshKeyPath field (folder-opened icon)
- Support both Unix (HOME) and Windows (USERPROFILE) for default path
- Share InputBox between promptAddFormFieldInput and promptFieldValueInput
- Add i18n keys "Browse..." and "Select SSH Key" in 17 languages
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* feat(security): add field-specific dangerous character validation
Add defense-in-depth validation for sshKeyPath:
- Layer 1: hasDangerousCharsForPath() - shell metacharacter detection
- Layer 2: hasPathTraversal() - path traversal detection
- Layer 3: isUnderSshDirectory() - SSH directory restriction
Changes:
- validators/common.ts: Add hasDangerousCharsForPath/ForText functions
- security/pathUtils.ts: Add isUnderSshDirectory() helper
- identity/identity.ts: Update validateSshKeyPathForField() with 3-layer defense
- FIELD_METADATA: Use hasDangerousCharsForText() for text fields
- Add comprehensive tests for new functions
This allows semicolons in text fields (e.g., "Null;Variant") while
maintaining strict validation for file paths.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test(e2e): add mock support for createInputBox and createQuickPick APIs
- Add createInputBox mock with value, buttons, validationMessage properties
and onDidAccept, onDidHide, onDidTriggerButton, onDidChangeValue events
- Add showOpenDialog mock for file picker support
- Add Uri.file() and ThemeIcon mocks
- Add activeItems property to createQuickPick mock
- Add INPUT_BOX_BACK symbol for back button testing
- Add gear button tests for showIdentityQuickPick (Select Profile screen)
- Add add button tests for showManageIdentitiesQuickPick (Manage Profiles screen)
- Update existing title tests for Phase 5.5 UI changes
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test: fix legacy tests for createInputBox/createQuickPick API
- Update Add Wizard tests to use quickPickSelections + inputBoxSelections
- Update Edit Wizard tests for createQuickPick API
- Fix Security validation tests to use integration test approach
- Fix Edit Loop Continuation tests (resolve timeout issues)
- Add Step 9.3/9.4 tests for property list style forms
All 41 tests now passing.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test: add showOpenDialog default path tests and fix validation
- Add 3 tests for showOpenDialog defaultUri (HOME, USERPROFILE, undefined)
- Add isUnderSshDirectory() check to validateSshKeyPathInput (Safety First)
- Fix createAddMockVSCode to support createQuickPick/createInputBox APIs
- Update FILE_PICKER_CLICK symbol for button click simulation
- All 301 E2E tests passing
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test(identityManager): add InputBox back button, file picker, and validation tests
- Add InputBox Back Button Tests (4 tests)
- QuickInputButtons.Back configuration for name/email fields
- Back button click returns 'back'
- Back button discards value without saving
- Add File Picker Button Tests (8 tests)
- Verify no file picker for name, email, service, gpgKeyId, sshHost
- Verify file picker shown only for sshKeyPath
- Test InputBox value update after file selection
- Test validation runs after file selection
- Add onDidChangeValue Tests (3 tests)
- Real-time validation registration
- validationMessage set on error
- validationMessage undefined on success
- Add hasFilePickerButtonInArray() helper function
- Update test count: 72 -> 90
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test(security): add Defense-in-Depth and field-specific validation tests
- Add multi-layer validation tests (Layer 1-3):
- hasDangerousCharsForPath() for dangerous characters
- hasPathTraversal() for path traversal
- isUnderSshDirectory() for SSH directory restriction
- Add field-specific dangerous character tests:
- name: allows semicolon, rejects backtick/$
- service/description/icon: rejects backtick/$
- sshKeyPath: stricter (rejects semicolon too)
- Add MAX_IDENTITIES limit tests
- Add audit log tests for add/edit operations
- Update test count: 90 -> 114
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* chore(release): prepare v0.16.0 release
- Update CHANGELOG.md with Phase 5.5 UX improvements
- Bump version from 0.15.1 to 0.16.0
- Fix ESLint prefer-const warnings in identityManager.test.ts
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix: resolve CI failures and code quality issues
- Add icon field validator (hasDangerousCharsForText) to FIELD_METADATA
- Use FIELD_METADATA validators in validateFieldInput for service/icon/description
- Extract duplicate cleanup function into createDisposableCleanup()
- Fix isUnderSshDirectory test to use actual home directory (cross-platform)
- Add test for isUnderSshDirectory when HOME/USERPROFILE are undefined
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(security): relax schema pattern for service/description fields
## Background
CI tests were failing because configSchema.ts blocked characters
that should be allowed in service/description fields.
## Changes
- service: allow & (for company names like 'AT&T')
- description: allow <> (for display formatting like '<main>')
- Both fields still block backtick and $ (command injection prevention)
- These fields are display-only and never passed to shell commands
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* refactor: rename Wizard functions to Profile/Form for clarity
- Rename showEditIdentityWizard → showEditProfileFlow
- Remove deprecated showAddIdentityWizard (use showAddIdentityForm)
- Update test describe blocks: "Wizard" → "Form"/"Profile"
- Update configSchema test to allow & in description (display-only field)
This change improves code clarity by using names that reflect
the actual UI behavior (property list form, not multi-step wizard).
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(test): update E2E tests for showAddIdentityForm return type
Update test assertions to match showAddIdentityForm's actual return type:
- Success: returns Identity object (not boolean true)
- Cancel/failure: returns undefined (not boolean false)
All 347 E2E tests now pass.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(test): use path.join for Windows cross-platform compatibility
Use path.join instead of string concatenation with forward slashes
to ensure correct path separators on Windows in SSH directory test.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix: Windows case-insensitive path comparison for isUnderSshDirectory
On Windows, file paths are case-insensitive but JavaScript's startsWith()
is case-sensitive. This caused SSH key path validation to fail when the
drive letter case differed between the input path and environment variable.
Changes:
- Add case-insensitive comparison for Windows in isUnderSshDirectory()
- Add Windows expanded path test (was previously Unix-only)
- Add Windows case-insensitivity test for drive letter comparison
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* test: add coverage ignore for Windows-only code path in isUnderSshDirectory
The Windows case-insensitive path comparison cannot be tested on Unix
because Node.js path module behavior is platform-specific at load time.
Added c8 ignore comments to exclude this code from coverage on Unix CI.
The Windows CI will test this code path.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix: accept Windows absolute paths in validateSshKeyPathFormat
The validation was rejecting Windows paths like C:\Users\... because
it only accepted paths starting with / or ~. Added check for Windows
drive letter pattern (e.g., C:) to support cross-platform SSH key paths.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(validation): accept Windows drive letters in SSH key path validation
- Add isWindowsAbsolutePath() to validators/common.ts for shared use
- Update validateSshKeyPathFormat() to accept Windows paths (C:\, D:\, etc.)
- Add unit tests for isWindowsAbsolutePath() function
This fixes E2E test failure on Windows where paths like
C:\Users est\.ssh\id_rsa were rejected as "not absolute path".
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* debug: add logging to diagnose Windows E2E test failure
Temporary commit to understand why isUnderSshDirectory fails on Windows CI.
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* debug: add more logging to diagnose validation flow
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
* fix(schema): accept Windows drive letters in sshKeyPath pattern
The schema pattern for sshKeyPath only accepted paths starting with
~ or /, which excluded Windows paths like C:\Users\...\.ssh\id_rsa.
Changes:
- Update sshKeyPath pattern to accept [A-Za-z]: prefix
- Add unit tests for Windows path validation
- Remove debug logging added during investigation
🖥️ IDE: [Cursor](https://cursor.sh)
🔌 Extension: [Claude Code](https://claude.ai/download)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Model-Raw: claude-opus-4-5-20251101
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>1 parent 5d12ba8 commit b4f7263
34 files changed
Lines changed: 4990 additions & 537 deletions
File tree
- extensions/git-id-switcher
- l10n
- src
- commands
- identity
- security
- test
- e2e
- ui
- validators
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
10 | 36 | | |
11 | 37 | | |
12 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
77 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
78 | 108 | | |
0 commit comments