TurtleGit for Mac

View Markdown source ↗

Issue tracker integration audit

The pinned TortoiseGit baseline is 7338078f8ddd924b8cddee35f512f2286072136d. The audited files are src/TortoiseProc/ProjectProperties.cpp, its header, and test/UnitTests/ProjectPropertiesTest.cpp. Their Git blob hashes match the repository inventory. The native Commit field, configuration loader, template line handling and warning sequence are implemented, with broader integration and signed sandbox acceptance still pending. Build, process, source reconstruction and signing evidence is recorded in runtime acceptance.

Matching engine

Upstream FindBugIDPositions uses C++ std::wregex with its default ECMAScript grammar. One expression extracts capture group 1. Two expressions use the complete second-expression matches inside each complete first-expression match. A captureless first expression can satisfy HasBugID while extracting no IDs. HasBugID searches only the first expression. UTF-16 character positions are required by the Windows source and by native NSString ranges.

TurtleGit retains this C++ algorithm in Sources/TurtleGitIssueRegex/main.cpp. macOS has 32-bit wchar_t, so the transport stores one UTF-16 code unit per wide character. A private helper process receives three UTF-16LE files and returns match presence and UTF-16 ranges. The Swift reader validates those ranges. Inputs are argument arrays without a shell; diagnostic text is limited to 1024 bytes. A shared runner bounds execution to five seconds plus a one-second termination grace and forcibly reaps its own unresponsive process. EditorConfig now uses the same runner. Excessive helper output is rejected.

The explicit Regex Tester reports malformed expressions as validation failures. Configured consumers use source syntax receipts: an invalid check yields no match; invalid extraction retains a successful first check with no ID ranges. Runtime and protocol failures remain failures. Configured properties are fresh value snapshots; the C++ mutable setters' previously compiled cache is a separate boundary. Matching grammar and UTF-16 positions are retained; libc++ versus MSVC locale, character-class, pathological expression and exception differences still need cross-platform acceptance. No Foundation/ICU regex substitution is used.

Build and distribution

Run python3 scripts/build-issue-regex-runtime.py before Swift tests or a direct Xcode build. CI and scripts/build.sh prepare it automatically. All Xcode configurations embed build/issue-regex-runtime/IssueRegex at Contents/Helpers/IssueRegex. The generated project includes the new Swift reader and shared runner. The package contains the complete helper source, GPL license, reconstruction and validation scripts, and source/binary hashes. Only system dynamic libraries are linked; no Homebrew C++ runtime is required.

The validator checks both architecture slices and their macOS 13 load commands, source correspondence, licenses and functional protocol examples. Add --all-architectures to execute arm64 and x86_64 explicitly; Apple Silicon requires Rosetta for the latter. This does not prove execution on an actual Intel Mac or macOS 13 host.

AppStore signing applies only App Sandbox and sandbox inheritance to this helper. Debug/Release use ordinary hardened-runtime signing. The unsigned package is executed before signing; inherited sandbox signatures and entitlements are inspected afterwards. Running an inherited helper directly from unsandboxed Python does not prove signed app invocation and is skipped. Debug preview signing updates both text-helper hashes and reseals the app. Signed native App Store execution and scoped configuration access remain unverified.

Native Commit controls

IssueTrackerProperties reads Git's system/global/XDG values, overlays the working tree's .tgitconfig, then overlays repository configuration. Native Git worktree and command scopes remain higher priority on macOS. Includes use Git's parser and relative file paths. A bare repository reads HEAD:.tgitconfig. The configured label and issue field appear in the upper-right branch row, as in the upstream resource at x=177/249, y=6/3; absent bugtraq.message hides them. Initial issue focus and template-line extraction were verified in dark mode.

Numeric IDs accept only ASCII digits, commas and spaces. Template extraction uses UTF-16 positions and trims only LF, including leaving CR from CRLF intact. Message insertion trims the field, performs the upstream comma-space replacement, avoids duplicate IDs and honors append/prepend. URL component escaping is implemented and tested; native tracker links are described below. Foundation supplies numeric comparison for natural ID ordering; full StrCmpLogicalW locale/punctuation/equivalent-ID behavior is not proven.

Commit checks missing issue ID, exact unedited template, and missing identity sign-off in that order. Each warning completes before committing or modifying the index. Add Signed-off-by and the warning use the same identity and trailer placement. Template comparison retains the upstream exact-text behavior: extracting a template line trims trailing LF, which can change equality with the original template. This source quirk is not normalized away.

Native No/Abort and numeric rejection retained HEAD and raw index bytes. A real checked-file commit added the exact configured sign-off and Refs: 42 line, committed the latest selected contents, and preserved unchecked staged and working versions. The field seeded 73 from a template and received initial focus in dark mode. All QA apps were closed. Twenty-eight focused Commit/issue/message tests and both unsigned app builds/resource audits passed. See control acceptance.

Actual native issue field Actual native seeded issue field in dark mode

SciEdit.cpp and its header were verified against inventory blobs 5d221b688a02e72bf8b5ef0a9e260f9aa2a3fc7e and 0c26375d84d7d27b111a5759af820d9058da9b6e. MarkEnteredBugID uses narrow C++ ECMAScript regexes over UTF-8 bytes, unlike the UTF-16 validation matcher. The bundled helper now retains that separate styling algorithm. Single-expression capture 1 becomes the identifier; its preceding matched context is bold. Two-expression matching styles complete inner matches and surrounding context. Identifiers are bold italic hotspots. Adjacent equal styles merge before resolving the link, matching Scintilla's contiguous style scan. No simple-template styling fallback is invented.

AppKit maps complete UTF-8 scalar boundaries to UTF-16 attributed ranges, using dynamic link colors and plain base typing attributes. Partial UTF-8 scalar ranges cannot be represented by AppKit and are omitted. Styling is serialized off the main thread, debounced and canceled when superseded; stale results do not replace newer text. Attribute updates preserve selection and Undo registration. Native link activation follows the configured URL with UTF-8 component escaping, and tooltips contain the resolved URL.

Recent messages matches CommitDlg.cpp's prefix gate and updates a visible issue field only when the chosen message yields nonempty IDs. A message with no IDs retains the prior field. Pick commit message and ordinary typing only insert text; they do not update the issue field. History matching uses the wide validation algorithm, not the editor's byte matcher.

Native acceptance verified bold/italic ranges after Unicode prefixes, ordinary link clicks opening the exact percent-escaped local QA target, retained Undo, Recent-message field updates, no-ID retention, revision-picker retention and removal of stale link attributes. Actual light and dark captures are below. HEAD, raw index and working contents were unchanged. One QA app ran at a time; all were closed after testing. See recorded evidence.

Actual native issue links in light mode Actual native issue links in dark mode

Full-message native restyling does not yet reproduce every incremental Scintilla anchor/styling state. Tracker providers, spell checking, snippets and the remaining SciEdit functionality are pending. URL/email matching is described below. Signed inherited-helper invocation remains unverified. Native link dispatch uses Apple's NSTextView delegate.

The verified src/Utils/URLFinder.h blob is 069cadee1eacb70a6d46ebeaf0933e76c8a3430d. Its FindURLMatches scanner is ported in MessageURLFinder.swift, using the same ASCII delimiter set, trailing punctuation removal, angle-bracket mode and supported case-sensitive prefixes: HTTP, HTTPS, Git, FTP, file and mailto (their lowercase spellings). Email targets receive mailto:. Git SSH addresses containing a colon after @ are not email links. Bracketed URLs retain spaces and Unicode, with native UTF-16 ranges advanced by complete scalars, matching SciEdit's byte traversal. The scanner retains the upstream bracket-at-end-of-text quirk.

The Windows PathIsURL gate is adapted using scheme syntax before the original prefix whitelist. Microsoft's API documentation describes URL-format testing but does not define every unusual scheme case. Those cross-platform classification edge cases and non-ASCII CRT character classification remain unverified; Foundation link guessing is disabled.

SciEdit::StyleURLs follows issue styling. Native composition therefore splits issue runs at ordinary URL boundaries and resolves any remaining ID hotspot from its actual visible substring. Ordinary links use the regular font and dynamic link color; issue context and IDs keep bold/italic styles. When configured issue syntax is invalid during typing, independent formatting and ordinary links still appear. Commit follows its source missing-issue warning policy; real matcher runtime/protocol failures remain preflight errors.

The upstream AppUtilsTest.cpp fixtures were verified at blob c2db167dc2893395ba497ba030d1a0e78b22bf6c. Their complete URL range examples, plus Unicode, punctuation, email/SSH gates and issue-style overlap tests pass. Native acceptance without any tracker configuration verifies plain-font links, Undo, removal of stale links, and a normal click opening the exact local file with a percent-escaped space. HEAD, raw index and working contents remained unchanged. The sole QA app quit normally; only its TextEdit QA document was closed. See URL acceptance.

Actual native ordinary message links

Marker formatting and preference

SciEdit::StyleEnteredText and FindStyleChars now map to MessageFormatting.swift. Only the contents of valid *bold*, ^italic^ and _underlined_ spans receive formatting; marker characters remain literal. Matching is per line, requires alphanumeric text beside the marker, and rejects markers inside ordinary words. Bold, italic and underline passes overwrite rather than combine traits, following the source order. Issue styles precede these passes; ordinary URL styles follow them. Overwritten issue hotspots are split before resolving their visible identifier text.

StyleCommitMessages is enabled by default, as in the pinned SettingsAdvanced.cpp blob 1b222ebf9053e0e902f79413899dc92d35071464. The macOS Commit settings tab exposes it and restyles open drafts when changed. Disabling it leaves issue/URL links active and does not change the draft or its Undo history. The native setting is saved in the app's defaults; the remaining upstream Advanced settings are not implied complete by this one mapping.

The source increments a scalar counter while indexing a UTF-16 CString for word classification. That supplementary-character boundary quirk is retained: 雪 *标题* styles its BMP text, while 🦎 *bold* can remain plain. Native ranges still use actual UTF-16 offsets. Null terminators and line boundaries stop a match. Windows IsCharAlphaNumericW uses the user's language semantics. Native letters/decimal-digit character sets are an adaptation; exact locale-dependent Windows classification needs cross-platform acceptance. Incremental Scintilla state is still pending.

Fifteen focused formatting/URL/issue tests pass, including nested precedence, word boundaries, CR/LF, BMP/supplementary text, null termination, disabled formatting and URL overrides. Native preference toggling, retained Undo and both appearances passed. Editor/preference changes preserved HEAD/index/working contents, and a subsequent real disposable commit retained the entire literal message and selected working contents. The QA app quit normally. See formatting acceptance.

Actual native light marker formatting Actual native dark marker formatting

Remaining Commit behavior

See Commit parity for the broader dialog audit. Original source references are ProjectProperties.cpp and the official integration manual.

Native Bugtraq Regex Tester — 2026-10-12

Ported BugtraqRegexTestDlg.cpp/.h and IDD_BUGTRAQREGEXTESTER's control order: editable source sample above Message part expression and Bug-ID expression, then OK/Cancel. The sample is the pinned source resource. The native text view uses the shared log font, UTF-16 issue runs, system light/dark issue colors and underlining. Its plain-text Cut/Copy/Paste/Select All context menu honors app icon preferences, using the original Copy icon and macOS symbols for the other editing actions. Native clipboard injection keeps QA separate from the general clipboard.

The existing C++ ECMAScript helper validates and extracts matches off the main thread; no ICU/Foundation grammar replaces it. An empty first field still validates the second field while producing no issue runs. Invalid edits report the helper error and restyle current sample text with the last valid expression pair, retaining source behavior rather than publishing old offsets for new text. A debounce, captured generation and cancellation token reject superseded or retired results even when an injected provider ignores cancellation. Active matcher requests fence app Quit until they finish; closing cancels owned work. OK returns trimmed expressions once, including source-style acceptance of an invalid draft, and Cancel/closure return no draft once.

The File-menu utility seeds from the current repository's existing issue properties, or starts empty without a repository. It explicitly does not persist configuration. The reusable controller's result callback is ready for the missing Issue Tracker Settings page; that page and parent Apply integration are still open. File-menu configuration seeding and signed grants are compiled/wired but not native-dispatch acceptance. The tester is partial-native-replacement, not certified complete. Field-specific invalid-regex adornment, complete SciEdit commands/spelling, physical focus/keyboard/layout and signed invocation remain open. The original C++ engine's libc++/MSVC edge differences also remain open.

The first Debug build failed on a main-actor model used as a default argument. Construction now occurs inside the controller initializer; the corrected build exited 0. XcodeGen initially regenerated unrelated manual references and omitted the app's existing exported diff type; those changes were restored, and the checked project adds only four new source references. The generator spec now also retains the existing diff type, verified with resolved JSON versus the Info.plist. No new type or document behavior was introduced.

The object-linked native receiver passed, then an expanded native Cut/Paste check also passed. Total: two receiver compilations/processes, both reaped. Checks cover the real sample control/highlight/private clipboard/menu icons/light-dark hosts, single/two-expression real-helper matching, Unicode/UTF-16 positions, invalid recovery/current-text fallback styling, empty-first-field validation, trimmed OK/Cancel, ignored-cancellation late-result/newer-preview/retirement fences and Quit accounting. Core was unchanged and was not rerun; neither the complete eighteen-family group nor physical/signed UI was exercised. No screenshot is claimed. See qa/issue-regex-tester-native-2026-10-12.json.

Scoped Issue Tracker Config and tester Apply — 2026-10-12

Ported SettingsBugtraqConfig.cpp/.h and IDD_SETTINGSBUGTRAQ_CONFIG's source group/ field order: Effective/Local/Project/Global/System, BugTraq URL/warning/message/ append/label/number/logregex, inheritance controls, IBugTraqProvider win32/x64 UUIDs/parameters, and Save to. The Settings tree now has Issue Tracker Config with the original bugtraq.ico, copied byte-for-byte with SHA-256/Git blob metadata. The source UI label bugtraq.warningifnoissue writes its actual source key bugtraq.warnifnoissue. Effective is read-only; stored scopes retain missing versus explicit-empty values and inherited booleans. Windows provider data is preserved but does not execute COM providers on macOS. The associations/provider integration dialogs remain unported. System is readable/copyable here; privileged system-file saving remains unsupported, like the existing native project pages.

Core shares scoped project read/write primitives with Dialogs 3, preserving .tgitconfig, includes, bare HEAD reads and source-ordered per-key writes. Saves affect only known BugTraq keys, retaining other Git settings and include files. Regex CRLF converts to LF when stored. Writes preflight destination/NUL values, use Git locks and report the failed key; multi-key writes are not atomic and do not promise stale-snapshot protection. Commit's existing property reader consumes the stored values without a second configuration representation.

The page owns its Regex Tester and captures the source generation. Duplicate opens, source changes and Apply are blocked while the child is active. Tester OK returns trimmed expressions into the page draft without saving; tester Cancel leaves the draft unchanged; shared Cancel restores the prior saved fields and destination. Parent retirement closes its child and owned permission/confirmation sheets, cancels reads and fences late replies. Hidden-page Apply captures the destination/draft and does not restore active state after retirement. Authorized source-ordered writes may finish after forced closure; presentation is fenced. Global file access and destination-change confirmation use the existing native permission workflow. Saves are counted for page-switch/close/Quit guards.

Validation: three focused Core tests passed, zero failures, 2.157 seconds. They cover scoped round trips/consumer settings, include/unrelated-key preservation, explicit-empty strings/implicit and empty booleans, regex newline normalization, Project/bare reads, invalid destinations/NUL/cancellation and a shared Dialogs reader/writer regression. Debug builds exited 0 before and after the source icon addition; the first emitted an existing exit-zero/no-output SwiftCompile diagnostic, so this is not a clean diagnostics claim.

Native page checks passed with system and bundled Git, then passed again with the added icon decode check: two cached receiver compilations, four owned processes, all reaped. Actual private Git/shared Settings Apply and Commit reading, Effective/ stored inheritance, destination-only Cancel/copy, owned tester OK/Cancel/draft-only/ duplicate/source gates, light/dark hosts, validation and held-save retirement/ Quit fencing passed. No plugin, general clipboard or user config was touched. No full Core/nineteen-family group, physical UI or signed grants were exercised. The resource is partial-native-replacement, not certified complete. See qa/issue-tracker-settings-native-2026-10-12.json. Physical focus/layout/help, no-repository/signed permissions, source plugin association/effective registry fallback, system saving and complete tracker integration remain open.

Displayed light/dark capture review — 2026-10-12

Four compositor captures now show the actual Issue Tracker Config page and Regex Tester in Aqua/Dark Aqua. The Settings page uses a dedicated native host and shared transaction footer; the full Settings navigation tree is absent. Private draft values and the original source sample were used; the matcher is the actual C++ helper. No screenshot pixels were generated, edited or reconstructed.

Reviewed the final captures against the pinned Windows doc/images/en/SettingsIssueTrackerConfig.png and both resource layouts. The source scope order, BugTraq field order, inheritance/boolean controls, regex/Test, provider group, Save-to and tester sample/expression/button order are present. Native rounded controls, system sizing/spacing and the provider-availability caption differ intentionally for macOS. The native page is scrollable and its standalone capture is wider than the source page. These images do not establish full navigation, minimum-size/focus/keyboard, field-specific invalid adornment, help, plugin or signed behavior.

AppKit cacheDisplay first produced incomplete SwiftUI/black captures; those were rejected and are not published. A compositor pass was readable but inactive, so the final pass explicitly activated only the owned windows and cleared field focus. All four final images were viewed and inspected before copying unchanged to the site. Four capture-only receiver compilations/processes ran during this render/visual repair, all exited 0 and were reaped; all owned windows/helper work retired. Visual review also removed repeated placeholders from empty fields, retaining accessibility labels and matching the source blank boxes. Its Debug build exited 0 and the displayed captures were refreshed and reviewed. No Core or behavioral suite was rerun for this presentation-only change. The optional capture case is excluded from the default CI group and requires local window-capture permission. See qa/issue-tracker-captures-2026-10-12.json for final dimensions and hashes.

The shared hotspot interaction family now owns editable link activation and captured icon menus across Commit, Merge, Rebase and Input/Notes/Description. It records the source's dormant relative-root helper instead of inventing a remote mapping. Existing byte styling/escaping is unchanged; physical/signed acceptance remains partial.

The hierarchical settings lifecycle batch adds shared read/Quit ownership, Dialogs 3 save ownership, captured confirmation context and owning hierarchy-hint preferences. Its grouped checkpoint records native checks and the remaining physical/signed scope.

Source configuration and exact tester drafts — October 17, 2026

Issue Tracker Config now retains the source Effective/Local/Project/Global/System radio hierarchy with precedence separators, BugTraq fields and inherit controls, provider fields and Save to order. The extra native provider fallback stays in a separate group below the source controls. All field, inheritance, boolean, source, destination and Test actions capture the owning model/read revision. Inherited, busy, hidden, cancelled, replaced and retired forms reject stale input. The owner observer remains attached while the cached page is hidden; authorized hidden Apply still works, while a closed owner cannot save.

Apply captures the whole draft/source/destination before confirmation and global folder authorization. A changed context refuses the write and retains its newer draft. Already accepted source-ordered writes still finish under their own scope and lifetime after forced closure; this does not add a multi-key rollback. Tester OK updates only the same parent draft, destination and window. The tester uses the parent's preference store. Cancel remains draft-only.

Native settings modification/captured comparisons and tester message/expression changes now preserve exact UTF-8 distinctions, including canonically equivalent Unicode spellings. The existing C++ matcher still supplies UTF-16 ranges. The native sample editor updates that exact text, bounds selections after replacement, retains editable plain text/Undo and original-icon clipboard menus, and rejects retired/dismantled clipboard, field and delegate callbacks. Its automatic hosting size is disabled so notes/sample text stay in the resizable native window.

All 42 configuration and eight tester controls receive explicit partial native mappings. The scoped Git configuration writer now passes a command-only core.precomposeUnicode=false: macOS Git otherwise precomposes every argv value, including configuration text. This preserves submitted UTF-8 in Local, Project and Global stores without changing the persistent repository preference. The shared Project Dialog/client-hook writer uses the same path. Regex grammar and configuration schema remain unchanged. The Debug build, 12 focused Core checks and five native case/engine runs pass. The initial source assertion and diagnostic recheck exposed Git’s argv precomposition; a private reproduction confirmed the cause, and the scoped writer now preserves exact values with a command-only override. Core verifies all writable scopes and the unchanged persistent preference; native source/configuration checks pass with system and bundled Git, plus the retained actual C++ Regex Tester. All four raw light/dark captures were individually reviewed, and all seven owned receivers were reaped and independently absent. See batch evidence for exact attempts, provenance and remaining acceptance. Windows COM execution, full SciEdit/editor/context-menu parity, every configuration/locale/IME boundary, physical keyboard/VoiceOver and signed sandbox/App Store acceptance remain open. No full dialog or port certification is claimed.

Configured expression failure family — October 25, 2026

Configured issue-regex semantics separates HasBugID from extracted ranges, preserves a valid first expression when the second is invalid, and routes Commit/history/shared consumers through caught configuration syntax behavior. The explicit tester stays strict. The family also separates syntax fallback from actual helper/protocol/cancellation failures and documents the fresh-property snapshot boundary. Its grouped checkpoint is recorded separately from full dialog, signed and hosted acceptance.