Updates, release notes, and technical write-ups about RsyncUI.
This is the multi-page printable view of this section. Click here to print.
Blog
Release Notes
RsyncUI version release notes and changelogs.
Version 2.9.0
Version 2.9.0 - Jan 16, 2026 in development
To compile your own version, please refer to the blog post titled “Compiling RsyncUI”. The main branch is consistently updated with the latest code revisions.
The development of the next version has commenced. Currently, a few enhancements have been implemented in this version. The version is scheduled for release by the end of January. It is likely that more updates will be committed in the future.
- In the Tasks menu, when using a single table for tasks, the “Use two tables Inspector” setting is disabled. Consequently, the Inspectors for Edit and Parameters are not closed when the tab is changed. Screenshots are provided below for reference.
- If the Parameters include the two parameters
--itemize-changesand--update, the output from rsync is enhanced. Please note that these parameters will increase the output from rsync. For more information, refer to the blog post titled “Verify remote”.
For further details, please refer to the following documents:
- a detailed Changelog
- a Code Quality Report



Version 2.8.7
Version 2.8.7 - Jan 14, 2026
It appears that the updated package successfully addresses the issue of missing statistics. I have not encountered the “no stats” problem after the update, and several users have downloaded the release candidate. The release candidate has been promoted to the official release.
In contrast to version 2.8.6, this release introduces only two updates: an updated package RsyncProcessStreaming and a function in package ParseRsyncOutput that writes debug data to a text file if the “no stats” issue occurs.
Additionally, there is a fixed issue with the command strings for Copy public SSH Key and Verify Public SSH Key within the “Verify Tasks” menu. The issue is that the displayed command incorrectly added the keygen command in front of the actual command.
For additional information regarding RsyncUI’s Swift Packages, kindly refer to the accompanying document.
Rsync Verify
In the coming days, I will release a release candidate for the new application, RsyncVerify. This application replaces the functionality that was removed from RsyncUI. You can read about the application in the blog post titled “Verify remote.” The application includes parsing and tagging of each line of output. It is important to note that RsyncVerify is not a replacement for RsyncUI. The motivation for developing RsyncVerify is outlined in the blog post.
Version 2.8.6
Version 2.8.6 - Jan 9, 2026
This release is a maintenance update. The previous release candidate has been upgraded to the new release.
There are a few UI updates.
The Verify remote functionality has been removed and will be integrated into its own standalone application. This change will enhance RsyncUI’s focus on its core functionality: data synchronization.
For further details, please refer to the following documents:
- a detailed Changelog
- a Code Quality Report
The “missing stats alert” continues to occasionally appear. The data synchronization is complete, but RsyncUI is reporting missing summary data. The package responsible for controlling the rsync process has been updated in development to resolve this issue. While I am aware of the cause, finding a solution that does not require setting a dedicated wait time appears to be challenging. However, I am actively working on this matter. The solution is scheduled to be released in the next version, 2.8.7, which is expected in late January 2026.
Additionally (in development), I have incorporated debug data writing within the package that processes the output from rsync. Whenever the “no stats” error is encountered, the package writes the complete output to storage for further investigation.
The package for the process object has been updated to ensure that all data is drained before the object is released. I am currently using it and it appears to be promising. A release candidate will be available in a few days. For more information about the package, please refer to the provided link.
The debug data when error
Upon incorporating debug data into the package responsible for processing the output generated by rsync, I successfully obtained the initial debug message in the test environment. Please refer to the following information, which elucidates the cause of the error encountered by RsyncUI and the expected output.
An error was encountered with this output. The output is missing after the line File list size:. The complete and expected output is provided below, there are six lines missing. Therefore, my assumptions are correct. Now, I need to determine how to delay the termination until all data has been read.
rsyncuidocs/.git/objects/e5/5d0b0156cfe35b9a3759bc708f46ca6383a08a
rsyncuidocs/.git/objects/e5/f2358069749eab3508ca3b65c05d434d147a88
deleting rsyncuidocs/content/en/blog/Version284.md
rsyncuidocs/.git/objects/f9/649c9b801b80bdb6f1c544b52bfc7ca90773c7
rsyncuidocs/.git/objects/fa/6ecc4f9f3638a30bb2b56a31b01fc31cc244f6
rsyncuidocs/.git/refs/heads/main
rsyncuidocs/.git/refs/remotes/origin/HEAD
rsyncuidocs/.git/refs/remotes/origin/main
rsyncuidocs/content/en/blog/Verifyremote.md
rsyncuidocs/content/en/blog/Version286.md
rsyncuidocs/content/en/docs/advanced/Verify.md
Number of files: 34,463 (reg: 28,218, dir: 6,201, link: 44)
Number of created files: 285 (reg: 262, dir: 23)
Number of deleted files: 26 (reg: 24, dir: 2)
Number of regular files transferred: 375
Total file size: 2,578,503,779 bytes
Total transferred file size: 4,537,894 bytes
Literal data: 4,537,894 bytes
Matched data: 0 bytes
File list size: 280,193
This is what the trailing output should be:
Number of files: 34,463 (reg: 28,218, dir: 6,201, link: 44)
Number of created files: 0
Number of deleted files: 0
Number of regular files transferred: 1
Total file size: 2,578,505,001 bytes
Total transferred file size: 3,957 bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 24,576 <-- "This is were the above trailing ouput is cut off and causing an error"
File list generation time: 0.002 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 1,261,175
Total bytes received: 6,764
sent 1,261,175 bytes received 6,764 bytes 845,292.67 bytes/sec
total size is 2,578,505,001 speedup is 2,033.62 (DRY RUN)
Empty stats file (no stats)
The process termination signal indicates that the external rsync process has completed and terminated. All tasks within the main synchronize view are updated with the latest run, but there is also separate logging that records the main result of each task with a timestamp.
Occasionally, when synchronizing a small amount of data, the termination signal is detected before all output from rsync has been read. In such cases, the separate logging may be incomplete. The process termination signal serves as a trigger to perform logging, but if the last summarized rsync output is missing, there is nothing to log.
Output from rsync refers to the information that rsync provides to the terminal during the execution of a task.
If RsyncUI detects an empty statistics file, it will append a default log record stating 0 files : 0.00 MB in 0.00 seconds.
If logging fails due to the aforementioned reason, this error will be generated, if enabled.

Technical Deep Dives
Technical articles about RsyncUI’s implementation, architecture, and advanced concepts.
Compiling RsyncUI
Overview
There are at least three methods to compile RsyncUI, one without an Apple Developer account and two with an Apple Developer account. Regardless of the method used, it is straightforward to compile RsyncUI, as it is not dependent on any third-party code or library.
The easist method is by using the included Makefile. The default make in /usr/bin/make does the job.
Compile by make
If you have an Apple Developer account, you should open the RsyncUI project and replace the Signing & Capabilities section with your own Apple Developer ID before using make and the procedure outlined below.
The use of the make command necessitates the application-specific password. There are two commands available for use with make: one creates a release build exclusively for RsyncUI, while the other generates a signed version that includes a DMG file.
If only utilizing the make archive command did not necessitate the application-specific password, it would suffice to update only the Signing & Capabilities section. It is highly probable that the make archive command will still function even if set to Sign to Run Locally.
To create a DMG file, the make command is dependent on the create-dmg tool. The instructions for create-dmg are included in the Makefile. Ensure that the fork of create-dmg is on the same level as the fork of RsyncUI. Before using make, create and store an app-specific password.
The following procedure creates and stores an app-specific password:
- Visit appleid.apple.com and log in with your Apple ID.
- Navigate to the Sign-In and Security section and select App-Specific Passwords → Generate an App-Specific Password.
- Provide a label to help identify the purpose of the password (e.g., notarytool).
- Click Create. The password will be displayed once; copy it and store it securely.
After creating the app-specific password, execute the following command and follow the prompts:
xcrun notarytool store-credentials --apple-id "youremail@gmail.com" --team-id "A1B2C3D4E5"
- Replace
youremail@gmail.comandA1B2C3D4E5with your actual credentials.
Name the app-specific password RsyncUI (in appleid.apple.com) and set Profile name: RsyncUI when executing the above command.
The following dialog will appear:
This process stores your credentials securely in the Keychain. You reference these credentials later using a profile name.
Profile name:
RsyncUI
App-specific password for youremail@gmail.com:
Validating your credentials...
Success. Credentials validated.
Credentials saved to Keychain.
To use them, specify `--keychain-profile "RsyncUI"`
Following the above steps, the following make commands are available from the root of RsyncUI’s source catalog:
make- will generate a signed and notified DMG file including the release version of RsyncUI.make archive- will produce a release version, removing all debug information, without signing within thebuildcatalog.make clean- will delete all build data.
Compile by Xcode
If you have an Apple Developer account, use your Apple Developer ID in Xcode.
Apple Developer account
Open the RsyncUI project by Xcode. Choose the top level of the project, and select the tab Signing & Capabilities. Replace Team with your team.
No Apple Developer account
As above, but choose in Signing Certificate to Sign to Run Locally.
To compile or run
Use Xcode for run, debug or build. You choose.
Number of files
Numbers updated: January 15, 2026 (version 2.9.0).
RsyncUI depends only on the standard Swift and SwiftUI toolchain—no external libraries.
cloc DecodeEncodeGeneric/Sources ParseRsyncOutput/Sources RsyncArguments/Sources RsyncUI/RsyncUI RsyncUIDeepLinks/Sources SSHCreateKey/Sources RsyncProcessStreaming/Sources ProcessCommand/Sources RsyncAnalyse/Sources
210 text files.
209 unique files.
12 files ignored.
github.com/AlDanial/cloc v 2.06 T=0.07 s (3067.2 files/s, 358028.7 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
Swift 203 2824 2713 18434
C 2 36 72 254
XML 2 0 0 53
JSON 1 0 0 6
C/C++ Header 1 1 3 0
-------------------------------------------------------------------------------
SUM: 209 2861 2788 18747
-------------------------------------------------------------------------------
Main Repository
- RsyncUI (https://github.com/rsyncOSX/RsyncUI) - the main repository for RsyncUI
Swift Packages used by RsyncUI
All packages track the main branch and are updated to latest revisions as of v2.9.0:
SSHCreateKey - SSH key generation and management
- Repository: https://github.com/rsyncOSX/SSHCreateKey
- Purpose: Public/private SSH key pair creation
DecodeEncodeGeneric - Generic JSON codec
- Repository: https://github.com/rsyncOSX/DecodeEncodeGeneric
- Purpose: Reusable JSON encoding/decoding utilities
ParseRsyncOutput - Rsync output parser
- Repository: https://github.com/rsyncOSX/ParseRsyncOutput
- Purpose: Extract statistics from rsync output
RsyncUIDeepLinks - Deep linking support
- Repository: https://github.com/rsyncOSX/RsyncUIDeepLinks
- Purpose: URL scheme handling for widgets and automation
ProcessCommand - Process execution wrapper
- Repository: https://github.com/rsyncOSX/ProcessCommand
- Purpose: Command-line process management
RsyncArguments - Rsync argument builder
- Repository: https://github.com/rsyncOSX/RsyncArguments
- Purpose: Type-safe rsync command generation
RsyncProcessStreaming - Streaming process handler
- Repository: https://github.com/rsyncOSX/RsyncProcessStreaming
- Purpose: Real-time rsync output streaming and progress tracking
RsyncAnalyse - Enhanced rsync output analysis
- Repository: https://github.com/rsyncOSX/RsyncAnalyse
- Purpose: Advanced parsing and analysis of rsync command output
Verify remote
Overview
This function has been removed from RsyncUI version 2.8.6 (January 8, 2026).
Currently, the function is being developed as a standalone application. Its continued use is essential, and it is preferable to use it independently rather than as a component of RsyncUI.
Utilizing the rsync parameter --itemize-changes will result in increased output from rsync. This parameter instructs rsync to generate a summary of changes for each file or directory it processes.
Synchronization of Multiple Macs to a Remote Server
I have over 3,000 bird photos (130 GB) from the past four years that are synchronized using RsyncUI to a local remote server at home. New photos are added, old photos are deleted, and updates are made to photo sidecars. As long as I was using only one Mac, all updates were made on that Mac. However, with two Macs, I now use both to work on my photos. When I synchronize my changes, I need to transfer those changes to my second Mac.
My Setup for securing bird photos
I back up my bird photography to multiple locations:
- a Raspberry Pi 5 server configured with two WD Red SA500 2.5" SSD 1TB drives set up as a mirrored ZFS pool
- a remote cloud service (JottaCloud)
- two 1TB NVMe external SSD drives attached to my computers
Typically, a synchronization action operates in a one-way direction. Local data is synchronized to backup media, such as an attached disk or a remote server. Restoring data, for instance, involves retrieving data from a backup when local data has become corrupted or inaccessible.
If you are using multiple Macs, as I do, and all Macs synchronize data to the same remote storage, there may be challenges maintaining synchronization
and preventing data loss, particularly if the remote storage is not a Git server, such as GitHub and Gitea. If the remote destinations are stored on a Git server, regular git push and git pull commands will suffice.
Git is a superior tool for version control. However, in certain situations, creating a Git repository may not be feasible, and this function may prove useful. As a reminder, the Verify function is designed for multiple Macs synchronizing data to a single remote server as a backup. It also assists in deciding whether to push or pull changes to keep the local repository updated.
The user is solely responsible for determining the appropriate action. RsyncUI provides only advisory guidance, based on a rudimentary evaluation of a push and pull data comparison. Additionally, the function requires version 3.x of rsync to be installed and enabled.
The Verify process necessitates that one of the Macs be synchronized with the remote. If both Macs have local unique updates, the outcome of the Verify is most likely inaccurate, potentially resulting in data loss.
The function is not intended to be automated. Users must verify their subsequent actions.
Arguments for rsync
The following arguments are used in both push and pull.
--itemize-changes- output change-summary for all updates--dry-run- rsync execute an estimate run--update- evaluates the timestamp
Itemized output - push or pull
The parameter -i or --itemize-changes produces details about each file. The format of the output is:
YXcstpoguax
|||||||||||
`-------------------------- the TYPE OF UPDATE:
|||||||||| <: file is being transferred to the remote host (pushed).
|||||||||| >: file is being transferred to the local host (pulled).
|||||||||| c: local change/creation for the item, such as:
|||||||||| - the creation of a directory
|||||||||| - the changing of a symlink,
|||||||||| - etc.
|||||||||| h: the item is a hard link to another item (requires --hard-links).
|||||||||| "+" - the file is newly created
|||||||||| .: the item is not being updated (though it might have attributes that are being modified).
|||||||||| *: means that the rest of the itemized-output area contains a message (e.g. "deleting").
||||||||||
`----------------------------- the FILE TYPE:
||||||||| f for a file,
||||||||| d for a directory,
||||||||| L for a symlink,
||||||||| D for a device,
||||||||| S for a special file (e.g. named sockets and fifos).
|||||||||
`--------- c: different checksum (for regular files)
|||||||| CHANGED VALUE (for symlink, device, and special file)
`-------- s: Size is different
`------- t: Modification time is different
`------ p: Permission are different
`----- o: Owner is different
`---- g: Group is different
`--- u: The u slot is reserved for future use.
`-- a: The ACL information changed
Position Letter Meaning
-------- ------ ----------------------------------
1 Y Update type (<, >, c, h, ., *)
2 X File type (f, d, L, D, S)
3 c Checksum/content
4 s Size
5 t Time (modification)
6 p Permissions
7 o Owner
8 g Group
9 u Reserved/user time
10 a ACL
11 x Extended attributes
Special: '.' = unchanged, '+' = new item
The Stand alone application
Utilize RsyncUI to create tasks. The application necessitates RsyncUI for task creation and the activation of version 3.x of rsync. Furthermore, it is imperative that you thoroughly review the introductory section of this blog post, which elucidates the application’s usage. I exclusively employ this application for synchronizing my bird photographs.
This application is currently in development. The majority of the code is derived from the code base of RsyncUI, and there are some new code modules associated with the Verify Remote function. Additionally, some new views have been added for evaluation purposes.



Overview
The --itemize-changes (or -i) option in rsync provides a detailed, itemized list of changes being made to each file during synchronization. The output format is an 11-character string followed by the file path.
Position 1: Update Type (Y)
The first character indicates the type of update operation.
| Character | Meaning | Description |
|---|---|---|
< | Sent | File is being transferred to the remote host (sent) |
> | Received | File is being transferred to the local host (received) |
c | Local change | Local change/creation occurring (e.g., creating a directory, changing a symlink) |
h | Hard link | Item is a hard link to another item (requires --hard-links option) |
. | Not updated | Item is not being updated (though attributes may be modified) |
* | Message | Rest of line contains a message (e.g., “deleting”) |
Position 2: File Type (X)
The second character indicates what type of filesystem object is being updated.
| Character | Type | Description |
|---|---|---|
f | File | Regular file |
d | Directory | Directory |
L | Symlink | Symbolic link |
D | Device | Device file |
S | Special | Special file (e.g., named sockets, fifos) |
Position 3: Checksum/Content (c)
| Character | Meaning | Context |
|---|---|---|
c | Changed | Checksum differs (regular files) OR changed value (symlinks, devices, special files) |
+ | New | New item being created |
. | Unchanged | No change to content/checksum |
(space) | Same | Content is the same |
Position 4: Size (s)
| Character | Meaning |
|---|---|
s | Size differs from source |
+ | New item |
. | Size unchanged |
Position 5: Modification Time (t)
| Character | Meaning |
|---|---|
t | Modification time is different (lowercase) |
T | Modification time is different (uppercase variant) |
+ | New item |
. | Time unchanged |
Position 6: Permissions (p)
| Character | Meaning |
|---|---|
p | Permissions are different |
+ | New item |
. | Permissions unchanged |
Position 7: Owner (o)
| Character | Meaning |
|---|---|
o | Owner is different |
+ | New item |
. | Owner unchanged |
Position 8: Group (g)
| Character | Meaning |
|---|---|
g | Group is different |
+ | New item |
. | Group unchanged |
Position 9: User/Reserved (u)
| Character | Meaning |
|---|---|
u | Reserved for future use (may indicate access time or creation time in some rsync versions) |
+ | New item |
. | Unchanged |
Note: This position is reserved and its behavior may vary between rsync versions.
Position 10: ACL (a)
| Character | Meaning |
|---|---|
a | ACL (Access Control List) information changed |
+ | New item with ACL |
. | ACL unchanged |
Note: Requires ACL support to be compiled into rsync.
Position 11: Extended Attributes (x)
| Character | Meaning |
|---|---|
x | Extended attribute (xattr) information changed |
+ | New item with extended attributes |
. | Extended attributes unchanged |
Note: Requires extended attribute support to be compiled into rsync.
Common Examples
New Files
>f+++++++++ documents/report.pdf
>= Receiving from remotef= Regular file+++++++++= All attributes are new (new file)
Updated File
>f. st.. .... images/photo.jpg
>= Receiving from remotef= Regular files= Size changedt= Modification time changed- Other attributes unchanged
Directory Timestamp Change
.d..t...... src/components/
.= Not being transferred (no update)d= Directoryt= Modification time changed- Other attributes unchanged
Permission Change
.f... p. .... scripts/deploy.sh
.= Not being transferredf= Regular filep= Permissions changed (e.g., made executable)- Other attributes unchanged
New Directory
cd+++++++++ backup/2024/
c= Local creationd= Directory+++++++++= All attributes are new
Symlink Changes
cLc.t...... config/current -> v2.0
c= Local changeL= Symlinkc= Target/value changed (position 3)t= Modification time changed- Other attributes unchanged
Hard Link
hf...... .... docs/readme.txt => docs/README.txt
h= Hard linkf= File- Other positions indicate which attributes differ between the link and its target
Deletion
*deleting old/obsolete.txt
*= Special message- Message indicates file is being deleted
File Being Sent
<f. st...... data/export.csv
<= Sending to remotef= Regular files= Size differst= Time differs
Complex Example: Multiple Changes
>f.stpog... /var/www/index.html
>= Receiving filef= Regular files= Size changedt= Modification time changedp= Permissions changedo= Owner changedg= Group changed
Version Differences
rsync 3.0.9+ (Modern)
- Uses 11 characters:
YXcstpoguax - Includes ACL (
a) and extended attributes (x)
rsync 2.6.8 and earlier (Legacy)
- Uses 9 characters:
YXcstpogz - No ACL or extended attribute indicators
- Position 9 was
z(related to compression)
Swift concurrency
My understanding of Swift concurrency is modest. If you want deeper coverage, I recommend exploring articles from authors who specialize in this topic.
RsyncUI is a GUI app; most work happens on the main thread. Heavier tasks run on threads from the cooperative thread pool (CTP) without blocking the UI. The Swift runtime manages the executors and CTP. There are three kinds of executors:
- the main executor manages jobs on the main thread
- the global concurrent executor and the serial executor execute jobs on threads from the CTP
Most work in RsyncUI runs on the main thread. SwiftUI keeps UI updates there by default. Examples include:
- preparing and executing
rsyncsynchronization tasks (including building arguments) - monitoring progress and termination of
rsynctasks- the collection of output from rsync is performed by an actor, while the actual reporting of the number of files transferred is executed on a main thread for UI updates
- some write and read operations
Swift Version 6 and the New Concurrency Model
Swift version 6 introduced strict concurrency checking. By enabling Swift 6 language mode and strict concurrency checking, Xcode helps identify and resolve possible data races at compile time.
Several compiler directives in Xcode influence concurrency. Review them before migrating an existing project. I recommend the Swift concurrency posts by Matt Massicotte and Antoine van der Lee.
Quote from swift.org: “More formally, a data race occurs when one thread accesses memory while the same memory is being modified by another thread. The Swift 6 language mode eliminates these issues by preventing data races at compile time.”
RsyncUI adheres to the Swift 6 concurrency model.
Swift Concurrency and Asynchronous Execution
Swift makes asynchronous code more approachable through async, await, and actor. RsyncUI adopts these features even though most work can remain on the main thread—as long as it does not block the UI.
Asynchronous work can happen on the main thread or on background threads from the CTP. On the main thread, structured concurrency with async/await is key; every await yields control so other tasks can proceed.
Cooperative Thread Pool (CTP)
These RsyncUI tasks run asynchronously on CTP threads under the actor protocol:
- read synchronization tasks from file
- JSON data decoding: asynchronous decoding that inherits the actor’s thread
- JSON data encoding: synchronous encoding on the main thread
- read and sort log records
- delete log records
- prepare output from rsync for display
- prepare data from the log file for display
- check for updates to RsyncUI
Adhering to the actor protocol, all access to actor properties must be asynchronous. RsyncUI has five actors, plus additional async functions; some also run on the main thread.
Structured Concurrency
Some functions use async let for structured concurrency. Multiple async let bindings run concurrently, and execution resumes once they all complete.
Structured concurrency also shapes ordering. Each await suspends until that async work finishes; sequential awaits run one after another.
Example of structured concurrency
About 800 of 1500 log records are selected for deletion. Two operations run concurrently on a background thread: deleting selected logs and updating the remaining records for display.
Deletion starts on the main thread. The user selects logs and taps Delete to begin or cancel. The asynchronous deletelogs() function is launched on the main thread.
Button("Delete", role: .destructive) {
Task {
await deletelogs(selectedloguuids)
}
}
deletelogs starts on the main thread and continues on a background thread inside Task {}.
func deletelogs(_ uuids: Set<UUID>) async {
Task {
print("(1) start async let updatedRecords deletelogs")
async let updatedRecords: [LogRecords]? = ActorReadLogRecordsJSON().deletelogs(
uuids,
logrecords: logrecords,
profile: rsyncUIdata.profile,
validhiddenIDs: validhiddenIDs
)
let records = await updatedRecords
print("(2) awaited updatedRecords deletelogs from (1))")
print("(3) start async let updatedRecords updatelogsbyhiddenID)")
async let updatedLogs: [Log]? = ActorReadLogRecordsJSON().updatelogsbyhiddenID(records, hiddenID)
logrecords = records
logs = await (updatedLogs ?? [])
print("(4) awaited updatedLogs from (3)")
WriteLogRecordsJSON(rsyncUIdata.profile, records)
selectedloguuids.removeAll()
}
}
The debug windows in Xcode display the following:
The actors also print whether they execute on the main thread. The first async let statement initiates execution, and the subsequent await statement for the result above (2) suspends the function’s execution until the asynchronous result is computed. The await statement is crucial for suspending the execution of the function until the asynchronous result is available. And then the next (3) and (4).
(1) start async let updatedRecords deletelogs
ActorReadLogRecordsJSON: deletelogs() NOT on main thread, currently on <NSThread: 0xa49e3c200>{number = 18}
ActorReadLogRecordsJSON: DEINIT
(2) awaited updatedRecords deletelogs from (1))
(3) start async let updatedRecords updatelogsbyhiddenID)
ActorReadLogRecordsJSON: updatelogsbyhiddenID() NOT on main thread, currently on <NSThread: 0xa49e3c280>{number = 17}
ActorReadLogRecordsJSON: DEINIT
(4) awaited updatedLogs from (3)
WriteLogRecordsJSON: writeJSONToPersistentStore file:///Users/thomas/.rsyncosx/VPxxxxxxxx/WDBackup/logrecords.json
WriteLogRecordsJSON DEINIT
ActorReadLogRecordsJSON: updatelogsbyhiddenID() NOT on main thread, currently on <NSThread: 0xa4bb72800>{number = 19}
ActorReadLogRecordsJSON: DEINIT
Tagging of data
Overview
RsyncUI must tag data accurately; otherwise some source data might not synchronize. RsyncUI supports both the latest rsync release and the legacy macOS default version.
Tagging is computed in the ParseRsyncOutput Swift package bundled with RsyncUI.
Example:
- Input string:
Number of created files: 7,191 (reg: 6,846, dir: 345) - Converted to:
[7191, 6846, 345](the thousands separator is also removed from the string before parsing)
The function below extracts only numbers from the input:
public func returnIntNumber(_ input: String) -> [Int] {
var numbers: [Int] = []
let str = input.replacingOccurrences(of: ",", with: "")
let stringArray = str.components(separatedBy: CharacterSet.decimalDigits.inverted)
.compactMap { $0.isEmpty == true ? nil : $0 }
for item in stringArray where item.isEmpty == false {
if let number = Int(item) {
numbers.append(number)
}
}
if numbers.count == 0 {
return [0]
} else {
return numbers
}
}
Parsing the rsync output is straightforward, but the formats differ between the latest rsync release and the default macOS version.
Version 3.4.x
The trailing output from the latest version of rsync (version 3.4.1) looks like:
....
Number of files: 7,192 (reg: 6,846, dir: 346)
Number of created files: 7,191 (reg: 6,846, dir: 345)
Number of deleted files: 0
Number of regular files transferred: 6,846
Total file size: 24,788,299 bytes
Total transferred file size: 24,788,299 bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 0
File list generation time: 0.003 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 394,304
Total bytes received: 22,226
sent 394,304 bytes received 22,226 bytes 833,060.00 bytes/sec
total size is 24,788,299 speedup is 59.51 (DRY RUN)
Openrsync
The trailing output from the default version of rsync looks like:
....
Number of files: 7192
Number of files transferred: 6846
Total file size: 24788299 bytes
Total transferred file size: 24788299 bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 336861
File list generation time: 0.052 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 380178
Total bytes received: 43172
sent 380178 bytes received 43172 bytes 169340.00 bytes/sec
total size is 24788299 speedup is 58.55
How the Tagging Works
The output from rsync is parsed and numbers are extracted. After parsing, these numbers determine whether data should be tagged for synchronization.
Latest Version of rsync
Three numbers decide whether data needs synchronization: updates (regular files transferred), new files, and deleted files. Each can be zero or positive, and all three are checked.
Default Versions
Only one number decides: the updates (files transferred).