Add dialog and progress
Baseline: TortoiseGit 7338078f8ddd924b8cddee35f512f2286072136d.
This is a native first pass, not complete Add/status-list/progress parity.
The official Add manual
and pinned AddDlg/AddCommand/AddProgressCommand/resource sources were compared.
Implemented behavior
File-only selections go directly to Add progress, following AddCommand; folder or mixed selections open a checked native list scoped to the requested paths. The Add dialog keeps the upstream list above Select/deselect all and Include ignored files, with OK/Cancel/Help below. Path and Extension are visible by default; native header menus expose optional Size and Modification date columns. Original status/menu icons, shared status colors, light/dark adaptation and resizable saved geometry are used. Add selector and progress now use the unchanged pinned AddBackground.ico, a translucent blue plus at the lower right of the list viewport. The native background draw preserves alpha and original colors without tinting, respects ShowListBackgroundImage (default on), and clips to the visible list. Progress uses the upstream two columns, Action and Path, with original Add icons and shared status colors; its former extra Status column has been removed. See the artwork verification record. Native table sorting, separate highlighted and checked rows, check/uncheck, preview and Explore context commands are present. Right-clicking a different row selects it before the menu is prepared. Space checks/unchecks highlighted rows. Open, Open With and alternative-editor actions use the working file and retain the repository grant; Open With uses a native application picker and a scoped launch. Clipboard actions provide full paths, relative paths, file/folder names, dotted extensions and all visible columns in displayed order. Single-column text has no heading; multiple columns use tabs and headings, with native LF separators. Command-C copies relative paths. Menu commands and nested icons update with selection, busy/quit state and icon preferences. File-opening commands are hidden for folders. Ignore adds source-shaped filename, extension-mask and containing-folder commands: a shared extension uses a submenu, and mixed extensions use direct name/mask entries. Names are captured in display order and passed to the existing five-radio native Ignore dialog as a sheet. The Add list is blocked while the sheet is open; Cancel preserves its checked selection. Successful Ignore writes refresh Add, Working Tree/Commit and the active repository cache. Hidden newly ignored files leave the Add list and unchecked unrelated rows stay unchecked. Ignore writes rules without staging or deleting working files. See the Ignore integration record for actual model checks and remaining sheet/signed acceptance. See the status-menu receiver record for verification and native acceptance limits. Copy to clipboard now also offers Column 'Path', Column 'Extension', Column 'Size' or Column 'Modification date', named for the right-clicked visible column. It copies selected cell values in displayed row order without a heading. Column identity survives reordering, and a hidden/invalid column disables the command. The native checkbox column maps to Path because upstream checkboxes occupy the Path column. Busy/quit guards apply to both the menu and copy action. Command-C continues to copy relative paths. See the current-column record for actual receiver checks; native mouse/keyboard menu gestures remain pending. Context images follow ShowAppContextMenuIcons when a menu is prepared.
Tracked-file context menus now expose Compare with base, Show log, old-name Log for renames/copies, and HEAD Blame with original icons. Newly added and deleted rows omit Blame; unversioned/ignored rows omit history and base comparison while retaining double-click preview. Two rows recorded as non-directory files expose Compare two files in displayed selection order. If a file disappears before the command runs, the shared backend reads that side from a pinned HEAD commit while using current disk bytes for the other side. The menu no longer disappears merely because a selected file was removed after the list loaded. Directory identity is recorded with each row, so a removed directory remains ineligible. Comparison revalidates path types and historical contents before opening; it does not stage or restore files. See the missing-file verification record. Right-click records the marked row even inside an existing multiple selection; base comparison, Ignore and Delete availability follows that row. Actions preserve the Add window's repository lease and are blocked during Add work and quit confirmation. See the history verification record.
Revert now follows the marked versioned row and captures selected status entries in displayed order. The native No/Yes sheet is shown only when a non-directory row has a modified/type-changed status flag; added-only, clean and other eligible selections start the existing Revert progress workflow directly. No preserves checks and files. Add is blocked while progress runs; its Cancel/close request forwards cancellation to that specific progress worker and waits for the terminal refresh before closing. The shared progress window retains errors/cancellation, Trash recovery and submodule follow-up; simple success auto-closes. Revert progress now uses a native Action/Path table, matching the two-column upstream shared progress list. Both columns use shared adaptive status colors; action cells retain the original Revert icon. Per-operation state remains in tooltips, and Copy to Clipboard exports the two displayed columns followed by the result information. See the progress-table record; displayed light/dark appearance and native clipboard/menu gestures remain pending.
Added files remain on disk, become unversioned and stay unchecked after success. Clean reverted file rows leave the Add list, unrelated checks/staged contents are retained, and saved restoration copies remain available for explicit restoration. Failures refresh the available rows and retain checks for rows that remain. Clean tracked rows explicitly selected in a mixed Add scope are now accepted by the shared backend, with the same stale-status check as changed rows. Modified contents are recoverable in Trash and unrelated staged files are preserved. The backend still rejects mixed unversioned/ignored selections before moving any files; broader mixed-status behavior remains an explicit parity gap, rather than silently filtering requested files. See the Revert record for actual Add/progress receivers, full regression and pending native acceptance.
Index-flag commands now follow the marked versioned row: Skip worktree excludes added/conflicted/already-skipped rows; Assume Unchanged also excludes deleted and already-assumed rows; Unflag appears when either flag is set. These are direct context commands with the shared original Ignore icon. Add captures all selected paths in display order and the marked path, then shows a native default-No/Yes sheet. No preserves checks and the index. Yes uses the existing locked private-index backend, preserving staged blob IDs/modes and working contents. An eligible marked row allows mixed selections; paths without stage-zero entries are reported after eligible paths are updated, matching the shared backend's partial-result behavior.
The parent blocks actions and close during confirmation/work. A queued cancellation prevents mutation; once the synchronous index transaction starts it finishes atomically, then the parent refreshes and honors a requested close. Add rereads index flags without refreshing the index and updates menu eligibility. Success or partial success refreshes repository consumers through the existing callback. See the index-flag record; displayed confirmation, menu and signed grant acceptance remain pending.
The tracked-file menu now exposes the shared Restore after commit command from upstream. In Add it saves temporary working-file copies and changes to Restore; it does not create a commit or automatically restore files when Add completes. Marked rows display the unchanged upstream restore overlay. The command follows the marked versioned, non-directory row; a mixed selection also copies eligible untracked regular files, while skipping directories and already saved copies. Binary contents, file permissions and symbolic-link targets are retained. The shared backend keeps its versioned-only default for other callers; Add explicitly enables mixed-selection capture and validates the containing repository. Restore revalidates ownership, rejecting a path whose parent has become a foreign nested repository since capture.
Restore uses a native Abort/Restore confirmation sheet, with Abort as default. Aborting preserves files, checks and saved copies. Successful paths consume their copies; failed paths keep their copies for retry while other selected paths still restore. Staged blob IDs and modes remain unchanged. The Add list and repository consumers refresh after any successful restoration. Copy/restore work disables parent actions and quit; cancellation is checked between files. An individual copy or atomic restoration finishes before cancellation is observed. Temporary copies are owned by the dialog and discarded on close. See the restoration record for actual receiver/core checks and pending sheet/overlay/signed acceptance.
Show changes as unified diff now follows the same marked-row eligibility as base comparison and is hidden in repositories without a commit. It captures selected paths in displayed order and loads HEAD-to-working diff statistics and patch bytes for each path. The existing read-only unified viewer retains original bytes for Save As; an existing Add viewer is reused, with no-change feedback for empty comparisons. The configured external viewer is supported, with Shift selecting the alternative choice. Viewers retain their originating repository permission and remain independent of the Add parent, matching upstream's separate helper. Add blocks actions while patch loading/launch is active; cancellation terminates owned Git work and prevents an outstanding patch from reaching the viewer. An already-started external launch finishes before the parent can close. Viewer errors preserve checks and leave the index unchanged. Existing viewer work/sheets and quit confirmation block replacement; viewer busy state is rechecked after patch loading to avoid replacing contents beneath an active operation. See the unified-diff record for native receiver verification and remaining displayed/signed acceptance.
Unversioned rows start checked; ignored rows are hidden until Include ignored is selected and start unchecked unless directly requested. Direct files in a mixed scope and removed-but-present copies are included. Refresh retains existing checks and initially checks new unversioned rows. F5 and Command/Control-Return are wired to refresh/accept. The later drop/lifetime batch adds the native table destination and scoped read-only drop/check refresh. Physical Finder delivery and signed acceptance remain unverified. Folder selections use path boundaries. Git still cannot track empty directories.
OK submits only checked paths and closes the selector. Direct file requests and accepted lists enter a separate progress window. The existing forced-add private-index transaction now accepts owned cancellation, checks it at operation boundaries and preserves the original index when cancelled before replacement. Preflight checks reject outside/admin paths and files owned by nested foreign repositories. Git path arguments stay literal, including Unicode/newline/glob names. File selection can add before the initial commit. Adding does not create a commit or push; progress offers a Commit handoff after success. Its adjacent action menu also provides Add as Executable (+x) and Add as Symlink with the original Add icon. These post-actions change only current stage-zero index modes: staged blob IDs, working file contents/permissions and unrelated staged files are preserved, even if a working file was edited or deleted after Add. Folder children and submodule gitlinks keep their modes. Missing/conflicted entries fail without replacing the real index. The shared private-index transaction retains lock and cancellation handling; controls are disabled during mode changes and quit confirmation.
Cancel terminates owned Git work through the shared cancellation machinery and closes a loading selector after cancellation finishes. Progress remains open to show success/cancellation/error. Closing/quit is blocked while Add work is active; other quit-confirmation flows freeze the new models. Native Add work retains its repository grant. Repository refresh after completion uses the existing app/cache flow when the same repository is still active. App menu and Finder entries use the original Add icon. Finder adds the four upstream visibility alternatives and the deleted-state flag; implemented root-menu projection now has 32 entries.
Verification and remaining work
Three new core cases cover scoped unversioned/ignored selection, unchecked ignored defaults, direct normal files, reviewed literal force-add with unchanged HEAD and working contents, unborn indexes, pre-cancelled unchanged indexes and foreign/ invalid paths. Existing WorkingFileAdd transaction/mode tests also pass. The focused run passes 21 tests; the final full regression passes 489 with zero failures.
The actual native Add model/table receiver verifies refresh/check retention, ignored defaults, path-captured checkboxes, native column definitions and disabled worker controls, checked-only OK/close, real Add progress and cancelled unchanged index. The actual Finder receiver verifies the 32-entry pinned source projection and prior icons/selection/cache routes. Both use Swift 6/macOS 13 minimum and display no windows/menus; they prove receiver behavior, not native gestures or screenshots. Debug and unsigned AppStore builds, bundle audits and site generation are recorded in the verification record.
Delete now captures exact status entries from the Add list and routes to the existing guarded working-file delete backend. A native confirmation sheet offers Trash by default; Shift selects permanent deletion with a separate warning. Both keyboard Delete keys are wired, using the upstream unversioned/ignored/copy eligibility rule. The Add parent is blocked during confirmation/work, Cancel preserves checks before acceptance and can cancel work at backend boundaries. Successful deletion refreshes Add and repository consumers; failure shows the backend error and any recoverable Trash locations, then refreshes partial effects. Unrelated unchecked rows remain unchanged. See the Delete record for actual effects and acceptance limits. The final Delete regression passes 491 tests with zero failures; both unsigned builds and bundle audits pass.
Save As and Export now use native save/folder panels and current working-file copies, matching FileSaveAs/FilesExport rather than exporting staged blobs. Save As's working-copy default stem includes the upstream trailing dash before the extension. Existing destination files are replaced by a complete temporary copy; source aliases and Git metadata destinations are rejected. Binary bytes and file attributes are retained, and file symlinks supply their target contents. Export preserves repository-relative folders, skips directories and omitted removed rows, and uses the existing preflighted working-file export backend. Chosen destination scopes are held for the operation; picker sheets and queued copies block close/quit. Cancellation is checked between exports and before replacement; a synchronous individual copy completes before cancellation is observed. Earlier completed exports remain when a later copy fails or cancels. See the copy verification record for actual model checks and remaining native/signed picker acceptance. The final copy regression passes 492 tests with zero failures; both unsigned builds and bundle audits pass.
The missing-file comparison regression passes 493 tests with zero failures. Actual receiver checks verify unchanged staging and pinned HEAD contents after working-file removal; both unsigned builds and package audits pass. Displayed menus/comparison windows and signed acceptance remain pending.
The restoration regression passes 494 tests with zero failures; both unsigned builds, bundle audits and the actual native receiver pass. Displayed overlay/sheet and signed acceptance remain pending.
The Add Revert regression passes 495 tests with zero failures; native Add and actual progress model checks, both unsigned builds and bundle audits pass. Native confirmation/progress gestures and signed acceptance remain pending.
Index-only executable/symlink post-actions are implemented; real native action-menu acceptance is pending. Add LFS commands, saved columns, Space and drop models now have the connected implementations recorded below. Other shared consumers, Shift alternative comparison and physical column/drop/keyboard gestures, progress notification granularity, saved histories/preferences, broader direct/ removed/ignored/submodule cases and real native visual/light/dark comparison remain unfinished. Signed Finder/picker/grant/quit acceptance and GitHub execution of these local changes remain unverified. This work does not complete the full port.
The Add selector now owns read/drop cancellation, invalidates on closure and counts model-owned tasks for Quit. See the connected source audit.
The batch passed fourteen Core tests, the Debug build and six unique native cases across Add/drop/Commit with both Git engines. See the scoped evidence and fixture repairs.
Add list LFS, columns and checkbox family — October 15, 2026
The Add status list now offers LFS Lock and LFS Unlock with the original icons when the repository has its common-directory LFS marker, the marked row is versioned/non-conflicted and every selected target is a file. AddDlg excludes the LFS owner column, so the source hidden-owner rule offers both commands without contacting the lock server to populate the menu. Unversioned/ignored marked rows keep both commands hidden. A live menu action revalidates its captured rows.
The shared LFS progress sheet captures the selected paths and holds Add busy through result review. Successful Lock opens Pull using the repository router; failed/cancelled batches do not. Unlock supports the existing Force retry. Dismissing results refreshes Add once and notifies repository/Commit/Working Tree consumers, preserving unchecked surviving rows. Forced parent closure retires and cancels the child and suppresses late progress, Pull and refresh callbacks; backend work remains counted for Quit until it settles. Server-side changes are not rolled back by cancellation.
The header exposes Extension, Modification date, Size and confirmed Reset columns. Path is mandatory. Native column order and widths are persisted using the shared column schema under Add.FileColumns, independently of other lists. Existing Add.ShowSize/Add.ShowModifiedDate visibility migrates if no schema is present. The native checkbox stays first; copy-all follows the visible native order. Reset restores source order/default visibility and original native widths, while No or forced closure preserves the current layout. Busy/quit states lock layout editing.
A checkbox on a selected row now checks/unchecks every selected row, while an unselected checkbox affects only itself, matching OnLvnItemchanged. Space chooses the new state from the marked row rather than whether every selection is checked. Command-Shift-C uses the shared relative-path/status format; Command-C retains relative paths. Conflict eligibility follows the marked row, including mixed selections, as in the pinned menu; directory exclusion still applies to every selected target. Physical gestures, authenticated LFS transport, shared comparison Shift behavior and signed Finder/App Store grants remain acceptance work.
The Debug build and two-engine native family passed. Raw captures exposed cramped optional columns in an inherited minimum-size window; explicit initial content size and column minimum widths were added, then only the affected Debug/native group was repeated successfully. Final light/dark captures were visually reviewed. Final source review corrected the conflict gate to follow the marked row; a real unmerged-index case and the affected native group pass with both engines. All six receiver processes were reaped; no real LFS server was contacted and Core operations were unchanged. See exact evidence.
Shared repository titles and path-cell tooltips now consume the source Advanced preferences; see repository presentation and its grouped evidence.
Exact file selection and captured menus
The connected Add/Revert selection family now retains exact valid UTF-8 Git names through checked/highlighted rows, marked menus, refresh and private-index operations. Revert checkboxes apply to the highlighted files as in the source; Add native menu invocations retain their original payload and reject stale or retired targets. See the family document for actual grouped evidence, light/dark captures and remaining physical/signed acceptance. This supersedes the pending Add/Revert outer-selection migration; full dialog parity remains partial.
Checked acceptance and owned file commands
The connected file-command flow now uses the source's checked-path ordering and once-only acceptance. Add owns Save/Export/ Open With/editor from its chooser through worker/launch drain; Add and Revert share a picker identity/release/retirement session. Actual grouped evidence, compatibility diagnosis and acceptance boundaries are in the batch record.
Captured command preparation — October 18, 2026
The source-file CLI family
adds the upstream add entry: explicit files go directly to progress, directories
to the scoped checklist. AreAllPathsFiles classifies a selected missing path as a
file; native Add now stages a tracked deletion or reports Git's missing-path error
rather than opening an empty checklist. Preparation checks cancellation before
and within classification, retains its repository/access owner through drain and
cannot open mutation progress after its initiating window closes. Pending
preparation blocks Quit. A directory command preserves an existing checked draft.
An Add result refreshes its captured repository's dialogs and updates workspace
output only while that repository is still current. The existing checklist,
colored file states, icon menus and normal/executable/symlink progress actions
remain the native implementation; full Add/progress visual parity remains open.
Notification-list progress — October 19, 2026
Add now has the source Action/Path notification list, original backdrop, timed Finished row, captured file menus, keyboard/menu clipboard formats, kill confirmation, automatic close and action logging. Commit retains the repository grant, preferences and appearance and opens only after the old result, sheets and workers close.
See the connected progress family for source distinctions, scoped validation and remaining physical, signed and whole-dialog requirements. This continuation does not certify the whole family or port.
Source-selected Add/index family — October 19, 2026
The Add/index continuation connects source-default Add10 selection, configured clean filters, private-index publication and mode post-actions to the native Add/status family. Commit's explicit Add now owns the shared progress sheet; Rebase and workspace entry retain accepted backend and preference snapshots. Per-path receipts, actual worker cancellation and final publication remain owned. General Commit staging and its separate backend bit retain their independent contracts. Grouped evidence and remaining acceptance are recorded with that family.