-
-@class UDiffScriptBuilder;
-@class UDiffChange;
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface UDiffFileData : NSObject {
- /** Vector, indexed by line number, containing an equivalence code for
- each line. It is this vector that is actually compared with that
- of another file to generate differences. */
- int* equivs;
-
- int* pequiv_max;
- BOOL* pno_discards;
-}
-
-/** Number of elements (lines) in this file. */
-@property (assign) NSUInteger buffered_lines;
-/** Array, indexed by real origin-1 line number, containing true for a line that is an insertion or a deletion. */
-@property (assign, nullable) BOOL* changed_flag;
-/** Vector, like the previous one except that the elements for discarded lines have been squeezed out. */
-@property (assign) int* undiscarded;
-/** Vector mapping virtual line numbers (not counting discarded lines) to real ones (counting those lines). Both are origin-0. */
-@property (assign) int* realindexes;
-/** Total number of nondiscarded lines. */
-@property (assign) int nondiscarded_lines;
-
-+ (instancetype)fileData:(NSArray*)data h:(NSMutableDictionary*)h equivMax:(int*)ppequiv_max noDiscards:(BOOL*)ppnoDiscards
- stringifier:(NSString* (^)(id obj))block;
-- (instancetype)initWithData:(NSArray*)data h:(NSMutableDictionary*)h equivMax:(int*)ppequiv_max noDiscards:(BOOL*)ppnoDiscards
- stringifier:(NSString* (^)(id obj))block;
-
-@end
-
-@interface UnifiedDiff : NSObject {
-@private
- /** 1 more than the maximum equivalence value used for this or its
- sibling file. */
- int equiv_max;
-
- /** When set to true, the comparison uses a heuristic to speed it up.
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
- BOOL heuristic;
-
- /** When set to true, the algorithm returns a guarranteed minimal
- set of changes. This makes things slower, sometimes much slower. */
- BOOL no_discards;
-
- int* xvec, *yvec; /* Vectors being compared. */
- int* fdiag; /* Vector, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the forward
- search of the edit matrix. */
- int* bdiag; /* Vector, indexed by diagonal, containing
- the X coordinate of the point furthest
- along the given diagonal in the backward
- search of the edit matrix. */
- int fdiagoff, bdiagoff;
- int cost;
-
- BOOL inhibit;
-}
-
-- (instancetype)initWithOriginalLines:(NSArray*)a revisedLines:(NSArray*)b stringifier:(NSString* (^)(id obj))block;
-- (nullable UDiffChange*)diff_2:(BOOL)reverse;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Sources/Legacy/DiffEngine/UnifiedDiff.m b/Sources/Legacy/DiffEngine/UnifiedDiff.m
deleted file mode 100644
index 38ba620..0000000
--- a/Sources/Legacy/DiffEngine/UnifiedDiff.m
+++ /dev/null
@@ -1,739 +0,0 @@
-//
-// UnifiedDiff.m
-// VisualDiffer
-//
-// Created by davide ficano on 23/05/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-#import "UnifiedDiff.h"
-#import "UDiffScriptBuilder.h"
-
-/** Snakes bigger than this are considered "big". */
-static const NSInteger SNAKE_LIMIT = 20;
-
-static UDiffScriptBuilder* forwardScript;
-static UDiffScriptBuilder* reverseScript;
-
-@interface UDiffFileData()
-- (char*)discardable:(int*)counts NS_RETURNS_INNER_POINTER;
-- (void)filterDiscards:(char*)discards;
-- (void)discard:(char*)discards;
-@end
-
-@interface UnifiedDiff()
-- (UDiffChange*)diff:(UDiffScriptBuilder*)bld;
-@end
-
-@implementation UDiffFileData
-
-+ (instancetype)fileData:(NSArray*)data h:(NSMutableDictionary*)h equivMax:(int*)ppequiv_max noDiscards:(BOOL*)ppno_discards
- stringifier:(NSString* (^)(id obj))block {
- return [[self alloc] initWithData:data h:h equivMax:ppequiv_max noDiscards:ppno_discards stringifier:block];
-}
-
-- (instancetype)initWithData:(NSArray*)data h:(NSMutableDictionary*)h equivMax:(int*)ppequiv_max noDiscards:(BOOL*)ppno_discards
- stringifier:(NSString* (^)(id obj))block {
- self = [super init];
-
- if (self) {
- pequiv_max = ppequiv_max;
- pno_discards = ppno_discards;
- _buffered_lines = data.count;
-
- equivs = calloc(_buffered_lines, sizeof(int));
- _undiscarded = calloc(_buffered_lines, sizeof(int));
- _realindexes = calloc(_buffered_lines, sizeof(int));
- _changed_flag = NULL;
-
- int i = 0;
- for (id o in data) {
- NSString* str = block(o);
- NSNumber* ir = h[str];
- if (ir == nil) {
- h[str] = @(equivs[i] = *pequiv_max);
- (*pequiv_max)++;
- } else {
- equivs[i] = [ir intValue];
- }
- ++i;
- }
- }
-
- return self;
-}
-
-- (void)dealloc {
- free(equivs);
- free(_undiscarded);
- free(_realindexes);
- free(_changed_flag);
-
-}
-
-/** Allocate changed array for the results of comparison. */
-- (void)clear {
- /* Allocate a flag for each line of each file, saying whether that line
- is an insertion or deletion.
- Allocate an extra element, always zero, at each end of each vector.
- */
- _changed_flag = calloc(_buffered_lines + 2, sizeof(BOOL));
-}
-
-/** Return equiv_count[I] as the number of lines in this file
- that fall in equivalence class I.
- @return the array of equivalence class counts.
- */
-- (int*)equivCount {
- int equiv_max = *pequiv_max;
- int* equiv_count = calloc(equiv_max, sizeof(int));
- for (int i = 0; i < (NSInteger)_buffered_lines; ++i)
- ++equiv_count[equivs[i]];
- return equiv_count;
-}
-
-/** Discard lines that have no matches in another file.
-
- A line which is discarded will not be considered by the actual
- comparison algorithm; it will be as if that line were not in the file.
- The file's `realindexes' table maps virtual line numbers
- (which don't count the discarded lines) into real line numbers;
- this is how the actual comparison algorithm produces results
- that are comprehensible when the discarded lines are counted.
-
- When we discard a line, we also mark it as a deletion or insertion
- so that it will be printed in the output.
- @param f the other file
- */
-- (void)discard_confusing_lines:(UDiffFileData*)f {
- [self clear];
- /* Set up table of which lines are going to be discarded. */
- int* tempEquivCount = [f equivCount];
- char* discarded = [self discardable:tempEquivCount];
-
- /* Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
- [self filterDiscards:discarded];
-
- /* Actually discard the lines. */
- [self discard:discarded];
-
- free(discarded);
- free(tempEquivCount);
-}
-
-/** Mark to be discarded each line that matches no line of another file.
- If a line matches many lines, mark it as provisionally discardable.
- @see equivCount()
- @param counts The count of each equivalence number for the other file.
- @return 0=nondiscardable, 1=discardable or 2=provisionally discardable
- for each line
- */
-
-- (char*)discardable:(int*)counts {
- NSInteger end = (NSInteger)_buffered_lines;
- char* discards = calloc(end, sizeof(char));
- int many = 5;
- NSUInteger tem = end / 64;
-
- /* Multiply MANY by approximate square root of number of lines.
- That is the threshold for provisionally discardable lines. */
- while ((tem = tem >> 2) > 0)
- many *= 2;
-
- for (int i = 0; i < end; i++)
- {
- int nmatch;
- if (equivs[i] == 0)
- continue;
- nmatch = counts[equivs[i]];
- if (nmatch == 0)
- discards[i] = 1;
- else if (nmatch > many)
- discards[i] = 2;
- }
- return discards;
-}
-
-/** Don't really discard the provisional lines except when they occur
- in a run of discardables, with nonprovisionals at the beginning
- and end. */
-
-- (void)filterDiscards:(char*)discards {
- NSInteger end = (NSInteger)_buffered_lines;
-
- for (int i = 0; i < end; i++)
- {
- /* Cancel provisional discards not in middle of run of discards. */
- if (discards[i] == 2)
- discards[i] = 0;
- else if (discards[i] != 0)
- {
- /* We have found a nonprovisional discard. */
- int j;
- int length;
- int provisional = 0;
-
- /* Find end of this run of discardable lines.
- Count how many are provisionally discardable. */
- for (j = i; j < end; j++)
- {
- if (discards[j] == 0)
- break;
- if (discards[j] == 2)
- ++provisional;
- }
-
- /* Cancel provisional discards at end, and shrink the run. */
- while (j > i && discards[j - 1] == 2) {
- discards[--j] = 0; --provisional;
- }
-
- /* Now we have the length of a run of discardable lines
- whose first and last are not provisional. */
- length = j - i;
-
- /* If 1/4 of the lines in the run are provisional,
- cancel discarding of all provisional lines in the run. */
- if (provisional * 4 > length)
- {
- while (j > i)
- if (discards[--j] == 2)
- discards[j] = 0;
- }
- else
- {
- int consec;
- int minimum = 1;
- int tem = length / 4;
-
- /* MINIMUM is approximate square root of LENGTH/4.
- A subrun of two or more provisionals can stand
- when LENGTH is at least 16.
- A subrun of 4 or more can stand when LENGTH >= 64. */
- while ((tem = tem >> 2) > 0)
- minimum *= 2;
- minimum++;
-
- /* Cancel any subrun of MINIMUM or more provisionals
- within the larger run. */
- for (j = 0, consec = 0; j < length; j++)
- if (discards[i + j] != 2)
- consec = 0;
- else if (minimum == ++consec)
- /* Back up to start of subrun, to cancel it all. */
- j -= consec;
- else if (minimum < consec)
- discards[i + j] = 0;
-
- /* Scan from beginning of run
- until we find 3 or more nonprovisionals in a row
- or until the first nonprovisional at least 8 lines in.
- Until that point, cancel any provisionals. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i + j] == 1)
- break;
- if (discards[i + j] == 2) {
- consec = 0; discards[i + j] = 0;
- }
- else if (discards[i + j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
-
- /* I advances to the last line of the run. */
- i += length - 1;
-
- /* Same thing, from end. */
- for (j = 0, consec = 0; j < length; j++)
- {
- if (j >= 8 && discards[i - j] == 1)
- break;
- if (discards[i - j] == 2) {
- consec = 0; discards[i - j] = 0;
- }
- else if (discards[i - j] == 0)
- consec = 0;
- else
- consec++;
- if (consec == 3)
- break;
- }
- }
- }
- }
-}
-
-/** Actually discard the lines.
- @param discards flags lines to be discarded
- */
-- (void)discard:(char*)discards {
- NSInteger end = (NSInteger)_buffered_lines;
- int j = 0;
- for (int i = 0; i < end; ++i)
- if (*pno_discards || discards[i] == 0)
- {
- _undiscarded[j] = equivs[i];
- _realindexes[j++] = i;
- }
- else
- _changed_flag[1+i] = true;
- _nondiscarded_lines = j;
-}
-
-/** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
-
- We do something when a run of changed lines include a blank
- line at one end and have an excluded blank line at the other.
- We are free to choose which blank line is included.
- `compareseq' always chooses the one at the beginning,
- but usually it is cleaner to consider the following blank line
- to be the "change". The only exception is if the preceding blank line
- would join this change to other changes.
- @param f the file being compared against
- */
-
-- (void)shift_boundaries:(UDiffFileData*)f {
- BOOL* changed = _changed_flag;
- BOOL* other_changed = f.changed_flag;
- int i = 0;
- int j = 0;
- NSInteger i_end = (NSInteger)_buffered_lines;
- int preceding = -1;
- int other_preceding = -1;
-
- for (;;)
- {
- int start, end, other_start;
-
- /* Scan forwards to find beginning of another run of changes.
- Also keep track of the corresponding point in the other file. */
-
- while (i < i_end && !changed[1+i])
- {
- while (other_changed[1+j++])
- /* Non-corresponding lines in the other file
- will count as the preceding batch of changes. */
- other_preceding = j;
- i++;
- }
-
- if (i == i_end)
- break;
-
- start = i;
- other_start = j;
-
- for (;;)
- {
- /* Now find the end of this run of changes. */
-
- while (i < i_end && changed[1+i]) i++;
- end = i;
-
- /* If the first changed line matches the following unchanged one,
- and this run does not follow right after a previous run,
- and there are no lines deleted from the other file here,
- then classify the first changed line as unchanged
- and the following line as changed in its place. */
-
- /* You might ask, how could this run follow right after another?
- Only because the previous run was shifted here. */
-
- if (end != i_end
- && equivs[start] == equivs[end]
- && !other_changed[1+j]
- && end != i_end
- && !((preceding >= 0 && start == preceding)
- || (other_preceding >= 0
- && other_start == other_preceding)))
- {
- changed[1+end++] = true;
- changed[1+start++] = false;
- ++i;
- /* Since one line-that-matches is now before this run
- instead of after, we must advance in the other file
- to keep in synch. */
- ++j;
- }
- else
- break;
- }
-
- preceding = i;
- other_preceding = j;
- }
-}
-@end
-
-#pragma mark -
-#pragma mark UnifiedDiff methods
-
-@interface UnifiedDiff()
-@property (strong) UDiffFileData* filevec0;
-@property (strong) UDiffFileData* filevec1;
-@end
-
-@implementation UnifiedDiff
-
-/** Prepare to find differences between two arrays. Each element of
- the arrays is translated to an "equivalence number" based on
- the result of equals. The original Object arrays
- are no longer needed for computing the differences. They will
- be needed again later to print the results of the comparison as
- an edit script, if desired.
- */
-- (instancetype)initWithOriginalLines:(NSArray*)a revisedLines:(NSArray*)b stringifier:(NSString* (^)(id obj))block {
- static dispatch_once_t pred;
- dispatch_once(&pred, ^{
- forwardScript = [[UDiffForwardScript alloc] init];
- reverseScript = [[UDiffReverseScript alloc] init];
- });
- self = [super init];
-
- if (self) {
- equiv_max = 1;
- heuristic = NO;
- no_discards = NO;
- inhibit = NO;
- NSMutableDictionary* h = [NSMutableDictionary dictionaryWithCapacity:a.count + b.count];
- _filevec0 = [UDiffFileData fileData:a h:h equivMax:&equiv_max noDiscards:&no_discards stringifier:block];
- _filevec1 = [UDiffFileData fileData:b h:h equivMax:&equiv_max noDiscards:&no_discards stringifier:block];
- }
-
- return self;
-}
-
-/** Find the midpoint of the shortest edit script for a specified
- portion of the two files.
-
- We scan from the beginnings of the files, and simultaneously from the ends,
- doing a breadth-first search through the space of edit-sequence.
- When the two searches meet, we have found the midpoint of the shortest
- edit sequence.
-
- The value returned is the number of the diagonal on which the midpoint lies.
- The diagonal number equals the number of inserted lines minus the number
- of deleted lines (counting only lines before the midpoint).
- The edit cost is stored into COST; this is the total number of
- lines inserted or deleted (counting only lines before the midpoint).
-
- This function assumes that the first lines of the specified portions
- of the two files do not match, and likewise that the last lines do not
- match. The caller must trim matching lines from the beginning and end
- of the portions it is going to specify.
-
- Note that if we return the "wrong" diagonal value, or if
- the value of bdiag at that diagonal is "wrong",
- the worst this can do is cause suboptimal diff output.
- It cannot cause incorrect diff output. */
-
-- (int)diag:(int)xoff xlim:(int)xlim yoff:(int)yoff ylim:(int)ylim {
- int* fd = fdiag; // Give the compiler a chance.
- int* bd = bdiag; // Additional help for the compiler.
- int* xv = xvec; // Still more help for the compiler.
- int* yv = yvec; // And more and more . . .
- int dmin = xoff - ylim; // Minimum valid diagonal.
- int dmax = xlim - yoff; // Maximum valid diagonal.
- int fmid = xoff - yoff; // Center diagonal of top-down search.
- int bmid = xlim - ylim; // Center diagonal of bottom-up search.
- int fmin = fmid, fmax = fmid; // Limits of top-down search.
- int bmin = bmid, bmax = bmid; // Limits of bottom-up search.
- /* True if southeast corner is on an odd
- diagonal with respect to the northwest. */
- BOOL odd = (fmid - bmid & 1) != 0;
-
- fd[fdiagoff + fmid] = xoff;
- bd[bdiagoff + bmid] = xlim;
-
- for (int c = 1;; ++c)
- {
- int d; /* Active diagonal. */
- BOOL big_snake = NO;
-
- /* Extend the top-down search by an edit step in each diagonal. */
- if (fmin > dmin)
- fd[fdiagoff + --fmin - 1] = -1;
- else
- ++fmin;
- if (fmax < dmax)
- fd[fdiagoff + ++fmax + 1] = -1;
- else
- --fmax;
- for (d = fmax; d >= fmin; d -= 2)
- {
- int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1];
-
- if (tlo >= thi)
- x = tlo + 1;
- else
- x = thi;
- oldx = x;
- y = x - d;
- while (x < xlim && y < ylim && xv[x] == yv[y]) {
- ++x; ++y;
- }
- if (x - oldx > SNAKE_LIMIT)
- big_snake = true;
- fd[fdiagoff + d] = x;
- if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c - 1;
- return d;
- }
- }
-
- /* Similar extend the bottom-up search. */
- if (bmin > dmin)
- bd[bdiagoff + --bmin - 1] = INT_MAX;
- else
- ++bmin;
- if (bmax < dmax)
- bd[bdiagoff + ++bmax + 1] = INT_MAX;
- else
- --bmax;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1];
-
- if (tlo < thi)
- x = tlo;
- else
- x = thi - 1;
- oldx = x;
- y = x - d;
- while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) {
- --x; --y;
- }
- if (oldx - x > SNAKE_LIMIT)
- big_snake = true;
- bd[bdiagoff + d] = x;
- if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d])
- {
- cost = 2 * c;
- return d;
- }
- }
-
- /* Heuristic: check occasionally for a diagonal that has made
- lots of progress compared with the edit distance.
- If we have any such, find the one that has made the most
- progress and return it as if it had succeeded.
-
- With this heuristic, for files with a constant small density
- of changes, the algorithm is linear in the file size. */
-
- if (c > 200 && big_snake && heuristic)
- {
- int best = 0;
- int bestpos = -1;
-
- for (d = fmax; d >= fmin; d -= 2)
- {
- int dd = d - fmid;
- int x = fd[fdiagoff + d];
- int y = x - d;
- int v = (x - xoff) * 2 - dd;
- if (v > 12 * (c + (dd < 0 ? -dd : dd)))
- {
- if (v > best
- && xoff + SNAKE_LIMIT <= x && x < xlim
- && yoff + SNAKE_LIMIT <= y && y < ylim)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
-
- for (k = 1; xvec[x - k] == yvec[y - k]; k++)
- if (k == SNAKE_LIMIT)
- {
- best = v;
- bestpos = d;
- break;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
-
- best = 0;
- for (d = bmax; d >= bmin; d -= 2)
- {
- int dd = d - bmid;
- int x = bd[bdiagoff + d];
- int y = x - d;
- int v = (xlim - x) * 2 + dd;
- if (v > 12 * (c + (dd < 0 ? -dd : dd)))
- {
- if (v > best
- && xoff < x && x <= xlim - SNAKE_LIMIT
- && yoff < y && y <= ylim - SNAKE_LIMIT)
- {
- /* We have a good enough best diagonal;
- now insist that it end with a significant snake. */
- int k;
-
- for (k = 0; xvec[x + k] == yvec[y + k]; k++)
- if (k == SNAKE_LIMIT)
- {
- best = v;
- bestpos = d;
- break;
- }
- }
- }
- }
- if (best > 0)
- {
- cost = 2 * c - 1;
- return bestpos;
- }
- }
- }
-}
-
-/** Compare in detail contiguous subsequences of the two files
- which are known, as a whole, to match each other.
-
- The results are recorded in the vectors filevec[N].changed_flag, by
- storing a 1 in the element for each line that is an insertion or deletion.
-
- The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
-
- Note that XLIM, YLIM are exclusive bounds.
- All line numbers are origin-0 and discarded lines are not counted. */
-
-- (void)compareseq:(int)xoff xlim:(int)xlim yoff:(int)yoff ylim:(int)ylim {
- /* Slide down the bottom initial diagonal. */
- while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) {
- ++xoff; ++yoff;
- }
- /* Slide up the top initial diagonal. */
- while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) {
- --xlim; --ylim;
- }
-
- /* Handle simple cases. */
- if (xoff == xlim)
- while (yoff < ylim)
- self.filevec1.changed_flag[1 + self.filevec1.realindexes[yoff++]] = YES;
- else if (yoff == ylim)
- while (xoff < xlim)
- self.filevec0.changed_flag[1 + self.filevec0.realindexes[xoff++]] = YES;
- else
- {
- /* Find a point of correspondence in the middle of the files. */
-
- int d = [self diag:xoff xlim:xlim yoff:yoff ylim:ylim];
- int c = cost;
-// int f = fdiag[fdiagoff + d];
- int b = bdiag[bdiagoff + d];
-
- if (c == 1)
- {
- /* This should be impossible, because it implies that
- one of the two subsequences is empty,
- and that case was handled above without calling `diag'.
- Let's verify that this is true. */
-// /throw new IllegalArgumentException("Empty subsequence");
- }
- else
- {
- /* Use that point to split this problem into two subproblems. */
- [self compareseq:xoff xlim:b yoff:yoff ylim:b - d];
- /* This used to use f instead of b,
- but that is incorrect!
- It is not necessarily the case that diagonal d
- has a snake from b to f. */
- [self compareseq:b xlim:xlim yoff:b - d ylim:ylim];
- }
- }
-}
-
-/** Discard lines from one file that have no matches in the other file.
- */
-
-- (void)discard_confusing_lines {
- [self.filevec0 discard_confusing_lines:self.filevec1];
- [self.filevec1 discard_confusing_lines:self.filevec0];
-}
-
-/** Adjust inserts/deletes of blank lines to join changes
- as much as possible.
- */
-
-- (void)shift_boundaries {
- if (inhibit)
- return;
- [self.filevec0 shift_boundaries:self.filevec1];
- [self.filevec1 shift_boundaries:self.filevec0];
-}
-
-/* Report the differences of two files. */
-- (UDiffChange*)diff_2:(BOOL)reverse {
- return [self diff:reverse ? reverseScript : forwardScript];
-}
-
-/** Get the results of comparison as an edit script. The script
- is described by a list of changes. The standard ScriptBuilder
- implementations provide for forward and reverse edit scripts.
- Alternate implementations could, for instance, list common elements
- instead of differences.
- @param bld an object to build the script from change flags
- @return the head of a list of changes
- */
-- (UDiffChange*)diff:(UDiffScriptBuilder*)bld {
-
- /* Some lines are obviously insertions or deletions
- because they don't match anything. Detect them now,
- and avoid even thinking about them in the main comparison algorithm. */
-
- [self discard_confusing_lines];
-
- /* Now do the main comparison algorithm, considering just the
- undiscarded lines. */
-
- xvec = self.filevec0.undiscarded;
- yvec = self.filevec1.undiscarded;
-
- int diags = self.filevec0.nondiscarded_lines + self.filevec1.nondiscarded_lines + 3;
- fdiag = calloc(diags, sizeof(int));
- fdiagoff = self.filevec1.nondiscarded_lines + 1;
- bdiag = calloc(diags, sizeof(int));
- bdiagoff = self.filevec1.nondiscarded_lines + 1;
-
- [self compareseq:0
- xlim:self.filevec0.nondiscarded_lines
- yoff:0
- ylim:self.filevec1.nondiscarded_lines];
- fdiag = nil;
- bdiag = nil;
-
- /* Modify the results slightly to make them prettier
- in cases where that can validly be done. */
-
- [self shift_boundaries];
-
- /* Get the results of comparison in the form of a chain
- of struct change's -- an edit script. */
- return [bld build_script:self.filevec0.changed_flag
- len0:self.filevec0.buffered_lines
- changed1:self.filevec1.changed_flag
- len1:self.filevec1.buffered_lines];
-}
-
-/** Data on one input file being compared.
- */
-
-
-@end
diff --git a/Sources/Legacy/FileManager/BigFileFileOperationManager.h b/Sources/Legacy/FileManager/BigFileFileOperationManager.h
deleted file mode 100644
index 8b0fc31..0000000
--- a/Sources/Legacy/FileManager/BigFileFileOperationManager.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// BigFileFileOperationManager.h
-// VisualDiffer
-//
-// Created by davide ficano on 10/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import
-
-NS_SWIFT_NAME(defaultBigFileSizeThreshold)
-static const uint64 BIG_FILE_SIZE_THRESHOLD = (uint64)(10 * 1024 * 1024);
-
-NS_ASSUME_NONNULL_BEGIN
-
-@protocol FileOperationManagerDelegate;
-@class FileOperationManager;
-@class CompareItem;
-
-@interface BigFileFileOperationManager: NSObject
-
-@property (strong) FileOperationManager* operationManager;
-@property (nullable, strong) id delegate;
-
-- (instancetype)init:(FileOperationManager*)operationManager
- delegate:(nullable id) delegate;
-
-- (BOOL)copy:(CompareItem*)srcRoot
-destFullPath:(NSString*)destFullPath
- error:(out NSError ** _Nullable)outError;
-
-- (BOOL)move:(CompareItem*)srcRoot
-destFullPath:(NSString*)destFullPath
- error:(out NSError ** _Nullable)outError;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Sources/Legacy/FileManager/BigFileFileOperationManager.m b/Sources/Legacy/FileManager/BigFileFileOperationManager.m
deleted file mode 100644
index 56edb7c..0000000
--- a/Sources/Legacy/FileManager/BigFileFileOperationManager.m
+++ /dev/null
@@ -1,190 +0,0 @@
-//
-// BigFileFileOperationManager.m
-// VisualDiffer
-//
-// Created by davide ficano on 10/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import "BigFileFileOperationManager.h"
-#import "VisualDiffer-Swift.h"
-
-typedef OSStatus (*FSOperationObjectAsync)(FSFileOperationRef fileOp, const FSRef *source, const FSRef *destDir, CFStringRef _Nullable destName, OptionBits flags, FSFileOperationStatusProcPtr callback, CFTimeInterval statusChangeInterval, FSFileOperationClientContext *clientContext);
-
-// disabled warning on deprecated api usage (FSMoveObjectAsync)
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-
-void copyStatusCallback(FSFileOperationRef fileOp,
- const FSRef *currentItem,
- FSFileOperationStage stage,
- OSStatus error,
- CFDictionaryRef statusDictionary,
- void *info);
-
-@implementation BigFileFileOperationManager
-
-- (instancetype)init:(FileOperationManager*)operationManager
- delegate:(id) delegate {
- self = [super init];
-
- if (self) {
- self.operationManager = operationManager;
- self.delegate = delegate;
- }
-
- return self;
-}
-
-
-- (BOOL)copy:(CompareItem*)srcRoot
-destFullPath:(NSString*)destFullPath
- error:(NSError**)outError {
- [self.delegate fileManager:self.operationManager startBigFileOperationForItem:srcRoot];
-
- NSError* error;
-
- [self.class copyObject:srcRoot.path
- destPath:destFullPath
- fileManager:self.operationManager
- asyncOperation:FSCopyObjectAsync
- error:&error];
- if ([self.delegate isBigFileOperationCancelled:self.operationManager]) {
- // error isn't stored if operation is cancelled
- [self.delegate fileManager:self.operationManager updateForItem:srcRoot];
- return NO;
- }
-
- if (outError) {
- *outError = error;
- }
- return error == nil;
-}
-
-- (BOOL)move:(CompareItem*)srcRoot
-destFullPath:(NSString*)destFullPath
- error:(NSError**)outError {
- [self.delegate fileManager:self.operationManager startBigFileOperationForItem:srcRoot];
-
- NSError* error;
-
- [self.class copyObject:srcRoot.path
- destPath:destFullPath
- fileManager:self.operationManager
- asyncOperation:FSMoveObjectAsync
- error:&error];
-
- if ([self.delegate isBigFileOperationCancelled:self.operationManager]) {
- // error isn't stored if operation is cancelled
- [self.delegate fileManager:self.operationManager updateForItem:srcRoot];
- return NO;
- }
-
- if (outError) {
- *outError = error;
- }
- return error == nil;
-}
-
-+ (BOOL)copyObject:(NSString*)srcPath
- destPath:(NSString*)destPath
- fileManager:(FileOperationManager*)fileManager
- asyncOperation:(FSOperationObjectAsync)operation
- error:(NSError**)error {
- CFRunLoopRef runLoop = CFRunLoopGetCurrent();
- FSFileOperationRef fileOp = FSFileOperationCreate(kCFAllocatorDefault);
- OSStatus status = FSFileOperationScheduleWithRunLoop(fileOp, runLoop, kCFRunLoopDefaultMode);
-
- if (status == noErr) {
- FSRef source;
- FSRef destination;
-
- FSPathMakeRef( (const UInt8 *)[srcPath fileSystemRepresentation], &source, NULL);
-
- Boolean isDir = true;
- FSPathMakeRef( (const UInt8 *)[[destPath stringByDeletingLastPathComponent] fileSystemRepresentation], &destination, &isDir);
-
- FSFileOperationClientContext clientContext = {};
- clientContext.info = (__bridge void *)(fileManager);
-
- status = operation(fileOp,
- &source,
- &destination, // Full path to destination dir
- NULL, // Use the same filename as source
- kFSFileOperationDefaultOptions,
- copyStatusCallback,
- 1.0,
- &clientContext);
- if (status == noErr) {
- while (![fileManager.delegate isBigFileOperationCompleted:fileManager] && CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2.0, true)) {
- ; //nop
- }
-
- FSFileOperationCopyStatus(fileOp, NULL, NULL, &status, NULL, NULL);
- }
- }
-
- CFRelease(fileOp);
- BOOL retVal = NO;
- if (status) {
- retVal = [self setError:error withStatus:status];
- }
- return retVal;
-}
-
-+ (BOOL)setError:(NSError **)error withStatus:(OSStatus)err {
- if (error) {
- *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
- }
- return error != nil;
-}
-
-@end
-
-#pragma mark -
-#pragma mark Static callbacks
-
-void copyStatusCallback(FSFileOperationRef fileOp,
- const FSRef *currentItem,
- FSFileOperationStage stage,
- OSStatus error,
- CFDictionaryRef statusDictionary,
- void *info) {
- FileOperationManager* fileManager = (__bridge FileOperationManager*)info;
- id delegate = fileManager.delegate;
-
- [delegate waitPauseFor:fileManager];
-
- if (stage == kFSOperationStageComplete) {
- [delegate fileManager:fileManager setCompleted:YES];
- } else {
- if ([delegate isBigFileOperationCancelled:fileManager]) {
- FSFileOperationCancel(fileOp);
- return;
- }
- }
-
- if (statusDictionary && stage == kFSOperationStageRunning) {
- CFNumberRef bytesCompleted = (CFNumberRef)CFDictionaryGetValue(statusDictionary, kFSOperationBytesCompleteKey);
- CGFloat floatBytesCompleted = 0.0;
- if (bytesCompleted) {
- CFNumberGetValue(bytesCompleted, kCFNumberMaxType, &floatBytesCompleted);
- }
-
- CFNumberRef throughput = (CFNumberRef)CFDictionaryGetValue(statusDictionary, kFSOperationThroughputKey);
- CGFloat floatThroughput = 0.0;
- if (throughput) {
- CFNumberGetValue(throughput, kCFNumberMaxType, &floatThroughput);
- }
-
- CFNumberRef totalBytes = (CFNumberRef)CFDictionaryGetValue(statusDictionary, kFSOperationTotalBytesKey);
- CGFloat floatTotalBytes = 0.0;
- if (totalBytes) {
- CFNumberGetValue(totalBytes, kCFNumberMaxType, &floatTotalBytes);
- }
-
- [delegate fileManager:fileManager
- updateBytesCompleted:floatBytesCompleted
- totalBytes:floatTotalBytes
- throughput:floatThroughput];
- }
-}
diff --git a/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.h b/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.h
deleted file mode 100644
index 9955ccf..0000000
--- a/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// MGRecessedPopUpButtonCell.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 20/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import
-
-/*
- This cell class is used only for NSPopUpButtons which do NOT automatically
- get their titles from their selected menu-items, since such popup-buttons
- are weirdly broken when using the recessed bezel-style.
-*/
-
-@interface MGRecessedPopUpButtonCell : NSPopUpButtonCell {
- NSButton *recessedButton; // we use a separate NSButton to do the bezel-drawing.
-}
-
-@end
diff --git a/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.m b/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.m
deleted file mode 100644
index f695d21..0000000
--- a/Sources/Legacy/MGScopeBar/MGRecessedPopUpButtonCell.m
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// MGRecessedPopUpButtonCell.m
-// MGScopeBar
-//
-// Created by Matt Gemmell on 20/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import "MGRecessedPopUpButtonCell.h"
-
-
-@implementation MGRecessedPopUpButtonCell
-
-
-- (instancetype)initTextCell:(NSString *)title pullsDown:(BOOL)pullsDown
-{
- if ((self = [super initTextCell:title pullsDown:pullsDown])) {
- recessedButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 30, 20)]; // arbitrary frame.
- [recessedButton setTitle:@""];
- [recessedButton setBezelStyle:NSBezelStyleAccessoryBar];
- [recessedButton setButtonType:NSButtonTypePushOnPushOff];
- [[recessedButton cell] setHighlightsBy:(NSCellStyleMask)(NSCellIsBordered | NSCellIsInsetButton)];
- [recessedButton setShowsBorderOnlyWhileMouseInside:NO];
- [recessedButton setState:NSControlStateValueOn]; // ensures it looks pushed-in.
- }
- return self;
-}
-
-
-
-
-- (void)drawTitleWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
-{
- // Inset title rect since its position is broken when NSPopUpButton
- // isn't using its selected item as its title.
- NSRect titleFrame = cellFrame;
- titleFrame.origin.y += 1.0;
- [super drawTitleWithFrame:titleFrame inView:controlView];
-}
-
-
-- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
-{
- [recessedButton setFrame:frame];
- [recessedButton drawRect:frame];
-}
-
-
-@end
diff --git a/Sources/Legacy/MGScopeBar/MGScopeBar.h b/Sources/Legacy/MGScopeBar/MGScopeBar.h
deleted file mode 100644
index dee9f7a..0000000
--- a/Sources/Legacy/MGScopeBar/MGScopeBar.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// MGScopeBar.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import
-#import "MGScopeBarDelegateProtocol.h"
-
-@interface MGScopeBar : NSView {
-@private
- IBOutlet id __unsafe_unretained delegate; // weak ref.
- NSMutableArray *_separatorPositions; // x-coords of separators, indexed by their group-number.
- NSMutableArray *_groups; // groups of items.
- NSView *_accessoryView; // weak ref since it's a subview.
- NSMutableDictionary *_identifiers; // map of identifiers to items.
- NSMutableArray *_selectedItems; // all selected items in all groups; see note below.
- CGFloat _lastWidth; // previous width of view from when we last resized.
- NSInteger _firstCollapsedGroup; // index of first group collapsed into a popup.
- CGFloat _totalGroupsWidthForPopups; // total width needed to show all groups expanded (excluding padding and accessory).
- CGFloat _totalGroupsWidth; // total width needed to show all groups as native-width popups (excluding padding and accessory).
- BOOL _smartResizeEnabled; // whether to do our clever collapsing/expanding of buttons when resizing (Smart Resizing).
- BOOL _notifyDefaultSelections; // Whether to notify the delegate of default selections
- CGFloat _fontSize; // Font size used by labels and buttons
-}
-
-@property(unsafe_unretained, nonatomic) id delegate; // should implement the MGScopeBarDelegate protocol.
-
-- (void)reloadData; // causes the scope-bar to reload all groups/items from its delegate.
-- (void)sizeToFit; // only resizes vertically to optimum height; does not affect width.
-- (void)adjustSubviews; // performs Smart Resizing if enabled. You should only need to call this yourself if you change the width of the accessoryView.
-
-// Smart Resize is the intelligent conversion of button-groups into NSPopUpButtons and vice-versa, based on available space.
-// This functionality is enabled (YES) by default. Changing this setting will automatically call -reloadData.
-@property (NS_NONATOMIC_IOSONLY) BOOL smartResizeEnabled;
-
-// The following method must be used to manage selections in the scope-bar; do not attempt to manipulate buttons etc directly.
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber;
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber informDelegate:(BOOL)informDelegate;
-@property (NS_NONATOMIC_IOSONLY, readonly, copy) NSArray *selectedItems;
-- (void)setEnabledAllGroups:(BOOL)enable;
-- (void)setEnabledGroup:(int)groupNumber enable:(BOOL)enable;
-
-@property (NS_NONATOMIC_IOSONLY) BOOL notifyDefaultSelections;
-
-@property (NS_NONATOMIC_IOSONLY) CGFloat fontSize;
-
-/*
- Note: The -selectedItems method returns an array of arrays.
- Each index in the returned array represents the group of items at that index.
- The contents of each sub-array are the identifiers of each selected item in that group.
- Sub-arrays may be empty, but will always be present (i.e. you will always find an NSArray).
- Depending on the group's selection-mode, sub-arrays may contain zero, one or many identifiers.
- The identifiers in each sub-array are not in any particular order.
- */
-
-@end
diff --git a/Sources/Legacy/MGScopeBar/MGScopeBar.m b/Sources/Legacy/MGScopeBar/MGScopeBar.m
deleted file mode 100644
index 01f9327..0000000
--- a/Sources/Legacy/MGScopeBar/MGScopeBar.m
+++ /dev/null
@@ -1,1046 +0,0 @@
-//
-// MGScopeBar.m
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import "MGScopeBar.h"
-#import "MGRecessedPopUpButtonCell.h"
-
-
-#define SCOPE_BAR_H_INSET 8.0 // inset on left and right
-#define SCOPE_BAR_HEIGHT 25.0 // used in -sizeToFit
-#define SCOPE_BAR_BORDER_COLOR [NSColor colorWithCalibratedWhite:0.69 alpha:1.0] // bottom line's color
-#define SCOPE_BAR_BORDER_WIDTH 1.0 // bottom line's width
-
-#define SCOPE_BAR_SEPARATOR_COLOR [NSColor colorWithCalibratedWhite:0.52 alpha:1.0] // color of vertical-line separators between groups
-#define SCOPE_BAR_SEPARATOR_WIDTH 1.0 // width of vertical-line separators between groups
-#define SCOPE_BAR_SEPARATOR_HEIGHT 16.0 // separators are vertically centered in the bar
-
-#define SCOPE_BAR_LABEL_COLOR [NSColor labelColor] // color of groups' labels
-#define SCOPE_BAR_FONTSIZE 12.0 // font-size of labels and buttons
-#define SCOPE_BAR_ITEM_SPACING 3.0 // spacing between buttons/separators/labels
-#define SCOPE_BAR_BUTTON_IMAGE_SIZE 16.0 // size of buttons' images (width and height)
-
-#define SCOPE_BAR_HIDE_POPUP_BG YES // whether the bezel background of an NSPopUpButton is hidden when none of its menu-items are selected.
-
-// Appearance metrics. These were chosen to mimic the Finder's "Find" (Spotlight / Smart Group / etc) window's scope-bar.
-#define MENU_PADDING 25.0 // how much wider a popup-button is than a regular button with the same title.
-#define MENU_MIN_WIDTH 60.0 // minimum width a popup-button can be narrowed to.
-
-// NSPopUpButton titles used for groups which allow multiple selection.
-#define POPUP_TITLE_EMPTY_SELECTION NSLocalizedString(@"(None)", nil) // title used when no items in the popup are selected.
-#define POPUP_TITLE_MULTIPLE_SELECTION NSLocalizedString(@"(Multiple)", nil) // title used when multiple items in the popup are selected.
-
-
-// ---- end of configurable settings ---- //
-
-
-// Keys for internal use.
-#define GROUP_IDENTIFIERS @"Identifiers" // NSMutableArray of identifier strings.
-#define GROUP_BUTTONS @"Buttons" // NSMutableArray of either NSButtons or NSMenuItems, one per item.
-#define GROUP_SELECTION_MODE @"SelectionMode" // MGScopeBarGroupSelectionMode (int) as NSNumber.
-#define GROUP_MENU_MODE @"MenuMode" // BOOL, YES if group is collected in a popup-menu, else NO.
-#define GROUP_POPUP_BUTTON @"PopupButton" // NSPopUpButton (only present if group is in menu-mode).
-#define GROUP_HAS_SEPARATOR @"HasSeparator" // BOOL, YES if group has a separator before it.
-#define GROUP_HAS_LABEL @"HasLabel" // BOOL, YES if group has a label.
-#define GROUP_LABEL_FIELD @"LabelField" // NSTextField for the label (optional; only if group has a label)
-#define GROUP_TOTAL_BUTTONS_WIDTH @"TotalButtonsWidth" // Width of all buttons in a group plus spacings between them (doesn't include label etc)
-#define GROUP_WIDEST_BUTTON_WIDTH @"WidestButtonWidth" // Width of widest button, used when making popup-menus.
-#define GROUP_CUMULATIVE_WIDTH @"CumulativeWidth" // Width from left of leftmost group to right of this group (all groups fully expanded).
-
-
-@interface MGScopeBar (MGPrivateMethods)
-
-- (IBAction)scopeButtonClicked:(id)sender;
-- (NSButton *)getButtonForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber; // returns relevant button/menu-item
-- (void)updateSelectedState:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber informDelegate:(BOOL)inform;
-- (NSButton *)buttonForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image; // creates a new NSButton
-- (NSMenuItem *)menuItemForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image; // creates a new NSMenuitem
-- (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group;
-- (void)setControl:(NSObject *)control forIdentifier:(NSString *)identifier inGroup:(NSInteger)groupNumber;
-- (void)updateMenuTitleForGroupAtIndex:(NSInteger)groupNumber;
-
-@end
-
-
-@implementation MGScopeBar
-
-
-#pragma mark Setup and teardown
-
-
-- (instancetype)initWithFrame:(NSRect)frame
-{
- self = [super initWithFrame:frame];
- if (self) {
- _smartResizeEnabled = YES;
- _notifyDefaultSelections = YES;
- _fontSize = SCOPE_BAR_FONTSIZE;
- // Everything else is reset in -reloadData.
- }
- return self;
-}
-
-
-- (void)dealloc
-{
- delegate = nil;
- if (_accessoryView) {
- [_accessoryView removeFromSuperview];
- _accessoryView = nil; // weak ref
- }
-
-}
-
-
-#pragma mark Data management
-
-
-- (void)reloadData
-{
- // Resize if necessary.
- [self sizeToFit];
-
- // Remove any old objects.
- if (_accessoryView) {
- [_accessoryView removeFromSuperview];
- _accessoryView = nil; // weak ref
- }
-
- NSArray *subviews = [[self subviews] copy]; // so we don't mutate the collection we're iterating over.
- [subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
- // because copies are retained.
-
- _separatorPositions = nil;
- _groups = nil;
- _identifiers = nil;
- _selectedItems = nil;
- _firstCollapsedGroup = NSNotFound;
- _lastWidth = NSNotFound;
- _totalGroupsWidth = 0;
- _totalGroupsWidthForPopups = 0;
-
- // Configure contents via delegate.
- if (self.delegate && [delegate conformsToProtocol:@protocol(MGScopeBarDelegate)]) {
- NSInteger numGroups = [delegate numberOfGroupsInScopeBar:self];
-
- if (numGroups > 0) {
- _separatorPositions = [[NSMutableArray alloc] initWithCapacity:numGroups];
- _groups = [[NSMutableArray alloc] initWithCapacity:numGroups];
- _identifiers = [[NSMutableDictionary alloc] initWithCapacity:0];
- _selectedItems = [[NSMutableArray alloc] initWithCapacity:numGroups];
-
- int xCoord = SCOPE_BAR_H_INSET;
- NSRect ctrlRect = NSZeroRect;
- BOOL providesImages = [delegate respondsToSelector:@selector(scopeBar:imageForItem:inGroup:)];
-
- for (int groupNum = 0; groupNum < numGroups; groupNum++) {
- // Add separator if appropriate.
- BOOL addSeparator = (groupNum > 0); // default behavior.
- if ([delegate respondsToSelector:@selector(scopeBar:showSeparatorBeforeGroup:)]) {
- addSeparator = [delegate scopeBar:self showSeparatorBeforeGroup:groupNum];
- }
- if (addSeparator) {
- [_separatorPositions addObject:@(xCoord)];
- xCoord += (int)(SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING);
-
- _totalGroupsWidth += SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING;
- _totalGroupsWidthForPopups += SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING;
- } else {
- [_separatorPositions addObject:[NSNull null]];
- }
-
- // Add label if appropriate.
- NSString *groupLabel = [delegate scopeBar:self labelForGroup:groupNum];
- NSTextField *labelField = nil;
- BOOL hasLabel = NO;
- if (groupLabel && [groupLabel length] > 0) {
- hasLabel = YES;
- ctrlRect = NSMakeRect(xCoord, 6, 15, 50);
- labelField = [[NSTextField alloc] initWithFrame:ctrlRect];
- [labelField setStringValue:groupLabel];
- [labelField setEditable:NO];
- [labelField setBordered:NO];
- [labelField setDrawsBackground:NO];
- [labelField setTextColor:SCOPE_BAR_LABEL_COLOR];
- [labelField setFont:[NSFont boldSystemFontOfSize:_fontSize]];
- [labelField sizeToFit];
- ctrlRect.size = [labelField frame].size;
- [labelField setFrame:ctrlRect];
- [self addSubview:labelField];
-
- xCoord += (int)(ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING);
-
- _totalGroupsWidth += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
- _totalGroupsWidthForPopups += ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING;
- }
-
- // Create group information for use during interaction.
- NSArray *identifiers = [delegate scopeBar:self itemIdentifiersForGroup:groupNum];
- NSMutableArray *usedIdentifiers = [NSMutableArray arrayWithCapacity:[identifiers count]];
- NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:[identifiers count]];
- MGScopeBarGroupSelectionMode selMode = [delegate scopeBar:self selectionModeForGroup:groupNum];
- if (selMode != MGScopeBarGroupSelectionModeRadio && selMode != MGScopeBarGroupSelectionModeMultiple) {
- // Sanity check, since this is just an int.
- selMode = MGScopeBarGroupSelectionModeRadio;
- }
- NSMutableDictionary *groupInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- usedIdentifiers, GROUP_IDENTIFIERS,
- buttons, GROUP_BUTTONS,
- @((int)selMode), GROUP_SELECTION_MODE,
- @NO, GROUP_MENU_MODE,
- @(hasLabel), GROUP_HAS_LABEL,
- @(addSeparator), GROUP_HAS_SEPARATOR,
- nil];
- if (hasLabel) {
- groupInfo[GROUP_LABEL_FIELD] = labelField;
- }
- [_groups addObject:groupInfo];
- [_selectedItems addObject:[NSMutableArray arrayWithCapacity:0]];
-
- // Add buttons for this group.
- CGFloat widestButtonWidth = 0;
- CGFloat totalButtonsWidth = 0;
- for (NSString *itemID in identifiers) {
- if (![usedIdentifiers containsObject:itemID]) {
- [usedIdentifiers addObject:itemID];
- } else {
- // Identifier already used for this group; skip it.
- continue;
- }
-
- NSString *title = [delegate scopeBar:self titleOfItem:itemID inGroup:groupNum];
- NSImage *image = nil;
- if (providesImages) {
- image = [delegate scopeBar:self imageForItem:itemID inGroup:groupNum];
- }
- NSButton *button = [self buttonForItem:itemID inGroup:groupNum withTitle:title image:image];
-
- ctrlRect = [button frame];
- ctrlRect.origin.x = xCoord;
- [button setFrame:ctrlRect];
- [self addSubview:button];
- [buttons addObject:button];
-
- // Adjust x-coordinate for next item in the bar.
- xCoord += (int)(ctrlRect.size.width + SCOPE_BAR_ITEM_SPACING);
-
- // Update total and widest button widths.
- if (totalButtonsWidth > 0) {
- // Add spacing before this item, since it's not the first in the group.
- totalButtonsWidth += SCOPE_BAR_ITEM_SPACING;
- }
- totalButtonsWidth += ctrlRect.size.width;
- if (ctrlRect.size.width > widestButtonWidth) {
- widestButtonWidth = ctrlRect.size.width;
- }
- }
-
- // Add the accumulated buttons' width and the widest button's width to groupInfo.
- groupInfo[GROUP_TOTAL_BUTTONS_WIDTH] = @(totalButtonsWidth);
- groupInfo[GROUP_WIDEST_BUTTON_WIDTH] = @(widestButtonWidth);
-
- _totalGroupsWidth += totalButtonsWidth;
- _totalGroupsWidthForPopups += widestButtonWidth + MENU_PADDING;
-
- CGFloat cumulativeWidth = _totalGroupsWidth + (groupNum * SCOPE_BAR_ITEM_SPACING);
- groupInfo[GROUP_CUMULATIVE_WIDTH] = @(cumulativeWidth);
-
- // If this is a radio-mode group, select the first item automatically.
- if (selMode == MGScopeBarGroupSelectionModeRadio) {
- [self updateSelectedState:YES forItem:identifiers[0] inGroup:groupNum informDelegate:_notifyDefaultSelections];
- }
- }
-
- _totalGroupsWidth += ((numGroups - 1) * SCOPE_BAR_ITEM_SPACING);
- _totalGroupsWidthForPopups += ((numGroups - 1) * SCOPE_BAR_ITEM_SPACING);
- }
-
- // Add accessoryView, if provided.
- if ([delegate respondsToSelector:@selector(accessoryViewForScopeBar:)]) {
- _accessoryView = [delegate accessoryViewForScopeBar:self];
- if (_accessoryView) {
- // Remove NSViewMaxXMargin flag from resizing mask, if present.
- NSUInteger mask = [_accessoryView autoresizingMask];
- if (mask & NSViewMaxXMargin) {
- mask &= ~NSViewMaxXMargin;
- }
-
- // Add NSViewMinXMargin flag to resizing mask, if not present.
- if (!(mask & NSViewMinXMargin)) {
- mask = (mask | NSViewMinXMargin);
- }
-
- // Update view sizing mask.
- [_accessoryView setAutoresizingMask:mask];
-
- // Adjust frame appropriately.
- NSRect frame = [_accessoryView frame];
- frame.origin.x = round(NSMaxX([self bounds]) - (frame.size.width + SCOPE_BAR_H_INSET));
- frame.origin.y = round(((SCOPE_BAR_HEIGHT - frame.size.height) / 2.0));
- [_accessoryView setFrame:frame];
-
- // Add as subview.
- [self addSubview:_accessoryView];
- }
- }
-
- // Layout subviews appropriately.
- [self adjustSubviews];
- }
-
- [self setNeedsDisplay:YES];
-}
-
-
-#pragma mark Utility methods
-
-
-- (void)sizeToFit
-{
- NSRect frame = [self frame];
- if (frame.size.height != SCOPE_BAR_HEIGHT) {
- CGFloat delta = SCOPE_BAR_HEIGHT - frame.size.height;
- frame.size.height += delta;
- frame.origin.y -= delta;
- [self setFrame:frame];
- }
-}
-
-
-- (void)adjustSubviews
-{
- if (!_smartResizeEnabled) {
- return;
- }
-
- /*
- We need to work out which groups we can show fully expanded, and which must be collapsed into popup-buttons.
- Any kind of frame-change may have happened, so we need to take care to create or remove buttons or popup-buttons as needed.
- */
-
- // Bail out if we have nothing to do.
- if (!_groups || [_groups count] == 0) {
- return;
- }
-
- // Obtain current width of view.
- CGFloat viewWidth = [self bounds].size.width;
-
- // Abort if there hasn't been any genuine change in width.
- if ((viewWidth == _lastWidth) && (_lastWidth != NSNotFound)) {
- return;
- }
-
- // Determine whether we got narrower or wider.
- BOOL narrower = ((_lastWidth == NSNotFound) || (viewWidth < _lastWidth));
-
- // Find width available for showing groups.
- CGFloat availableWidth = viewWidth - (SCOPE_BAR_H_INSET * 2.0);
- if (_accessoryView) {
- // Account for _accessoryView, leaving a normal amount of spacing to the left of it.
- availableWidth -= ([_accessoryView frame].size.width + SCOPE_BAR_ITEM_SPACING);
- }
-
- BOOL shouldAdjustPopups = (availableWidth < _totalGroupsWidthForPopups);
- NSInteger oldFirstCollapsedGroup = _firstCollapsedGroup;
-
- // Work out which groups we should now check for collapsibility/expandability.
- NSEnumerator *groupsEnumerator = nil;
- NSRange enumRange;
- BOOL proceed = YES;
-
- if (narrower) {
- // Got narrower, so work backwards from oldFirstCollapsedGroup (excluding that group, since it's already collapsed),
- // checking to see if we need to collapse any more groups to the left.
- enumRange = NSMakeRange(0, oldFirstCollapsedGroup);
- // If no groups were previously collapsed, work backwards from the last group (including that group).
- if (oldFirstCollapsedGroup == NSNotFound) {
- enumRange.length = [_groups count];
- }
- groupsEnumerator = [[_groups subarrayWithRange:enumRange] reverseObjectEnumerator];
-
- } else {
- // Got wider, so work forwards from oldFirstCollapsedGroup (including that group) checking to see if we can
- // expand any groups into full buttons.
- enumRange = NSMakeRange(oldFirstCollapsedGroup, [_groups count] - oldFirstCollapsedGroup);
- // If no groups were previously collapsed, we have nothing to do here.
- if (oldFirstCollapsedGroup == NSNotFound) {
- proceed = NO;
- }
- if (proceed) {
- groupsEnumerator = [[_groups subarrayWithRange:enumRange] objectEnumerator];
- }
- }
-
- // Get the current occupied width within this view.
- CGFloat currentOccupiedWidth = 0;
- NSDictionary *group = _groups[0];
- BOOL menuMode = [group[GROUP_MENU_MODE] boolValue];
- NSButton *firstButton = nil;
- if (menuMode) {
- firstButton = group[GROUP_POPUP_BUTTON];
- } else {
- firstButton = group[GROUP_BUTTONS][0];
- }
- CGFloat leftLimit = NSMinX([firstButton frame]);
- // Account for label in first group, if present.
- if ([group[GROUP_HAS_LABEL] boolValue]) {
- NSTextField *label = (NSTextField *)group[GROUP_LABEL_FIELD];
- leftLimit -= (SCOPE_BAR_ITEM_SPACING + [label frame].size.width);
- }
-
- group = [_groups lastObject];
- menuMode = [group[GROUP_MENU_MODE] boolValue];
- NSButton *lastButton = nil;
- if (menuMode) {
- lastButton = group[GROUP_POPUP_BUTTON];
- } else {
- lastButton = [group[GROUP_BUTTONS] lastObject];
- }
- CGFloat rightLimit = NSMaxX([lastButton frame]);
- currentOccupiedWidth = rightLimit - leftLimit;
-
- // Work out whether we need to try collapsing groups at all, if we're narrowing.
- // We have already handled the case of not requiring to expand groups if we're widening, above.
- if (proceed && narrower) {
- if (availableWidth >= currentOccupiedWidth) {
- // We still have enough room for what we're showing; no change needed.
- proceed = NO;
- }
- }
-
- if (proceed) {
- // See how many further groups we can expand or contract.
- CGFloat theoreticalOccupiedWidth = currentOccupiedWidth;
- for (NSDictionary *groupInfo in groupsEnumerator) {
- BOOL complete = NO;
- float expandedWidth = [groupInfo[GROUP_TOTAL_BUTTONS_WIDTH] floatValue];
- CGFloat contractedWidth = [groupInfo[GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING;
-
- if (narrower) {
- // We're narrowing. See if collapsing this group brings us within availableWidth.
- if (((theoreticalOccupiedWidth - expandedWidth) + contractedWidth) <= availableWidth) {
- // We're now within width constraints, so we're done iterating.
- complete = YES;
- } // else, continue trying to to collapse groups.
- theoreticalOccupiedWidth = ((theoreticalOccupiedWidth - expandedWidth) + contractedWidth);
-
- } else {
- // We're widening. See if we can expand this group and still be within availableWidth.
- if (((theoreticalOccupiedWidth - contractedWidth) + expandedWidth) > availableWidth) {
- // We'd be too wide if we expanded this group. Terminate iteration without updating _firstCollapsedGroup.
- //NSLog(@"We'd be too wide if we expanded right now");
- break;
- } // else, continue trying to expand groups.
- theoreticalOccupiedWidth = ((theoreticalOccupiedWidth - contractedWidth) + expandedWidth);
- //NSLog(@"We can continue expanding");
- }
-
- // Update _firstCollapsedGroup appropriately.
- if (_firstCollapsedGroup == NSNotFound) {
- _firstCollapsedGroup = ((narrower) ? [_groups count] : -1);
- oldFirstCollapsedGroup = _firstCollapsedGroup;
- }
- _firstCollapsedGroup += ((narrower) ? -1 : 1);
-
- // Terminate if we now fit the available space as best we can.
- if (complete) {
- break;
- }
- }
-
- // Work out how many groups we need to actually change.
- NSRange changedRange = NSMakeRange(0, [_groups count]);
- BOOL adjusting = YES;
- //NSLog(@"Old firstCollapsedGroup: %d, new: %d", oldFirstCollapsedGroup, _firstCollapsedGroup);
- if (_firstCollapsedGroup != oldFirstCollapsedGroup) {
- if (narrower) {
- // Narrower. _firstCollapsedGroup will be less (earlier) than oldFirstCollapsedGroup.
- changedRange.location = _firstCollapsedGroup;
- changedRange.length = (oldFirstCollapsedGroup - _firstCollapsedGroup);
- } else {
- // Wider. _firstCollapsedGroup will be greater (later) than oldFirstCollapsedGroup.
- changedRange.location = oldFirstCollapsedGroup;
- changedRange.length = (_firstCollapsedGroup - oldFirstCollapsedGroup);
- }
- } else {
- // _firstCollapsedGroup and oldFirstCollapsedGroup are the same; nothing needs changed.
- adjusting = NO;
- }
-
- // If a change is required, ensure that each group is expanded or contracted as appropriate.
- if (adjusting || shouldAdjustPopups) {
- //NSLog(@"Got %@ - modifying groups %@", ((narrower) ? @"narrower" : @"wider"), NSStringFromRange(changedRange));
- NSInteger nextXCoord = NSNotFound;
- if (adjusting) {
- for (NSUInteger i = changedRange.location; i < NSMaxRange(changedRange); i++) {
- NSMutableDictionary *groupInfo = _groups[i];
-
- if (nextXCoord == NSNotFound) {
- BOOL groupMenuMode = [groupInfo[GROUP_MENU_MODE] boolValue];
- NSButton *firstGroupButton = nil;
- if (!groupMenuMode) {
- firstGroupButton = groupInfo[GROUP_BUTTONS][0];
- } else {
- firstGroupButton = groupInfo[GROUP_POPUP_BUTTON];
- }
- nextXCoord = (NSInteger)[firstGroupButton frame].origin.x;
- } else {
- // Add group-spacing, separator and label as appropriate.
- nextXCoord += (NSInteger)SCOPE_BAR_ITEM_SPACING;
- if ([groupInfo[GROUP_HAS_SEPARATOR] boolValue]) {
- nextXCoord += (NSInteger)(SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING);
- }
- if ([groupInfo[GROUP_HAS_LABEL] boolValue]) {
- NSTextField *labelField = (NSTextField *)groupInfo[GROUP_LABEL_FIELD];
- CGFloat labelWidth = [labelField frame].size.width;
- nextXCoord += (NSInteger)(labelWidth + SCOPE_BAR_ITEM_SPACING);
- }
- }
-
- NSPopUpButton *popup = nil;
- if (narrower) {
- // Remove buttons.
- NSArray *buttons = groupInfo[GROUP_BUTTONS];
- [buttons makeObjectsPerformSelector:@selector(removeFromSuperview)];
-
- // Create popup and add it to this view.
- popup = [self popupButtonForGroup:groupInfo];
- NSRect popupFrame = [popup frame];
- popupFrame.origin.x = nextXCoord;
- [popup setFrame:popupFrame];
- groupInfo[GROUP_POPUP_BUTTON] = popup;
- [self addSubview:popup positioned:NSWindowBelow relativeTo:_accessoryView];
- nextXCoord += (NSInteger)(popupFrame.size.width);
-
- // Ensure popup has appropriate title.
- [self updateMenuTitleForGroupAtIndex:i];
-
- } else {
- // Remove and release popup.
- popup = groupInfo[GROUP_POPUP_BUTTON];
- [popup removeFromSuperview];
- [groupInfo removeObjectForKey:GROUP_POPUP_BUTTON];
-
- // Replace menuItems with buttons.
- CGFloat buttonX = nextXCoord;
- NSMutableArray *menuItems = groupInfo[GROUP_BUTTONS];
- NSArray *selectedItems = _selectedItems[i];
- for (NSUInteger ii = 0; ii < [menuItems count]; ii++) {
- NSMenuItem *menuItem = menuItems[ii];
- NSString *itemIdentifier = [menuItem representedObject];
- NSButton *button = [self buttonForItem:itemIdentifier
- inGroup:[menuItem tag]
- withTitle:[menuItem title]
- image:[menuItem image]];
- NSRect buttonFrame = [button frame];
- buttonFrame.origin.x = buttonX;
- [button setFrame:buttonFrame];
- if ([selectedItems containsObject:itemIdentifier]) {
- [button setState:NSControlStateValueOn];
- }
- [self addSubview:button positioned:NSWindowBelow relativeTo:_accessoryView];
- menuItems[ii] = button;
- buttonX += [button frame].size.width + SCOPE_BAR_ITEM_SPACING;
- }
- nextXCoord = (NSInteger)(buttonX - SCOPE_BAR_ITEM_SPACING);
- }
-
- // Update GROUP_MENU_MODE for this group.
- groupInfo[GROUP_MENU_MODE] = @(narrower);
- }
- }
-
- // Modify positions/sizes of groups and separators as required.
- float startIndex = MIN(changedRange.location, (NSUInteger)_firstCollapsedGroup);
- CGFloat xCoord = 0;
- CGFloat perGroupDelta = 0;
- if (shouldAdjustPopups) {
- perGroupDelta = ((_totalGroupsWidthForPopups - availableWidth) / [_groups count]);
- }
- for (NSUInteger i = (NSInteger)startIndex; i < [_groups count]; i++) {
- NSDictionary *groupInfo = _groups[i];
- BOOL groupMenuMode = [groupInfo[GROUP_MENU_MODE] boolValue];
-
- // Further contract or expand popups if appropriate.
- if (shouldAdjustPopups) {
- CGFloat fullPopupWidth = [groupInfo[GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING;
- CGFloat popupWidth = fullPopupWidth - perGroupDelta;
- popupWidth = MAX(popupWidth, MENU_MIN_WIDTH);
- popupWidth = MIN(popupWidth, fullPopupWidth);
-
- NSPopUpButton *button = groupInfo[GROUP_POPUP_BUTTON];
- NSRect buttonRect = [button frame];
- buttonRect.size.width = popupWidth;
- [button setFrame:buttonRect];
- }
-
- // Reposition groups appropriately.
- if (i > startIndex) {
- // Reposition separator if present.
- if ([groupInfo[GROUP_HAS_SEPARATOR] boolValue]) {
- _separatorPositions[i] = @((int)xCoord);
- xCoord += (SCOPE_BAR_SEPARATOR_WIDTH + SCOPE_BAR_ITEM_SPACING);
- }
-
- // Reposition label if present.
- if ([groupInfo[GROUP_HAS_LABEL] boolValue]) {
- NSTextField *label = groupInfo[GROUP_LABEL_FIELD];
- NSRect labelFrame = [label frame];
- labelFrame.origin.x = xCoord;
- [label setFrame:labelFrame];
- xCoord = NSMaxX(labelFrame) + SCOPE_BAR_ITEM_SPACING;
- }
-
- // Reposition buttons or popup.
- if (groupMenuMode) {
- NSPopUpButton *button = groupInfo[GROUP_POPUP_BUTTON];
- NSRect buttonRect = [button frame];
- buttonRect.origin.x = xCoord;
- [button setFrame:buttonRect];
- xCoord = NSMaxX(buttonRect) + SCOPE_BAR_ITEM_SPACING;
-
- } else {
- NSArray *buttons = groupInfo[GROUP_BUTTONS];
- for (NSButton *button in buttons) {
- NSRect buttonRect = [button frame];
- buttonRect.origin.x = xCoord;
- [button setFrame:buttonRect];
- xCoord = NSMaxX(buttonRect) + SCOPE_BAR_ITEM_SPACING;
- }
- }
-
- } else {
- // Set up initial value of xCoord.
- NSButton *button = nil;
- if (groupMenuMode) {
- button = groupInfo[GROUP_POPUP_BUTTON];
- } else {
- button = [groupInfo[GROUP_BUTTONS] lastObject];
- }
- xCoord = NSMaxX([button frame]) + SCOPE_BAR_ITEM_SPACING;
- }
- }
-
- // Reset _firstCollapsedGroup to NSNotFound if necessary.
- if (!narrower) {
- if (_firstCollapsedGroup >= (NSInteger)[_groups count]) {
- _firstCollapsedGroup = NSNotFound;
- }
- }
- }
- }
-
- // Take note of our width for comparison next time.
- _lastWidth = viewWidth;
-}
-
-
-- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
-{
- [super resizeSubviewsWithOldSize:oldBoundsSize];
- [self adjustSubviews];
-}
-
-- (NSButton *)getButtonForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber
-{
- NSButton *button = nil;
- NSArray *group = _identifiers[identifier];
- if (group && (NSInteger)[group count] > groupNumber) {
- NSObject *element = group[groupNumber];
- if (element != [NSNull null]) {
- button = (NSButton *)element;
- }
- }
-
- return button;
-}
-
-
-- (NSButton *)buttonForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image
-{
- NSRect ctrlRect = NSMakeRect(0, 0, 50, 20); // arbitrary size; will be resized later.
- NSButton *button = [[NSButton alloc] initWithFrame:ctrlRect];
- [button setTitle:title];
- [[button cell] setRepresentedObject:identifier];
- [button setTag:groupNumber];
- [button setFont:[NSFont boldSystemFontOfSize:_fontSize]];
- [button setTarget:self];
- [button setAction:@selector(scopeButtonClicked:)];
- [button setBezelStyle:NSBezelStyleAccessoryBar];
- [button setButtonType:NSButtonTypePushOnPushOff];
- [[button cell] setHighlightsBy:(NSCellStyleMask)(NSCellIsBordered | NSCellIsInsetButton)];
- [button setShowsBorderOnlyWhileMouseInside:YES];
- if (image) {
- [image setSize:NSMakeSize(SCOPE_BAR_BUTTON_IMAGE_SIZE, SCOPE_BAR_BUTTON_IMAGE_SIZE)];
- [button setImagePosition:NSImageLeft];
- [button setImage:image];
- }
- [button sizeToFit];
- ctrlRect = [button frame];
- ctrlRect.origin.y = floor(([self frame].size.height - ctrlRect.size.height) / 2.0);
- [button setFrame:ctrlRect];
-
- [self setControl:button forIdentifier:identifier inGroup:groupNumber];
-
- return button;
-}
-
-
-- (NSMenuItem *)menuItemForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber
- withTitle:(NSString *)title image:(NSImage *)image
-{
- NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:title action:@selector(scopeButtonClicked:) keyEquivalent:@""];
- [menuItem setTarget:self];
- [menuItem setImage:image];
- [menuItem setRepresentedObject:identifier];
- [menuItem setTag:groupNumber];
-
- [self setControl:menuItem forIdentifier:identifier inGroup:groupNumber];
-
- return menuItem;
-}
-
-
-- (NSPopUpButton *)popupButtonForGroup:(NSDictionary *)group
-{
- CGFloat popWidth = floor([group[GROUP_WIDEST_BUTTON_WIDTH] floatValue] + MENU_PADDING);
- NSRect popFrame = NSMakeRect(0, 0, popWidth, 20); // arbitrary height.
- NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame:popFrame pullsDown:NO];
-
- // Since we're not using the selected item's title, we need to specify a NSMenuItem for the title.
- BOOL multiSelect = ([group[GROUP_SELECTION_MODE] intValue] == MGScopeBarGroupSelectionModeMultiple);
- if (multiSelect) {
- MGRecessedPopUpButtonCell *cell = [[MGRecessedPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO];
- [popup setCell:cell];
-
- [[popup cell] setUsesItemFromMenu:NO];
- NSMenuItem *titleItem = [[NSMenuItem alloc] init];
- [[popup cell] setMenuItem:titleItem];
- }
-
- // Configure appearance and behaviour.
- [popup setFont:[NSFont boldSystemFontOfSize:_fontSize]];
- [popup setBezelStyle:NSBezelStyleAccessoryBar];
- [popup setButtonType:NSButtonTypePushOnPushOff];
- [[popup cell] setHighlightsBy:(NSCellStyleMask)(NSCellIsBordered | NSCellIsInsetButton)];
- [popup setShowsBorderOnlyWhileMouseInside:NO];
- [[popup cell] setAltersStateOfSelectedItem:NO];
- [[popup cell] setArrowPosition:NSPopUpArrowAtBottom];
- [popup setPreferredEdge:NSMaxXEdge];
-
- // Add appropriate items.
- [popup removeAllItems];
- NSMutableArray *buttons = group[GROUP_BUTTONS];
- for (NSUInteger i = 0; i < [buttons count]; i++) {
- NSButton *button = (NSButton *)buttons[i];
- NSMenuItem *menuItem = [self menuItemForItem:[[button cell] representedObject]
- inGroup:[button tag]
- withTitle:[button title]
- image:[button image]];
- [menuItem setState:[button state]];
- buttons[i] = menuItem;
- [[popup menu] addItem:menuItem];
- }
-
- // Vertically center the popup within our frame.
- if (!multiSelect) {
- [popup sizeToFit];
- }
- popFrame = [popup frame];
- popFrame.origin.y = ceil(([self frame].size.height - popFrame.size.height) / 2.0);
- [popup setFrame:popFrame];
-
- return popup;
-}
-
-
-- (void)setControl:(NSObject *)control forIdentifier:(NSString *)identifier inGroup:(NSInteger)groupNumber
-{
- if (!_identifiers) {
- _identifiers = [[NSMutableDictionary alloc] initWithCapacity:0];
- }
-
- NSMutableArray *identArray = _identifiers[identifier];
- if (!identArray) {
- identArray = [[NSMutableArray alloc] initWithCapacity:groupNumber + 1];
- _identifiers[identifier] = identArray;
- }
-
- NSInteger count = [identArray count];
- if (groupNumber >= count) {
- // Pad identArray with nulls if appropriate, so this control lies at index groupNumber.
- for (NSInteger i = count; i < groupNumber; i++) {
- [identArray addObject:[NSNull null]];
- }
- [identArray addObject:control];
- } else {
- identArray[groupNumber] = control;
- }
-}
-
-
-- (void)updateMenuTitleForGroupAtIndex:(NSInteger)groupNumber
-{
- // Ensure that this group's popup (if present) has the correct title,
- // accounting for the group's selection-mode and selected item(s).
-
- if (groupNumber < 0 || groupNumber >= (NSInteger)[_groups count]) {
- return;
- }
-
- NSDictionary *group = _groups[groupNumber];
- if (group) {
- NSPopUpButton *popup = group[GROUP_POPUP_BUTTON];
- if (popup) {
- NSArray *groupSelection = _selectedItems[groupNumber];
- NSInteger numSelected = [groupSelection count];
- if (numSelected == 0) {
- // No items selected.
- [popup setTitle:POPUP_TITLE_EMPTY_SELECTION];
- [[[popup cell] menuItem] setImage:nil];
-
- } else if (numSelected > 1) {
- // Multiple items selected.
- [popup setTitle:POPUP_TITLE_MULTIPLE_SELECTION];
- [[[popup cell] menuItem] setImage:nil];
-
- } else {
- // One item selected.
- NSString *identifier = groupSelection[0];
- NSArray *items = group[GROUP_BUTTONS];
- NSMenuItem *item = nil;
- for (NSMenuItem *thisItem in items) {
- if ([[thisItem representedObject] isEqualToString:identifier]) {
- item = thisItem;
- break;
- }
- }
- if (item) {
- [popup setTitle:[item title]];
- [[[popup cell] menuItem] setImage:[item image]];
- }
- }
-
- if (SCOPE_BAR_HIDE_POPUP_BG) {
- BOOL hasBackground = [[popup cell] isBordered];
- if (numSelected == 0 && hasBackground) {
- [[popup cell] setBordered:NO];
- } else if (!hasBackground) {
- [[popup cell] setBordered:YES];
- }
- }
- }
- }
-}
-
-
-#pragma mark Drawing
-
-
-- (void)drawRect:(NSRect)rect
-{
- [super drawRect:rect];
-
- // Draw border.
- NSRect lineRect = [self bounds];
- lineRect.size.height = SCOPE_BAR_BORDER_WIDTH;
- [SCOPE_BAR_BORDER_COLOR set];
- NSRectFill(lineRect);
-
- // Draw separators.
- if ([_separatorPositions count] > 0) {
- [SCOPE_BAR_SEPARATOR_COLOR set];
- NSRect sepRect = NSMakeRect(0, 0, SCOPE_BAR_SEPARATOR_WIDTH, SCOPE_BAR_SEPARATOR_HEIGHT);
- sepRect.origin.y = (([self bounds].size.height - sepRect.size.height) / 2.0);
- for (NSObject *sepPosn in _separatorPositions) {
- if (sepPosn != [NSNull null]) {
- sepRect.origin.x = [(NSNumber *)sepPosn intValue];
- NSRectFill(sepRect);
- }
- }
- }
-}
-
-
-#pragma mark Interaction
-
-
-- (IBAction)scopeButtonClicked:(id)sender
-{
- NSButton *button = (NSButton *)sender;
- BOOL menuMode = [sender isKindOfClass:[NSMenuItem class]];
- NSString *identifier = [((menuMode) ? sender : [sender cell]) representedObject];
- NSInteger groupNumber = [sender tag];
- BOOL nowSelected = YES;
- if (menuMode) {
- // MenuItem. Ensure item has appropriate state.
- nowSelected = ![_selectedItems[groupNumber] containsObject:identifier];
- [sender setState:((nowSelected) ? NSControlStateValueOn : NSControlStateValueOff)];
- } else {
- // Button. Item will already have appropriate state.
- nowSelected = ([button state] != NSControlStateValueOff);
- }
- [self setSelected:nowSelected forItem:identifier inGroup:groupNumber];
-}
-
-
-#pragma mark Accessors and properties
-
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber informDelegate:(BOOL)informDelegate {
- // Change state of other items in group appropriately, informing delegate if possible.
- // First we find the appropriate group-info for the item's identifier.
- if (identifier && groupNumber >= 0 && groupNumber < (NSInteger)[_groups count]) {
- NSDictionary *group = _groups[groupNumber];
- BOOL nowSelected = selected;
-
- if (group) {
- // We found the group which this item belongs to. Obtain selection-mode and identifiers.
- MGScopeBarGroupSelectionMode selMode = [group[GROUP_SELECTION_MODE] intValue];
- BOOL radioMode = (selMode == MGScopeBarGroupSelectionModeRadio);
-
- if (radioMode) {
- // This is a radio-mode group. Ensure this item isn't already selected.
- NSArray *groupSelections = [_selectedItems[groupNumber] copy];
-
- if (nowSelected) {
- // Before selecting this item, we first need to deselect any other selected items in this group.
- for (NSString *selectedIdentifier in groupSelections) {
- // Reselect the just-deselected item without informing the delegate, since nothing really changed.
- [self updateSelectedState:NO forItem:selectedIdentifier inGroup:groupNumber informDelegate:NO];
- }
- } else {
- // Prevent deselection if this item is already selected.
- if ([groupSelections containsObject:identifier]) {
- nowSelected = YES;
- informDelegate = NO;
- }
- }
- }
-
- // Change selected state of this item.
- [self updateSelectedState:nowSelected forItem:identifier inGroup:groupNumber informDelegate:informDelegate];
-
- // Update popup-menu's title if appropriate.
- if ([group[GROUP_MENU_MODE] boolValue]) {
- [self updateMenuTitleForGroupAtIndex:groupNumber];
- }
- }
- }
-}
-
-- (void)setSelected:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber {
- [self setSelected:selected forItem:identifier inGroup:groupNumber informDelegate:YES];
-}
-
-- (void)updateSelectedState:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber informDelegate:(BOOL)inform
-{
- if (identifier == nil) {
- return;
- }
- // This method simply updates the selected state of the item's control, maintains selectedItems, and informs the delegate.
- // All management of dependencies (such as deselecting other selected items in a radio-selection-mode group) is performed
- // in the setSelected:forItem:inGroup: method.
-
- // Determine whether we can inform the delegate about this change.
- SEL stateChangedSel = @selector(scopeBar:selectedStateChanged:forItem:inGroup:);
- BOOL responds = (delegate && [delegate respondsToSelector:stateChangedSel]);
-
- // Ensure selected status of item's control reflects desired value.
- NSButton *button = [self getButtonForItem:identifier inGroup:groupNumber];
- if (selected && [button state] == NSControlStateValueOff) {
- [button setState:NSControlStateValueOn];
- } else if (!selected && [button state] != NSControlStateValueOff) {
- [button setState:NSControlStateValueOff];
- }
-
- // Maintain _selectedItems appropriately.
- if (_selectedItems && (NSInteger)[_selectedItems count] > groupNumber) {
- NSMutableArray *groupSelections = _selectedItems[groupNumber];
- BOOL alreadySelected = [groupSelections containsObject:identifier];
- if (selected && !alreadySelected) {
- [groupSelections addObject:identifier];
- } else if (!selected && alreadySelected) {
- [groupSelections removeObject:identifier];
- }
- }
-
- // Inform delegate about this change if possible.
- if (inform && responds) {
- [delegate scopeBar:self selectedStateChanged:selected forItem:identifier inGroup:groupNumber];
- }
-}
-
-
-- (NSArray *)selectedItems
-{
- return [_selectedItems copy];
-}
-
-
-- (void)setDelegate:(id)newDelegate
-{
- if (delegate != newDelegate) {
- delegate = newDelegate;
- [self reloadData];
- }
-}
-
-
-- (BOOL)smartResizeEnabled
-{
- return _smartResizeEnabled;
-}
-
-
-- (void)setSmartResizeEnabled:(BOOL)enabled
-{
- if (enabled != _smartResizeEnabled) {
- _smartResizeEnabled = enabled;
- [self reloadData];
- }
-}
-
-- (void)setEnabledAllGroups:(BOOL)enable {
- for (int i = 0; i < (NSInteger)_groups.count; i++) {
- [self setEnabledGroup:i enable:enable];
- }
-}
-
-- (void)setEnabledGroup:(int)groupNumber enable:(BOOL)enable {
- NSDictionary *group = _groups[groupNumber];
- if (group) {
- NSArray* buttons = group[GROUP_BUTTONS];
- for (NSButton* button in buttons) {
- [button setEnabled:enable];
- }
- }
-}
-
-- (BOOL)notifyDefaultSelections {
- return _notifyDefaultSelections;
-}
-
-- (void)setNotifyDefaultSelections:(BOOL)v {
- _notifyDefaultSelections = v;
-}
-
-- (CGFloat)fontSize {
- return _fontSize;
-}
-
-- (void)setFontSize:(CGFloat)fontSize {
- _fontSize = fontSize;
-}
-
-@synthesize delegate;
-
-
-@end
diff --git a/Sources/Legacy/MGScopeBar/MGScopeBarDelegateProtocol.h b/Sources/Legacy/MGScopeBar/MGScopeBarDelegateProtocol.h
deleted file mode 100644
index 178eef8..0000000
--- a/Sources/Legacy/MGScopeBar/MGScopeBarDelegateProtocol.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// MGScopeBarDelegateProtocol.h
-// MGScopeBar
-//
-// Created by Matt Gemmell on 15/03/2008.
-// Copyright 2008 Instinctive Code.
-//
-
-#import
-
-NS_ASSUME_NONNULL_BEGIN
-
-// Selection modes for the buttons within a group.
-typedef NS_ENUM(NSInteger, MGScopeBarGroupSelectionMode) {
- MGScopeBarGroupSelectionModeRadio = 0, // Exactly one item in the group will be selected at a time (no more, and no less).
- MGScopeBarGroupSelectionModeMultiple = 1 // Any number of items in the group (including none) may be selected at a time.
-};
-
-
-@class MGScopeBar;
-@protocol MGScopeBarDelegate
-
-
-// Methods used to configure the scope bar.
-// Note: all groupNumber parameters are zero-based.
-
-@required
-- (NSInteger)numberOfGroupsInScopeBar:(MGScopeBar *)theScopeBar;
-- (NSArray *)scopeBar:(MGScopeBar *)theScopeBar itemIdentifiersForGroup:(NSInteger)groupNumber;
-- (nullable NSString *)scopeBar:(MGScopeBar *)theScopeBar labelForGroup:(NSInteger)groupNumber; // return nil or an empty string for no label.
-- (MGScopeBarGroupSelectionMode)scopeBar:(MGScopeBar *)theScopeBar selectionModeForGroup:(NSInteger)groupNumber;
-- (nullable NSString *)scopeBar:(MGScopeBar *)theScopeBar titleOfItem:(NSString *)identifier inGroup:(NSInteger)groupNumber;
-
-@optional
-// If the following method is not implemented, all groups except the first will have a separator before them.
-- (BOOL)scopeBar:(MGScopeBar *)theScopeBar showSeparatorBeforeGroup:(NSInteger)groupNumber;
-- (nullable NSImage *)scopeBar:(MGScopeBar *)theScopeBar imageForItem:(NSString *)identifier inGroup:(NSInteger)groupNumber; // default is no image. Will be shown at 16x16.
-- (nullable NSView *)accessoryViewForScopeBar:(MGScopeBar *)theScopeBar; // default is no accessory view.
-
-
-// Notification methods.
-
-@optional
-- (void)scopeBar:(MGScopeBar *)theScopeBar selectedStateChanged:(BOOL)selected forItem:(NSString *)identifier inGroup:(NSInteger)groupNumber;
-
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Sources/Legacy/MGScopeBar/ScopeBarItem.swift b/Sources/Legacy/MGScopeBar/ScopeBarItem.swift
deleted file mode 100644
index 1eb8d6d..0000000
--- a/Sources/Legacy/MGScopeBar/ScopeBarItem.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// ScopeBarItem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/06/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-enum ScopeBarGroupKey: String {
- case label = "Label" // string
- case separator = "HasSeparator" // Bool as NSNumber
- case selectionMode = "SelectionMode" // MGScopeBarGroupSelectionMode (int) as NSNumber
- case items = "Items" // array of dictionaries, each containing the following keys
-}
-
-enum ScopeBarItem: String {
- case identifier = "Identifier" // string
- case name = "Name" // string
-}
diff --git a/Sources/Legacy/Predicate/NSPredicate+Objc.h b/Sources/Legacy/Predicate/NSPredicate+Objc.h
deleted file mode 100644
index 7dd638d..0000000
--- a/Sources/Legacy/Predicate/NSPredicate+Objc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// NSPredicate+Objc.h
-// VisualDiffer
-//
-// Created by davide ficano on 02/06/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface NSPredicate (Helper)
-
-/**
- * Create NSPredicate handling Objective-C NSException
- */
-+ (nullable instancetype)createSafeWithFormat:(NSString*)format error:(NSError *_Nullable * _Nullable)outError;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Sources/Legacy/Predicate/NSPredicate+Objc.m b/Sources/Legacy/Predicate/NSPredicate+Objc.m
deleted file mode 100644
index 12dcc34..0000000
--- a/Sources/Legacy/Predicate/NSPredicate+Objc.m
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// NSPredicate+Objc.m
-// VisualDiffer
-//
-// Created by davide ficano on 02/06/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import "NSPredicate+Objc.h"
-
-@implementation NSPredicate (Helper)
-
-+ (instancetype)createSafeWithFormat:(NSString*)format error: (NSError**)outError {
- @try {
- return [NSPredicate predicateWithFormat: format];
- }
- @catch (NSException* exception) {
- if (outError) {
- *outError = [NSError errorWithDomain:NSCocoaErrorDomain
- code:NSFormattingError
- userInfo:@{NSLocalizedDescriptionKey: exception.description}];
-
- }
- }
- return nil;
-}
-
-@end
diff --git a/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.h b/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.h
deleted file mode 100644
index d215e62..0000000
--- a/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// FileSizePredicateEditorRowTemplate.h
-// VisualDiffer
-//
-// Created by davide ficano on 07/03/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-#import
-#import "TitlePredicateEditorRowTemplate.h"
-
-@interface TOPFileSizePredicateEditorRowTemplate : TitlePredicateEditorRowTemplate
-
-@property (strong) NSPopUpButton* sizePopupButton;
-@end
diff --git a/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.m b/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.m
deleted file mode 100644
index 02558d8..0000000
--- a/Sources/Legacy/Predicate/TOPFileSizePredicateEditorRowTemplate.m
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// FileSizePredicateEditorRowTemplate.m
-// VisualDiffer
-//
-// Created by davide ficano on 07/03/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-#import "TOPFileSizePredicateEditorRowTemplate.h"
-
-static const NSInteger VD_SIZE_KB = (1024L);
-static const NSInteger VD_SIZE_MB = (VD_SIZE_KB * 1024);
-static const NSInteger VD_SIZE_GB = (VD_SIZE_MB * 1024);
-
-@implementation TOPFileSizePredicateEditorRowTemplate
-
-- (NSArray *)templateViews {
- if (self.sizePopupButton == nil) {
- self.sizePopupButton = [[NSPopUpButton alloc] init];
- [self.sizePopupButton addItemsWithTitles:@[@"Bytes", @"KB", @"MB", @"GB"]];
- }
- NSArray* myviews = super.templateViews;
- return @[myviews[0],
- myviews[1],
- myviews[2],
- self.sizePopupButton];
-}
-
-- (void)setPredicate:(NSPredicate *)predicate {
- NSComparisonPredicate* comparisonPredicate = (NSComparisonPredicate *)predicate;
- long long num = [comparisonPredicate.rightExpression.constantValue longLongValue];
- long long size;
-
- // show in the view the original value entered by user
- if ((num % VD_SIZE_GB) == 0) {
- size = num / VD_SIZE_GB;
- [self.sizePopupButton selectItemAtIndex:3];
- } else if ((num % VD_SIZE_MB) == 0) {
- size = num / VD_SIZE_MB;
- [self.sizePopupButton selectItemAtIndex:2];
- } else if ((num % VD_SIZE_KB) == 0) {
- size = num / VD_SIZE_KB;
- [self.sizePopupButton selectItemAtIndex:1];
- } else {
- size = num;
- [self.sizePopupButton selectItemAtIndex:0];
- }
-
- NSExpression* bytesExpression = [NSExpression expressionForConstantValue:@(size)];
- predicate = [NSComparisonPredicate predicateWithLeftExpression:comparisonPredicate.leftExpression
- rightExpression:bytesExpression
- modifier:comparisonPredicate.comparisonPredicateModifier
- type:comparisonPredicate.predicateOperatorType
- options:comparisonPredicate.options];
- [super setPredicate:predicate];
-}
-
-- (NSPredicate *)predicateWithSubpredicates:(NSArray *)subpredicates {
- long unitySize = 1;
-
- NSPopUpButton* button = (NSPopUpButton*)self.templateViews[3];
- switch (button.indexOfSelectedItem) {
- case 0:
- unitySize = 1;
- break;
- case 1:
- unitySize = VD_SIZE_KB;
- break;
- case 2:
- unitySize = VD_SIZE_MB;
- break;
- case 3:
- unitySize = VD_SIZE_GB;
- break;
- }
-
- NSComparisonPredicate *predicate = (NSComparisonPredicate *)[super predicateWithSubpredicates:subpredicates];
- long long num = [predicate.rightExpression.constantValue longLongValue];
-
- // create the NSPredicate multiplying the value by unity size
- NSExpression* bytesExpression = [NSExpression expressionForConstantValue:@(num * unitySize)];
- return [NSComparisonPredicate predicateWithLeftExpression:predicate.leftExpression
- rightExpression:bytesExpression
- modifier:predicate.comparisonPredicateModifier
- type:predicate.predicateOperatorType
- options:predicate.options];
-}
-
-@end
diff --git a/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.h b/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.h
deleted file mode 100644
index 7a577b3..0000000
--- a/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// VDTimestampPredicateEditorRowTemplate.h
-// VisualDiffer
-//
-// Created by davide ficano on 07/03/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-#import
-#import "TitlePredicateEditorRowTemplate.h"
-
-@interface TOPTimestampPredicateEditorRowTemplate : TitlePredicateEditorRowTemplate
-
-@end
diff --git a/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.m b/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.m
deleted file mode 100644
index 372a28b..0000000
--- a/Sources/Legacy/Predicate/TOPTimestampPredicateEditorRowTemplate.m
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// VDTimestampPredicateEditorRowTemplate.m
-// VisualDiffer
-//
-// Created by davide ficano on 07/03/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-#import "TOPTimestampPredicateEditorRowTemplate.h"
-
-const NSInteger VDTimestampElementFlag = NSDatePickerElementFlagYearMonthDay | NSDatePickerElementFlagHourMinuteSecond;
-
-static NSDateFormatter* TOPTimestampPredicateEditorDateFormatter;
-
-@interface TOPTimestampPredicateEditorRowTemplate() {
- BOOL isDefaultValuesSet;
-}
-@end;
-
-@implementation TOPTimestampPredicateEditorRowTemplate
-
-- (instancetype)init
-{
- self = [super init];
- if (self) {
- static dispatch_once_t pred;
-
- dispatch_once(&pred, ^{
- TOPTimestampPredicateEditorDateFormatter = [[NSDateFormatter alloc] init];
- TOPTimestampPredicateEditorDateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss z";
- TOPTimestampPredicateEditorDateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
- TOPTimestampPredicateEditorDateFormatter.timeZone = [NSTimeZone defaultTimeZone];
- TOPTimestampPredicateEditorDateFormatter.formatterBehavior = NSDateFormatterBehaviorDefault;
- });
- }
- return self;
-}
-
-- (NSArray *)templateViews {
- if (!isDefaultValuesSet) {
- NSDatePicker* picker = (NSDatePicker*)super.templateViews[2];
- picker.datePickerElements = VDTimestampElementFlag;
- picker.dateValue = [NSDate date];
- isDefaultValuesSet = YES;
- }
-
- return super.templateViews;
-}
-
-- (NSPredicate *)predicateWithSubpredicates:(NSArray *)subpredicates {
- NSComparisonPredicate *predicate = (NSComparisonPredicate *)[super predicateWithSubpredicates:subpredicates];
- // set to zero from the decimal part present in the NSTimeInterval
- // so exact compares (eg a == b) can be done correctly
- NSDatePicker* picker = (NSDatePicker*)super.templateViews[2];
- NSDate* d1 = picker.dateValue;
- NSDate* d2 = [TOPTimestampPredicateEditorDateFormatter dateFromString:d1.description];
-
- NSExpression* dateExpression = [NSExpression expressionForConstantValue:d2];
- return [NSComparisonPredicate predicateWithLeftExpression:predicate.leftExpression
- rightExpression:dateExpression
- modifier:predicate.comparisonPredicateModifier
- type:predicate.predicateOperatorType
- options:predicate.options];
-}
-
-@end
diff --git a/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.h b/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.h
deleted file mode 100644
index e7c5cb8..0000000
--- a/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// TitlePredicateEditorRowTemplate.h
-// VisualDiffer
-//
-// Created by davide ficano on 25/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface TitlePredicateEditorRowTemplate : NSPredicateEditorRowTemplate
-
-- (instancetype)initWithKeyPathDisplayNames:(NSDictionary*)displayNames
- leftKeyPath:(NSString *)leftKeyPath
- rightExpressionAttributeType:(NSAttributeType)attributeType
- caseInsensitive:(BOOL)caseInsensitive
- operators:(NSArray*>*)operators;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.m b/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.m
deleted file mode 100644
index c821f54..0000000
--- a/Sources/Legacy/Predicate/TitlePredicateEditorRowTemplate.m
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// TitlePredicateEditorRowTemplate.m
-// VisualDiffer
-//
-// Created by davide ficano on 25/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-#import "TitlePredicateEditorRowTemplate.h"
-
-@interface TitlePredicateEditorRowTemplate()
-@property (nonatomic, copy) NSDictionary* keyPathDisplayNames;
-@property (nonatomic, copy) NSDictionary* operatorDisplayNames;
-@end
-
-@implementation TitlePredicateEditorRowTemplate
-
-- (instancetype)initWithKeyPathDisplayNames:(NSDictionary*)displayNames
- leftKeyPath:(NSString *)leftKeyPath
- rightExpressionAttributeType:(NSAttributeType)attributeType
- caseInsensitive:(BOOL)caseInsensitive
- operators:(NSArray*>*)operators {
- NSExpression *leftExpr = [NSExpression expressionForKeyPath:leftKeyPath];
- NSMutableArray* ops = [NSMutableArray array];
-
- // used to maintain the order inside popup menu
- for (NSDictionary* dict in operators) {
- [ops addObjectsFromArray:dict.allKeys];
- }
-
- self = [super initWithLeftExpressions:@[leftExpr]
- rightExpressionAttributeType:attributeType
- modifier:NSDirectPredicateModifier
- operators:ops
- options:caseInsensitive ? NSCaseInsensitivePredicateOption : 0];
-
- if (self) {
- NSMutableDictionary* map = [NSMutableDictionary dictionary];
-
- for (NSDictionary* dict in operators) {
- [dict enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
- map[key] = obj;
- }];
- }
- self.operatorDisplayNames = map;
- self.keyPathDisplayNames = displayNames;
- }
- return self;
-};
-
-- (NSArray *)templateViews {
- NSArray *views = [super templateViews];
-
- for (NSView *view in views) {
- if ([view isKindOfClass:[NSPopUpButton class]]) {
- NSPopUpButton *popup = (NSPopUpButton *)view;
-
- for (NSMenuItem *item in popup.itemArray) {
- id represented = item.representedObject;
-
- // Customize key path titles
- if ([represented isKindOfClass:[NSExpression class]]) {
- NSExpression *expr = (NSExpression *)represented;
-
- if (expr.expressionType == NSKeyPathExpressionType) {
- NSString *keyPath = expr.keyPath;
- NSString *display = self.keyPathDisplayNames[keyPath];
- if (display) {
- item.title = display;
- }
- }
- }
-
- // Customize operator titles
- if ([represented isKindOfClass:[NSNumber class]]) {
- NSNumber *opType = (NSNumber *)represented;
- NSString *customOp = self.operatorDisplayNames[opType];
- if (customOp) {
- item.title = customOp;
- }
- }
- }
- }
- }
-
- return views;
-}
-@end
diff --git a/Sources/Services/AppleScript/OpenDiffCommand.swift b/Sources/Services/AppleScript/OpenDiffCommand.swift
deleted file mode 100644
index 9309bd5..0000000
--- a/Sources/Services/AppleScript/OpenDiffCommand.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// OpenDiffCommand.swift
-// VisualDiffer
-//
-// Created by davide ficano on 04/11/20.
-// Copyright (c) 2020 visualdiffer.com
-//
-
-enum CommandError: Int {
- case invalidPath = 4000
- case invalidDocument
-}
-
-// the attribute @objc is necessary to work correctly in Swift
-@objc(OpenDiffCommand) class OpenDiffCommand: NSScriptCommand {
- override func performDefaultImplementation() -> Any? {
- guard let evaluatedArguments,
- let leftPath = evaluatedArguments["LeftPath"] as? String,
- let rightPath = evaluatedArguments["RightPath"] as? String else {
- return nil
- }
-
- let leftUrl = URL(filePath: leftPath)
- let rightUrl = URL(filePath: rightPath)
-
- var isDir = false
- var leftExists = false
- var rightExists = false
-
- let matches = leftUrl.matchesFileType(
- of: rightUrl,
- isDir: &isDir,
- leftExists: &leftExists,
- rightExists: &rightExists
- )
-
- if matches {
- return openDocument(
- leftUrl: leftUrl,
- rightUrl: rightUrl
- )
- } else {
- let message = invalidPathMessage(
- isDir: isDir,
- leftExists: leftExists,
- rightExists: rightExists
- )
- setScriptError(error: .invalidPath, message: message)
- }
- return nil
- }
-
- func openDocument(
- leftUrl: URL,
- rightUrl: URL
- ) -> String? {
- do {
- return try MainActor.assumeIsolated {
- try VDDocumentController.shared.openDifferDocument(
- leftUrl: leftUrl,
- rightUrl: rightUrl
- )?.uuid
- }
- } catch {
- setScriptError(error: .invalidDocument, message: error.localizedDescription)
-
- return nil
- }
- }
-
- func invalidPathMessage(isDir: Bool, leftExists: Bool, rightExists: Bool) -> String {
- if leftExists, rightExists {
- if isDir {
- return NSLocalizedString("Left path is a folder but the right is a file; both must be folders or files", comment: "")
- } else {
- return NSLocalizedString("Left path is a file but the right is a folder; both must be folders or files", comment: "")
- }
- }
- if !leftExists {
- return NSLocalizedString("Left path doesn't exist", comment: "")
- }
- return NSLocalizedString("Right path doesn't exist", comment: "")
- }
-
- func setScriptError(error: CommandError, message: String) {
- scriptErrorNumber = error.rawValue
- scriptErrorString = message
- }
-}
diff --git a/Sources/SharedKit/Extensions/Appearance/NSAppearance+DarkMode.swift b/Sources/SharedKit/Extensions/Appearance/NSAppearance+DarkMode.swift
deleted file mode 100644
index eb9417f..0000000
--- a/Sources/SharedKit/Extensions/Appearance/NSAppearance+DarkMode.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// NSAppearance+DarkMode.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/10/20.
-// Copyright (c) 2020 visualdiffer.com
-//
-
-extension NSAppearance {
- static var isDarkMode: Bool {
- if #available(macOS 10.14, *) {
- return MainActor.assumeIsolated {
- let basicAppearance = NSApp.effectiveAppearance.bestMatch(from: [
- NSAppearance.Name.aqua,
- NSAppearance.Name.darkAqua,
- ])
- return basicAppearance == NSAppearance.Name.darkAqua
- }
- }
- // check 'AppleInterfaceStyle'
- return UserDefaults.standard.string(forKey: "AppleInterfaceStyle") == "Dark"
- }
-
- @objc @MainActor static func change() {
- if #available(macOS 10.14, *) {
- switch UserDefaults.standard.integer(forKey: "appAppearance") {
- case 1:
- NSApp.appearance = NSAppearance(named: .aqua)
- case 2:
- NSApp.appearance = NSAppearance(named: .darkAqua)
- default:
- break
- }
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Collections/Array+MoveIndexes.swift b/Sources/SharedKit/Extensions/Collections/Array+MoveIndexes.swift
deleted file mode 100644
index dab4c7f..0000000
--- a/Sources/SharedKit/Extensions/Collections/Array+MoveIndexes.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Array+MoveIndexes.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/05/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-extension Array {
- mutating func move(from indexes: IndexSet, to toIndex: Int) -> IndexSet {
- var toIndexBlock = toIndex
- var delta = 0
-
- for fromIdx in indexes {
- if fromIdx < toIndexBlock {
- let obj = self[fromIdx + delta]
- insert(obj, at: toIndexBlock)
- remove(at: fromIdx + delta)
- delta -= 1
- } else if fromIdx > toIndexBlock {
- let obj = self[fromIdx]
- remove(at: fromIdx)
- insert(obj, at: toIndexBlock)
- toIndexBlock += 1
- }
- }
- var movedIndexes = IndexSet()
- for i in 0 ..< indexes.count {
- movedIndexes.insert(toIndex + delta + i)
- }
- return movedIndexes
- }
-}
diff --git a/Sources/SharedKit/Extensions/Color/NSColor+Hex.swift b/Sources/SharedKit/Extensions/Color/NSColor+Hex.swift
deleted file mode 100644
index 205ff35..0000000
--- a/Sources/SharedKit/Extensions/Color/NSColor+Hex.swift
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// NSColor+Hex.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Cocoa
-
-extension NSColor {
- @objc static func colorRGBA(_ red: UInt, green: UInt, blue: UInt, alpha: UInt) -> NSColor {
- NSColor(
- calibratedRed: CGFloat(red) / 255.0,
- green: CGFloat(green) / 255.0,
- blue: CGFloat(blue) / 255.0,
- alpha: CGFloat(alpha) / 255.0
- )
- }
-
- @objc static func colorFromHexRGBA(_ inColorString: String) -> NSColor? {
- var red: UInt = 0
- var green: UInt = 0
- var blue: UInt = 0
- var alpha: UInt = 0
-
- if hexRGBA(inColorString, red: &red, green: &green, blue: &blue, alpha: &alpha) {
- return colorRGBA(red, green: green, blue: blue, alpha: alpha)
- }
- return nil
- }
-
- static func hexRGBA(
- _ inColorString: String,
- red: inout UInt,
- green: inout UInt,
- blue: inout UInt,
- alpha: inout UInt
- ) -> Bool {
- let scanner = Scanner(string: inColorString)
-
- // skip the prefix character if present
- _ = scanner.scanString("#")
-
- let hexDigitsCount = scanner.string.distance(
- from: scanner.currentIndex,
- to: scanner.string.endIndex
- )
- var hex: UInt64 = 0
-
- guard scanner.scanHexInt64(&hex) else {
- return false
- }
- switch hexDigitsCount {
- case 3:
- red = UInt((hex >> 8) & 15)
- red += red << 4
- green = UInt((hex >> 4) & 15)
- green += green << 4
- blue = UInt(hex & 15)
- blue += blue << 4
- alpha = 255
- case 6:
- red = UInt((hex >> 16) & 255)
- green = UInt((hex >> 8) & 255)
- blue = UInt(hex & 255)
- alpha = 255
- default:
- red = UInt((hex >> 24) & 255)
- green = UInt((hex >> 16) & 255)
- blue = UInt((hex >> 8) & 255)
- alpha = UInt(hex & 255)
- }
- return true
- }
-}
diff --git a/Sources/SharedKit/Extensions/CoreData/NSManagedObjectContext+Helpers.swift b/Sources/SharedKit/Extensions/CoreData/NSManagedObjectContext+Helpers.swift
deleted file mode 100644
index d685397..0000000
--- a/Sources/SharedKit/Extensions/CoreData/NSManagedObjectContext+Helpers.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// NSManagedObjectContext+Helpers.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/10/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-extension NSManagedObjectContext {
- ///
- /// Wrap the block around disable/enable undo registration pair
- ///
- /// Parameters:
- /// - block: the code to execute with registration disabled
- @MainActor func updateWithoutRecordingModifications(_ block: () -> Void) {
- undoManager?.disableUndoRegistration()
-
- block()
-
- processPendingChanges()
- undoManager?.enableUndoRegistration()
- }
-}
diff --git a/Sources/SharedKit/Extensions/Date/TimeInterval+Helper.swift b/Sources/SharedKit/Extensions/Date/TimeInterval+Helper.swift
deleted file mode 100644
index a983ccb..0000000
--- a/Sources/SharedKit/Extensions/Date/TimeInterval+Helper.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// TimeInterval+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/05/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-extension TimeInterval {
- func format() -> String {
- if self < 60 {
- return String(format: NSLocalizedString("%.2f seconds", comment: ""), self)
- }
- let longInterval = Int64(self)
- let hours = longInterval / 3600
- let minutes = (longInterval % 3600) / 60
- let seconds = longInterval % 60
-
- var result = [String]()
- if hours > 0 {
- result.append(String.localizedStringWithFormat(NSLocalizedString("%ld hours", comment: ""), hours))
- }
- if minutes > 0 {
- result.append(String.localizedStringWithFormat(NSLocalizedString("%ld minutes", comment: ""), minutes))
- }
- if seconds > 0 {
- result.append(String.localizedStringWithFormat(NSLocalizedString("%ld seconds", comment: ""), seconds))
- }
- return result.joined(separator: ", ")
- }
-}
diff --git a/Sources/SharedKit/Extensions/Encoding/CFStringEncoding+StringEncoding.swift b/Sources/SharedKit/Extensions/Encoding/CFStringEncoding+StringEncoding.swift
deleted file mode 100644
index e03c9b1..0000000
--- a/Sources/SharedKit/Extensions/Encoding/CFStringEncoding+StringEncoding.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// CFStringEncoding+StringEncoding.swift
-// VisualDiffer
-//
-// Created by davide ficano on 16/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-let noStringEncoding = String.Encoding(rawValue: UInt.max - 1)
-
-extension CFStringEncoding {
- @inline(__always) var stringEncoding: String.Encoding? {
- let nsEncoding = CFStringConvertEncodingToNSStringEncoding(self)
- if nsEncoding == kCFStringEncodingInvalidId {
- return nil
- }
- return String.Encoding(rawValue: nsEncoding)
- }
-}
-
-extension CFStringEncodings {
- @inline(__always) var stringEncoding: String.Encoding? {
- CFStringEncoding(rawValue).stringEncoding
- }
-}
diff --git a/Sources/SharedKit/Extensions/Error/NSError+Format.swift b/Sources/SharedKit/Extensions/Error/NSError+Format.swift
deleted file mode 100644
index c60248f..0000000
--- a/Sources/SharedKit/Extensions/Error/NSError+Format.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// NSError+Format.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/08/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-extension NSError {
- func format(withPath path: String) -> String {
- switch domain {
- case NSOSStatusErrorDomain:
- String(format: "%@: %@", path, self)
- case NSCocoaErrorDomain:
- if code == NSFileReadNoPermissionError,
- let attrs = try? FileManager.default.attributesOfItem(atPath: path).fileAttributeType,
- attrs == .typeSymbolicLink,
- let destination = try? FileManager.default.destinationOfSymbolicLink(atPath: path) {
- String.localizedStringWithFormat(
- NSLocalizedString("Permission denied: symbolic link at %@ points to destination %@. Add the destination to 'Trusted Paths' to allow access.", comment: ""),
- path,
- destination
- )
- } else {
- String(format: "%@: %@", path, localizedDescription)
- }
- default:
- String(format: "%@: %@", path, localizedDescription)
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/FileManager/FileManager+Attributes.swift b/Sources/SharedKit/Extensions/FileManager/FileManager+Attributes.swift
deleted file mode 100644
index 6f5858c..0000000
--- a/Sources/SharedKit/Extensions/FileManager/FileManager+Attributes.swift
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// FileManager+Attributes.swift
-// VisualDiffer
-//
-// Created by davide ficano on 13/01/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-import Foundation
-
-public extension FileManager {
- /**
- * 'Modification date' change isn't reliable on smb volumes
- * sometimes it's ignored without reporting error so this method
- * uses an hack to bypass this bug.
- * The hack consists to call twice the setAttribute for modification date on smb
- */
- func setFileAttributes(
- _ attrs: [FileAttributeKey: Any],
- ofItemAtPath path: URL,
- volumeType type: String
- ) throws {
- try setFileAttributes(
- attrs,
- ofItemAtPath: path.osPath,
- volumeType: type
- )
- }
-
- @objc func setFileAttributes(
- _ attrs: [FileAttributeKey: Any],
- ofItemAtPath path: String,
- volumeType type: String
- ) throws {
- if type == "smbfs" {
- let creation = attrs[.creationDate] as? Date
- let modification = attrs[.modificationDate] as? Date
-
- if creation != nil || modification != nil {
- var patchedAttrs = attrs
- var correctDates = [FileAttributeKey: Any]()
-
- if let creation {
- patchedAttrs[.creationDate] = Date()
- correctDates[.creationDate] = creation
- }
- if let modification {
- patchedAttrs[.modificationDate] = Date()
- correctDates[.modificationDate] = modification
- }
- try setAttributes(
- patchedAttrs,
- ofItemAtPath: path
- )
- try setAttributes(
- correctDates,
- ofItemAtPath: path
- )
- }
- }
- // and set attributes the second time...
- try setAttributes(
- attrs,
- ofItemAtPath: path
- )
- }
-}
-
-extension [FileAttributeKey: Any] {
- var fileAttributeType: FileAttributeType? {
- if let type = self[.type] as? String {
- FileAttributeType(rawValue: type)
- } else {
- nil
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Formatters/DateFormatter+Helper.swift b/Sources/SharedKit/Extensions/Formatters/DateFormatter+Helper.swift
deleted file mode 100644
index 7527dcd..0000000
--- a/Sources/SharedKit/Extensions/Formatters/DateFormatter+Helper.swift
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// DateFormatter+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/01/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-@objc extension DateFormatter {
- func widthOfLongestDateStringWithLevel(attrs: [NSAttributedString.Key: Any]) -> CGFloat {
- // This code is rather tied to the gregorian date.
- // We pick an arbitrary date, and iterate through each of the days of the week
- // and each of the months to find the longest string for the given detail level.
- // Because a person can customize (via the intl prefs) the string,
- // we need to iterate through each level for each item.
- let weekDayCount = weekdaySymbols.isEmpty ? 7 : weekdaySymbols.count
-
- var dateComponents = DateComponents()
- dateComponents.year = 2015
- dateComponents.month = 5
- dateComponents.day = 16
- dateComponents.hour = 10
- dateComponents.minute = 40
- dateComponents.second = 30
- dateComponents.timeZone = TimeZone.current
- let gregorian = Calendar(identifier: .gregorian)
-
- // Find the longest week day
- var longestWeekDay = 1
- var result: CGFloat = 0
-
- for dayOfWeek in 1 ... weekDayCount {
- dateComponents.day = dayOfWeek
- if let date = gregorian.date(from: dateComponents) {
- let str = string(from: date)
- let length = (str as NSString).size(withAttributes: attrs).width
- if length > result {
- result = length
- longestWeekDay = dayOfWeek
- }
- }
- }
-
- let monthCount = monthSymbols.isEmpty ? 12 : monthSymbols.count
-
- for month in 1 ... monthCount {
- dateComponents.day = longestWeekDay
- dateComponents.month = month
- if let date = gregorian.date(from: dateComponents) {
- let str = string(from: date)
- let length = (str as NSString).size(withAttributes: attrs).width
- result = max(result, length)
- }
- }
-
- return result
- }
-}
diff --git a/Sources/SharedKit/Extensions/Image/NSImage+Tint.swift b/Sources/SharedKit/Extensions/Image/NSImage+Tint.swift
deleted file mode 100644
index 3a94498..0000000
--- a/Sources/SharedKit/Extensions/Image/NSImage+Tint.swift
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// NSImage+Tint.swift
-// VisualDiffer
-//
-// Created by davide ficano on 04/07/15.
-// Converted to Swift by davide ficano on 03/05/25.
-// Copyright (c) 2010 visualdiffer.com
-
-import Cocoa
-
-public extension NSImage {
- // copied from https://stackoverflow.com/a/1415200/195893
- // On Catalina kCIContextUseSoftwareRenderer raises error
- // ** OpenCL Error Notification: [CL_DEVICE_NOT_AVAILABLE] : OpenCL Error : Error: build program driver returned (-1) **
- // ** OpenCL Error Notification: OpenCL Warning : clBuildProgram failed: could not build program for 0xffffffff (Intel(R) Core(TM) i5-3210M CPU 2.50GHz) (err:-1) **
- // https://developer.apple.com/devcenter/download.action?path=/videos/wwdc_2011__hd/session_422__using_core_image_on_ios_and_mac_os_x.m4v
- // https://docs.huihoo.com/apple/wwdc/2011/session_422__using_core_image_on_ios_and_mac_os_x.pdf
- /**
- * Apply the tint color to image using monochrome filter
- */
- func monochromaticTint(
- _ tint: NSColor?,
- useSoftwareRenderer: Bool
- ) -> NSImage {
- if let tint,
- let color = CIColor(color: tint),
- let compositingFilter = composingFilter(colorFilter(color: color), monochromeFilter()),
- let outputImage = compositingFilter.value(forKey: kCIOutputImageKey) as? CIImage {
- let extend = outputImage.extent
- let tintedImage = NSImage(size: size)
-
- tintedImage.lockFocus()
- if let contextRef = NSGraphicsContext.current?.cgContext {
- let ciContext = CIContext(
- cgContext: contextRef,
- options: [CIContextOption.useSoftwareRenderer: useSoftwareRenderer]
- )
- let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
- ciContext.draw(outputImage, in: rect, from: extend)
- }
- tintedImage.unlockFocus()
-
- return tintedImage
- }
- // swiftlint:disable:next force_cast
- return copy() as! NSImage
- }
-
- /**
- * Create a new image drawing the overImage in front of current image (the background image).
- * Use NSImageRep to improve image quality results
- * @param overImage the image to draw over the background
- */
- func overImage(_ overImage: NSImage) -> NSImage {
- let size = overImage.size
- let imageBounds = NSRect(x: 0, y: 0, width: size.width, height: size.height)
- let rep = NoodleCustomImageRep { _ in
- self.draw(at: NSPoint.zero, from: imageBounds, operation: .copy, fraction: 1)
- overImage.draw(at: NSPoint.zero, from: imageBounds, operation: .sourceOver, fraction: 1)
- }
- rep.size = size
- let image = NSImage(size: size)
- image.addRepresentation(rep)
- return image
- }
-
- private func colorFilter(color: CIColor) -> CIFilter? {
- guard let colorGenerator = CIFilter(name: "CIConstantColorGenerator"),
- let colorFilter = CIFilter(name: "CIColorControls") else {
- return nil
- }
- colorGenerator.setValue(color, forKey: kCIInputColorKey)
-
- colorFilter.setValue(colorGenerator.value(forKey: kCIOutputImageKey), forKey: kCIInputImageKey)
- colorFilter.setValue(NSNumber(value: 3.0), forKey: kCIInputSaturationKey)
- colorFilter.setValue(NSNumber(value: 0.35), forKey: kCIInputBrightnessKey)
- colorFilter.setValue(NSNumber(value: 1.0), forKey: kCIInputContrastKey)
-
- return colorFilter
- }
-
- private func monochromeFilter() -> CIFilter? {
- guard let monochromeFilter = CIFilter(name: "CIColorMonochrome"),
- let data = tiffRepresentation,
- let baseImage = CIImage(data: data) else {
- return nil
- }
-
- monochromeFilter.setValue(baseImage, forKey: kCIInputImageKey)
- monochromeFilter.setValue(CIColor(red: 0.75, green: 0.75, blue: 0.75), forKey: kCIInputColorKey)
- monochromeFilter.setValue(NSNumber(value: 1.0), forKey: kCIInputIntensityKey)
-
- return monochromeFilter
- }
-
- private func composingFilter(_ colorFilter: CIFilter?, _ monochromeFilter: CIFilter?) -> CIFilter? {
- guard let colorFilter,
- let monochromeFilter,
- let compositingFilter = CIFilter(name: "CIMultiplyCompositing") else {
- return nil
- }
-
- compositingFilter.setValue(
- colorFilter.value(forKey: kCIOutputImageKey),
- forKey: kCIInputImageKey
- )
- compositingFilter.setValue(
- monochromeFilter.value(forKey: kCIOutputImageKey),
- forKey: kCIInputBackgroundImageKey
- )
-
- return compositingFilter
- }
-
- /**
- * Apply the tint color to image
- */
- func tinted(with color: NSColor) -> NSImage {
- guard let image = copy() as? NSImage else {
- return self
- }
- image.lockFocus()
- color.set()
- let imageRect = NSRect(origin: .zero, size: image.size)
- imageRect.fill(using: .sourceAtop)
- image.unlockFocus()
- return image
- }
-}
diff --git a/Sources/SharedKit/Extensions/Menu/NSMenu+File.swift b/Sources/SharedKit/Extensions/Menu/NSMenu+File.swift
deleted file mode 100644
index e8198ae..0000000
--- a/Sources/SharedKit/Extensions/Menu/NSMenu+File.swift
+++ /dev/null
@@ -1,250 +0,0 @@
-//
-// NSMenu+File.swift
-// VisualDiffer
-//
-// Created by davide ficano on 20/12/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-enum AppNameAttributeKey: String {
- case preferred = "appNamePreferred"
- case system = "appNameSystem"
-}
-
-extension NSMenu {
- static let preferredEditorPrefName = "preferredEditor"
-
- @objc static func appsMenuForFile(
- _ path: URL?,
- openAppAction: Selector,
- openOtherAppAction: Selector
- ) -> NSMenu {
- let appsMenu = NSMenu()
-
- appsMenu.addMenuItemsForFile(
- path,
- openAppAction: openAppAction,
- openOtherAppAction: openOtherAppAction
- )
-
- return appsMenu
- }
-
- @objc func addMenuItemsForFile(
- _ path: URL?,
- openAppAction: Selector,
- openOtherAppAction: Selector
- ) {
- guard let path else {
- addItem(
- withTitle: NSLocalizedString("", comment: ""),
- action: nil,
- keyEquivalent: ""
- )
- return
- }
-
- let appNames = addTopMenusForFile(
- path,
- descriptionColor: NSColor.gray,
- openAppAction: openAppAction
- )
-
- // get all apps able to open path
- let url = path as CFURL
- guard let arr = LSCopyApplicationURLsForURL(url, .all)?.takeRetainedValue() as? [URL] else {
- return
- }
-
- // if default app exists it is surely into array
- if arr.isEmpty {
- if appNames[.preferred] == nil {
- addItem(
- withTitle: NSLocalizedString("", comment: ""),
- action: nil,
- keyEquivalent: ""
- )
- }
- } else {
- if !appNames.isEmpty {
- addItem(NSMenuItem.separator())
- }
-
- addAppMenuItems(
- mapAppNameToPath(arr, excludeAppNames: Array(appNames.values)),
- openAppAction: openAppAction
- )
- }
-
- // this happens when the preferred editor is equal to the default system
- // application and it is the only application
- if let item = item(at: numberOfItems - 1),
- !item.isSeparatorItem {
- addItem(NSMenuItem.separator())
- }
- addItem(
- withTitle: NSLocalizedString("Other...", comment: ""),
- action: openOtherAppAction,
- keyEquivalent: ""
- )
- }
-
- func addAppMenuItems(
- _ dictAppNames: [String: URL],
- openAppAction: Selector
- ) {
- let arrNames = dictAppNames.keys.sorted {
- $0.localizedCaseInsensitiveCompare($1) == .orderedAscending
- }
- for name in arrNames {
- if let path = dictAppNames[name] {
- addAppItem(
- title: name,
- openAppAction: openAppAction,
- appPath: path
- )
- }
- }
- }
-
- func addTopMenusForFile(
- _ path: URL,
- descriptionColor: NSColor,
- openAppAction: Selector
- ) -> [AppNameAttributeKey: String] {
- var appNames = [AppNameAttributeKey: String]()
-
- let (defaultAppUrl, defaultAppName) = getSystemDefaultAppForFile(path)
- let (preferredAppUrl, preferredAppName) = getPreferredAppForFile(path)
-
- if let defaultAppUrl, let preferredAppUrl, defaultAppUrl == preferredAppUrl {
- addItem(
- defaultAppName ?? "",
- description: NSLocalizedString(" (System Default)", comment: ""),
- descriptionColor: descriptionColor,
- appPath: defaultAppUrl,
- openAppAction: openAppAction
- )
- appNames[.preferred] = preferredAppName
- appNames[.system] = defaultAppName
- } else {
- if let preferredAppName, let preferredAppUrl {
- addItem(
- preferredAppName,
- description: NSLocalizedString(" (App Default)", comment: ""),
- descriptionColor: descriptionColor,
- appPath: preferredAppUrl,
- openAppAction: openAppAction
- )
- appNames[.preferred] = preferredAppName
- }
- if let defaultAppName, let defaultAppUrl {
- addItem(
- defaultAppName,
- description: NSLocalizedString(" (System Default)", comment: ""),
- descriptionColor: descriptionColor,
- appPath: defaultAppUrl,
- openAppAction: openAppAction
- )
- appNames[.system] = defaultAppName
- }
- }
-
- return appNames
- }
-
- @discardableResult
- func addItem(
- _ title: String,
- description: String,
- descriptionColor: NSColor,
- appPath: URL,
- openAppAction: Selector
- ) -> NSMenuItem {
- let item = addAppItem(
- title: "",
- openAppAction: openAppAction,
- appPath: appPath
- )
- if let font {
- let attributes = AttributedMenuItem.createAttributes(
- title: title,
- description: description,
- descriptionColor: descriptionColor,
- font: font
- )
- item.attributedTitle = AttributedMenuItem.createTitle(attributes)
- }
-
- return item
- }
-
- @discardableResult
- func addAppItem(
- title: String,
- openAppAction: Selector,
- appPath: URL
- ) -> NSMenuItem {
- let image = NSWorkspace.shared.icon(forFile: appPath.osPath)
- image.size = NSSize(width: 16.0, height: 16.0)
-
- let item = addItem(
- withTitle: title,
- action: openAppAction,
- keyEquivalent: ""
- )
- item.representedObject = appPath.osPath
- item.image = image
-
- return item
- }
-
- func getSystemDefaultAppForFile(_ path: URL) -> (appUrl: URL?, appName: String?) {
- guard let appUrl = NSWorkspace.shared.urlForApplication(toOpen: path) else {
- return (nil, nil)
- }
- guard let values = try? appUrl.resourceValues(forKeys: [URLResourceKey.localizedNameKey]),
- let appName = values.localizedName else {
- return (appUrl, nil)
- }
-
- return (appUrl, appName)
- }
-
- func getPreferredAppForFile(_: URL) -> (appUrl: URL?, appName: String?) {
- guard let appPath = UserDefaults.standard.string(forKey: Self.preferredEditorPrefName) else {
- return (nil, nil)
- }
-
- let appUrl = URL(filePath: appPath)
-
- guard let values = try? appUrl.resourceValues(forKeys: [URLResourceKey.localizedNameKey]),
- let appName = values.localizedName else {
- return (appUrl, nil)
- }
-
- return (appUrl, appName)
- }
-
- func mapAppNameToPath(
- _ appUrls: [URL],
- excludeAppNames: [String]
- ) -> [String: URL] {
- var dictAppNames = [String: URL]()
-
- for url in appUrls {
- if let values = try? url.resourceValues(forKeys: [.localizedNameKey]),
- let displayName = values.localizedName {
- dictAppNames[displayName] = url
- } else {
- dictAppNames[url.lastPathComponent] = url
- }
- }
-
- for appName in excludeAppNames {
- dictAppNames.removeValue(forKey: appName)
- }
-
- return dictAppNames
- }
-}
diff --git a/Sources/SharedKit/Extensions/OptionSet/FlagSet.swift b/Sources/SharedKit/Extensions/OptionSet/FlagSet.swift
deleted file mode 100644
index 62d86a3..0000000
--- a/Sources/SharedKit/Extensions/OptionSet/FlagSet.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// FlagSet.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/12/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-public protocol FlagSet: OptionSet {}
-
-public extension FlagSet {
- @inlinable
- subscript(option: Self.Element) -> Bool {
- get {
- contains(option)
- }
- set {
- if newValue {
- insert(option)
- } else {
- remove(option)
- }
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/OptionSet/OptionSet+Toggle.swift b/Sources/SharedKit/Extensions/OptionSet/OptionSet+Toggle.swift
deleted file mode 100644
index d0b9b28..0000000
--- a/Sources/SharedKit/Extensions/OptionSet/OptionSet+Toggle.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// OptionSet+Toggle.swift
-// VisualDiffer
-//
-// Created by davide ficano on 23/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-extension OptionSet {
- func toggled(_ member: Self) -> Self {
- symmetricDifference(member)
- }
-
- // periphery:ignore
- mutating func toggle(_ member: Self) {
- formSymmetricDifference(member)
- }
-
- mutating func setValue(_ newValue: Bool, element: Self.Element) {
- if newValue {
- insert(element)
- } else {
- remove(element)
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Panel/NSAlert+Helper.swift b/Sources/SharedKit/Extensions/Panel/NSAlert+Helper.swift
deleted file mode 100644
index b038a57..0000000
--- a/Sources/SharedKit/Extensions/Panel/NSAlert+Helper.swift
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// NSAlert+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/01/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-@objc extension NSAlert {
- static func showModalConfirm(
- messageText: String,
- informativeText: String,
- suppressPropertyName: String? = nil,
- yesText: String? = nil,
- noText: String? = nil
- ) -> Bool {
- let defaults = UserDefaults.standard
-
- if let suppressPropertyName {
- if defaults.bool(forKey: suppressPropertyName) {
- return true
- }
- }
- let alert = Self()
-
- alert.messageText = messageText
- alert.informativeText = informativeText
- alert.showsSuppressionButton = suppressPropertyName != nil
- alert.addButton(withTitle: yesText ?? NSLocalizedString("Yes", comment: ""))
- alert.addButton(withTitle: noText ?? NSLocalizedString("No", comment: ""))
- alert.buttons[1].keyEquivalent = KeyEquivalent.escape
-
- let result = alert.runModal() == .alertFirstButtonReturn
-
- if result,
- let suppressPropertyName,
- let button = alert.suppressionButton,
- button.state == .on {
- defaults.setValue(true, forKey: suppressPropertyName)
- }
-
- return result
- }
-
- static func showModalInfo(
- messageText: String,
- informativeText: String,
- suppressPropertyName: String?
- ) {
- let defaults = UserDefaults.standard
-
- if let suppressPropertyName {
- if defaults.bool(forKey: suppressPropertyName) {
- return
- }
- }
- let alert = Self()
-
- alert.messageText = messageText
- alert.alertStyle = .informational
- alert.informativeText = informativeText
- alert.showsSuppressionButton = suppressPropertyName != nil
-
- alert.runModal()
-
- if let suppressPropertyName,
- let button = alert.suppressionButton,
- button.state == .on {
- defaults.setValue(true, forKey: suppressPropertyName)
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Panel/NSOpenPanel+Application.swift b/Sources/SharedKit/Extensions/Panel/NSOpenPanel+Application.swift
deleted file mode 100644
index 2c9f0cc..0000000
--- a/Sources/SharedKit/Extensions/Panel/NSOpenPanel+Application.swift
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// NSOpenPanel+Application.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/08/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-extension NSOpenPanel {
- @objc func openApplication(title: String) -> NSOpenPanel {
- self.title = title
- // since 10.11 the title is no longer shown so we use the message property
- message = title
- allowsMultipleSelection = false
- allowedContentTypes = [
- .application,
- .applicationBundle,
- .executable,
- ]
- let paths = NSSearchPathForDirectoriesInDomains(
- .applicationDirectory,
- .localDomainMask,
- true
- )
- if !paths.isEmpty {
- directoryURL = URL(filePath: paths[0])
- }
- return self
- }
-}
diff --git a/Sources/SharedKit/Extensions/Panel/QLPreviewPanel.swift b/Sources/SharedKit/Extensions/Panel/QLPreviewPanel.swift
deleted file mode 100644
index 85f64fc..0000000
--- a/Sources/SharedKit/Extensions/Panel/QLPreviewPanel.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// QLPreviewPanel.swift
-// VisualDiffer
-//
-// Created by davide ficano on 30/07/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-import Quartz
-
-extension QLPreviewPanel {
- @objc static func toggle() {
- if sharedPreviewPanelExists(), shared().isVisible {
- shared().orderOut(nil)
- } else {
- shared().makeKeyAndOrderFront(nil)
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Pasteboard/NSPasteboard+Helper.swift b/Sources/SharedKit/Extensions/Pasteboard/NSPasteboard+Helper.swift
deleted file mode 100644
index 21d1199..0000000
--- a/Sources/SharedKit/Extensions/Pasteboard/NSPasteboard+Helper.swift
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// NSPasteboard+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/07/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-extension NSPasteboard {
- @discardableResult
- @objc func copy(lines: [String]) -> Bool {
- clearContents()
- return writeObjects([lines.joined(separator: "\n")] as [NSString])
- }
-
- @discardableResult
- @objc func copy(urls: [URL]) -> Bool {
- if urls.isEmpty {
- return false
- }
- clearContents()
- return writeObjects(urls as [NSURL])
- }
-}
diff --git a/Sources/SharedKit/Extensions/Predicate/NSPredicateEditor+Fix.swift b/Sources/SharedKit/Extensions/Predicate/NSPredicateEditor+Fix.swift
deleted file mode 100644
index a9b15e3..0000000
--- a/Sources/SharedKit/Extensions/Predicate/NSPredicateEditor+Fix.swift
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// NSPredicateEditor+Fix.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/10/20.
-// Copyright (c) 2020 visualdiffer.com
-//
-
-extension NSPredicateEditor {
- /**
- * Resize editor input text
- */
- func resizeRows(_ width: CGFloat) {
- let rowTemplates = rowTemplates
- for row in rowTemplates {
- let views = row.templateViews
- for view in views {
- if let view = view as? NSTextField {
- var r = view.frame
- r.size.width = width
- view.frame = r
-
- break
- }
- }
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/String/String+Helper.swift b/Sources/SharedKit/Extensions/String/String+Helper.swift
deleted file mode 100644
index 06fdbc3..0000000
--- a/Sources/SharedKit/Extensions/String/String+Helper.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// String+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/08/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-import Foundation
-
-public extension String {
- func hasPrefix(_ prefix: String, ignoreCase: Bool) -> Bool {
- if ignoreCase {
- return range(of: prefix, options: [.caseInsensitive, .anchored]) != nil
- }
- return hasPrefix(prefix)
- }
-
- func hasSuffix(_ suffix: String, ignoreCase: Bool) -> Bool {
- if ignoreCase {
- return range(of: suffix, options: [.caseInsensitive, .anchored, .backwards]) != nil
- }
- return hasSuffix(suffix)
- }
-
- func trimmingSuffix(_ prefix: Character) -> String {
- if let index = lastIndex(where: { $0 != prefix }) {
- return String(self[..],
- normalStyle: [NSAttributedString.Key: Any],
- highlightStyle: [NSAttributedString.Key: Any]
- ) -> NSAttributedString {
- if ranges.isEmpty {
- return NSAttributedString(string: self, attributes: normalStyle)
- }
- let attrString = NSMutableAttributedString(string: self)
-
- attrString.beginEditing()
- var start = startIndex
-
- for range in ranges {
- let normalRange = NSRange(start ..< range.lowerBound, in: self)
- let highlightRange = NSRange(range, in: self)
- attrString.addAttributes(highlightStyle, range: highlightRange)
- attrString.addAttributes(normalStyle, range: normalRange)
-
- start = range.upperBound
- }
- let remainingRange = start ..< endIndex
- attrString.addAttributes(normalStyle, range: NSRange(remainingRange, in: self))
- attrString.endEditing()
-
- return attrString
- }
-
- func highlights(
- _ ranges: [Range],
- normalColor: NSColor,
- highlightColor: NSColor,
- font: NSFont
- ) -> NSAttributedString {
- let normalStyle = [
- NSAttributedString.Key.font: font,
- NSAttributedString.Key.foregroundColor: normalColor,
- ]
-
- let boldFont = NSFontManager.shared.convert(font, toHaveTrait: [.boldFontMask, .unitalicFontMask])
- let hightlightStyle = [
- NSAttributedString.Key.font: boldFont,
- NSAttributedString.Key.foregroundColor: highlightColor,
- ]
-
- return highlights(
- ranges,
- normalStyle: normalStyle,
- highlightStyle: hightlightStyle
- )
- }
-}
diff --git a/Sources/SharedKit/Extensions/String/String+Occcurrences.swift b/Sources/SharedKit/Extensions/String/String+Occcurrences.swift
deleted file mode 100644
index 56e1d38..0000000
--- a/Sources/SharedKit/Extensions/String/String+Occcurrences.swift
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// String+Occcurrences.swift
-// VisualDiffer
-//
-// Created by davide ficano on 05/05/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-extension String {
- // periphery:ignore
- func countOccurrences(
- _ pattern: String,
- options: NSString.CompareOptions = []
- ) -> Int {
- var count = 0
- var remainingRange = startIndex ..< endIndex
-
- while let foundRange = range(
- of: pattern,
- options: options,
- range: remainingRange
- ) {
- count += 1
- remainingRange = foundRange.upperBound ..< endIndex
- }
-
- return count
- }
-
- func rangesOfString(
- _ pattern: String,
- options: NSString.CompareOptions
- ) -> [Range] {
- var ranges = [Range]()
- var remainingRange = startIndex ..< endIndex
-
- while let foundRange = range(
- of: pattern,
- options: options,
- range: remainingRange
- ) {
- ranges.append(foundRange)
- remainingRange = foundRange.upperBound ..< endIndex
- }
-
- return ranges
- }
-}
diff --git a/Sources/SharedKit/Extensions/String/String+Path.swift b/Sources/SharedKit/Extensions/String/String+Path.swift
deleted file mode 100644
index 1b55387..0000000
--- a/Sources/SharedKit/Extensions/String/String+Path.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// String+Path.swift
-// VisualDiffer
-//
-// Created by davide ficano on 16/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-extension String {
- func isAbsolutePath() -> Bool {
- hasPrefix("/")
- }
-
- /**
- * No native valid alteratives to the NSString version
- */
- var standardizingPath: String {
- (self as NSString).standardizingPath
- }
-}
diff --git a/Sources/SharedKit/Extensions/String/String+RegularExpression.swift b/Sources/SharedKit/Extensions/String/String+RegularExpression.swift
deleted file mode 100644
index 2d2f19b..0000000
--- a/Sources/SharedKit/Extensions/String/String+RegularExpression.swift
+++ /dev/null
@@ -1,138 +0,0 @@
-//
-// String+RegularExpression.swift
-// VisualDiffer
-//
-// Created by davide ficano on 05/05/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Foundation
-
-private struct GlobConverter {
- private var regex = [NSRegularExpression]()
- private var templates = [String]()
-
- init() {
- let globs = [
- ("([.^$+(){}\\[\\]\\\\|])", "\\\\$1"),
- ("\\?", "(.|[\r\n])"),
- ("\\*", "(.|[\r\n])*"),
- ]
-
- for (regexString, templateString) in globs {
- // swiftlint:disable:next force_try
- let re = try! NSRegularExpression(
- pattern: regexString,
- options: .caseInsensitive
- )
- regex.append(re)
- templates.append(templateString)
- }
- }
-
- private func replace(index: Int, in str: String) -> String {
- let re = regex[index]
- let template = templates[index]
-
- return re.stringByReplacingMatches(
- in: str,
- options: [],
- range: NSRange(location: 0, length: str.count),
- withTemplate: template
- )
- }
-
- func convert(_ str: String) -> String {
- var re = str
-
- for i in 0 ..< regex.count {
- re = replace(index: i, in: re)
- }
- return re
- }
-}
-
-public extension String {
- /**
- * Replace tagged expressions ($1, $2, ...) present in template
- * with substrings ranges present in result
- * Example: self = 001.jpg template = $1.raw returns 001.raw
- */
- func replace(
- template chars: String,
- result: NSTextCheckingResult
- ) -> String {
- let size = chars.count
- var foundTagged = false
- var foundEscape = false
- var i = 0
-
- var inString = ""
-
- while i < size {
- if foundTagged {
- foundTagged = false
- var value = 0
- var position = chars.index(chars.startIndex, offsetBy: i)
-
- if chars[position] == "$" {
- inString.append(chars[position])
- i += 1
- } else {
- while i < size, let num = chars[position].wholeNumberValue {
- value = value * 10 + num
- i += 1
- position = chars.index(chars.startIndex, offsetBy: i)
- }
- if value < result.numberOfRanges, let range = Range(result.range(at: value), in: self) {
- inString.append(String(self[range]))
- }
- }
- } else if foundEscape {
- foundEscape = false
- let position = chars.index(chars.startIndex, offsetBy: i)
- i += 1
- switch chars[position] {
- case "t":
- inString.append("\t")
- case "\\":
- inString.append("\\")
- default:
- break
- }
- }
- // should exceed array range
- if i < size {
- let position = chars.index(chars.startIndex, offsetBy: i)
- i += 1
- let ch = chars[position]
-
- if ch == "$" {
- foundTagged = true
- } else if ch == "\\" {
- foundEscape = true
- } else {
- inString.append(ch)
- }
- }
- }
- return inString
- }
-
- /**
- * Convert a glob string to a valid regular expression string
- * Strings like "*m" are converted to ".*m"
- * Brackets and "?" are correctly escaped
- */
- private func _convertGlobMetaCharsToRegexpMetaChars() -> String {
- enum Static {
- static let converter: GlobConverter = .init()
- }
-
- return Static.converter.convert(self)
- }
-
- func convertGlobMetaCharsToRegexpMetaChars() -> String {
- _convertGlobMetaCharsToRegexpMetaChars()
- }
-}
diff --git a/Sources/SharedKit/Extensions/TableView/NSTableView+Font.swift b/Sources/SharedKit/Extensions/TableView/NSTableView+Font.swift
deleted file mode 100644
index df854c9..0000000
--- a/Sources/SharedKit/Extensions/TableView/NSTableView+Font.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// NSTableView+Font.swift
-// VisualDiffer
-//
-// Created by davide ficano on 07/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-@objc extension NSTableView {
- func updateFont(
- _ font: NSFont,
- reloadData reload: Bool
- ) {
- let layoutManager = NSLayoutManager()
- rowHeight = layoutManager.defaultLineHeight(for: font) + 4
-
- if reload {
- reloadData()
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/TableView/NSTableView+Row.swift b/Sources/SharedKit/Extensions/TableView/NSTableView+Row.swift
deleted file mode 100644
index cdc32c1..0000000
--- a/Sources/SharedKit/Extensions/TableView/NSTableView+Row.swift
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// NSTableView+Row.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/08/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-import Foundation
-
-extension NSTableView {
- // Select the row or the closest to it, return the closest row or the original value
- @discardableResult
- @objc func selectRow(
- closestTo row: Int,
- byExtendingSelection: Bool,
- ensureVisible: Bool
- ) -> Int {
- let closestRow = findValid(row: row)
-
- selectRowIndexes(IndexSet(integer: closestRow), byExtendingSelection: byExtendingSelection)
-
- if ensureVisible {
- scrollRowToVisible(row)
- }
-
- return closestRow
- }
-
- private func findValid(row: Int) -> Int {
- if row < 0 || dataSource == nil {
- return 0
- }
- if let dataSource,
- let rows = dataSource.numberOfRows?(in: self) {
- let lastRow = rows - 1
- if lastRow < row {
- return lastRow
- }
- }
- return row
- }
-
- @objc var firstVisibleRow: Int {
- guard let superview else {
- return -1
- }
- let bounds = superview.bounds
-
- return row(at: bounds.origin)
- }
-
- @objc var lastVisibleRow: Int {
- guard let superview else {
- return -1
- }
- var bounds = superview.bounds
- bounds.origin.y += bounds.size.height - 1
-
- return row(at: bounds.origin)
- }
-
- /**
- * If no row is visible then scroll to suggestedRow, if suggested row is -1 scroll to row 0
- */
- @discardableResult
- @objc func ensureRowVisibility(suggestedRow: Int) -> Int {
- var visibleRow = firstVisibleRow
-
- if visibleRow < 0 {
- if suggestedRow < 0 {
- visibleRow = 0
- } else {
- visibleRow = suggestedRow
- }
- }
- scrollRowToVisible(visibleRow)
- return visibleRow
- }
-
- @objc func scrollTo(row: Int, center: Bool) {
- if row < 0 {
- return
- }
-
- // copied from https://stackoverflow.com/a/49192512/195893
- let rowRect = frameOfCell(atColumn: 0, row: row)
-
- let scrollView = enclosingScrollView
- let headerHeight = headerView?.frame.size.height ?? 0
-
- let point = if center,
- let scrollView {
- NSPoint(
- x: 0,
- y: rowRect.origin.y - headerHeight + (rowRect.size.height / 2) - (scrollView.frame.size.height / 2)
- )
- } else {
- NSPoint(
- x: 0,
- y: rowRect.origin.y - headerHeight
- )
- }
- scroll(point)
- }
-}
diff --git a/Sources/SharedKit/Extensions/Toolbar/NSToolbar+Create.swift b/Sources/SharedKit/Extensions/Toolbar/NSToolbar+Create.swift
deleted file mode 100644
index c32cab2..0000000
--- a/Sources/SharedKit/Extensions/Toolbar/NSToolbar+Create.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// NSToolbar+Create.swift
-// VisualDiffer
-//
-// Created by davide ficano on 07/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-@objc extension NSToolbar {
- convenience init(identifier: String, delegate dele: NSToolbarDelegate) {
- self.init(identifier: identifier)
-
- displayMode = .iconAndLabel
- allowsUserCustomization = true
- autosavesConfiguration = true
- delegate = dele
- }
-}
diff --git a/Sources/SharedKit/Extensions/Toolbar/NSToolbarItem+Create.swift b/Sources/SharedKit/Extensions/Toolbar/NSToolbarItem+Create.swift
deleted file mode 100644
index 01491bd..0000000
--- a/Sources/SharedKit/Extensions/Toolbar/NSToolbarItem+Create.swift
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// NSToolbarItem+Create.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@objc extension NSToolbarItem {
- convenience init(
- identifier: NSToolbarItem.Identifier,
- label: String,
- tooltip: String?,
- image: NSImage?,
- target: AnyObject?,
- action: Selector?
- ) {
- self.init(itemIdentifier: identifier)
- _ = with(
- label: label,
- tooltip: tooltip,
- image: image,
- target: target,
- action: action
- )
- }
-
- func with(
- label: String,
- tooltip: String?,
- image: NSImage?,
- target: AnyObject?,
- action: Selector?
- ) -> Self {
- self.label = label
- paletteLabel = label
-
- toolTip = tooltip
- self.image = image
-
- self.target = target
- self.action = action
-
- return self
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+FileManager.swift b/Sources/SharedKit/Extensions/URL/URL+FileManager.swift
deleted file mode 100644
index 21e15fc..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+FileManager.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// URL+FileManager.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-public extension URL {
- func isFileDirectory() throws -> Bool {
- let resources = try resourceValues(forKeys: [.isDirectoryKey])
-
- if let isDirectory = resources.isDirectory {
- return isDirectory
- }
-
- return false
- }
-
- /**
- * URL appends "/" to the end but this causes problems with the symlink, so it is removed to get the correct result
- */
- func destinationOfSymbolicLink(directoryHint: DirectoryHint = .inferFromPath) throws -> URL {
- let realPath = try FileManager.default.destinationOfSymbolicLink(atPath: osPath)
-
- return URL(filePath: realPath, directoryHint: directoryHint)
- }
-
- func createSymbolicLink(withDestination destination: URL) throws {
- try FileManager.default.createSymbolicLink(atPath: osPath, withDestinationPath: destination.osPath)
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+Finder.swift b/Sources/SharedKit/Extensions/URL/URL+Finder.swift
deleted file mode 100644
index 5ff2025..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+Finder.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// URL+Finder.swift
-// VisualDiffer
-//
-// Created by davide ficano on 29/10/10.
-// Copyright (c) 2010 visualdiffer.com
-//
-
-extension URL {
- func labelNumber() -> Int? {
- guard let resources = try? resourceValues(forKeys: [.labelNumberKey]) else {
- return nil
- }
- return resources.labelNumber
- }
-
- func tagNames(sorted: Bool) -> [String]? {
- guard let resources = try? resourceValues(forKeys: [.tagNamesKey]) else {
- return nil
- }
- guard let tagNames = resources.tagNames else {
- return []
- }
-
- return if sorted {
- tagNames.sorted { $0.caseInsensitiveCompare($1) == .orderedAscending }
- } else {
- tagNames
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+Metadata.swift b/Sources/SharedKit/Extensions/URL/URL+Metadata.swift
deleted file mode 100644
index 40e4502..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+Metadata.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// URL+Metadata.swift
-// VisualDiffer
-//
-// Created by davide ficano on 03/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-public extension URL {
- func copyTags(to toUrl: inout URL) throws {
- let resources = try resourceValues(forKeys: [.tagNamesKey])
- try toUrl.setResourceValues(resources)
- }
-
- func copyLabel(to toUrl: inout URL) throws {
- let resources = try resourceValues(forKeys: [.labelNumberKey])
- try toUrl.setResourceValues(resources)
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+Path.swift b/Sources/SharedKit/Extensions/URL/URL+Path.swift
deleted file mode 100644
index fa9e426..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+Path.swift
+++ /dev/null
@@ -1,258 +0,0 @@
-//
-// URL+Path.swift
-// VisualDiffer
-//
-// Created by davide ficano on 19/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-public extension URL {
- /**
- * Directory url contains "/" at the end and this cause many problems (eg symlinks)
- * so we return the path without it
- */
- var osPath: String {
- path(percentEncoded: false).trimmingSuffix("/")
- }
-
- /**
- * Standardize and then trim trailing separators
- */
- var standardizingPath: String {
- path(percentEncoded: false).standardizingPath
- }
-
- func volumeType() -> String? {
- if let values = try? resourceValues(forKeys: [.volumeTypeNameKey]),
- let type = values.volumeTypeName {
- return type
- }
- return nil
- }
-
- static func buildDestinationPath(
- _ srcURL: URL,
- _ destURL: URL?,
- _ srcBaseURL: URL,
- _ destBaseURL: URL
- ) -> URL {
- let srcBaseDir = srcBaseURL.osPath
- let srcPath = srcURL.osPath
-
- if let destURL {
- // use destination file name if it is present so
- // file names using a not match-case alignment works fine
- let lastPathIndex = srcPath.lastIndex(of: "/") ?? srcPath.startIndex
- let startIndex = srcBaseDir.endIndex
- let relativePath = srcPath[startIndex ..< lastPathIndex].trimmingPrefix("/")
-
- return destBaseURL
- .appending(path: String(relativePath))
- .appending(
- path: destURL.lastPathComponent,
- directoryHint: destURL.hasDirectoryPath ? .isDirectory : .notDirectory
- )
- }
- let trailingPath = String(srcPath[srcBaseDir.endIndex...]).trimmingPrefix("/")
- return destBaseURL
- .appending(path: trailingPath, directoryHint: srcURL.hasDirectoryPath ? .isDirectory : .notDirectory)
- }
-}
-
-// MARK: - Path check and selection
-
-public extension URL {
- /**
- * Check that self is the same type as the passed item (both are files or both are folders)
- */
- func matchesFileType(
- of rightUrl: URL,
- isDir: inout Bool,
- leftExists: inout Bool,
- rightExists: inout Bool
- ) -> Bool {
- let fileManager = FileManager.default
- var isLeftDir = ObjCBool(false)
- var isRightDir = ObjCBool(false)
-
- let leftPath = osPath
- let rightPath = rightUrl.osPath
-
- leftExists = fileManager.fileExists(atPath: leftPath, isDirectory: &isLeftDir)
- rightExists = fileManager.fileExists(atPath: rightPath, isDirectory: &isRightDir)
-
- isDir = isLeftDir.boolValue
- // must be both folders or both files
- return leftExists && rightExists && (isLeftDir.boolValue == isRightDir.boolValue)
- }
-
- func matchesFileType(of rightUrl: URL) -> Bool {
- var isDir = false
- var leftExists = false
- var rightExists = false
-
- return matchesFileType(
- of: rightUrl,
- isDir: &isDir,
- leftExists: &leftExists,
- rightExists: &rightExists
- )
- }
-
- @MainActor func selectPath(
- panelTitle: String,
- chooseFiles: Bool,
- chooseDirectories: Bool
- ) -> URL? {
- let url = promptUrl(
- at: findNearestExistingDirectory(),
- title: panelTitle,
- chooseDirectories: chooseDirectories,
- chooseFiles: chooseFiles
- )
-
- if let url {
- SecureBookmark.shared.add(url)
- }
-
- return url
- }
-
- /**
- * Check if path is already sandboxed and doesn't need to be selected by user (e.g. using OpenPanel)
- * @param allowFile the url can be a file
- * @param allowDirectory the url can be a directory
- * @return true if file is sandboxed and its type matches the allowed types, false otherwise
- */
- func isSandboxed(allowFile: Bool, allowDirectory: Bool) -> Bool {
- let fileManager = FileManager.default
- var isDir = ObjCBool(false)
- let startDir = osPath
-
- let securedURL = SecureBookmark.shared.secure(fromBookmark: self, startSecured: true)
- defer {
- SecureBookmark.shared.stopAccessing(url: securedURL)
- }
- let result = fileManager.fileExists(atPath: startDir, isDirectory: &isDir)
- && fileManager.isReadableFile(atPath: startDir)
-
- let isFileTypeAllowed = if allowFile, allowDirectory {
- true
- } else if allowFile {
- isDir.boolValue == false
- } else if allowDirectory {
- isDir.boolValue == true
- } else {
- false
- }
- return result && isFileTypeAllowed
- }
-
- func findNearestExistingDirectory() -> URL {
- let fileManager = FileManager.default
- var isDir = ObjCBool(false)
- var currDir = self
-
- while !fileManager.fileExists(atPath: currDir.osPath, isDirectory: &isDir) || !isDir.boolValue {
- currDir.deleteLastPathComponent()
- }
-
- return currDir
- }
-
- @MainActor func promptUrl(
- at startUrl: URL,
- title: String,
- chooseDirectories: Bool,
- chooseFiles: Bool
- ) -> URL? {
- let openPanel = NSOpenPanel()
-
- openPanel.title = title
- openPanel.canChooseDirectories = chooseDirectories
- openPanel.canChooseFiles = chooseFiles
- // since 10.11 the title is no longer shown so we use the message property
- openPanel.message = title
- openPanel.directoryURL = startUrl
-
- if openPanel.runModal() == .OK {
- return openPanel.urls[0]
- }
- return nil
- }
-
- static func compare(fileName lhs: String, with rhs: String) -> ComparisonResult {
- lhs.localizedStandardCompare(rhs)
- }
-
- static func compare(
- path path1: URL?,
- with path2: URL?
- ) -> ComparisonResult {
- guard let path1 else {
- return .orderedAscending
- }
- guard let path2 else {
- return .orderedDescending
- }
- let components1 = path1.pathComponents
- let components2 = path2.pathComponents
- let count1 = components1.count
- let count2 = components2.count
-
- // do not compare last component because we compare only directory components
- let minComponents = min(count1, count2) - 1
-
- for i in 0 ..< minComponents {
- let comp1 = components1[i]
- let comp2 = components2[i]
- let compareResult = compare(fileName: comp1, with: comp2)
-
- if compareResult != .orderedSame {
- return compareResult
- }
- }
-
- let delta = count1 - count2
- var comp1: String
- var comp2: String
-
- var isDir1 = path1.hasDirectoryPath
- var isDir2 = path2.hasDirectoryPath
-
- if delta > 0 {
- comp1 = components1[minComponents]
- comp2 = components2[count2 - 1]
- isDir1 = true
- // comp1 is a comp2's subdirectory so we can compare them
- if isDir2 {
- let r = compare(fileName: comp1, with: comp2)
- if r == .orderedSame {
- return .orderedDescending
- }
- return r
- }
- } else if delta < 0 {
- comp1 = components1[count1 - 1]
- comp2 = components2[minComponents]
- isDir2 = true
- // comp2 is a subdirectory so we can compare them
- if isDir1 {
- let r = compare(fileName: comp1, with: comp2)
- if r == .orderedSame {
- return .orderedAscending
- }
- return r
- }
- } else {
- comp1 = components1[count1 - 1]
- comp2 = components2[count2 - 1]
- }
-
- if isDir1 == isDir2 {
- return comp1.compare(comp2, options: .caseInsensitive)
- }
-
- return isDir1 ? .orderedAscending : .orderedDescending
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+ResourceFork.swift b/Sources/SharedKit/Extensions/URL/URL+ResourceFork.swift
deleted file mode 100644
index 743dc9c..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+ResourceFork.swift
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// URL+ResourceFork.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/11/24.
-// Copyright (c) 2024 visualdiffer.com
-//
-
-import Foundation
-
-public extension URL {
- /**
- * Return resource fork sizes
- * @param rsrcPhysicalSize - the physical size of the resource fork
- * @param dataPhysicalSize - the physical size of the data fork
- * @param rsrcLogicalSize - the logical size of the resource fork
- * @param dataLogicalSize - the logical size of the data fork
- */
- func resourceForkForPath(
- _ rsrcPhysicalSize: inout Int,
- _ dataPhysicalSize: inout Int,
- _ rsrcLogicalSize: inout Int,
- _ dataLogicalSize: inout Int
- ) throws {
- let keys: Set = [
- .fileSizeKey,
- .fileAllocatedSizeKey,
- .totalFileAllocatedSizeKey,
- .totalFileSizeKey,
- ]
-
- let values = try resourceValues(forKeys: keys)
- let fileAllocatedSize = values.fileAllocatedSize ?? 0
- let totalFileAllocatedSize = values.totalFileAllocatedSize ?? 0
- let fileSize = values.fileSize ?? 0
- let totalFileSize = values.totalFileSize ?? 0
-
- // FSGetCatalogInfo is deprecated so we us NSURL and compute the values manually
- rsrcPhysicalSize = totalFileAllocatedSize - fileAllocatedSize
- dataPhysicalSize = fileAllocatedSize
- rsrcLogicalSize = totalFileSize - fileSize
- dataLogicalSize = fileSize
- }
-
- /**
- * Return the physical file size
- */
- func resourceForkSize() throws -> Int {
- var rsrcPhysicalSize = 0
- var dataPhysicalSize = 0
- var rsrcLogicalSize = 0
- var dataLogicalSize = 0
-
- try resourceForkForPath(
- &rsrcPhysicalSize,
- &dataPhysicalSize,
- &rsrcLogicalSize,
- &dataLogicalSize
- )
- return dataLogicalSize + rsrcLogicalSize
- }
-
- func volumeSupportsCaseSensitive() throws -> Bool {
- let values = try resourceValues(forKeys: [.volumeSupportsCaseSensitiveNamesKey])
- return values.volumeSupportsCaseSensitiveNames ?? false
- }
-
- func readResFork() throws -> Data {
- let resForkPath = appending(path: "/..namedfork/rsrc")
- let fileHandle = try FileHandle(forReadingFrom: resForkPath)
- defer {
- fileHandle.closeFile()
- }
- return fileHandle.readDataToEndOfFile()
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+StructuredContent.swift b/Sources/SharedKit/Extensions/URL/URL+StructuredContent.swift
deleted file mode 100644
index b22390e..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+StructuredContent.swift
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// URL+StructuredContent.swift
-// VisualDiffer
-//
-// Created by davide ficano on 14/06/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import UniformTypeIdentifiers
-import PDFKit
-
-struct StructuredContentValues {
- let originalType: UTType?
- let contentType: UTType?
- let plainText: String?
- let encoding: String.Encoding?
-}
-
-extension URL {
- /**
- * Return the plain text content from current url. If the content is a rich format like
- * Word .doc files the text content is extracted and returned.
- * If the content is a plain text format then use the encoding specified into options (if any)
- * then the NSWindowsCP1252StringEncoding and at least the auto detect offered by NSAttributedString
- * @param options passed to [NSAttributedString initWithURL:url]
- * @param docAttrs passed to [NSAttributedString initWithURL:url]
- * @return the plain text url content on success, nil otherwise
- */
- func readPlainText(
- options: [NSAttributedString.DocumentReadingOptionKey: Any],
- documentAttributes docAttrs: inout [NSAttributedString.DocumentAttributeKey: Any]
- ) throws -> String? {
- if let text = try readHandlingInapplicableStringEncoding(options: options, documentAttributes: &docAttrs) {
- return text.string
- }
- // try fallback encoding NSWindowsCP1252StringEncoding
- let optionsWithBestEncoding = options.merging(
- [.characterEncoding: NSWindowsCP1252StringEncoding]
- ) { _, new in new }
-
- if let text = try readHandlingInapplicableStringEncoding(
- options: optionsWithBestEncoding,
- documentAttributes: &docAttrs
- ) {
- return text.string
- }
- // try removing encoding
- var optionsWithoutEncoding = options
- optionsWithoutEncoding.removeValue(forKey: .characterEncoding)
- if let text = try readHandlingInapplicableStringEncoding(
- options: optionsWithoutEncoding,
- documentAttributes: &docAttrs
- ) {
- return text.string
- }
-
- return nil
- }
-
- private func readHandlingInapplicableStringEncoding(
- options: [NSAttributedString.DocumentReadingOptionKey: Any],
- documentAttributes docAttrs: inout [NSAttributedString.DocumentAttributeKey: Any]
- ) throws -> NSAttributedString? {
- var nsDocAttrs: NSDictionary? = docAttrs as NSDictionary?
- do {
- let text = try NSAttributedString(
- url: self,
- options: options,
- documentAttributes: &nsDocAttrs
- )
- if let nsDocAttrs = nsDocAttrs as? [NSAttributedString.DocumentAttributeKey: Any] {
- docAttrs.merge(nsDocAttrs) { _, new in new }
- }
- return text
- } catch let error as NSError {
- if error.domain == NSCocoaErrorDomain,
- error.code == NSFileReadInapplicableStringEncodingError {
- return nil
- }
- throw error
- }
- }
-
- func readStructuredContent(encoding: String.Encoding) throws -> StructuredContentValues {
- enum Static {
- static let documentTypeToUTType: [NSAttributedString.DocumentType: UTType] = {
- var mapping: [NSAttributedString.DocumentType: UTType] = [
- .plain: .plainText,
- .rtf: .rtf,
- .rtfd: .rtfd,
- .html: .html,
- ]
-
- // add only if are not nil
- mapping[.officeOpenXML] = UTType("org.openxmlformats.wordprocessingml.document")
- mapping[.docFormat] = UTType("com.microsoft.word.doc")
-
- return mapping
- }()
-
- static let supportedFormats = Set(documentTypeToUTType.values)
- }
- let values = try resourceValues(forKeys: [.contentTypeKey])
- let fileType = values.contentType
-
- if let fileType,
- fileType == .pdf {
- let pdfDoc = PDFDocument(url: self)
-
- return StructuredContentValues(
- originalType: fileType,
- contentType: fileType,
- plainText: pdfDoc?.string,
- encoding: nil
- )
- }
-
- let usePlainText = if let fileType {
- !Static.supportedFormats.contains(fileType)
- } else {
- true
- }
-
- var options = [NSAttributedString.DocumentReadingOptionKey: Any]()
-
- // NSAttributedString parses HTML files but we want to show the source
- // code so we force plain type for other supported formats
- if usePlainText {
- options[.documentType] = NSAttributedString.DocumentType.plain
- }
- options[.characterEncoding] = NSNumber(value: encoding.rawValue)
-
- var docAttrs = [NSAttributedString.DocumentAttributeKey: Any]()
- let content = try readPlainText(
- options: options,
- documentAttributes: &docAttrs
- )
-
- let docEnconding: String.Encoding? = if let enc = docAttrs[.characterEncoding] as? NSNumber {
- String.Encoding(rawValue: enc.uintValue)
- } else {
- nil
- }
- let contentType: UTType? = if let contentType = docAttrs[.documentType] as? NSAttributedString.DocumentType {
- Static.documentTypeToUTType[contentType]
- } else {
- nil
- }
-
- return StructuredContentValues(
- originalType: fileType,
- contentType: contentType,
- plainText: content,
- encoding: docEnconding
- )
- }
-}
diff --git a/Sources/SharedKit/Extensions/URL/URL+SymLink.swift b/Sources/SharedKit/Extensions/URL/URL+SymLink.swift
deleted file mode 100644
index 7976559..0000000
--- a/Sources/SharedKit/Extensions/URL/URL+SymLink.swift
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// URL+SymLink.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/08/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-import os.log
-
-extension URL {
- // MARK: - SymLinks
-
- ///
- /// This differs from `[NSString stringByResolvingSymlinksInPath]` in the fact that
- /// `/private` is resolved, too
- /// - Returns: The resolved `URL`
- /// - Throws: `POSIXError` if resolution fails
- ///
- func resolveSymlinks() throws -> URL {
- guard let cPath = osPath.cString(using: .utf8) else {
- throw EncodingError.conversionFailed(.utf8)
- }
-
- guard let result = realpath(cPath, nil) else {
- throw POSIXError(.init(rawValue: errno) ?? .ENOENT)
- }
-
- let resolved = String(cString: result)
-
- free(result)
-
- return URL(filePath: resolved)
- }
-
- ///
- /// Resolve any symlink and alias from `self` then check if path is already secured.
- /// If isn't secured shows the open panel to select path and then store it as secured
- /// - Parameters:
- /// - chooseFiles: Can choose files
- /// - chooseDirectories: Can choose directories
- /// - panelTitle: The text to show as title if the open panel must be shown
- /// - alwaysResolveSymlinks: Try to resolve symlinks before check for aliases
- /// - Returns: A tuple containing:
- /// - `resolvedPath`: The selected path with aliases and symlinks resolved
- /// - `userSelectOtherPath`: `true` if the selected path differs from the passed one
- /// - Returns `nil` if the user doesn't select any path
- ///
- @MainActor func resolveSymLinksAndAliases(
- chooseFiles: Bool,
- chooseDirectories: Bool,
- panelTitle: String,
- alwaysResolveSymlinks: Bool
- ) -> (resolvedPath: URL, userSelectOtherPath: Bool)? {
- // temporary files saved on /private require to be opened using resolved symlinks
- // otherwise the paths contained inside secure bookmarks don't match
- var path = self
- if alwaysResolveSymlinks {
- do {
- path = try path.resolveSymlinks()
- } catch {
- Logger.general.error("unable to resolve symlink for \(path) (error \(error))")
- }
- }
- do {
- if try path.isAliasFile() {
- path = try path.realPathByAlias()
- }
- } catch {
- Logger.general.error("unable to resolve alias for \(path) (error \(error))")
- }
-
- let selectedPath = if path.isSandboxed(allowFile: chooseFiles, allowDirectory: chooseDirectories) {
- path
- } else {
- path.selectPath(
- panelTitle: panelTitle,
- chooseFiles: chooseFiles,
- chooseDirectories: chooseDirectories
- )
- }
-
- guard let selectedPath else {
- return nil
- }
- return (selectedPath, selectedPath != path)
- }
-
- // MARK: - Aliases
-
- func isAliasFile() throws -> Bool {
- guard let contentType = try resourceValues(forKeys: [.contentTypeKey]).contentType else {
- return false
- }
- return contentType == .aliasFile
- }
-
- func realPathByAlias() throws -> URL {
- let alias = try URL.bookmarkData(withContentsOf: self)
-
- var isStale = false
- return try URL(
- resolvingBookmarkData: alias,
- options: .withoutUI,
- relativeTo: nil,
- bookmarkDataIsStale: &isStale
- )
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/Box/NSBox+Helper.swift b/Sources/SharedKit/Extensions/View/Box/NSBox+Helper.swift
deleted file mode 100644
index 8f48516..0000000
--- a/Sources/SharedKit/Extensions/View/Box/NSBox+Helper.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// NSBox+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-@objc extension NSBox {
- static func separator() -> NSBox {
- let view = NSBox()
-
- view.boxType = .separator
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/Button/NSButton+Helper.swift b/Sources/SharedKit/Extensions/View/Button/NSButton+Helper.swift
deleted file mode 100644
index a892d13..0000000
--- a/Sources/SharedKit/Extensions/View/Button/NSButton+Helper.swift
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// NSButton+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 13/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Cocoa
-import Foundation
-
-extension NSButton {
- static func button(title: String, keyEquivalent: String) -> NSButton {
- let view = NSButton(frame: .zero)
- view.title = title
- view.setButtonType(.momentaryPushIn)
-
- view.isBordered = true
- view.state = .off
- view.bezelStyle = .flexiblePush
- view.imagePosition = .noImage
- view.alignment = .center
- view.keyEquivalent = keyEquivalent
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- static func cancelButton(title: String, target: Any? = nil, action: Selector? = nil) -> NSButton {
- let button = NSButton(
- title: title,
- target: target,
- action: action
- )
- button.keyEquivalent = KeyEquivalent.escape
- button.tag = NSApplication.ModalResponse.cancel.rawValue
- button.translatesAutoresizingMaskIntoConstraints = false
-
- return button
- }
-
- static func okButton(title: String, target: Any? = nil, action: Selector? = nil) -> NSButton {
- let button = NSButton(
- title: title,
- target: target,
- action: action
- )
- button.keyEquivalent = KeyEquivalent.enter
- button.tag = NSApplication.ModalResponse.OK.rawValue
- button.translatesAutoresizingMaskIntoConstraints = false
-
- return button
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/Button/NSPopUpButton+Helper.swift b/Sources/SharedKit/Extensions/View/Button/NSPopUpButton+Helper.swift
deleted file mode 100644
index 54d3ce1..0000000
--- a/Sources/SharedKit/Extensions/View/Button/NSPopUpButton+Helper.swift
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// NSPopUpButton+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-@objc extension NSPopUpButton {
- convenience init(
- identifier: NSUserInterfaceItemIdentifier,
- menuTitle: String,
- menuImage: NSImage?
- ) {
- self.init(frame: .zero, pullsDown: true)
-
- bezelStyle = .texturedRounded
- setButtonType(.momentaryPushIn)
- imagePosition = .imageOnly
- alignment = .left
- lineBreakMode = .byTruncatingTail
- state = .on
- isBordered = true
- imageScaling = .scaleProportionallyDown
-
- let menuItem = NSMenuItem()
- menuItem.state = .on
- menuItem.image = menuImage
- menuItem.isHidden = true
-
- let popupMenu = NSMenu(title: menuTitle)
- popupMenu.identifier = identifier
- popupMenu.addItem(menuItem)
-
- menu = popupMenu
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/ProgressIndicator/NSProgressIndicator+Helper.swift b/Sources/SharedKit/Extensions/View/ProgressIndicator/NSProgressIndicator+Helper.swift
deleted file mode 100644
index c26f7a4..0000000
--- a/Sources/SharedKit/Extensions/View/ProgressIndicator/NSProgressIndicator+Helper.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// NSProgressIndicator+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 18/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-extension NSProgressIndicator {
- static func bar() -> NSProgressIndicator {
- let view = NSProgressIndicator()
-
- view.isIndeterminate = false
- view.minValue = 0
- view.maxValue = 0
- view.doubleValue = 0
- view.controlSize = .regular
- view.style = .bar
-
- return view
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/TextField/NSTextField+Helper.swift b/Sources/SharedKit/Extensions/View/TextField/NSTextField+Helper.swift
deleted file mode 100644
index d54c995..0000000
--- a/Sources/SharedKit/Extensions/View/TextField/NSTextField+Helper.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// NSTextField+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@objc extension NSTextField {
- static func labelWithTitle(_ title: String) -> NSTextField {
- let view = NSTextField(frame: .zero)
-
- view.stringValue = title
- view.isEditable = false
- view.isSelectable = false
- view.drawsBackground = false
- view.isBordered = false
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- static func hintWithTitle(_ title: String) -> NSTextField {
- let view = NSTextField(frame: .zero)
-
- view.stringValue = title
- view.isEditable = false
- view.isSelectable = false
- view.drawsBackground = false
- view.isBordered = false
- view.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-}
diff --git a/Sources/SharedKit/Extensions/View/TextView/NSTextView+Style.swift b/Sources/SharedKit/Extensions/View/TextView/NSTextView+Style.swift
deleted file mode 100644
index 0400533..0000000
--- a/Sources/SharedKit/Extensions/View/TextView/NSTextView+Style.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// NSTextView+Style.swift
-// VisualDiffer
-//
-// Created by davide ficano on 14/11/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-@objc extension NSTextView {
- func setTabStop(_ tabSpaces: Int) {
- guard let font else {
- return
- }
- guard let paragraphStyle = defaultParagraphStyle?.mutableCopy() as? NSMutableParagraphStyle
- ?? NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle else {
- return
- }
- let charWidth = (" " as NSString).size(withAttributes: [.font: font]).width
-
- paragraphStyle.defaultTabInterval = charWidth * Double(tabSpaces)
- paragraphStyle.tabStops = []
- defaultParagraphStyle = paragraphStyle
-
- var typingAttributes = typingAttributes
- typingAttributes[NSAttributedString.Key.paragraphStyle] = paragraphStyle
- typingAttributes[NSAttributedString.Key.font] = font
- self.typingAttributes = typingAttributes
-
- let rangeOfChange = NSRange(location: 0, length: string.count)
- shouldChangeText(in: rangeOfChange, replacementString: nil)
- textStorage?.setAttributes(
- typingAttributes,
- range: rangeOfChange
- )
-
- didChangeText()
- }
-
- func disableWordWrap() {
- guard let textContainer else {
- return
- }
- let largeNumberForText = 1.0e7
-
- textContainer.containerSize = NSSize(width: largeNumberForText, height: largeNumberForText)
- textContainer.widthTracksTextView = false
- maxSize = NSSize(width: largeNumberForText, height: maxSize.height)
- isHorizontallyResizable = true
- }
-
- func setTextColor(_ textColor: NSColor?, backgroundColor: NSColor?) {
- if textColor == nil, backgroundColor == nil {
- return
- }
- guard let textStorage else {
- return
- }
- let string = textStorage.string
- let length = string.count
-
- // remove the old colors
- let area = NSRange(location: 0, length: length)
- textStorage.removeAttribute(NSAttributedString.Key.foregroundColor, range: area)
- textStorage.removeAttribute(NSAttributedString.Key.backgroundColor, range: area)
-
- if let textColor {
- textStorage.addAttribute(
- NSAttributedString.Key.foregroundColor,
- value: textColor,
- range: area
- )
- }
- if let backgroundColor {
- textStorage.addAttribute(
- NSAttributedString.Key.backgroundColor,
- value: backgroundColor,
- range: area
- )
- }
- }
-
- func append(text: String, attributes: [NSAttributedString.Key: Any]? = nil) {
- let attrString = NSAttributedString(string: text, attributes: attributes)
- if let textStorage {
- textStorage.append(attrString)
- }
- scrollRangeToVisible(NSRange(location: string.count, length: 0))
- }
-}
diff --git a/Sources/SharedKit/Extensions/Window/NSWindow+Editing.swift b/Sources/SharedKit/Extensions/Window/NSWindow+Editing.swift
deleted file mode 100644
index 6efb09f..0000000
--- a/Sources/SharedKit/Extensions/Window/NSWindow+Editing.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// NSWindow+Editing.swift
-// VisualDiffer
-//
-// Created by davide ficano on 07/12/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-// Copied from https://red-sweater.com/blog/229/stay-responsive
-// see http://stackoverflow.com/questions/14049913/update-property-bound-from-text-field-without-needing-to-press-enter
-// This category allows to update text field's bindings without pressing enter or changing first responder
-
-extension NSWindow {
- func endEditing() {
- // Save the current first responder, respecting the fact
- // that it might conceptually be the delegate of the
- // field editor that is "first responder."
- var oldFirstResponder: NSResponder?
-
- if let textView = firstResponder as? NSTextView,
- textView.isFieldEditor {
- // A field editor's delegate is the view we're editing
- if let responder = textView.delegate as? NSResponder {
- oldFirstResponder = responder
- }
- }
- // Gracefully end all editing in our window (from Erik Buck).
- // This will cause the user's changes to be committed.
- if makeFirstResponder(self) {
- // All editing is now ended and delegate messages sent etc.
- } else {
- // For some reason the text object being edited will
- // not resign first responder status so force an
- /// end to editing anyway
- endEditing(for: nil)
- }
-
- // If we had a first responder before, restore it
- if let oldFirstResponder {
- makeFirstResponder(oldFirstResponder)
- }
- }
-}
diff --git a/Sources/SharedKit/Extensions/Workspace/NSWorkspace+Finder.swift b/Sources/SharedKit/Extensions/Workspace/NSWorkspace+Finder.swift
deleted file mode 100644
index 32fb156..0000000
--- a/Sources/SharedKit/Extensions/Workspace/NSWorkspace+Finder.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// NSWorkspace+Finder.swift
-// VisualDiffer
-//
-// Created by davide ficano on 15/11/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-let suppressShowInFinder = "suppressShowInFinder"
-let maxFoldersToShowWithoutAlert = 8
-
-extension NSWorkspace {
- /**
- * @paths array containing absolute file path strings
- * Show the paths on Finder
- */
- @MainActor @objc func show(inFinder paths: [String]) {
- if paths.count > maxFoldersToShowWithoutAlert {
- let confirmOpen = NSAlert.showModalConfirm(
- messageText: String(format: NSLocalizedString("Are you sure you want to open %lu Finder windows?", comment: ""), paths.count),
- informativeText: NSLocalizedString("You have chosen to open a large number of windows. This can take a long time", comment: ""),
- suppressPropertyName: suppressShowInFinder,
- yesText: nil,
- noText: nil
- )
- if !confirmOpen {
- return
- }
- }
-
- if !paths.isEmpty {
- var urls = [URL]()
- // Get secure urls to avoid the warning
- // __CFPasteboardIssueSandboxExtensionForPath: error for [/path/to/folder]
-
- var secureURLs = [URL]()
-
- for p in paths {
- let pUrl = URL(filePath: p)
- urls.append(pUrl)
- if let secureURL = SecureBookmark.shared.secure(fromBookmark: pUrl, startSecured: true) {
- secureURLs.append(secureURL)
- }
- }
- NSWorkspace.shared.activateFileViewerSelecting(urls)
-
- for url in secureURLs {
- SecureBookmark.shared.stopAccessing(url: url)
- }
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/Document/SecureBookmark.swift b/Sources/SharedKit/Utilities/Document/SecureBookmark.swift
deleted file mode 100644
index 40095ee..0000000
--- a/Sources/SharedKit/Utilities/Document/SecureBookmark.swift
+++ /dev/null
@@ -1,118 +0,0 @@
-//
-// SecureBookmark.swift
-// VisualDiffer
-//
-// Created by davide ficano on 02/09/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-import os.log
-
-private let sandboxedPaths = "sandboxedPaths"
-
-class SecureBookmark: @unchecked Sendable {
- static let shared = SecureBookmark()
-
- private init() {}
-
- /**
- * Add a new url to the secure bookmarks
- * @return true if the url is bookmarked with success, false otherwise
- */
- @discardableResult
- func add(_ path: URL, searchClosestPath: Bool = true) -> Bool {
- var bookmark: Data?
-
- if searchClosestPath,
- let securedPaths {
- if let closestPath = findClosestPath(to: path, searchPaths: Array(securedPaths.keys)) {
- bookmark = securedPaths[closestPath]
- }
- } else {
- bookmark = securedPaths?[path.osPath]
- }
-
- if bookmark == nil {
- do {
- bookmark = try path.bookmarkData(
- options: .withSecurityScope,
- includingResourceValuesForKeys: nil,
- relativeTo: nil
- )
- var dict = securedPaths
-
- if dict == nil {
- dict = [String: Data]()
- }
- // swiftlint:disable:next force_unwrapping
- dict![path.osPath] = bookmark
- UserDefaults.standard.set(dict, forKey: sandboxedPaths)
- } catch {
- Logger.general.error("Secure bookmark failed \(error)")
- return false
- }
- }
- return true
- }
-
- func secure(fromBookmark path: URL?, startSecured: Bool) -> URL? {
- guard let path else {
- return nil
- }
- guard let dict = securedPaths,
- let bookmarkPath = findClosestPath(to: path, searchPaths: Array(dict.keys)),
- let data = dict[bookmarkPath] else {
- return nil
- }
- var isStale = false
- do {
- let url = try URL(
- resolvingBookmarkData: data,
- options: .withSecurityScope,
- relativeTo: nil,
- bookmarkDataIsStale: &isStale
- )
- if startSecured {
- _ = url.startAccessingSecurityScopedResource()
- }
- return url
- } catch {
- Logger.general.error("Secure bookmark error while resolving bookmark \(error)")
- }
- return nil
- }
-
- func stopAccessing(url: URL?) {
- url?.stopAccessingSecurityScopedResource()
- }
-
- func removePaths(_ paths: [String]) {
- guard var dict = securedPaths else {
- return
- }
- for path in paths {
- dict.removeValue(forKey: path)
- }
- UserDefaults.standard.set(dict, forKey: sandboxedPaths)
- }
-
- var securedPaths: [String: Data]? {
- UserDefaults.standard.dictionary(forKey: sandboxedPaths) as? [String: Data]
- }
-
- func findClosestPath(to path: URL, searchPaths: [String]) -> String? {
- // don't matter if path is a file or a directory, add the separator in any case
- // so hasPrefix works fine with last path component
- // eg "/Users/app 2 3" has prefix "/Users/app 2" but
- // "/Users/app 2 3/" hasn't prefix "/Users/app 2/" and this is the correct result
- let pathWithSep = path.osPath + "/"
- let sorted = searchPaths.sorted {
- $0.caseInsensitiveCompare($1) == .orderedDescending
- }
- for key in sorted where pathWithSep.hasPrefix(key + "/") {
- return key
- }
- return nil
- }
-}
diff --git a/Sources/SharedKit/Utilities/Encoding/EncodingError.swift b/Sources/SharedKit/Utilities/Encoding/EncodingError.swift
deleted file mode 100644
index 1bad6a6..0000000
--- a/Sources/SharedKit/Utilities/Encoding/EncodingError.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// EncodingError.swift
-// VisualDiffer
-//
-// Created by davide ficano on 08/09/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-enum EncodingError: Error {
- case conversionFailed(String.Encoding)
-}
-
-extension EncodingError: LocalizedError {
- var errorDescription: String? {
- switch self {
- case let .conversionFailed(encoding):
- // do not use localizedStringWithFormat to avoid formatting the number
- String(format: NSLocalizedString("Can't convert to encoding: %ld", comment: ""), encoding.rawValue)
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/Event/NSEvent+VirtualKeys.swift b/Sources/SharedKit/Utilities/Event/NSEvent+VirtualKeys.swift
deleted file mode 100644
index c0c1f12..0000000
--- a/Sources/SharedKit/Utilities/Event/NSEvent+VirtualKeys.swift
+++ /dev/null
@@ -1,277 +0,0 @@
-//
-// NSEvent+VirtualKeys.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/04/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-// swiftlint:disable identifier_name
-@objc enum KeyCode: UInt16 {
- case ansi_A = 0x00
- case ansi_S = 0x01
- case ansi_D = 0x02
- case ansi_F = 0x03
- case ansi_H = 0x04
- case ansi_G = 0x05
- case ansi_Z = 0x06
- case ansi_X = 0x07
- case ansi_C = 0x08
- case ansi_V = 0x09
- case ansi_B = 0x0B
- case ansi_Q = 0x0C
- case ansi_W = 0x0D
- case ansi_E = 0x0E
- case ansi_R = 0x0F
- case ansi_Y = 0x10
- case ansi_T = 0x11
- case ansi_1 = 0x12
- case ansi_2 = 0x13
- case ansi_3 = 0x14
- case ansi_4 = 0x15
- case ansi_6 = 0x16
- case ansi_5 = 0x17
- case ansi_Equal = 0x18
- case ansi_9 = 0x19
- case ansi_7 = 0x1A
- case ansi_Minus = 0x1B
- case ansi_8 = 0x1C
- case ansi_0 = 0x1D
- case ansi_RightBracket = 0x1E
- case ansi_O = 0x1F
- case ansi_U = 0x20
- case ansi_LeftBracket = 0x21
- case ansi_I = 0x22
- case ansi_P = 0x23
- case ansi_L = 0x25
- case ansi_J = 0x26
- case ansi_Quote = 0x27
- case ansi_K = 0x28
- case ansi_Semicolon = 0x29
- case ansi_Backslash = 0x2A
- case ansi_Comma = 0x2B
- case ansi_Slash = 0x2C
- case ansi_N = 0x2D
- case ansi_M = 0x2E
- case ansi_Period = 0x2F
- case ansi_Grave = 0x32
- case ansi_KeypadDecimal = 0x41
- case ansi_KeypadMultiply = 0x43
- case ansi_KeypadPlus = 0x45
- case ansi_KeypadClear = 0x47
- case ansi_KeypadDivide = 0x4B
- case ansi_KeypadEnter = 0x4C
- case ansi_KeypadMinus = 0x4E
- case ansi_KeypadEquals = 0x51
- case ansi_Keypad0 = 0x52
- case ansi_Keypad1 = 0x53
- case ansi_Keypad2 = 0x54
- case ansi_Keypad3 = 0x55
- case ansi_Keypad4 = 0x56
- case ansi_Keypad5 = 0x57
- case ansi_Keypad6 = 0x58
- case ansi_Keypad7 = 0x59
- case ansi_Keypad8 = 0x5B
- case ansi_Keypad9 = 0x5C
-
- /* keycodes for keys that are independent of keyboard layout */
- case returnKey = 0x24
- case tab = 0x30
- case space = 0x31
- case delete = 0x33
- case escape = 0x35
- case command = 0x37
- case shift = 0x38
- case capsLock = 0x39
- case option = 0x3A
- case control = 0x3B
- case rightShift = 0x3C
- case rightOption = 0x3D
- case rightControl = 0x3E
- case function = 0x3F
- case f17 = 0x40
- case volumeUp = 0x48
- case volumeDown = 0x49
- case mute = 0x4A
- case f18 = 0x4F
- case f19 = 0x50
- case f20 = 0x5A
- case f5 = 0x60
- case f6 = 0x61
- case f7 = 0x62
- case f3 = 0x63
- case f8 = 0x64
- case f9 = 0x65
- case f11 = 0x67
- case f13 = 0x69
- case f16 = 0x6A
- case f14 = 0x6B
- case f10 = 0x6D
- case f12 = 0x6F
- case f15 = 0x71
- case help = 0x72
- case home = 0x73
- case pageUp = 0x74
- case forwardDelete = 0x75
- case f4 = 0x76
- case end = 0x77
- case f2 = 0x78
- case pageDown = 0x79
- case f1 = 0x7A
- case leftArrow = 0x7B
- case rightArrow = 0x7C
- case downArrow = 0x7D
- case upArrow = 0x7E
-
- /* ISO keyboards only */
- case iso_Section = 0x0A
-
- /* JIS keyboards only */
- case jis_Yen = 0x5D
- case jis_Underscore = 0x5E
- case jis_KeypadComma = 0x5F
- case jis_Eisu = 0x66
- case jis_Kana = 0x68
-}
-
-extension KeyCode {
- static var ansi_ACharacter: Int { Int(KeyCode.ansi_A.rawValue) }
- static var ansi_SCharacter: Int { Int(KeyCode.ansi_S.rawValue) }
- static var ansi_DCharacter: Int { Int(KeyCode.ansi_D.rawValue) }
- static var ansi_FCharacter: Int { Int(KeyCode.ansi_F.rawValue) }
- static var ansi_HCharacter: Int { Int(KeyCode.ansi_H.rawValue) }
- static var ansi_GCharacter: Int { Int(KeyCode.ansi_G.rawValue) }
- static var ansi_ZCharacter: Int { Int(KeyCode.ansi_Z.rawValue) }
- static var ansi_XCharacter: Int { Int(KeyCode.ansi_X.rawValue) }
- static var ansi_CCharacter: Int { Int(KeyCode.ansi_C.rawValue) }
- static var ansi_VCharacter: Int { Int(KeyCode.ansi_V.rawValue) }
- static var ansi_BCharacter: Int { Int(KeyCode.ansi_B.rawValue) }
- static var ansi_QCharacter: Int { Int(KeyCode.ansi_Q.rawValue) }
- static var ansi_WCharacter: Int { Int(KeyCode.ansi_W.rawValue) }
- static var ansi_ECharacter: Int { Int(KeyCode.ansi_E.rawValue) }
- static var ansi_RCharacter: Int { Int(KeyCode.ansi_R.rawValue) }
- static var ansi_YCharacter: Int { Int(KeyCode.ansi_Y.rawValue) }
- static var ansi_TCharacter: Int { Int(KeyCode.ansi_T.rawValue) }
- static var ansi_1Character: Int { Int(KeyCode.ansi_1.rawValue) }
- static var ansi_2Character: Int { Int(KeyCode.ansi_2.rawValue) }
- static var ansi_3Character: Int { Int(KeyCode.ansi_3.rawValue) }
- static var ansi_4Character: Int { Int(KeyCode.ansi_4.rawValue) }
- static var ansi_6Character: Int { Int(KeyCode.ansi_6.rawValue) }
- static var ansi_5Character: Int { Int(KeyCode.ansi_5.rawValue) }
- static var ansi_EqualCharacter: Int { Int(KeyCode.ansi_Equal.rawValue) }
- static var ansi_9Character: Int { Int(KeyCode.ansi_9.rawValue) }
- static var ansi_7Character: Int { Int(KeyCode.ansi_7.rawValue) }
- static var ansi_MinusCharacter: Int { Int(KeyCode.ansi_Minus.rawValue) }
- static var ansi_8Character: Int { Int(KeyCode.ansi_8.rawValue) }
- static var ansi_0Character: Int { Int(KeyCode.ansi_0.rawValue) }
- static var ansi_RightBracketCharacter: Int { Int(KeyCode.ansi_RightBracket.rawValue) }
- static var ansi_OCharacter: Int { Int(KeyCode.ansi_O.rawValue) }
- static var ansi_UCharacter: Int { Int(KeyCode.ansi_U.rawValue) }
- static var ansi_LeftBracketCharacter: Int { Int(KeyCode.ansi_LeftBracket.rawValue) }
- static var ansi_ICharacter: Int { Int(KeyCode.ansi_I.rawValue) }
- static var ansi_PCharacter: Int { Int(KeyCode.ansi_P.rawValue) }
- static var ansi_LCharacter: Int { Int(KeyCode.ansi_L.rawValue) }
- static var ansi_JCharacter: Int { Int(KeyCode.ansi_J.rawValue) }
- static var ansi_QuoteCharacter: Int { Int(KeyCode.ansi_Quote.rawValue) }
- static var ansi_KCharacter: Int { Int(KeyCode.ansi_K.rawValue) }
- static var ansi_SemicolonCharacter: Int { Int(KeyCode.ansi_Semicolon.rawValue) }
- static var ansi_BackslashCharacter: Int { Int(KeyCode.ansi_Backslash.rawValue) }
- static var ansi_CommaCharacter: Int { Int(KeyCode.ansi_Comma.rawValue) }
- static var ansi_SlashCharacter: Int { Int(KeyCode.ansi_Slash.rawValue) }
- static var ansi_NCharacter: Int { Int(KeyCode.ansi_N.rawValue) }
- static var ansi_MCharacter: Int { Int(KeyCode.ansi_M.rawValue) }
- static var ansi_PeriodCharacter: Int { Int(KeyCode.ansi_Period.rawValue) }
- static var ansi_GraveCharacter: Int { Int(KeyCode.ansi_Grave.rawValue) }
- static var ansi_KeypadDecimalCharacter: Int { Int(KeyCode.ansi_KeypadDecimal.rawValue) }
- static var ansi_KeypadMultiplyCharacter: Int { Int(KeyCode.ansi_KeypadMultiply.rawValue) }
- static var ansi_KeypadPlusCharacter: Int { Int(KeyCode.ansi_KeypadPlus.rawValue) }
- static var ansi_KeypadClearCharacter: Int { Int(KeyCode.ansi_KeypadClear.rawValue) }
- static var ansi_KeypadDivideCharacter: Int { Int(KeyCode.ansi_KeypadDivide.rawValue) }
- static var ansi_KeypadEnterCharacter: Int { Int(KeyCode.ansi_KeypadEnter.rawValue) }
- static var ansi_KeypadMinusCharacter: Int { Int(KeyCode.ansi_KeypadMinus.rawValue) }
- static var ansi_KeypadEqualsCharacter: Int { Int(KeyCode.ansi_KeypadEquals.rawValue) }
- static var ansi_Keypad0Character: Int { Int(KeyCode.ansi_Keypad0.rawValue) }
- static var ansi_Keypad1Character: Int { Int(KeyCode.ansi_Keypad1.rawValue) }
- static var ansi_Keypad2Character: Int { Int(KeyCode.ansi_Keypad2.rawValue) }
- static var ansi_Keypad3Character: Int { Int(KeyCode.ansi_Keypad3.rawValue) }
- static var ansi_Keypad4Character: Int { Int(KeyCode.ansi_Keypad4.rawValue) }
- static var ansi_Keypad5Character: Int { Int(KeyCode.ansi_Keypad5.rawValue) }
- static var ansi_Keypad6Character: Int { Int(KeyCode.ansi_Keypad6.rawValue) }
- static var ansi_Keypad7Character: Int { Int(KeyCode.ansi_Keypad7.rawValue) }
- static var ansi_Keypad8Character: Int { Int(KeyCode.ansi_Keypad8.rawValue) }
- static var ansi_Keypad9Character: Int { Int(KeyCode.ansi_Keypad9.rawValue) }
-
- /* keycodes for keys that are independent of keyboard layout */
- static var returnKeyCharacter: Int { Int(KeyCode.returnKey.rawValue) }
- static var tabCharacter: Int { Int(KeyCode.tab.rawValue) }
- static var spaceCharacter: Int { Int(KeyCode.space.rawValue) }
- static var deleteCharacter: Int { Int(KeyCode.delete.rawValue) }
- static var escapeCharacter: Int { Int(KeyCode.escape.rawValue) }
- static var commandCharacter: Int { Int(KeyCode.command.rawValue) }
- static var shiftCharacter: Int { Int(KeyCode.shift.rawValue) }
- static var capsLockCharacter: Int { Int(KeyCode.capsLock.rawValue) }
- static var optionCharacter: Int { Int(KeyCode.option.rawValue) }
- static var controlCharacter: Int { Int(KeyCode.control.rawValue) }
- static var rightShiftCharacter: Int { Int(KeyCode.rightShift.rawValue) }
- static var rightOptionCharacter: Int { Int(KeyCode.rightOption.rawValue) }
- static var rightControlCharacter: Int { Int(KeyCode.rightControl.rawValue) }
- static var functionCharacter: Int { Int(KeyCode.function.rawValue) }
- static var f17Character: Int { Int(KeyCode.f17.rawValue) }
- static var volumeUpCharacter: Int { Int(KeyCode.volumeUp.rawValue) }
- static var volumeDownCharacter: Int { Int(KeyCode.volumeDown.rawValue) }
- static var muteCharacter: Int { Int(KeyCode.mute.rawValue) }
- static var f18Character: Int { Int(KeyCode.f18.rawValue) }
- static var f19Character: Int { Int(KeyCode.f19.rawValue) }
- static var f20Character: Int { Int(KeyCode.f20.rawValue) }
- static var f5Character: Int { Int(KeyCode.f5.rawValue) }
- static var f6Character: Int { Int(KeyCode.f6.rawValue) }
- static var f7Character: Int { Int(KeyCode.f7.rawValue) }
- static var f3Character: Int { Int(KeyCode.f3.rawValue) }
- static var f8Character: Int { Int(KeyCode.f8.rawValue) }
- static var f9Character: Int { Int(KeyCode.f9.rawValue) }
- static var f11Character: Int { Int(KeyCode.f11.rawValue) }
- static var f13Character: Int { Int(KeyCode.f13.rawValue) }
- static var f16Character: Int { Int(KeyCode.f16.rawValue) }
- static var f14Character: Int { Int(KeyCode.f14.rawValue) }
- static var f10Character: Int { Int(KeyCode.f10.rawValue) }
- static var f12Character: Int { Int(KeyCode.f12.rawValue) }
- static var f15Character: Int { Int(KeyCode.f15.rawValue) }
- static var helpCharacter: Int { Int(KeyCode.help.rawValue) }
- static var homeCharacter: Int { Int(KeyCode.home.rawValue) }
- static var pageUpCharacter: Int { Int(KeyCode.pageUp.rawValue) }
- static var forwardDeleteCharacter: Int { Int(KeyCode.forwardDelete.rawValue) }
- static var f4Character: Int { Int(KeyCode.f4.rawValue) }
- static var endCharacter: Int { Int(KeyCode.end.rawValue) }
- static var f2Character: Int { Int(KeyCode.f2.rawValue) }
- static var pageDownCharacter: Int { Int(KeyCode.pageDown.rawValue) }
- static var f1Character: Int { Int(KeyCode.f1.rawValue) }
- static var leftArrowCharacter: Int { Int(KeyCode.leftArrow.rawValue) }
- static var rightArrowCharacter: Int { Int(KeyCode.rightArrow.rawValue) }
- static var downArrowCharacter: Int { Int(KeyCode.downArrow.rawValue) }
- static var upArrowCharacter: Int { Int(KeyCode.upArrow.rawValue) }
-
- /* ISO keyboards only */
- static var iso_SectionCharacter: Int { Int(KeyCode.iso_Section.rawValue) }
-
- /* JIS keyboards only */
- static var jis_YenCharacter: Int { Int(KeyCode.jis_Yen.rawValue) }
- static var jis_UnderscoreCharacter: Int { Int(KeyCode.jis_Underscore.rawValue) }
- static var jis_KeypadCommaCharacter: Int { Int(KeyCode.jis_KeypadComma.rawValue) }
- static var jis_EisuCharacter: Int { Int(KeyCode.jis_Eisu.rawValue) }
- static var jis_KanaCharacter: Int { Int(KeyCode.jis_Kana.rawValue) }
-
- var intValue: Int {
- Int(rawValue)
- }
-}
-
-// swiftlint:enable identifier_name
-
-extension NSEvent {
- @objc func isDeleteShortcutKey(_ checkCommandDeleteKey: Bool) -> Bool {
- if checkCommandDeleteKey, modifierFlags.contains(.command), keyCode == KeyCode.deleteCharacter {
- return true
- }
- return keyCode == KeyCode.forwardDeleteCharacter
- }
-}
diff --git a/Sources/SharedKit/Utilities/Formatters/FileSizeFormatter.swift b/Sources/SharedKit/Utilities/Formatters/FileSizeFormatter.swift
deleted file mode 100644
index e6b1f7a..0000000
--- a/Sources/SharedKit/Utilities/Formatters/FileSizeFormatter.swift
+++ /dev/null
@@ -1,77 +0,0 @@
-//
-// FileSizeFormatter.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/08/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-@objc class FileSizeFormatter: NumberFormatter, @unchecked Sendable {
- private(set) var showInBytes = false
- private(set) var showUnitForBytes = true
-
- @objc static let `default` = FileSizeFormatter()
-
- @objc override init() {
- super.init()
-
- numberStyle = .decimal
- maximumFractionDigits = 2
- }
-
- @objc convenience init(
- showInBytes: Bool,
- showUnitForBytes: Bool
- ) {
- self.init()
-
- self.showInBytes = showInBytes
- self.showUnitForBytes = showUnitForBytes
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func string(
- from number: NSNumber,
- showInBytes: Bool,
- showUnitForBytes: Bool
- ) -> String? {
- var floatSize = number.doubleValue
-
- if floatSize < 1023 || showInBytes {
- if let value = super.string(from: NSNumber(value: floatSize)) {
- return String(format: "%@%@", value, showUnitForBytes ? " bytes" : "")
- }
- return "\(floatSize)"
- }
-
- floatSize /= 1024
- if floatSize < 1023 {
- if let value = super.string(from: NSNumber(value: floatSize)) {
- return String(format: "%@ KB", value)
- }
- return "\(floatSize)"
- }
-
- floatSize /= 1024
- if floatSize < 1023 {
- if let value = super.string(from: NSNumber(value: floatSize)) {
- return String(format: "%@ MB", value)
- }
- return "\(floatSize)"
- }
-
- floatSize /= 1024
- if let value = super.string(from: NSNumber(value: floatSize)) {
- return String(format: "%@ GB", value)
- }
- return "\(floatSize)"
- }
-
- override func string(from number: NSNumber) -> String? {
- string(from: number, showInBytes: showInBytes, showUnitForBytes: showUnitForBytes)
- }
-}
diff --git a/Sources/SharedKit/Utilities/Formatters/IntegerFormatter.swift b/Sources/SharedKit/Utilities/Formatters/IntegerFormatter.swift
deleted file mode 100644
index 9c979e6..0000000
--- a/Sources/SharedKit/Utilities/Formatters/IntegerFormatter.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// IntegerFormatter.swift
-// VisualDiffer
-//
-// Created by davide ficano on 07/03/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-class IntegerFormatter: NumberFormatter, @unchecked Sendable {
- override open func isPartialStringValid(
- _ partialString: String,
- newEditingString _: AutoreleasingUnsafeMutablePointer?,
- errorDescription _: AutoreleasingUnsafeMutablePointer?
- ) -> Bool {
- if partialString.isEmpty {
- return true
- }
-
- // it is valid if contains only decimal digits
- return partialString.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
- }
-}
diff --git a/Sources/SharedKit/Utilities/IO/BufferedInputStream.swift b/Sources/SharedKit/Utilities/IO/BufferedInputStream.swift
deleted file mode 100644
index 24b0631..0000000
--- a/Sources/SharedKit/Utilities/IO/BufferedInputStream.swift
+++ /dev/null
@@ -1,269 +0,0 @@
-//
-// BufferedInputStream.swift
-// VisualDiffer
-//
-// Created by davide ficano on 15/07/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-import Foundation
-import AppKit
-
-/// A line-by-line `InputStream` supporting `\n`, `\r`, and `\r\n` terminators.
-// swiftlint:disable force_unwrapping
-public class BufferedInputStream: InputStream {
- public enum Constants {
- public static let invalidated = -2
- public static let unmarked = -1
- public static let defaultCharBufferSize = 8192
- public static let defaultExpectedLineLength = 80
- }
-
- // The decorated stream
- private var stream: InputStream
- // The size of each chunk read from the stream into memory
- private var bufferSize: Int = 0
- // The encoding of the text represented by the underlying stream
- private var encoding: String.Encoding
-
- // Buffer containing the bytes of the current chunk read from the stream
- private var dataBuffer: [UInt8] = []
- private var dataBufferLen: Int = 0
-
- // Whether the stream was opened by this decorator and should therefore be closed with it
- private var shouldCloseStream = false
-
- private var skipLF = false
- private var nextChar = 0
- private var nChars = 0
- private var markedChar = Constants.unmarked
- private var readAheadLimit = 0
-
- /**
- * if using the object encoding doesn't create a valid string
- * then try to determine the best one
- */
- private let detectBestEncoding: Bool
-
- public init(
- stream: InputStream,
- encoding: String.Encoding,
- bufferSize: Int,
- detectBestEncoding: Bool = false
- ) {
- self.stream = stream
- self.encoding = encoding
- self.bufferSize = bufferSize
- self.detectBestEncoding = detectBestEncoding
-
- super.init()
- }
-
- public convenience init(
- url: URL,
- encoding: String.Encoding,
- bufferSize: Int = Constants.defaultCharBufferSize,
- detectBestEncoding: Bool = false
- ) throws {
- if let stream = InputStream(url: url) {
- self.init(
- stream: stream,
- encoding: encoding,
- bufferSize: bufferSize,
- detectBestEncoding: detectBestEncoding
- )
- shouldCloseStream = true
- } else {
- throw FileError.openFile(path: url.osPath)
- }
- }
-
- // MARK: read methods
-
- func readLine(ignoreLF: Bool = false) -> String? {
- var line: String?
- if let data = readLineAsData(ignoreLF: ignoreLF) {
- // we can't use the native Swift String(data:encoding) because the results are different
- // For example
- // let data: Data = Data([0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd4, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05])
- // let swiftString = String(data: data, encoding: .ascii)
- // let nsString = NSString(data: data, encoding: String.Encoding.ascii.rawValue)
- // swiftString is nil but nsString is not nil
- line = NSString(data: data, encoding: encoding.rawValue) as String?
- if line == nil, detectBestEncoding {
- line = lineWithBestEncoding(data: data)
- }
- }
-
- return line
- }
-
- private func lineWithBestEncoding(data: Data) -> String? {
- if let line = String(data: data, encoding: String.Encoding.windowsCP1252) {
- encoding = String.Encoding.windowsCP1252
- return line as String
- }
- // use NSAttributedString to detect best encoding
- var docAttrs = NSDictionary()
- let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
- .documentType: NSAttributedString.DocumentType.plain,
- ]
- do {
- let line = try withUnsafeMutablePointer(to: &docAttrs) { docAttrsPointer in
- try NSAttributedString(
- data: data,
- options: options,
- documentAttributes: AutoreleasingUnsafeMutablePointer(docAttrsPointer)
- ).string
- }
-
- if let val = docAttrs[NSAttributedString.DocumentAttributeKey.characterEncoding] as? NSNumber {
- encoding = String.Encoding(rawValue: val.uintValue)
- }
- return line
- } catch {}
- return nil
- }
-
- public func readLineAsData(ignoreLF: Bool = false) -> Data? {
- var data: Data?
- var startChar = 0
-
- var omitLF = ignoreLF || skipLF
-
- while true {
- if nextChar >= nChars {
- fill()
- }
- if nextChar >= nChars { // EOF
- if let data, !data.isEmpty {
- return data
- } else {
- return nil
- }
- }
- var eol = false
- var chInt: UInt8 = 0
- // Skip a leftover '\n', if necessary
- if omitLF, dataBuffer[nextChar] == 0x0A {
- nextChar += 1
- }
- skipLF = false
- omitLF = false
- var i = nextChar
- while i < nChars {
- chInt = dataBuffer[i]
- if (chInt == 0x0A) || (chInt == 0x0D) {
- eol = true
- break
- }
- i += 1
- }
- startChar = nextChar
- nextChar = i
- if eol {
- dataBuffer.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
- let ptr = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self).advanced(by: startChar)
- if data == nil {
- data = Data(bytes: ptr, count: i - startChar)
- } else {
- data!.append(ptr, count: i - startChar)
- }
- }
-
- nextChar += 1
- if chInt == 0x0D {
- skipLF = true
- }
- return data
- }
- if data == nil {
- data = Data(capacity: Constants.defaultExpectedLineLength)
- }
- dataBuffer.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
- let ptr = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self).advanced(by: startChar)
- data!.append(ptr, count: i - startChar)
- }
- }
- }
-
- private func fill() {
- var dst = 0
- if markedChar <= Constants.unmarked {
- // No mark
- dst = 0
- } else {
- // Marked
- let delta = nextChar - markedChar
- if delta >= readAheadLimit {
- // Gone past read-ahead limit: Invalidate mark
- markedChar = Constants.invalidated
- readAheadLimit = 0
- dst = 0
- } else {
- if readAheadLimit <= dataBufferLen {
- // Shuffle in the current buffer
- dataBuffer.replaceSubrange(markedChar ..< delta, with: dataBuffer)
- markedChar = 0
- dst = delta
- } else {
- var ncb = [UInt8](repeating: 0, count: readAheadLimit)
- ncb.replaceSubrange(markedChar ..< delta, with: dataBuffer)
- // Reallocate buffer to accommodate read-ahead limit
- dataBuffer = ncb
- dataBufferLen = readAheadLimit
- markedChar = 0
- dst = delta
- }
- nChars = delta
- nextChar = delta
- }
- }
-
- let bytesRead = dataBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutableRawBufferPointer) -> Int in
- let ptr = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self).advanced(by: dst)
- return stream.read(ptr, maxLength: dataBufferLen - dst)
- }
-
- if bytesRead > 0 {
- nChars = dst + bytesRead
- nextChar = dst
- }
- }
-
- // MARK: NSInputStream methods
-
- override public func open() {
- shouldCloseStream = stream.streamStatus == Stream.Status.notOpen
- if shouldCloseStream {
- // If the underlying stream is not already open, we open it ourselves
- // and we will close it when the decorator is closed
- stream.open()
- }
- dataBuffer = [UInt8](repeating: 0, count: bufferSize)
- dataBufferLen = bufferSize
-
- skipLF = false
- nChars = 0
- nextChar = 0
- markedChar = Constants.unmarked
- readAheadLimit = 0
- }
-
- override public var hasBytesAvailable: Bool {
- stream.hasBytesAvailable
- }
-
- public func getBuffer(buffer: UnsafeMutablePointer?>, length len: UnsafeMutablePointer) -> Bool {
- stream.getBuffer(buffer, length: len)
- }
-
- override public func close() {
- if shouldCloseStream {
- // Close the underlying stream if is was opened by this decorator
- stream.close()
- }
- }
-}
-
-// swiftlint:enable force_unwrapping
diff --git a/Sources/SharedKit/Utilities/IO/CompareUtil.swift b/Sources/SharedKit/Utilities/IO/CompareUtil.swift
deleted file mode 100644
index 39d65a7..0000000
--- a/Sources/SharedKit/Utilities/IO/CompareUtil.swift
+++ /dev/null
@@ -1,141 +0,0 @@
-//
-// CompareUtil.swift
-// VisualDiffer
-//
-// Created by davide ficano on 31/01/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-public func compareTextFiles(
- _ lhs: URL,
- _ rhs: URL,
- _ encoding: String.Encoding,
- _ bufferSize: Int,
- _ isRunning: () -> Bool
-) throws -> ComparisonResult {
- let leftBis = try BufferedInputStream(
- url: lhs,
- encoding: encoding,
- bufferSize: bufferSize
- )
- defer {
- leftBis.close()
- }
-
- let rightBis = try BufferedInputStream(
- url: rhs,
- encoding: encoding,
- bufferSize: bufferSize
- )
-
- defer {
- rightBis.close()
- }
-
- leftBis.open()
- rightBis.open()
-
- var ret: ComparisonResult = .orderedSame
- var eof = false
-
- repeat {
- autoreleasepool {
- ret = compareLine(leftBis, rightBis, &eof)
- }
- } while !eof && ret == .orderedSame && isRunning()
-
- return ret
-}
-
-func compareLine(
- _ leftBis: BufferedInputStream,
- _ rightBis: BufferedInputStream,
- _ eof: inout Bool
-) -> ComparisonResult {
- let leftLine = leftBis.readLine()
- let rightLine = rightBis.readLine()
- if let leftLine,
- let rightLine {
- return leftLine.compare(rightLine)
- }
- eof = true
- if leftLine == nil, rightLine == nil {
- return .orderedSame
- }
- if leftLine == nil {
- return .orderedAscending
- }
- return .orderedDescending
-}
-
-public func compareDates(
- _ lhs: Date,
- _ rhs: Date,
- _ timestampToleranceSeconds: Int
-) -> ComparisonResult {
- let interval = Int(lhs.timeIntervalSince(rhs))
-
- if interval == 0 || (-timestampToleranceSeconds <= interval && interval <= timestampToleranceSeconds) {
- return .orderedSame
- }
- return interval < 0 ? .orderedAscending : .orderedDescending
-}
-
-func compareData(_ lhs: Data, _ rhs: Data) -> ComparisonResult {
- let lCount = lhs.count
- let rCount = rhs.count
-
- return lhs.withUnsafeBytes { lBytes in
- rhs.withUnsafeBytes { rBytes in
- var ret = memcmp(lBytes.baseAddress, rBytes.baseAddress, min(lCount, rCount))
- if ret == 0, lCount != rCount {
- ret = lCount < rCount ? 1 : -1
- }
- // normalize to ComparisonResult value
- if ret < 0 {
- return .orderedAscending
- } else if ret > 0 {
- return .orderedDescending
- } else {
- return .orderedSame
- }
- }
- }
-}
-
-public func compareBinaryFiles(
- _ left: URL,
- _ right: URL,
- _ bufferSize: Int,
- _ isRunning: () -> Bool
-) throws -> ComparisonResult {
- let leftFile = try FileHandle(forReadingFrom: left)
-
- defer {
- leftFile.closeFile()
- }
-
- let rightFile = try FileHandle(forReadingFrom: right)
-
- defer {
- rightFile.closeFile()
- }
-
- var result: ComparisonResult = .orderedSame
-
- repeat {
- if let leftData = try? leftFile.read(upToCount: bufferSize),
- let rightData = try? rightFile.read(upToCount: bufferSize) {
- if leftData.isEmpty || rightData.isEmpty {
- break
- }
- result = compareData(leftData, rightData)
- } else {
- break
- }
- } while result == .orderedSame && isRunning()
-
- return result
-}
diff --git a/Sources/SharedKit/Utilities/IO/FileError.swift b/Sources/SharedKit/Utilities/IO/FileError.swift
deleted file mode 100644
index fa23cd4..0000000
--- a/Sources/SharedKit/Utilities/IO/FileError.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// FileError.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/12/10.
-// Copyright (c) 2010 visualdiffer.com
-//
-
-public enum FileError: Error, Equatable {
- case symlinkLoop(path: String)
- case createSymLink(path: String)
- case openFile(path: String)
- case fileNotExists(path: URL, side: DisplaySide)
- case unknownVolumeType
-}
-
-extension FileError: LocalizedError {
- public var errorDescription: String? {
- switch self {
- case let .symlinkLoop(path):
- let message = NSLocalizedString("Detected recursive loop for symbolic link '%@'", comment: "")
- return String.localizedStringWithFormat(message, path)
- case let .openFile(path):
- let message = NSLocalizedString("Unable to open file '%@'", comment: "")
- return String.localizedStringWithFormat(message, path)
- case let .createSymLink(path):
- let message = NSLocalizedString("Unable to create symbolic link to destination '%@' because the existing file isn't a symbolic link", comment: "")
- return String.localizedStringWithFormat(message, path)
- case let .fileNotExists(path, side):
- let message = switch side {
- case .left:
- NSLocalizedString("Left file '%@' no longer exists", comment: "")
- case .right:
- NSLocalizedString("Right file '%@' no longer exists", comment: "")
- }
- return String.localizedStringWithFormat(message, path.osPath)
- case .unknownVolumeType:
- return NSLocalizedString("Unable to determine the disk volume type", comment: "")
- }
- }
-
- public var recoverySuggestion: String? {
- switch self {
- case .fileNotExists:
- NSLocalizedString("Maybe it was located in a temporary directory and another process deleted it", comment: "")
- default:
- nil
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/IO/PowerAssertion.swift b/Sources/SharedKit/Utilities/IO/PowerAssertion.swift
deleted file mode 100644
index bdf9a27..0000000
--- a/Sources/SharedKit/Utilities/IO/PowerAssertion.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-//
-// PowerAssertion.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/12/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-import IOKit.pwr_mgt
-
-private class PowerItem {
- var pmAssertion = IOPMAssertionID(kIOPMNullAssertionID)
- var refCount = 0
-
- var name = ""
-
- init() {}
-
- convenience init(name: String) {
- self.init()
-
- self.name = name
- }
-
- deinit {
- releasePMAssertion()
- }
-
- @discardableResult
- func createPMAssertion(type: String) -> IOReturn {
- guard pmAssertion == kIOPMNullAssertionID else {
- return kIOReturnError
- }
- return IOPMAssertionCreateWithName(
- type as CFString,
- IOPMAssertionLevel(kIOPMAssertionLevelOn),
- name as CFString,
- &pmAssertion
- )
- }
-
- func releasePMAssertion() {
- guard pmAssertion != kIOPMNullAssertionID else {
- return
- }
-
- IOPMAssertionRelease(pmAssertion)
- pmAssertion = IOPMAssertionID(kIOPMNullAssertionID)
- }
-
- func setDisableSystemSleep(_ disableSleep: Bool) {
- if disableSleep {
- refCount += 1
- if refCount == 1 {
- createPMAssertion(type: kIOPMAssertPreventUserIdleSystemSleep)
- }
- } else {
- // Prevent refCount from becoming negative
- if refCount > 0 {
- refCount -= 1
- if refCount == 0 {
- releasePMAssertion()
- }
- }
- }
- }
-}
-
-/**
- * Disable computer sleep using IOPMAssertion implemented as singleton
- * Minimize the number of IOPMAssertions creating different instances only when the name differs
- *
- */
-@objc class PowerAssertion: NSObject, @unchecked Sendable {
- @objc static let shared = PowerAssertion()
- private var pmAssertions: [String: PowerItem] = [:]
-
- override private init() {}
-
- @objc func setDisableSystemSleep(_ disableSleep: Bool, with name: String) {
- let item: PowerItem
-
- if let existingItem = pmAssertions[name] {
- item = existingItem
- } else {
- item = PowerItem(name: name)
- pmAssertions[name] = item
- }
- item.setDisableSystemSleep(disableSleep)
- }
-}
diff --git a/Sources/SharedKit/Utilities/Image/IconUtils.swift b/Sources/SharedKit/Utilities/Image/IconUtils.swift
deleted file mode 100644
index 6457c37..0000000
--- a/Sources/SharedKit/Utilities/Image/IconUtils.swift
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// IconUtils.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/01/12.
-// Converted to Swift by davide ficano on 02/05/25.
-// Copyright (c) 2010 visualdiffer.com
-
-import Cocoa
-import UniformTypeIdentifiers
-
-/**
- Is @unchecked Sendable because icons are modified only inside the lock so it's thread safe
- */
-public class IconUtils: @unchecked Sendable {
- static let shared = IconUtils()
-
- private let lock = NSLock()
- private var icons = [String: NSImage]()
-
- private init() {}
-
- public func badge(_ badge: NSImage, icon: NSImage, size: CGFloat) -> NSImage {
- let image = NSImage(size: NSSize(width: size, height: size))
-
- image.lockFocus()
- icon.draw(
- in: NSRect(x: 0, y: 0, width: size, height: size),
- from: NSRect.zero,
- operation: .sourceOver,
- fraction: 1.0,
- respectFlipped: true,
- hints: nil
- )
- badge.draw(
- in: NSRect(x: 0, y: 0, width: size, height: size),
- from: NSRect.zero,
- operation: .sourceOver,
- fraction: 1.0,
- respectFlipped: true,
- hints: nil
- )
- image.unlockFocus()
-
- return image
- }
-
- public func icon(forType type: UTType, size: CGFloat) -> NSImage {
- if let icon = icons[type.identifier] {
- return icon
- }
-
- let icon = NSWorkspace.shared.icon(for: type)
- addIconByName(type.identifier, icon: icon, size: size)
-
- return icon
- }
-
- public func icon(forFile url: URL, size: CGFloat) -> NSImage {
- let fullPath = url.osPath
- if let icon = icons[fullPath] {
- return icon
- }
-
- let icon = NSWorkspace.shared.icon(forFile: fullPath)
- addIconByName(fullPath, icon: icon, size: size)
-
- return icon
- }
-
- // /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/AliasBadgeIcon.icns
- public func icon(forSymbolicLink url: URL, size: CGFloat) -> NSImage {
- badge(forPath: url, icon: iconNamed("aliasbadge", size: size), size: size)
- }
-
- // /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/LockedBadgeIcon.icns
- public func icon(forLockedFile url: URL, size: CGFloat) -> NSImage {
- badge(forPath: url, icon: iconNamed("lockedbadge", size: size), size: size)
- }
-
- public func badge(forPath url: URL, icon badgeImage: NSImage, size: CGFloat) -> NSImage {
- guard let iconName = badgeImage.name() else {
- fatalError("Unable to get icon name for \(url) and icon \(badgeImage)")
- }
- let name = url
- .appendingPathComponent(iconName)
- .osPath
- if let icon = icons[name] {
- return icon
- }
-
- let path = url.osPath
- let isAbsolute = path.hasPrefix("/")
- let fileIcon = isAbsolute ? icon(forFile: url, size: size) : iconNamed(path, size: size)
- let icon = badge(badgeImage, icon: fileIcon, size: size)
-
- addIconByName(name, icon: icon, size: size)
-
- return icon
- }
-
- private func addIconByName(_ name: String, icon: NSImage, size: CGFloat) {
- lock.lock()
- // Cache only images size x size
- let reps = icon.representations
- for rep in reps where rep.pixelsHigh != Int(size) {
- if reps.count > 1 {
- icon.removeRepresentation(rep)
- }
- }
-
- icon.size = NSSize(width: size, height: size)
- icons[name] = icon
- lock.unlock()
- }
-
- private func iconNamed(_ name: String, size: CGFloat) -> NSImage {
- if let icon = icons[name] {
- return icon
- }
-
- guard let icon = NSImage(named: name) else {
- fatalError("Unable to find icon \(name)")
- }
- addIconByName(name, icon: icon, size: size)
-
- return icon
- }
-}
diff --git a/Sources/SharedKit/Utilities/Image/NoodleCustomImageRep.swift b/Sources/SharedKit/Utilities/Image/NoodleCustomImageRep.swift
deleted file mode 100644
index ff2a05c..0000000
--- a/Sources/SharedKit/Utilities/Image/NoodleCustomImageRep.swift
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// NoodleCustomImageRep.swift
-// NoodleKit
-//
-// Created by Paul Kim on 3/16/11.
-// Copyright 2011 Noodlesoft, LLC. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person
-// obtaining a copy of this software and associated documentation
-// files (the "Software"), to deal in the Software without
-// restriction, including without limitation the rights to use,
-// copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the
-// Software is furnished to do so, subject to the following
-// conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-//
-// Converted to Swift by davide ficano on 03/05/25.
-
-import Cocoa
-
-typealias NoodleCustomImageRepDrawBlock = (NoodleCustomImageRep) -> Void
-
-/*
- This image rep just provides a way to specify the image drawing via a block.
-
- For more details, check out the related blog post at http://www.noodlesoft.com/blog/2011/04/15/the-proper-care-and-feeding-of-nsimage
- */
-class NoodleCustomImageRep: NSImageRep {
- private var drawBlock: NoodleCustomImageRepDrawBlock?
-
- init(drawBlock block: NoodleCustomImageRepDrawBlock?) {
- super.init()
-
- drawBlock = block
- }
-
- init?(
- drawBlock block: NoodleCustomImageRepDrawBlock?,
- coder: NSCoder
- ) {
- super.init(coder: coder)
-
- drawBlock = block
- }
-
- override convenience init() {
- self.init(drawBlock: nil)
- }
-
- required convenience init?(coder: NSCoder) {
- self.init(drawBlock: nil, coder: coder)
- }
-
- override func copy(with zone: NSZone? = nil) -> Any {
- // swiftlint:disable:next force_cast
- let copy = super.copy(with: zone) as! NoodleCustomImageRep
-
- // NSImageRep uses NSCopyObject so we have to force a copy here
- copy.drawBlock = drawBlock
-
- return copy
- }
-
- override func draw() -> Bool {
- guard let drawBlock else {
- return false
- }
- drawBlock(self)
- return true
- }
-}
diff --git a/Sources/SharedKit/Utilities/Image/TiledImageView.swift b/Sources/SharedKit/Utilities/Image/TiledImageView.swift
deleted file mode 100644
index f1648d0..0000000
--- a/Sources/SharedKit/Utilities/Image/TiledImageView.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// TiledImageView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 14/11/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-final class TiledImageView: NSView {
- var image: NSImage? {
- didSet { needsDisplay = true }
- }
-
- override var isFlipped: Bool { false }
-
- override func draw(_ dirtyRect: NSRect) {
- NSBezierPath(rect: bounds).addClip()
-
- super.draw(dirtyRect)
- guard let img = image else {
- return
- }
-
- let tileSize = img.size
- guard tileSize.width > 0, tileSize.height > 0 else {
- return
- }
-
- var y: CGFloat = 0
- while y < bounds.height {
- var x: CGFloat = 0
- while x < bounds.width {
- img.draw(
- in: NSRect(x: x, y: y, width: tileSize.width, height: tileSize.height),
- from: .zero,
- operation: .sourceOver,
- fraction: 1.0
- )
- x += tileSize.width
- }
- y += tileSize.height
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/Menu/AttributedMenuItem.swift b/Sources/SharedKit/Utilities/Menu/AttributedMenuItem.swift
deleted file mode 100644
index e3feb9a..0000000
--- a/Sources/SharedKit/Utilities/Menu/AttributedMenuItem.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// AttributedMenuItem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 19/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-struct AttributedMenuItem {
- var text: String
- var attributes: [NSAttributedString.Key: Any]
-
- static func createAttributes(
- title: String,
- description: String,
- descriptionColor: NSColor,
- font: NSFont
- ) -> [AttributedMenuItem] {
- [
- AttributedMenuItem(text: title, attributes: [
- NSAttributedString.Key.font: font,
- NSAttributedString.Key.foregroundColor: NSColor.controlTextColor,
- ]),
- AttributedMenuItem(text: description, attributes: [
- NSAttributedString.Key.font: font,
- NSAttributedString.Key.foregroundColor: descriptionColor,
- ]),
- ]
- }
-
- static func createTitle(_ items: [AttributedMenuItem]) -> NSAttributedString {
- var str = ""
-
- for data in items {
- str += data.text
- }
- let attrString = NSMutableAttributedString(string: str)
-
- attrString.beginEditing()
- var normalRange = NSRange()
-
- for data in items {
- let text = data.text
- let attrs = data.attributes
- normalRange.length = text.count
- attrString.addAttributes(attrs, range: normalRange)
- normalRange.location += text.count
- }
- attrString.endEditing()
-
- return attrString
- }
-}
diff --git a/Sources/SharedKit/Utilities/OpenEditor/OpenEditor.swift b/Sources/SharedKit/Utilities/OpenEditor/OpenEditor.swift
deleted file mode 100644
index ef90759..0000000
--- a/Sources/SharedKit/Utilities/OpenEditor/OpenEditor.swift
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// OpenEditor.swift
-// VisualDiffer
-//
-// Created by davide ficano on 23/07/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import os.log
-
-struct OpenEditor {
- let attributes: [OpenEditorAttribute]
-
- init(attributes: [OpenEditorAttribute]) {
- self.attributes = attributes
- }
-
- init(attributes: OpenEditorAttribute) {
- self.init(attributes: [attributes])
- }
-
- init(path: String) {
- self.init(attributes: [OpenEditorAttribute(path: path)])
- }
-}
-
-extension OpenEditor {
- @MainActor func browseApplicationAndLaunch() throws {
- let openPanel = NSOpenPanel().openApplication(title: NSLocalizedString("Select Application", comment: ""))
-
- if openPanel.runModal() == .OK {
- try open(withApplication: openPanel.urls[0])
- }
- }
-
- /**
- * Run the editor application opening passed files and if editor is supported
- * move the cursor to the line/column specified into attributes
- * @param application the application path used to open the files, if nil uses the default system application
- **/
- func open(withApplication: URL?) throws {
- guard let item = attributes.first,
- let secureURL = SecureBookmark.shared.secure(fromBookmark: item.path, startSecured: true) else {
- return
- }
- defer {
- SecureBookmark.shared.stopAccessing(url: secureURL)
- }
- let application = if let withApplication {
- withApplication
- } else {
- NSWorkspace.shared.urlForApplication(toOpen: item.path)
- }
-
- guard let application else {
- throw OpenEditorError.applicationNotFound(item.path)
- }
- if let scriptURL = fullScriptURL(application) {
- try runUnixScript(scriptURL)
- } else {
- NSWorkspace.shared.open(
- [item.path],
- withApplicationAt: application,
- configuration: NSWorkspace.OpenConfiguration()
- ) { _, error in
- if let error {
- Logger.general.error("Unable to open file \(item.path): \(error)")
- }
- }
- }
- }
-
- private func fullScriptURL(_ application: URL) -> URL? {
- guard let scriptsURL = try? FileManager.default.url(
- for: .applicationScriptsDirectory,
- in: .userDomainMask,
- appropriateFor: nil,
- create: false
- ),
- let bundle = Bundle(url: application),
- let bundleIdentifier = bundle.bundleIdentifier else {
- return nil
- }
-
- var fullScriptURL = scriptsURL
- fullScriptURL.appendPathComponent("editors")
- fullScriptURL.appendPathComponent(bundleIdentifier)
- fullScriptURL.appendPathExtension("sh")
-
- return FileManager.default.fileExists(atPath: fullScriptURL.osPath) ? fullScriptURL : nil
- }
-
- func runUnixScript(_ scriptURL: URL) throws {
- do {
- let task = try NSUserUnixTask(url: scriptURL)
- task.execute(withArguments: arguments()) { taskError in
- if let taskError {
- Logger.general.error("Unable to launch \(scriptURL.osPath), \(taskError)")
- }
- }
- } catch {
- try checkExecutablePermissions(scriptURL, rethrow: error)
- }
- }
-
- private func checkExecutablePermissions(_ scriptURL: URL, rethrow _: Error) throws {
- guard let attrs = try? FileManager.default.attributesOfItem(atPath: scriptURL.osPath),
- let permissions = attrs[.posixPermissions] as? Int,
- (permissions & 0o100) == 0 else {
- return
- }
-
- throw OpenEditorError.missingExecutePermission(scriptURL)
- }
-
- private func arguments() -> [String] {
- attributes.flatMap { $0.arguments() }
- }
-}
diff --git a/Sources/SharedKit/Utilities/OpenEditor/OpenEditorAttribute.swift b/Sources/SharedKit/Utilities/OpenEditor/OpenEditorAttribute.swift
deleted file mode 100644
index b1aef9c..0000000
--- a/Sources/SharedKit/Utilities/OpenEditor/OpenEditorAttribute.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// OpenEditorAttribute.swift
-// VisualDiffer
-//
-// Created by davide ficano on 23/07/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-struct OpenEditorAttribute {
- var path: URL
- var lineNumber: Int
- var columnNumber: Int
-
- init(path: String, lineNumber: Int = 1, columnNumber: Int = 1) {
- self.init(url: URL(filePath: path), lineNumber: lineNumber, columnNumber: columnNumber)
- }
-
- init(url: URL, lineNumber: Int = 1, columnNumber: Int = 1) {
- path = url
- self.lineNumber = lineNumber
- self.columnNumber = columnNumber
- }
-}
-
-extension OpenEditorAttribute {
- func arguments() -> [String] {
- [
- path.osPath,
- "\(lineNumber)",
- "\(columnNumber)",
- ]
- }
-}
diff --git a/Sources/SharedKit/Utilities/OpenEditor/OpenEditorError.swift b/Sources/SharedKit/Utilities/OpenEditor/OpenEditorError.swift
deleted file mode 100644
index ce688e7..0000000
--- a/Sources/SharedKit/Utilities/OpenEditor/OpenEditorError.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// OpenEditorError.swift
-// VisualDiffer
-//
-// Created by davide ficano on 08/09/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-enum OpenEditorError: Error {
- case applicationNotFound(URL)
- case missingExecutePermission(URL)
-}
-
-extension OpenEditorError: LocalizedError {
- var errorDescription: String? {
- switch self {
- case let .applicationNotFound(url):
- let message = NSLocalizedString("Application '%@' not found", comment: "")
- return String.localizedStringWithFormat(message, url.osPath)
- case let .missingExecutePermission(url):
- let message = NSLocalizedString("The Unix task '%@' must have the executable flag set (e.g., chmod +x)", comment: "")
- return String.localizedStringWithFormat(message, url.osPath)
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/PopupButton/PreferredEditorPopupCell.swift b/Sources/SharedKit/Utilities/PopupButton/PreferredEditorPopupCell.swift
deleted file mode 100644
index 8255e23..0000000
--- a/Sources/SharedKit/Utilities/PopupButton/PreferredEditorPopupCell.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// PreferredEditorPopupCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 20/12/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-@objc class PreferredEditorPopupCell: NSPopUpButtonCell {
- override init(textCell stringValue: String, pullsDown pullDown: Bool) {
- super.init(textCell: stringValue, pullsDown: pullDown)
- setupPopUpCell()
- }
-
- required init(coder: NSCoder) {
- super.init(coder: coder)
- setupPopUpCell()
- }
-
- /**
- * Do not allow selecting the "Choose" item and the separator before it.
- * (Note that the Choose item can be chosen and an action will be sent, but the selection doesn't change to it.)
- */
- override func selectItem(at index: Int) {
- if (index + 2) <= numberOfItems {
- super.selectItem(at: index)
- }
- }
-
- private func setupPopUpCell() {
- removeAllItems()
-
- if let editorPath = UserDefaults.standard.string(forKey: NSMenu.preferredEditorPrefName) {
- addItem(withTitle: "")
- if let lastItem {
- fillPath(menuItem: lastItem, path: URL(filePath: editorPath))
- }
- } else {
- addItem(withTitle: NSLocalizedString("", comment: ""))
- }
- menu?.addItem(NSMenuItem.separator())
-
- addItem(withTitle: NSLocalizedString("Choose...", comment: ""))
- if let lastItem {
- lastItem.action = #selector(choosePreferredEditor)
- lastItem.target = self
- }
-
- selectItem(at: 0)
- }
-
- func fillPath(menuItem item: NSMenuItem, path: URL) {
- guard let defaultAppPath = NSWorkspace.shared.urlForApplication(toOpen: path) else {
- return
- }
- // get the localized display name for the app
- if let values = try? defaultAppPath.resourceValues(forKeys: [URLResourceKey.localizedNameKey]),
- let defaultAppName = values.localizedName {
- item.title = defaultAppName
- } else {
- item.title = defaultAppPath.lastPathComponent
- }
- let image = NSWorkspace.shared.icon(forFile: path.osPath)
- image.size = NSSize(width: 16.0, height: 16.0)
- item.image = image
- }
-
- @objc func choosePreferredEditor(_: AnyObject) {
- let openPanel = NSOpenPanel()
- .openApplication(title: NSLocalizedString("Select Preferred Editor", comment: ""))
-
- if openPanel.runModal() == .OK {
- if let applicationPath = openPanel.urls.first?.osPath {
- UserDefaults.standard.setValue(
- applicationPath,
- forKey: NSMenu.preferredEditorPrefName
- )
- setupPopUpCell()
- }
- }
- }
-
- @objc func removePreferredEditor(_: AnyObject) {
- UserDefaults.standard.removeObject(forKey: NSMenu.preferredEditorPrefName)
- setupPopUpCell()
- }
-}
diff --git a/Sources/SharedKit/Utilities/String/VisibleWhitespaces.swift b/Sources/SharedKit/Utilities/String/VisibleWhitespaces.swift
deleted file mode 100644
index 8607090..0000000
--- a/Sources/SharedKit/Utilities/String/VisibleWhitespaces.swift
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// VisibleWhitespaces.swift
-// VisualDiffer
-//
-// Created by davide ficano on 05/01/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-class VisibleWhitespaces: NSObject {
- static let visibleTab = "\u{BB}"
- static let visibleSpace = "\u{B7}"
-
- @objc var tabWidth = 4
-
- func getVisibleCharFor(_ ch: Character) -> String {
- if ch == " " {
- return Self.visibleSpace
- }
- return String(ch)
- }
-
- func getString(_ component: DiffLineComponent, isWhitespacesVisible: Bool) -> String {
- if isWhitespacesVisible {
- return showWhitespaces(component.text + component.eol.visibleSymbol)
- }
- return Self.tabs2space(component.text, tabWidth: tabWidth)
- }
-
- static func tabs2space(_ line: String, tabWidth: Int) -> String {
- var dest = ""
-
- for ch in line {
- if ch == "\t" {
- let spaces = tabWidth - (dest.count % tabWidth)
- dest += String(repeating: " ", count: spaces)
- } else {
- dest.append(ch)
- }
- }
- return dest
- }
-
- func showWhitespaces(_ line: String) -> String {
- let whitespaces = CharacterSet.whitespaces
- var dest = ""
-
- for ch in line {
- guard let scalar = ch.unicodeScalars.first,
- whitespaces.contains(scalar) else {
- dest.append(ch)
- continue
- }
- if ch == "\t" {
- // subtract from spaces the character representing TAB
- let spaces = (tabWidth - (dest.count % tabWidth)) - 1
- if spaces > 0 {
- let leftSpaces = spaces / 2
- let rightSpaces = spaces - leftSpaces
-
- if leftSpaces > 0 {
- dest += String(repeating: " ", count: leftSpaces)
- }
- dest += Self.visibleTab
- if rightSpaces > 0 {
- dest += String(repeating: " ", count: rightSpaces)
- }
- } else {
- dest += Self.visibleTab
- }
- } else {
- dest += getVisibleCharFor(ch)
- }
- }
- return dest
- }
-}
diff --git a/Sources/SharedKit/Utilities/TableView/DescriptionOutlineNode.swift b/Sources/SharedKit/Utilities/TableView/DescriptionOutlineNode.swift
deleted file mode 100644
index cba25ad..0000000
--- a/Sources/SharedKit/Utilities/TableView/DescriptionOutlineNode.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// DescriptionOutlineNode.swift
-// VisualDiffer
-//
-// Created by davide ficano on 02/02/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-class DescriptionOutlineNode: NSObject {
- let text: String
- let isContainer: Bool
- var children: [DescriptionOutlineNode]
- var items: [CompareItem]?
-
- init(text: String, isContainer: Bool = false) {
- self.text = text
- self.isContainer = isContainer
- children = []
- }
-
- convenience init(
- relativePath text: String,
- items: [CompareItem],
- rootPath: String
- ) {
- self.init(text: text, isContainer: true)
-
- self.items = items
- let rootPathLen = rootPath.standardizingPath.count + 1
-
- for item in items {
- guard let path = item.path else {
- continue
- }
- let start = path.index(path.startIndex, offsetBy: rootPathLen)
- let relativePath = String(path[start ..< path.endIndex])
- let node = DescriptionOutlineNode(text: relativePath)
- children.append(node)
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/TableView/TableViewCommon.swift b/Sources/SharedKit/Utilities/TableView/TableViewCommon.swift
deleted file mode 100644
index 578469c..0000000
--- a/Sources/SharedKit/Utilities/TableView/TableViewCommon.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// TableViewCommon.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/04/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-protocol TableViewCommonDelegate: AnyObject {
- @MainActor func tableViewCommonKeyDown(_ tableView: NSTableView, event: NSEvent) -> Bool
-}
-
-class TableViewCommon: NSTableView {
- override func keyDown(with event: NSEvent) {
- if let delegate = delegate as? TableViewCommonDelegate {
- if delegate.tableViewCommonKeyDown(self, event: event) {
- return
- }
- }
- super.keyDown(with: event)
- }
-}
diff --git a/Sources/SharedKit/Utilities/TableView/TableViewContextMenuDelegate.swift b/Sources/SharedKit/Utilities/TableView/TableViewContextMenuDelegate.swift
deleted file mode 100644
index f3ab905..0000000
--- a/Sources/SharedKit/Utilities/TableView/TableViewContextMenuDelegate.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-//
-// TableViewContextMenuDelegate.swift
-// VisualDiffer
-//
-// Created by davide ficano on 03/01/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-protocol TableViewContextMenuDelegate: AnyObject {
- @MainActor func tableView(_ tableView: NSTableView, menuItem: NSMenuItem, hideMenuItem hide: inout Bool) -> Bool
-}
diff --git a/Sources/SharedKit/Utilities/TextField/NSTextFieldCell+Helper.swift b/Sources/SharedKit/Utilities/TextField/NSTextFieldCell+Helper.swift
deleted file mode 100644
index b603edf..0000000
--- a/Sources/SharedKit/Utilities/TextField/NSTextFieldCell+Helper.swift
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// NSTextFieldCell+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/01/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-@objc extension NSTextFieldCell {
- var textAttributes: [NSAttributedString.Key: Any] {
- var attributes = [NSAttributedString.Key: Any]()
-
- var cellTextColor = textColor
- if interiorBackgroundStyle == .emphasized {
- cellTextColor = NSColor.alternateSelectedControlTextColor
- }
- if let cellTextColor {
- attributes[NSAttributedString.Key.foregroundColor] = cellTextColor
- }
-
- if let font {
- attributes[NSAttributedString.Key.font] = font
- }
-
- if let paraStyle = NSParagraphStyle.default.mutableCopy() as? NSMutableParagraphStyle {
- paraStyle.alignment = alignment
- paraStyle.lineBreakMode = lineBreakMode
- paraStyle.baseWritingDirection = baseWritingDirection
-
- attributes[NSAttributedString.Key.paragraphStyle] = paraStyle
- }
-
- return attributes
- }
-
- func widthNumber(_ number: Int = Int.max) -> CGFloat {
- let str = if let formatter {
- formatter.string(for: number) ?? String(format: "%lld", number)
- } else {
- String(format: "%lld", number)
- }
- return (str as NSString).size(withAttributes: textAttributes).width
- }
-
- func widthString(_ str: String) -> CGFloat {
- (str as NSString).size(withAttributes: textAttributes).width
- }
-}
diff --git a/Sources/SharedKit/Utilities/TextField/RSVerticallyCenteredTextFieldCell.swift b/Sources/SharedKit/Utilities/TextField/RSVerticallyCenteredTextFieldCell.swift
deleted file mode 100644
index eec11dc..0000000
--- a/Sources/SharedKit/Utilities/TextField/RSVerticallyCenteredTextFieldCell.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// RSVerticallyCenteredTextFieldCell.swift
-// VisualDiffer
-//
-// Created by Daniel Jalkut on 6/17/06.
-// Copyright 2006 Red Sweater Software. All rights reserved.
-//
-
-class RSVerticallyCenteredTextFieldCell: NSTextFieldCell {
- private var isEditingOrSelecting = false
-
- override func drawingRect(forBounds rect: NSRect) -> NSRect {
- // Get the parent's idea of where we should draw
- var newRect = super.drawingRect(forBounds: rect)
-
- // When the text field is being
- // edited or selected, we have to turn off the magic because it screws up
- // the configuration of the field editor. We sneak around this by
- // intercepting selectWithFrame and editWithFrame and sneaking a
- // reduced, centered rect in at the last minute.
- if !isEditingOrSelecting {
- // Get our ideal size for current text
- let textSize = cellSize(forBounds: rect)
-
- // Center that in the proposed rect
- let heightDelta = newRect.size.height - textSize.height
- if heightDelta > 0 {
- newRect.size.height -= heightDelta
- newRect.origin.y += (heightDelta / 2)
- }
- }
-
- return newRect
- }
-}
diff --git a/Sources/SharedKit/Utilities/Toolbar/CustomValidationToolbarItem.swift b/Sources/SharedKit/Utilities/Toolbar/CustomValidationToolbarItem.swift
deleted file mode 100644
index f46391c..0000000
--- a/Sources/SharedKit/Utilities/Toolbar/CustomValidationToolbarItem.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// CustomValidationToolbarItem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 03/03/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-// The delegate validateToolbarItem is called only for Image View Toolbar items
-// so we need to subclass it and apply the custom validation
-// see "View item validation" at
-// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Toolbars/Tasks/ValidatingTBItems.html#//apple_ref/doc/uid/20000753-BAJGFHDD
-class CustomValidationToolbarItem: NSToolbarItem {
- override func validate() {
- isEnabled = if let target {
- target.validateToolbarItem(self)
- } else {
- false
- }
- }
-
- override var menuFormRepresentation: NSMenuItem? {
- get {
- let menuItem = NSMenuItem(
- title: label,
- action: action,
- keyEquivalent: ""
- )
- let strongTarget = target
- menuItem.target = strongTarget
- menuItem.isEnabled = if let strongTarget {
- strongTarget.validateToolbarItem(self)
- } else {
- false
- }
-
- return menuItem
- }
-
- set {
- super.menuFormRepresentation = newValue
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/ActionBar/ActionBarView.swift b/Sources/SharedKit/Utilities/View/ActionBar/ActionBarView.swift
deleted file mode 100644
index cb9c0d7..0000000
--- a/Sources/SharedKit/Utilities/View/ActionBar/ActionBarView.swift
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// ActionBarView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-class ActionBarView: NSStackView {
- lazy var firstButton: NSButton = createButton(image: NSImage(named: NSImage.addTemplateName))
- lazy var secondButton: NSButton = createButton(image: NSImage(named: NSImage.removeTemplateName))
- lazy var popup: NSPopUpButton = createMenu()
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- translatesAutoresizingMaskIntoConstraints = false
- orientation = .horizontal
- spacing = 1
- alignment = .centerY
-
- // ensure the height is correctly set
- setHuggingPriority(.required, for: .vertical)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init?(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- func setupViews() {
- addArrangedSubview(firstButton)
- addArrangedSubview(secondButton)
- addArrangedSubview(popup)
-
- setupConstraints()
- }
-
- func setupConstraints() {
- NSLayoutConstraint.activate([
- firstButton.widthAnchor.constraint(equalToConstant: 24),
- firstButton.heightAnchor.constraint(equalToConstant: 24),
-
- secondButton.widthAnchor.constraint(equalToConstant: 24),
- secondButton.heightAnchor.constraint(equalToConstant: 24),
-
- popup.widthAnchor.constraint(equalToConstant: 32),
- popup.heightAnchor.constraint(equalToConstant: 24),
- ])
- }
-
- private func createButton(image: NSImage?) -> NSButton {
- let view = NSButton(frame: .zero)
-
- view.bezelStyle = .shadowlessSquare
- view.setButtonType(.momentaryPushIn)
- view.isBordered = true
- view.alignment = .center
-
- view.image = image
- view.imagePosition = .imageOnly
- view.imageScaling = .scaleProportionallyDown
-
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- private func createMenu() -> NSPopUpButton {
- let popupMenu = NSMenu()
-
- // the button title image
- popupMenu
- .addItem(
- withTitle: "",
- action: nil,
- keyEquivalent: ""
- )
- .image = NSImage(named: NSImage.actionTemplateName)
-
- let view = NSPopUpButton(frame: .zero, pullsDown: true)
-
- view.bezelStyle = .shadowlessSquare
- view.setButtonType(.momentaryPushIn)
- view.isBordered = true
- view.alignment = .left
- view.menu = popupMenu
-
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Button/LinkButton.swift b/Sources/SharedKit/Utilities/View/Button/LinkButton.swift
deleted file mode 100644
index e255fb3..0000000
--- a/Sources/SharedKit/Utilities/View/Button/LinkButton.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// LinkButton.swift
-// VisualDiffer
-//
-// Created by davide ficano on 05/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class LinkButton: NSButton {
- init(title: String, target: AnyObject? = nil, action: Selector? = nil) {
- super.init(frame: .zero)
-
- self.title = title
- self.target = target
- self.action = action
-
- styleAsLink()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- override func resetCursorRects() {
- addCursorRect(bounds, cursor: .pointingHand)
- }
-
- func styleAsLink() {
- isBordered = false
- wantsLayer = true
- layer?.backgroundColor = NSColor.clear.cgColor
-
- let attributes: [NSAttributedString.Key: Any] = [
- .foregroundColor: NSColor.linkColor,
- .underlineStyle: NSUnderlineStyle.single.rawValue,
- ]
-
- attributedTitle = NSAttributedString(string: title, attributes: attributes)
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Button/StandardButtons.swift b/Sources/SharedKit/Utilities/View/Button/StandardButtons.swift
deleted file mode 100644
index 41b7b58..0000000
--- a/Sources/SharedKit/Utilities/View/Button/StandardButtons.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// StandardButtons.swift
-// VisualDiffer
-//
-// Created by davide ficano on 13/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Cocoa
-import Foundation
-
-@objc class StandardButtons: NSStackView {
- @objc private(set) var primaryButton: NSButton
- @objc private(set) var secondaryButton: NSButton
-
- @objc init(
- primaryTitle: String,
- secondaryTitle: String,
- target: Any?,
- action: Selector?
- ) {
- secondaryButton = NSButton.cancelButton(
- title: secondaryTitle,
- target: target,
- action: action
- )
-
- primaryButton = NSButton.okButton(
- title: primaryTitle,
- target: target,
- action: action
- )
-
- super.init(frame: .zero)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func setupViews() {
- orientation = .horizontal
- alignment = .centerY
- spacing = 20
- translatesAutoresizingMaskIntoConstraints = false
-
- addArrangedSubview(secondaryButton)
- addArrangedSubview(primaryButton)
-
- primaryButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
- secondaryButton.widthAnchor.constraint(equalToConstant: 100).isActive = true
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Console/ConsoleToolbarView.swift b/Sources/SharedKit/Utilities/View/Console/ConsoleToolbarView.swift
deleted file mode 100644
index f29cf97..0000000
--- a/Sources/SharedKit/Utilities/View/Console/ConsoleToolbarView.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// ConsoleToolbarView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 29/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class ConsoleToolbarView: NSView {
- @objc let clearButton: NSButton
- @objc let hideButton: NSButton
-
- override init(frame frameRect: NSRect) {
- clearButton = NSButton(frame: .zero)
- hideButton = NSButton(frame: .zero)
-
- super.init(frame: frameRect)
- setupViews()
- }
-
- @available(*, unavailable)
- required init?(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func setupViews() {
- setup(button: clearButton, title: NSLocalizedString("Clear", comment: ""))
- setup(button: hideButton, title: NSLocalizedString("Hide", comment: ""))
-
- addSubview(clearButton)
- addSubview(hideButton)
-
- setupConstraints()
- }
-
- private func setupConstraints() {
- NSLayoutConstraint.activate([
- clearButton.topAnchor.constraint(equalTo: topAnchor, constant: 4),
- clearButton.trailingAnchor.constraint(equalTo: hideButton.leadingAnchor, constant: -6),
-
- hideButton.topAnchor.constraint(equalTo: topAnchor, constant: 4),
- hideButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
- ])
- }
-
- private func setup(button: NSButton, title: String) {
- button.bezelStyle = .roundRect
- button.setButtonType(.momentaryPushIn)
- button.isBordered = true
- button.state = .on
- button.title = title
- button.alignment = .center
- button.controlSize = .small
- button.translatesAutoresizingMaskIntoConstraints = false
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Console/ConsoleView.swift b/Sources/SharedKit/Utilities/View/Console/ConsoleView.swift
deleted file mode 100644
index f0d26ea..0000000
--- a/Sources/SharedKit/Utilities/View/Console/ConsoleView.swift
+++ /dev/null
@@ -1,161 +0,0 @@
-//
-// ConsoleView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 30/04/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-protocol ConsoleViewDelegate: AnyObject {
- func hide(console: ConsoleView)
-}
-
-class ConsoleView: NSView, NSTextViewDelegate {
- var delegate: ConsoleViewDelegate?
-
- private lazy var dateFormatter: DateFormatter = {
- let dateFormatter = DateFormatter()
- dateFormatter.dateFormat = DateFormatter.dateFormat(
- fromTemplate: "ddMMyyHHmmss",
- options: 0,
- locale: Locale.current
- )
-
- return dateFormatter
- }()
-
- private lazy var toolbar: ConsoleToolbarView = {
- let view = ConsoleToolbarView(frame: .zero)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- view.clearButton.target = self
- view.clearButton.action = #selector(clear)
-
- view.hideButton.target = self
- view.hideButton.action = #selector(hide)
-
- return view
- }()
-
- private lazy var consoleText: NSTextView = {
- let view = NSTextView(frame: .zero)
-
- view.isEditable = true
- view.isSelectable = true
- view.isRichText = true
- view.font = CommonPrefs.shared.consoleLogFont
- view.autoresizingMask = [.width, .height]
- view.delegate = self
-
- return view
- }()
-
- private lazy var scrollView: NSScrollView = {
- let view = NSScrollView(frame: .zero)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- view.borderType = .bezelBorder
- view.autohidesScrollers = true
- view.hasHorizontalScroller = true
- view.hasVerticalScroller = true
- view.horizontalLineScroll = 19
- view.horizontalPageScroll = 10
- view.verticalLineScroll = 19
- view.verticalPageScroll = 10
- view.usesPredominantAxisScrolling = false
-
- view.documentView = consoleText
-
- return view
- }()
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- private func setupViews() {
- addSubview(toolbar)
- addSubview(scrollView)
-
- setupConstraints()
- }
-
- private func setupConstraints() {
- NSLayoutConstraint.activate([
- toolbar.topAnchor.constraint(equalTo: topAnchor),
- toolbar.leadingAnchor.constraint(equalTo: leadingAnchor),
- toolbar.trailingAnchor.constraint(equalTo: trailingAnchor),
- toolbar.heightAnchor.constraint(equalToConstant: 25),
-
- scrollView.topAnchor.constraint(equalTo: toolbar.bottomAnchor),
- scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
- scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
- scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
- ])
- }
-
- override func draw(_ dirtyRect: NSRect) {
- super.draw(dirtyRect)
-
- NSColor.textBackgroundColor.setFill()
- bounds.fill()
- }
-
- func log(info message: String) {
- let colors = CommonPrefs.shared.consoleLogColors(.info)
- log(message: message, at: Date(), colors: colors)
- }
-
- func log(warning message: String) {
- let colors = CommonPrefs.shared.consoleLogColors(.warning)
- log(message: message, at: Date(), colors: colors)
- }
-
- func log(error message: String) {
- let colors = CommonPrefs.shared.consoleLogColors(.error)
- log(message: message, at: Date(), colors: colors)
- }
-
- private func log(
- message: String,
- at atTime: Date,
- colors: ColorSet
- ) {
- let dateText = dateFormatter.string(from: atTime)
- let dict: [NSAttributedString.Key: Any] = [
- .font: consoleText.font ?? CommonPrefs.shared.consoleLogFont,
- .foregroundColor: colors.text,
- .backgroundColor: colors.background,
- ]
- consoleText.append(
- text: String(format: "%@ %@\n", dateText, message),
- attributes: dict
- )
- }
-
- @objc func clear(_: AnyObject) {
- consoleText.string = ""
- }
-
- @objc func hide(_: AnyObject) {
- delegate?.hide(console: self)
- }
-
- func focus() {
- window?.makeFirstResponder(consoleText)
- }
-
- func textView(_: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
- if commandSelector == #selector(cancelOperation(_:)) {
- hide(self)
- return true
- }
- return false
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitView.swift b/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitView.swift
deleted file mode 100644
index 77a5584..0000000
--- a/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitView.swift
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// DualPaneSplitView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class DualPaneSplitView: NSSplitView {
- var isSubviewCollapsed = false
-
- @objc var firstViewSize: CGFloat = 0
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(subviewResized),
- name: NSSplitView.didResizeSubviewsNotification,
- object: self
- )
- }
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(subviewResized),
- name: NSSplitView.didResizeSubviewsNotification,
- object: self
- )
- }
-
- deinit {
- NotificationCenter.default.removeObserver(
- self,
- name: NSSplitView.didResizeSubviewsNotification,
- object: self
- )
- }
-
- @objc func subviewResized(_ notification: Notification) {
- if hasSubviewCollapsed {
- return
- }
- guard let num = notification.userInfo?["NSSplitViewUserResizeKey"] as? NSNumber else {
- return
- }
- let isUserResize = num.boolValue
- if isUserResize {
- let view = subviews[0]
- firstViewSize = isVertical ? view.frame.width : view.frame.height
- }
- }
-
- @objc var hasSubviewCollapsed: Bool {
- if subviews.isEmpty {
- return true
- }
- for view in subviews where isSubviewCollapsed(view) {
- return true
- }
- return false
- }
-
- @objc func toggleSubview(at index: Int) {
- if hasSubviewCollapsed {
- expandSubview(at: index)
- } else {
- collapseSubview(at: index)
- }
- }
-
- @objc func collapseSubview(at index: Int) {
- if hasSubviewCollapsed {
- return
- }
- if index == 0 {
- let collapseView = subviews[0]
- collapseView.isHidden = true
- setPosition(0, ofDividerAt: 0)
- } else if index == 1 {
- let expandView = subviews[0]
- let collapseView = subviews[1]
- collapseView.isHidden = true
- let position = isVertical ? expandView.frame.width : expandView.frame.height
- setPosition(position, ofDividerAt: 0)
- } else {
- return
- }
- adjustSubviews()
- }
-
- @objc func expandSubview(at index: Int) {
- if !hasSubviewCollapsed {
- return
- }
- if index == 0 {
- let collapseView = subviews[0]
- collapseView.isHidden = false
- setPosition(firstViewSize, ofDividerAt: 0)
- } else if index == 1 {
- let collapseView = subviews[1]
- collapseView.isHidden = false
- setPosition(firstViewSize, ofDividerAt: 0)
- } else {
- return
- }
- adjustSubviews()
- }
-
- override var dividerThickness: CGFloat {
- hasSubviewCollapsed ? 0.0 : super.dividerThickness
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitViewDelegate.swift b/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitViewDelegate.swift
deleted file mode 100644
index 2e9b0e5..0000000
--- a/Sources/SharedKit/Utilities/View/DualPane/DualPaneSplitViewDelegate.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// DualPaneSplitViewDelegate.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/07/20.
-// Copyright (c) 2020 visualdiffer.com
-//
-
-class DualPaneSplitViewDelegate: NSObject, NSSplitViewDelegate {
- var minSize: CGFloat = 0
- var maxSize: CGFloat = 0
- var collapsableSubviewIndex = 0
-
- @objc init(
- collapsableSubViewIndex index: Int,
- minSize: CGFloat,
- maxSize: CGFloat
- ) {
- super.init()
-
- collapsableSubviewIndex = index
- self.minSize = minSize
- self.maxSize = maxSize
- }
-
- func splitView(_: NSSplitView, shouldHideDividerAt _: Int) -> Bool {
- true
- }
-
- func splitView(_: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt _: Int) -> CGFloat {
- proposedMinimumPosition + minSize
- }
-
- func splitView(_: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt _: Int) -> CGFloat {
- proposedMaximumPosition - maxSize
- }
-
- func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
- subview == splitView.subviews[collapsableSubviewIndex]
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Encoding/EncodingManager.swift b/Sources/SharedKit/Utilities/View/Encoding/EncodingManager.swift
deleted file mode 100644
index e93c2ee..0000000
--- a/Sources/SharedKit/Utilities/View/Encoding/EncodingManager.swift
+++ /dev/null
@@ -1,250 +0,0 @@
-//
-// EncodingManager.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Foundation
-import CoreFoundation
-
-private let encodingsPrefName = "userEncodings"
-private let encodingSeparator = String.Encoding(rawValue: UInt.max)
-
-let defaultStringsEncodings: [String.Encoding] = [
- .utf8,
- .utf16,
- encodingSeparator,
- .utf16BigEndian,
- .utf16LittleEndian,
- encodingSeparator,
- .macOSRoman,
- .windowsCP1252,
- .isoLatin1,
- CFStringEncodings.isoLatin9.stringEncoding,
- CFStringEncodings.dosLatinUS.stringEncoding,
- encodingSeparator,
- CFStringEncodings.macJapanese.stringEncoding,
- CFStringEncodings.shiftJIS.stringEncoding,
- CFStringEncodings.macChineseTrad.stringEncoding,
- CFStringEncodings.macKorean.stringEncoding,
- CFStringEncodings.macChineseSimp.stringEncoding,
-].compactMap(\.self)
-
-@MainActor class EncodingManager: NSObject, @unchecked Sendable {
- static let listNotification = Notification.Name("EncodingsListChanged")
-
- static let shared = EncodingManager()
-
- override private init() {}
-
- private lazy var stickyStringEncodings: [String.Encoding] = createStickyEncodings()
- private lazy var allEncodings: [String.Encoding] = allAvailableStringEncodings()
- private var popupEncodingsList: [String.Encoding]?
-
- private var encodingPanel: SelectEncodingsPanel?
-
- func setupPopUpCell(
- _ popup: EncodingPopUpButtonCell,
- selectedEncoding: String.Encoding,
- withDefaultEntry _: Bool
- ) {
- var itemToSelect = 0
-
- // Put the encodings in the popup
- popup.removeAllItems()
-
- for encoding in enabledEncodingsGroups() {
- if encoding == encodingSeparator {
- popup.menu?.addItem(NSMenuItem.separator())
- } else {
- popup.addItem(withTitle: String.localizedName(of: encoding))
-
- popup.lastItem?.representedObject = NSNumber(value: encoding.rawValue)
- popup.lastItem?.isEnabled = true
- if encoding == selectedEncoding {
- itemToSelect = popup.numberOfItems - 1
- }
- }
- }
-
- // Add an optional separator and "customize" item at end
- if popup.numberOfItems > 0 {
- popup.menu?.addItem(NSMenuItem.separator())
- }
- popup.addItem(withTitle: NSLocalizedString("Other...", comment: ""))
- popup.lastItem?.action = #selector(showPanel)
- popup.lastItem?.target = self
-
- popup.selectItem(at: itemToSelect)
- }
-
- @objc func showPanel(_ sender: AnyObject) {
- if encodingPanel == nil {
- encodingPanel = SelectEncodingsPanel.createSheet()
- encodingPanel?.onClose = onClose
-
- // Initialize the list (only need to do this once)
- setupEncodingsList()
- }
- guard let encodingPanel else {
- return
- }
- if encodingPanel.isVisible {
- encodingPanel.makeKeyAndOrderFront(sender)
- return
- }
- NSApp.keyWindow?.beginSheet(encodingPanel)
- }
-
- func onClose(_ response: NSApplication.ModalResponse, _ selectedEncodings: [String.Encoding]) {
- if response == .OK {
- noteEncodingListChange(selectedEncodings, updateList: false, postNotification: true)
- }
- }
-
- private func enabledEncodingsGroups() -> [String.Encoding] {
- if let popupEncodingsList {
- return popupEncodingsList
- }
- let list = createPopupEncodingList()
- popupEncodingsList = list
-
- return list
- }
-
- /**
- * Return a sorted list of all available string encodings.
- **/
- func allAvailableStringEncodings() -> [String.Encoding] {
- var nameEncodings = [[String.Encoding: String]]()
- guard let cfEncodings = CFStringGetListOfAvailableEncodings() else {
- return []
- }
- var index = 0
-
- while true {
- let enc = cfEncodings[index]
-
- if enc == kCFStringEncodingInvalidId {
- break
- }
- if let nsEncoding = (enc as CFStringEncoding).stringEncoding {
- nameEncodings.append([nsEncoding: String.localizedName(of: nsEncoding)])
- }
-
- index += 1
- }
-
- nameEncodings.sort {
- if let name1 = $0.values.first,
- let name2 = $1.values.first {
- return name1 < name2
- }
- return false
- }
-
- var allEncodings = [String.Encoding]()
- allEncodings.reserveCapacity(nameEncodings.count)
- for dict in nameEncodings {
- if let key = dict.keys.first {
- allEncodings.append(key)
- }
- }
-
- return allEncodings
- }
-
- func setupEncodingsList() {
- var all = allEncodings
-
- // remove encodings present on sticky list
- for encoding in stickyStringEncodings.reversed() {
- if let index = all.firstIndex(of: encoding) {
- all.remove(at: index)
- }
- }
- encodingPanel?.encodingsList = all
-
- noteEncodingListChange(nil, updateList: true, postNotification: false)
- }
-
- func noteEncodingListChange(
- _ listToWrite: [String.Encoding]?,
- updateList: Bool,
- postNotification post: Bool
- ) {
- if let listToWrite {
- saveEncodings(listToWrite)
- popupEncodingsList = nil
- }
-
- if updateList, let encodingPanel {
- if let otherEncs = readEncodings() {
- var selected = IndexSet()
- for encoding in otherEncs {
- if let index = encodingPanel.encodingsList.firstIndex(of: encoding) {
- selected.insert(index)
- }
- }
- encodingPanel.select(encodings: selected)
- }
- }
-
- if post {
- NotificationCenter.default.post(name: Self.listNotification, object: nil)
- }
- }
-
- private func createStickyEncodings() -> [String.Encoding] {
- let defaultEncoding = String.defaultCStringEncoding
- var hasDefault = false
-
- var encs = [String.Encoding]()
-
- for encSupported in defaultStringsEncodings {
- if encSupported == encodingSeparator {
- encs.append(encodingSeparator)
- } else {
- encs.append(encSupported)
- if encSupported == defaultEncoding {
- hasDefault = true
- }
- }
- }
-
- if !hasDefault {
- encs.append(defaultEncoding)
- }
-
- return encs
- }
-
- private func createPopupEncodingList() -> [String.Encoding] {
- var enabledEncs = stickyStringEncodings
-
- if let userList = readEncodings(),
- !userList.isEmpty {
- enabledEncs.append(encodingSeparator)
- enabledEncs.append(contentsOf: userList)
- }
- return enabledEncs
- }
-
- private func saveEncodings(_ list: [String.Encoding]) {
- let nsNumbers = list.map {
- NSNumber(value: $0.rawValue)
- }
- UserDefaults.standard.set(nsNumbers, forKey: encodingsPrefName)
- }
-
- private func readEncodings() -> [String.Encoding]? {
- guard let encs = UserDefaults.standard.array(forKey: encodingsPrefName) as? [NSNumber] else {
- return nil
- }
- return encs.map {
- String.Encoding(rawValue: $0.uintValue)
- }
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Encoding/EncodingPopUpButtonCell.swift b/Sources/SharedKit/Utilities/View/Encoding/EncodingPopUpButtonCell.swift
deleted file mode 100644
index edfbeeb..0000000
--- a/Sources/SharedKit/Utilities/View/Encoding/EncodingPopUpButtonCell.swift
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// EncodingPopUpButtonCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 15/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-private let wantsAutomaticTag = -1
-
-class EncodingPopUpButtonCell: NSPopUpButtonCell {
- override init(textCell stringValue: String, pullsDown pullDown: Bool) {
- super.init(textCell: stringValue, pullsDown: pullDown)
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(encodingsListChanged),
- name: EncodingManager.listNotification,
- object: nil
- )
- EncodingManager.shared.setupPopUpCell(
- self,
- selectedEncoding: noStringEncoding,
- withDefaultEntry: false
- )
- }
-
- required init(coder: NSCoder) {
- super.init(coder: coder)
-
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(encodingsListChanged),
- name: EncodingManager.listNotification,
- object: nil
- )
- EncodingManager.shared.setupPopUpCell(
- self,
- selectedEncoding: noStringEncoding,
- withDefaultEntry: false
- )
- }
-
- deinit {
- NotificationCenter.default.removeObserver(self)
- }
-
- /**
- * Do not allow selecting the "Customize" item and the separator before it.
- * (Note that the customize item can be chosen and an action will be sent, but the selection doesn't change to it.)
- */
- override func selectItem(at index: Int) {
- if index + 2 <= numberOfItems {
- super.selectItem(at: index)
- }
- }
-
- @objc func encodingsListChanged(_: Notification) {
- let encoding = if let value = selectedItem?.representedObject as? NSNumber {
- String.Encoding(rawValue: value.uintValue)
- } else {
- noStringEncoding
- }
- EncodingManager.shared.setupPopUpCell(
- self,
- selectedEncoding: encoding,
- withDefaultEntry: numberOfItems > 0 && item(at: 0)?.tag == wantsAutomaticTag
- )
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/Encoding/SelectEncodingsPanel.swift b/Sources/SharedKit/Utilities/View/Encoding/SelectEncodingsPanel.swift
deleted file mode 100644
index aeb12a4..0000000
--- a/Sources/SharedKit/Utilities/View/Encoding/SelectEncodingsPanel.swift
+++ /dev/null
@@ -1,218 +0,0 @@
-//
-// SelectEncodingsPanel.swift
-// VisualDiffer
-//
-// Created by davide ficano on 15/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class SelectEncodingsPanel: NSWindow, NSTableViewDataSource, NSTableViewDelegate {
- private lazy var titleText: NSTextField = {
- let view = NSTextField(frame: .zero)
-
- view.isEditable = false
- view.isBordered = false
- view.drawsBackground = false
- view.translatesAutoresizingMaskIntoConstraints = false
-
- let cell = TextFieldVerticalCentered()
- cell.lineBreakMode = .byClipping
- cell.title = NSLocalizedString("Select encodings to show on the main list", comment: "")
-
- view.cell = cell
-
- // set the font after the cell otherwise it is lost
- view.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
-
- return view
- }()
-
- private lazy var scrollView: NSScrollView = {
- let view = NSScrollView(frame: .zero)
-
- view.borderType = .bezelBorder
- view.autohidesScrollers = true
- view.hasHorizontalScroller = true
- view.hasVerticalScroller = true
- view.horizontalLineScroll = 19
- view.horizontalPageScroll = 10
- view.verticalLineScroll = 19
- view.verticalPageScroll = 10
- view.usesPredominantAxisScrolling = false
- view.translatesAutoresizingMaskIntoConstraints = false
-
- view.documentView = tableView
-
- return view
- }()
-
- private lazy var tableView: NSTableView = {
- let view = TableViewCommon(frame: .zero)
-
- view.allowsEmptySelection = true
- view.allowsColumnReordering = false
- view.allowsColumnResizing = true
- view.allowsMultipleSelection = true
- view.allowsColumnSelection = true
- view.allowsTypeSelect = true
-
- view.allowsExpansionToolTips = true
- view.columnAutoresizingStyle = .uniformColumnAutoresizingStyle
- view.autosaveTableColumns = false
- view.intercellSpacing = .zero
- view.headerView = nil
-
- // the column is full width and it resizes properly when the table changes dimensions
- // see https://stackoverflow.com/a/15390614/195893
- let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Encodings"))
- column.resizingMask = .autoresizingMask
- view.addTableColumn(column)
- view.sizeLastColumnToFit()
-
- view.delegate = self
- view.dataSource = self
-
- return view
- }()
-
- private lazy var standardButtons: StandardButtons = {
- let view = StandardButtons(
- primaryTitle: NSLocalizedString("OK", comment: ""),
- secondaryTitle: NSLocalizedString("Cancel", comment: ""),
- target: self,
- action: #selector(closeSheet)
- )
-
- view.primaryButton.tag = NSApplication.ModalResponse.OK.rawValue
- view.secondaryButton.tag = NSApplication.ModalResponse.cancel.rawValue
-
- return view
- }()
-
- var encodingsList = [String.Encoding]() {
- didSet {
- tableView.reloadData()
- }
- }
-
- var onClose: (@MainActor (NSApplication.ModalResponse, [String.Encoding]) -> Void)?
-
- override init(
- contentRect: NSRect,
- styleMask style: NSWindow.StyleMask,
- backing backingStoreType: NSWindow.BackingStoreType,
- defer flag: Bool
- ) {
- super.init(
- contentRect: contentRect,
- styleMask: style,
- backing: backingStoreType,
- defer: flag
- )
-
- minSize = NSSize(width: 400, height: 200)
-
- setupViews()
- }
-
- private func setupViews() {
- if let contentView {
- contentView.addSubview(titleText)
- contentView.addSubview(scrollView)
- contentView.addSubview(standardButtons)
- }
-
- setupConstraints()
- }
-
- private func setupConstraints() {
- guard let contentView else {
- return
- }
- let heightConstraint = scrollView.heightAnchor.constraint(greaterThanOrEqualToConstant: 200)
- heightConstraint.priority = .defaultHigh
-
- NSLayoutConstraint.activate([
- titleText.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
- titleText.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
- titleText.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
-
- scrollView.topAnchor.constraint(equalTo: titleText.bottomAnchor, constant: 20),
- scrollView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
- scrollView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
- heightConstraint,
- scrollView.bottomAnchor.constraint(equalTo: standardButtons.topAnchor, constant: -20),
-
- standardButtons.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
- standardButtons.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
- ])
- }
-
- static func createSheet() -> SelectEncodingsPanel {
- let styleMask: NSWindow.StyleMask = [
- .titled,
- .closable,
- .miniaturizable,
- .resizable,
- ]
-
- return SelectEncodingsPanel(
- contentRect: NSRect(x: 0, y: 0, width: 500, height: 300),
- styleMask: styleMask,
- backing: .buffered,
- defer: false
- )
- }
-
- @objc func closeSheet(_ sender: AnyObject) {
- let response = NSApplication.ModalResponse(sender.tag)
- var selectedEncodings = [String.Encoding]()
- if response == .OK {
- selectedEncodings = tableView.selectedRowIndexes.map { encodingsList[$0] }
- }
-
- onClose?(response, selectedEncodings)
- sheetParent?.endSheet(self)
- }
-
- func select(encodings selected: IndexSet) {
- tableView.selectRowIndexes(selected, byExtendingSelection: false)
- }
-
- func numberOfRows(in _: NSTableView) -> Int {
- encodingsList.count
- }
-
- func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
- guard let identifier = tableColumn?.identifier else {
- return nil
- }
- let cell = tableView.makeView(
- withIdentifier: identifier,
- owner: self
- ) as? NSTableCellView ?? createCell(identifier)
-
- cell.textField?.stringValue = String.localizedName(of: encodingsList[row])
-
- return cell
- }
-
- private func createCell(_ identifier: NSUserInterfaceItemIdentifier) -> NSTableCellView {
- let cell = NSTableCellView()
- cell.identifier = identifier
-
- let textField = NSTextField(frame: cell.bounds)
- textField.autoresizingMask = [.width, .height]
-
- textField.isBezeled = false
- textField.drawsBackground = false
- textField.isEditable = false
- textField.isSelectable = false
- textField.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
-
- cell.addSubview(textField)
- cell.textField = textField
-
- return cell
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/FileDrop/FileDropView+Helper.swift b/Sources/SharedKit/Utilities/View/FileDrop/FileDropView+Helper.swift
deleted file mode 100644
index a7c5289..0000000
--- a/Sources/SharedKit/Utilities/View/FileDrop/FileDropView+Helper.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// FileDropView+Helper.swift
-// VisualDiffer
-//
-// Created by davide ficano on 16/05/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-extension FileDropView {
- @MainActor static func create(
- title: String,
- delegate: FileDropImageViewDelegate
- ) -> FileDropView {
- let view = FileDropView(frame: .zero)
-
- view.delegate = delegate
- view.translatesAutoresizingMaskIntoConstraints = false
-
- let label = NSTextField(frame: .zero)
-
- label.stringValue = title
- label.isBordered = false
- label.isBezeled = false
- label.drawsBackground = false
- label.isEditable = false
- label.isSelectable = false
- label.alignment = .center
- label.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
- label.translatesAutoresizingMaskIntoConstraints = false
-
- view.addSubview(label)
-
- NSLayoutConstraint.activate([
- label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
- label.bottomAnchor.constraint(equalTo: view.topAnchor, constant: -10),
- ])
-
- return view
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/FileDrop/FileDropView.swift b/Sources/SharedKit/Utilities/View/FileDrop/FileDropView.swift
deleted file mode 100644
index c68012b..0000000
--- a/Sources/SharedKit/Utilities/View/FileDrop/FileDropView.swift
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// FileDropView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/03/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Foundation
-import Cocoa
-
-@MainActor protocol FileDropImageViewDelegate: AnyObject {
- // Return true if delegate update path
- func fileDropImageViewUpdatePath(_ view: FileDropView, paths: [URL]) -> Bool
-}
-
-class FileDropView: NSImageView {
- var filePath = "" {
- willSet {
- if filePath != newValue {
- updateDropImage(newValue)
- }
- }
- }
-
- var delegate: FileDropImageViewDelegate?
-
- var dragEntered = false
- var currentIcon: NSImage?
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- registerForDraggedTypes([NSPasteboard.PasteboardType.fileURL])
- imageScaling = .scaleProportionallyUpOrDown
- imageFrameStyle = .grayBezel
- }
-
- @available(*, unavailable)
- required init?(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- override func draw(_ dirtyRect: NSRect) {
- if dragEntered {
- NSColor.keyboardFocusIndicatorColor.set()
- let path = NSBezierPath()
- path.appendRoundedRect(bounds, xRadius: 5, yRadius: 5)
- path.fill()
- }
-
- super.draw(dirtyRect)
- }
-
- // MARK: Drag & Drop
-
- override func draggingEntered(_ sender: any NSDraggingInfo) -> NSDragOperation {
- let pasteboard = sender.draggingPasteboard
-
- guard pasteboard.availableType(from: [NSPasteboard.PasteboardType.fileURL]) != nil,
- let arr = pasteboard.readObjects(forClasses: [NSURL.self], options: nil) as? [URL] else {
- return []
- }
-
- highlightDropArea()
- updateDropImage(arr[0].path)
-
- return .copy
- }
-
- override func draggingExited(_: (any NSDraggingInfo)?) {
- if let currentIcon {
- image = currentIcon
- }
- removeDropAreaHighlight()
- }
-
- override func draggingEnded(_: any NSDraggingInfo) {
- removeDropAreaHighlight()
- }
-
- override func prepareForDragOperation(_: any NSDraggingInfo) -> Bool {
- true
- }
-
- override func performDragOperation(_ sender: any NSDraggingInfo) -> Bool {
- let pasteboard = sender.draggingPasteboard
-
- guard pasteboard.availableType(from: [NSPasteboard.PasteboardType.fileURL]) != nil,
- let arr = pasteboard.readObjects(forClasses: [NSURL.self], options: nil) as? [URL] else {
- return false
- }
-
- if let delegate,
- !delegate.fileDropImageViewUpdatePath(self, paths: arr) {
- filePath = arr[0].path
- }
- return true
- }
-
- // MARK: Private Methods
-
- private func updateDropImage(_ path: String) {
- if FileManager.default.fileExists(atPath: path) {
- image = NSWorkspace.shared.icon(forFile: path)
- } else {
- image = NSImage(named: NSImage.cautionName)
- }
- if let image {
- image.size = NSSize(width: 100.0, height: 100.0)
- }
- }
-
- private func highlightDropArea() {
- if currentIcon == nil {
- currentIcon = image
- }
- dragEntered = true
- needsDisplay = true
- }
-
- private func removeDropAreaHighlight() {
- currentIcon = nil
- dragEntered = false
- needsDisplay = true
- }
-
- override func mouseDown(with event: NSEvent) {
- if event.clickCount == 2 {
- if FileManager.default.fileExists(atPath: filePath) {
- // for some unknown (to me!!) reason mouseDown is called inside a different runloop context
- // preventing the sandbox to correctly "talk" with Finder so we must explicitly call `show` inside the main thread
- DispatchQueue.main.async {
- NSWorkspace.shared.show(inFinder: [self.filePath])
- }
- }
- }
- super.mouseDown(with: event)
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/ProgressBar/ProgressBarView.swift b/Sources/SharedKit/Utilities/View/ProgressBar/ProgressBarView.swift
deleted file mode 100644
index 3070c40..0000000
--- a/Sources/SharedKit/Utilities/View/ProgressBar/ProgressBarView.swift
+++ /dev/null
@@ -1,131 +0,0 @@
-//
-// ProgressBarView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/04/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-class ProgressBarView: NSView {
- private lazy var progressIndicator: NSProgressIndicator = {
- let view = NSProgressIndicator(frame: .zero)
-
- view.translatesAutoresizingMaskIntoConstraints = false
- view.style = .bar
- view.isDisplayedWhenStopped = true
- view.minValue = 0
- view.maxValue = 100
- view.controlSize = .small
- view.isIndeterminate = false
-
- return view
- }()
-
- private lazy var messageText: NSTextField = {
- let view = NSTextField(frame: .zero)
-
- view.translatesAutoresizingMaskIntoConstraints = false
- view.stringValue = NSLocalizedString("Waiting...", comment: "")
- view.isBordered = false
- view.isEditable = false
- view.isBezeled = false
- view.drawsBackground = false
- view.textColor = NSColor.controlTextColor
- view.backgroundColor = NSColor.controlColor
- view.lineBreakMode = .byTruncatingMiddle
- view.controlSize = .small
- view.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
-
- return view
- }()
-
- private lazy var stopButton: NSButton = {
- let view = NSButton(frame: .zero)
-
- view.translatesAutoresizingMaskIntoConstraints = false
- view.setButtonType(.momentaryPushIn)
- view.isBordered = false
- view.state = .off
- view.alignment = .center
- view.image = NSImage(named: VDImageNameStop)
- view.imagePosition = .imageOnly
- view.imageScaling = .scaleProportionallyDown
- view.keyEquivalent = KeyEquivalent.escape
-
- return view
- }()
-
- var waitStopMessage = ""
-
- override var isHidden: Bool {
- didSet {
- if !isHidden {
- stopButton.isEnabled = true
- messageText.stringValue = ""
- setProgress(position: 0, maxValue: 1)
- }
- }
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func setupViews() {
- addSubview(stopButton)
- addSubview(progressIndicator)
- addSubview(messageText)
-
- setupConstraints()
- }
-
- func setupConstraints() {
- NSLayoutConstraint.activate([
- stopButton.leadingAnchor.constraint(equalTo: leadingAnchor),
- stopButton.topAnchor.constraint(equalTo: topAnchor),
- stopButton.bottomAnchor.constraint(equalTo: bottomAnchor),
- stopButton.widthAnchor.constraint(equalToConstant: 16),
-
- progressIndicator.leadingAnchor.constraint(equalTo: stopButton.trailingAnchor, constant: 4),
- progressIndicator.topAnchor.constraint(equalTo: topAnchor),
- progressIndicator.bottomAnchor.constraint(equalTo: bottomAnchor),
- progressIndicator.widthAnchor.constraint(equalToConstant: 250),
-
- messageText.leadingAnchor.constraint(equalTo: progressIndicator.trailingAnchor, constant: 4),
- messageText.topAnchor.constraint(equalTo: topAnchor),
- messageText.bottomAnchor.constraint(equalTo: bottomAnchor),
- messageText.trailingAnchor.constraint(equalTo: trailingAnchor),
- ])
- }
-
- func updateMessage(_ text: String) {
- messageText.stringValue = text
- messageText.needsDisplay = true
- }
-
- func setProgress(position: Double, maxValue: Double) {
- progressIndicator.doubleValue = position
- progressIndicator.maxValue = maxValue
- }
-
- func advanceProgress() {
- progressIndicator.increment(by: 1)
- }
-
- func stop() {
- stopButton.isEnabled = false
- updateMessage(waitStopMessage)
- }
-
- func setStop(action: Selector, target: AnyObject) {
- stopButton.target = target
- stopButton.action = action
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/SynchroScroll/SynchroScrollView.swift b/Sources/SharedKit/Utilities/View/SynchroScroll/SynchroScrollView.swift
deleted file mode 100644
index 7b66f0d..0000000
--- a/Sources/SharedKit/Utilities/View/SynchroScroll/SynchroScrollView.swift
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// SynchroScrollView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 05/11/10.
-// Copyright (c) 2010 visualdiffer.com
-//
-
-@MainActor class SynchroScrollView: NSScrollView {
- private var synchronizedScrollView: NSScrollView? // not retained
-
- @objc func setSynchronized(scrollview: NSScrollView) {
- // stop an existing scroll view synchronizing
- stopSynchronizing()
-
- // don't retain the watched view, because we assume that it will
- // be retained by the view hierarchy for as long as we're around.
- synchronizedScrollView = scrollview
-
- // get the content view of the
- let synchronizedContentView = scrollview.contentView
-
- // Make sure the watched view is sending bounds changed
- // notifications (which is probably does anyway, but calling
- // this again won't hurt).
- scrollview.postsBoundsChangedNotifications = true
-
- // a register for those notifications on the synchronized content view.
- NotificationCenter.default.addObserver(
- self,
- selector: #selector(synchronizedViewContentBoundsDidChange),
- name: NSView.boundsDidChangeNotification,
- object: synchronizedContentView
- )
- }
-
- @objc func synchronizedViewContentBoundsDidChange(_ notification: Notification) {
- // get the changed content view from the notification
- guard let changedContentView = notification.object as? NSClipView else {
- return
- }
-
- // get the origin of the NSClipView of the scroll view that
- // we're watching
- let changedBoundsOrigin = changedContentView.documentVisibleRect.origin
-
- // get our current origin
- let curOffset = contentView.bounds.origin
- var newOffset = curOffset
-
- // scrolling is synchronized in the vertical plane
- // so only modify the y component of the offset
- newOffset.y = changedBoundsOrigin.y
-
- // if our synced position is different from our current
- // position, reposition our content view
-
- if curOffset != changedBoundsOrigin {
- // note that a scroll view watching this one will
- // get notified here
- contentView.scroll(to: newOffset)
-
- // we have to tell the NSScrollView to update its
- // scrollers
- reflectScrolledClipView(contentView)
- }
- }
-
- func stopSynchronizing() {
- guard let synchronizedScrollView else {
- return
- }
- let synchronizedContentView = synchronizedScrollView.contentView
-
- // remove any existing notification registration
- NotificationCenter.default.removeObserver(
- self,
- name: NSView.boundsDidChangeNotification,
- object: synchronizedContentView
- )
-
- self.synchronizedScrollView = nil
- }
-}
diff --git a/Sources/SharedKit/Utilities/View/TextField/TextFieldSelectionHolder.swift b/Sources/SharedKit/Utilities/View/TextField/TextFieldSelectionHolder.swift
deleted file mode 100644
index 079f9c9..0000000
--- a/Sources/SharedKit/Utilities/View/TextField/TextFieldSelectionHolder.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// TextFieldSelectionHolder.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/08/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-/*
- * Hold the selected text range set when the field loses focus.
- * If user clicks on attached popup menu while this field hasn't the focus
- * the field become first responder and selection is restored.
- */
-class TextFieldSelectionHolder: NSTextField, NSMenuDelegate {
- private var selectionRange = NSRange(location: NSNotFound, length: 0)
-
- @objc func attachTo(popUpButton popup: NSPopUpButton) {
- popup.menu?.delegate = self
- }
-
- override func textShouldEndEditing(_ textObject: NSText) -> Bool {
- if let currentEditor = currentEditor() {
- selectionRange = currentEditor.selectedRange
- }
- return super.textShouldEndEditing(textObject)
- }
-
- func menuWillOpen(_: NSMenu) {
- // currentEditor is nil until the input box got focus (by clicking, on entering text)
- if currentEditor() == nil {
- window?.makeFirstResponder(self)
- restoreSelectionRange()
- }
- }
-
- private func restoreSelectionRange() {
- if selectionRange.location == NSNotFound {
- selectionRange = NSRange(location: stringValue.count, length: 0)
- }
- currentEditor()?.selectedRange = selectionRange
- }
-}
diff --git a/Sources/SharedKit/Utilities/Window/WindowCancelOperation.swift b/Sources/SharedKit/Utilities/Window/WindowCancelOperation.swift
deleted file mode 100644
index f2ddfea..0000000
--- a/Sources/SharedKit/Utilities/Window/WindowCancelOperation.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// WindowCancelOperation.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/01/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-class WindowCancelOperation: NSWindow {
- override func cancelOperation(_ sender: Any?) {
- // override NSWindow.cancelOperation() instead of NSWindowController.cancelOperation()
- // because on NSWindowController the standard beep is played
- // (unless overriding first responder's cancelOperation like NSTableView)
-
- // if sender is nil (eg when on search fields) doesn't close window/app
- // if window is full screen doesn't close window/app
- if let sender,
- CommonPrefs.shared.bool(forKey: .escCloseWindow),
- !styleMask.contains(.fullScreen) {
- let docs = NSDocumentController.shared.documents
-
- if docs.count == 1 {
- NSApp.terminate(sender)
- } else {
- performClose(sender)
- }
- } else {
- super.cancelOperation(sender)
- }
- }
-
- @objc static func createWindow() -> WindowCancelOperation {
- let styleMask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable]
-
- let window = WindowCancelOperation(
- contentRect: NSRect(x: 500, y: 600, width: 1100, height: 600),
- styleMask: styleMask,
- backing: .buffered,
- defer: false
- )
- window.hasShadow = true
- window.isReleasedWhenClosed = true
- window.allowsToolTipsWhenApplicationIsInactive = true
- window.autorecalculatesKeyViewLoop = false
- window.setIsVisible(false)
- window.minSize = NSSize(width: 480, height: 400)
- window.contentMinSize = NSSize(width: 300, height: 200)
- window.contentView?.autoresizingMask = [.width, .height]
-
- return window
- }
-}
diff --git a/Sources/SharedKit/Utilities/Window/WindowOSD.swift b/Sources/SharedKit/Utilities/Window/WindowOSD.swift
deleted file mode 100644
index 21ec129..0000000
--- a/Sources/SharedKit/Utilities/Window/WindowOSD.swift
+++ /dev/null
@@ -1,191 +0,0 @@
-//
-// WindowOSD.swift
-// VisualDiffer
-//
-// Created by davide ficano on 22/11/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-class WindowOSD: NSWindow, NSAnimationDelegate {
- private static let textColor = NSColor.white
- private static let backgroundColor = NSColor(
- calibratedRed: 83.0 / 255,
- green: 83.0 / 255,
- blue: 83.0 / 255,
- alpha: 1.0
- )
-
- // the image distance from the window top
- private static let imageOffsetY: CGFloat = 10.0
- // the text distance from the window bottom
- private static let textOffsetY: CGFloat = 10.0
-
- private static let textFontFamily = "Lucida Grande"
- private static let textFontSize: CGFloat = 14.0
-
- private static let windowWidth: CGFloat = 160.0
- private static let windowHeight: CGFloat = 150.0
-
- private var viewAnimation: NSViewAnimation?
-
- @objc init(image: NSImage, parent: NSWindow?) {
- let windowFrame = NSRect(x: 0, y: 0, width: Self.windowWidth, height: Self.windowHeight)
-
- super.init(
- contentRect: windowFrame,
- styleMask: .borderless,
- backing: .buffered,
- defer: false
- )
-
- let content = Self.createContent(frame: windowFrame)
- content.addSubview(Self.createImageView(image: image, windowFrame: windowFrame))
- content.addSubview(Self.createTextField())
-
- contentView = content
- isOpaque = false
- backgroundColor = NSColor.clear
- animationBehavior = .none
-
- if let parent {
- parent.addChildWindow(self, ordered: .above)
- }
-
- // the window is not visible at init time
- // this is necessary because the createContent forces thw window to be visible after creation
- orderOut(nil)
- }
-
- private static func createContent(frame: NSRect) -> NSView {
- // The frame uses the entire window size
- let content = NSView(frame: frame)
-
- content.wantsLayer = true
- if let layer = content.layer {
- layer.masksToBounds = true
- layer.cornerRadius = 10.0
- // wantsLayer is enabled so we don't need to subclass NSView and fill with color in drawRect
- // we can use the layer background color directly
- layer.backgroundColor = backgroundColor.cgColor
- }
-
- return content
- }
-
- private static func createImageView(image: NSImage, windowFrame: NSRect) -> NSImageView {
- let imageFrame = NSRect(
- x: 0,
- y: windowFrame.height - image.size.height - Self.imageOffsetY,
- width: windowFrame.width,
- height: image.size.height
- )
- let view = NSImageView(frame: imageFrame)
- view.imageScaling = .scaleNone
- view.image = image
-
- return view
- }
-
- private static func createTextField() -> NSTextField {
- let view = NSTextField(frame: .zero)
-
- view.isSelectable = false
- view.isEditable = false
- view.font = NSFontManager.shared.font(
- withFamily: textFontFamily,
- traits: .boldFontMask,
- weight: 0,
- size: textFontSize
- )
- view.alignment = .center
- view.isBordered = false
- view.textColor = textColor
- view.backgroundColor = .clear
-
- return view
- }
-
- override var acceptsFirstResponder: Bool {
- false
- }
-
- @objc func animateInside(_ areaFrame: NSRect) {
- let frame = frame
- setFrameOrigin(NSPoint(
- x: areaFrame.origin.x + (areaFrame.width - frame.width) / 2,
- y: areaFrame.origin.y + (areaFrame.height - frame.height) / 2
- ))
-
- if let viewAnimation {
- // set progress to 1.0 so that animation will display its last frame (eg. to get correct window height)
- viewAnimation.currentProgress = 1.0
- viewAnimation.stop()
- }
- alphaValue = 1.0
- orderFront(NSApp)
-
- viewAnimation = createViewAnimation()
- }
-
- private func createViewAnimation() -> NSViewAnimation {
- let animateOutDict: [NSViewAnimation.Key: Any] = [
- .target: self,
- .effect: NSViewAnimation.EffectName.fadeOut,
- ]
- let animation = NSViewAnimation(viewAnimations: [animateOutDict])
- animation.delegate = self
- animation.start()
-
- return animation
- }
-
- func animationDidEnd(_: NSAnimation) {
- Task { @MainActor in
- self.viewAnimation = nil
- }
- }
-
- // MARK: - Image
-
- @objc func setImage(_ image: NSImage?) {
- guard let imageView = contentView?.subviews[0] as? NSImageView else {
- return
- }
-
- if imageView.image != image {
- imageView.image = image
- }
- }
-
- func setBackgroundColor(_ backgroundColor: NSColor) {
- contentView?.layer?.backgroundColor = backgroundColor.cgColor
- }
-
- // MARK: - Text
-
- @objc func setText(_ text: String) {
- guard let textField = contentView?.subviews[1] as? NSTextField,
- let font = textField.font else {
- return
- }
- let height = (text as NSString).size(withAttributes: [.font: font]).height
-
- let windowFrame = frame
- textField.frame = NSRect(x: 0, y: Self.textOffsetY, width: windowFrame.size.width, height: height)
- textField.stringValue = text
- }
-
- func setTextColor(_ textColor: NSColor) {
- guard let textField = contentView?.subviews[1] as? NSTextField else {
- return
- }
- textField.textColor = textColor
- }
-
- func setTextFont(_ textFont: NSFont) {
- guard let textField = contentView?.subviews[1] as? NSTextField else {
- return
- }
- textField.font = textFont
- }
-}
diff --git a/Sources/SharedUI/Cells/AlignPopupButtonCell.swift b/Sources/SharedUI/Cells/AlignPopupButtonCell.swift
deleted file mode 100644
index 72e97ee..0000000
--- a/Sources/SharedUI/Cells/AlignPopupButtonCell.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// AlignPopupButtonCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 08/08/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-class AlignPopupButtonCell: NSPopUpButtonCell {
- override init(textCell stringValue: String, pullsDown pullDown: Bool) {
- super.init(textCell: stringValue, pullsDown: pullDown)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func setupViews() {
- removeAllItems()
-
- addItem(withTitle: NSLocalizedString("Match File Name Case", comment: ""))
- lastItem?.tag = ComparatorOptions.alignMatchCase.rawValue
-
- addItem(withTitle: NSLocalizedString("Ignore File Name Case", comment: ""))
- lastItem?.tag = ComparatorOptions.alignIgnoreCase.rawValue
-
- addItem(withTitle: NSLocalizedString("Use Filesystem Case", comment: ""))
- lastItem?.tag = ComparatorOptions.alignFileSystemCase.rawValue
- }
-}
diff --git a/Sources/SharedUI/Cells/ComparatorPopUpButtonCell.swift b/Sources/SharedUI/Cells/ComparatorPopUpButtonCell.swift
deleted file mode 100644
index c11d552..0000000
--- a/Sources/SharedUI/Cells/ComparatorPopUpButtonCell.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// ComparatorPopUpButtonCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 23/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-class ComparatorPopUpButtonCell: NSPopUpButtonCell {
- private var previousSelected: NSMenuItem?
-
- override init(textCell stringValue: String, pullsDown pullDown: Bool) {
- super.init(textCell: stringValue, pullsDown: pullDown)
-
- setupViews()
- }
-
- required init(coder: NSCoder) {
- super.init(coder: coder)
-
- setupViews()
- }
-
- override func selectItem(at index: Int) {
- if pullsDown {
- if let prevItem = previousSelected {
- prevItem.state = .off
- }
-
- if index >= 0, index < itemArray.count {
- itemArray[index].state = .on
- previousSelected = itemArray[index]
- }
- }
- super.selectItem(at: index)
- }
-
- private func setupViews() {
- let root = itemArray.first
- removeAllItems()
-
- if pullsDown {
- if let menu, let root {
- menu.addItem(root)
- }
- }
-
- let flags: [ComparatorOptions] = [
- .filename,
- .asText,
- .content,
- .size,
- .timestamp,
- [.timestamp, .size],
- [.timestamp, .content, .size],
- ]
- for flag in flags {
- addItem(withTitle: flag.description)
- lastItem?.tag = flag.rawValue
- }
- }
-}
diff --git a/Sources/SharedUI/Cells/DisplayFiltersPopUpButtonCell.swift b/Sources/SharedUI/Cells/DisplayFiltersPopUpButtonCell.swift
deleted file mode 100644
index 17024ae..0000000
--- a/Sources/SharedUI/Cells/DisplayFiltersPopUpButtonCell.swift
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// DisplayFiltersPopUpButtonCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 23/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-class DisplayFiltersPopUpButtonCell: NSPopUpButtonCell {
- override init(textCell stringValue: String, pullsDown pullDown: Bool) {
- super.init(textCell: stringValue, pullsDown: pullDown)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func setupViews() {
- removeAllItems()
-
- addItem(withTitle: NSLocalizedString("Show All", comment: ""))
- lastItem?.tag = DisplayOptions.showAll.rawValue
-
- addItem(withTitle: NSLocalizedString("Only Mismatches", comment: ""))
- lastItem?.tag = DisplayOptions.onlyMismatches.rawValue
-
- addItem(withTitle: NSLocalizedString("Only Matches", comment: ""))
- lastItem?.tag = DisplayOptions.onlyMatches.rawValue
-
- addItem(withTitle: NSLocalizedString("No Orphans", comment: ""))
- lastItem?.tag = DisplayOptions.noOrphan.rawValue
-
- addItem(withTitle: NSLocalizedString("Only Orphans", comment: ""))
- lastItem?.tag = DisplayOptions.onlyOrphans.rawValue
- }
-}
diff --git a/Sources/SharedUI/Cells/FilePathTableCellView.swift b/Sources/SharedUI/Cells/FilePathTableCellView.swift
deleted file mode 100644
index e165582..0000000
--- a/Sources/SharedUI/Cells/FilePathTableCellView.swift
+++ /dev/null
@@ -1,119 +0,0 @@
-//
-// FilePathTableCellView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 16/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class FilePathTableCellView: NSTableCellView {
- @objc convenience init(identifier: NSUserInterfaceItemIdentifier) {
- self.init(frame: .zero)
- self.identifier = identifier
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func setupViews() {
- let image = createImageView()
- addSubview(image)
- imageView = image
-
- let text = createFilePathTextField()
- addSubview(text)
- textField = text
-
- setupConstraints()
- }
-
- private func createImageView() -> NSImageView {
- let view = NSImageView(frame: .zero)
-
- view.imageScaling = .scaleProportionallyUpOrDown
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- private func createFilePathTextField() -> FilePathTextField {
- let view = FilePathTextField(frame: .zero)
-
- view.isBezeled = false
- view.drawsBackground = false
- view.isEditable = false
- view.isSelectable = false
- view.lineBreakMode = .byTruncatingMiddle
- view.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- private func setupConstraints() {
- guard let imageView, let textField else {
- return
- }
- NSLayoutConstraint.activate([
- imageView.leadingAnchor.constraint(equalTo: leadingAnchor),
- imageView.centerYAnchor.constraint(equalTo: centerYAnchor),
- imageView.widthAnchor.constraint(equalToConstant: 17),
- imageView.heightAnchor.constraint(equalToConstant: 17),
-
- textField.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 4),
- textField.centerYAnchor.constraint(equalTo: centerYAnchor),
- textField.trailingAnchor.constraint(equalTo: trailingAnchor),
- ])
- }
-
- func update(path: String) {
- guard let pathTextField = textField as? FilePathTextField else {
- return
- }
- pathTextField.path = path
-
- guard let imageView else {
- return
- }
-
- if pathTextField.fileExists {
- imageView.image = IconUtils.shared.icon(
- forFile: URL(filePath: path, directoryHint: .notDirectory),
- size: 16.0
- )
- } else {
- imageView.image = NSImage(named: NSImage.cautionName)
- imageView.image?.size = NSSize(width: 16.0, height: 16.0)
- }
- }
-
- func update(pattern: String) {
- guard let pathTextField = textField as? FilePathTextField else {
- return
- }
-
- pathTextField.pattern = pattern
- }
-
- /**
- * This is called by the parent as discussed on
- * https://developer.apple.com/documentation/appkit/nstablecellview/1483206-backgroundstyle?language=objc
- * "The default implementation automatically forwards calls to all subviews that implement setBackgroundStyle"
- */
- override var backgroundStyle: NSView.BackgroundStyle {
- didSet {
- guard let pathTextField = textField as? FilePathTextField else {
- return
- }
- pathTextField.highlightsPattern(backgroundStyle)
- }
- }
-}
diff --git a/Sources/SharedUI/Components/DiffCounters/DiffCountersItem.swift b/Sources/SharedUI/Components/DiffCounters/DiffCountersItem.swift
deleted file mode 100644
index 582ee27..0000000
--- a/Sources/SharedUI/Components/DiffCounters/DiffCountersItem.swift
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// DiffCountersItem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/06/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-class DiffCountersItem: NSObject {
- var text: NSString
- var color: NSColor
-
- init(withText text: String, color: NSColor) {
- self.text = text as NSString
- self.color = color
-
- super.init()
- }
-
- static func diffCounterItem(withText text: String, color: NSColor) -> DiffCountersItem {
- DiffCountersItem(withText: text, color: color)
- }
-}
diff --git a/Sources/SharedUI/Components/DiffCounters/DiffCountersTextFieldCell.swift b/Sources/SharedUI/Components/DiffCounters/DiffCountersTextFieldCell.swift
deleted file mode 100644
index ae77698..0000000
--- a/Sources/SharedUI/Components/DiffCounters/DiffCountersTextFieldCell.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// DiffCountersTextFieldCell.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/06/15.
-// Copyright (c) 2015 visualdiffer.com
-//
-
-let kDotWidth: CGFloat = 10.0
-let kDotPaddingEnd: CGFloat = 4.0
-let kTextPaddingEnd: CGFloat = 4.0
-let kStrokelineWidth: CGFloat = 1.0
-let kDotBlendFraction: CGFloat = 0.5
-
-class DiffCountersTextFieldCell: NSTextFieldCell {
- @objc var counterItems = [DiffCountersItem]()
-
- override func draw(withFrame cellFrame: NSRect, in controlView: NSView) {
- if !stringValue.isEmpty {
- super.draw(withFrame: cellFrame, in: controlView)
- return
- }
- var attrs: [NSAttributedString.Key: Any] = [
- NSAttributedString.Key.foregroundColor: NSColor.controlTextColor,
- ]
-
- if let font {
- attrs[NSAttributedString.Key.font] = font
- }
-
- var rect = cellFrame
- rect.origin.x += kStrokelineWidth
- rect.size = NSSize(width: kDotWidth, height: kDotWidth)
-
- for item in counterItems {
- let textSize = item.text.size(withAttributes: attrs)
-
- var dotRect = rect
- var textOrigin = NSPoint(x: rect.origin.x + dotRect.size.width + kDotPaddingEnd, y: rect.origin.y)
- let offset = (textSize.height - dotRect.size.height) / 2
-
- // the dot height is smaller than the text so center it
- if offset > 0 {
- dotRect.origin.y += offset
- } else {
- // the dot height is taller than the text so center the text
- textOrigin.y -= offset
- }
- drawDot(item.color, rect: dotRect, strokeLineWidth: kStrokelineWidth)
-
- item.text.draw(at: textOrigin, withAttributes: attrs)
- // move to next dot position
- rect.origin.x = textOrigin.x + textSize.width + kTextPaddingEnd
- }
- }
-
- func drawDot(
- _ color: NSColor,
- rect: NSRect,
- strokeLineWidth: CGFloat
- ) {
- let strokeColor = NSColor.highlightColor
- let path = NSBezierPath()
- path.appendOval(in: rect)
- path.lineWidth = strokeLineWidth
- color.setFill()
- strokeColor.setStroke()
- path.stroke()
- path.fill()
- }
-}
diff --git a/Sources/SharedUI/Components/DiffCounters/DifferenceCounters.swift b/Sources/SharedUI/Components/DiffCounters/DifferenceCounters.swift
deleted file mode 100644
index c428d12..0000000
--- a/Sources/SharedUI/Components/DiffCounters/DifferenceCounters.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// DifferenceCounters.swift
-// VisualDiffer
-//
-// Created by davide ficano on 02/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class DifferenceCounters: NSTextField {
- private var counter: DiffCountersTextFieldCell
-
- override init(frame frameRect: NSRect) {
- counter = DiffCountersTextFieldCell(textCell: "")
-
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func setupViews() {
- counter.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
-
- isHidden = true
- drawsBackground = false
- isBezeled = false
- isBordered = false
- textColor = NSColor.controlTextColor
- backgroundColor = NSColor.controlColor
- controlSize = .small
- cell = counter
- }
-
- @objc func update(counters: [DiffCountersItem]) {
- stringValue = ""
- counter.counterItems = counters
- counter.controlView?.needsDisplay = true
- }
-}
diff --git a/Sources/SharedUI/Components/FilePathTextField.swift b/Sources/SharedUI/Components/FilePathTextField.swift
deleted file mode 100644
index fdede71..0000000
--- a/Sources/SharedUI/Components/FilePathTextField.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// FilePathTextField.swift
-// VisualDiffer
-//
-// Created by davide ficano on 22/09/20.
-// Copyright (c) 2020 visualdiffer.com
-//
-
-class FilePathTextField: NSTextField {
- var path = "" {
- didSet {
- fileExists = FileManager.default.fileExists(atPath: path)
-
- if fileExists {
- stringValue = path
- toolTip = path
- } else {
- stringValue = path
- toolTip = NSLocalizedString("Path no longer exists", comment: "")
- }
- }
- }
-
- private(set) var fileExists = false
- var pattern: String?
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- func highlightsPattern(_ backgroundStyle: NSView.BackgroundStyle) {
- var normalColor: NSColor
- var highlightColor: NSColor
-
- if backgroundStyle == .emphasized {
- normalColor = .alternateSelectedControlTextColor
- highlightColor = .alternateSelectedControlTextColor
- } else {
- if fileExists {
- normalColor = .controlTextColor
- highlightColor = .controlTextColor
- } else {
- normalColor = .systemRed
- highlightColor = .systemRed
- }
- }
-
- if let pattern,
- let font {
- let ranges = path.rangesOfString(pattern, options: [.literal, .caseInsensitive])
- attributedStringValue = path.highlights(
- ranges,
- normalColor: normalColor,
- highlightColor: highlightColor,
- font: font
- )
- } else {
- stringValue = path
- textColor = normalColor
- }
- }
-}
diff --git a/Sources/SharedUI/Components/FindText.swift b/Sources/SharedUI/Components/FindText.swift
deleted file mode 100644
index 35015f5..0000000
--- a/Sources/SharedUI/Components/FindText.swift
+++ /dev/null
@@ -1,237 +0,0 @@
-//
-// FindText.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/10/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-protocol FindTextDelegate: AnyObject {
- func find(findText: FindText, searchPattern pattern: String) -> Bool
- func find(findText: FindText, moveToMatchIndex index: Int) -> Bool
- func numberOfMatches(in findText: FindText) -> Int
- func clearMatches(in findText: FindText)
-}
-
-class FindText: NSView, NSSearchFieldDelegate {
- private var lastIndexFound = -1
-
- var delegate: FindTextDelegate?
-
- private lazy var rewindView: WindowOSD = .init(
- // swiftlint:disable:next force_unwrapping
- image: NSImage(named: VDImageNameRewind)!,
- parent: window
- )
-
- private lazy var arrows: NSSegmentedControl = {
- let images = [
- // swiftlint:disable:next force_unwrapping
- NSImage(named: NSImage.goLeftTemplateName)!,
- // swiftlint:disable:next force_unwrapping
- NSImage(named: NSImage.goRightTemplateName)!,
- ]
- let view = NSSegmentedControl(
- images: images,
- trackingMode: .momentary,
- target: self,
- action: #selector(moveByArrow)
- )
-
- view.segmentStyle = .roundRect
- view.isEnabled = false
- view.setWidth(16, forSegment: 0)
- view.setWidth(16, forSegment: 1)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }()
-
- private lazy var countLabel: NSTextField = {
- let view = NSTextField(frame: .zero)
-
- view.isBezeled = false
- view.isBordered = false
- view.drawsBackground = false
- view.controlSize = .small
- view.alignment = .right
- view.focusRingType = .none
- view.isEditable = false
- view.isSelectable = false
- view.textColor = NSColor.controlTextColor
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }()
-
- private lazy var searchField: NSSearchField = {
- let view = NSSearchField(frame: .zero)
-
- view.placeholderString = NSLocalizedString("Find File Name <⌘F>", comment: "")
- view.bezelStyle = .roundedBezel
- view.controlSize = .small
- view.translatesAutoresizingMaskIntoConstraints = false
-
- // allow to scroll when the text
- if let cell = view.cell as? NSSearchFieldCell {
- cell.isScrollable = true
- cell.wraps = false
- }
-
- view.target = self
- view.action = #selector(search)
- // used to receive NSControlTextEditingDelegate notifications
- view.delegate = self
-
- return view
- }()
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupView()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- private func setupView() {
- addSubview(searchField)
- addSubview(arrows)
- addSubview(countLabel)
-
- setupConstraints()
- }
-
- private func setupConstraints() {
- NSLayoutConstraint.activate([
- searchField.topAnchor.constraint(equalTo: topAnchor, constant: 2),
- searchField.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2),
- searchField.trailingAnchor.constraint(equalTo: trailingAnchor),
- searchField.widthAnchor.constraint(equalToConstant: 240),
-
- arrows.topAnchor.constraint(equalTo: topAnchor, constant: 2),
- arrows.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2),
- arrows.trailingAnchor.constraint(equalTo: searchField.leadingAnchor, constant: -2),
-
- countLabel.topAnchor.constraint(equalTo: topAnchor, constant: 2),
- countLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -2),
- countLabel.leadingAnchor.constraint(equalTo: leadingAnchor),
- countLabel.trailingAnchor.constraint(equalTo: arrows.leadingAnchor, constant: -4),
- ])
- }
-
- // MARK: - Find methods
-
- var hasMatches: Bool {
- guard let delegate else {
- return false
- }
- return delegate.numberOfMatches(in: self) > 0
- }
-
- func updateCount() {
- guard let delegate else {
- return
- }
- let count = delegate.numberOfMatches(in: self)
- if count > 0 {
- arrows.isEnabled = true
- countLabel.stringValue = String(format: "%ld/%ld", lastIndexFound + 1, count)
- } else {
- arrows.isEnabled = false
- countLabel.stringValue = NSLocalizedString("Not found", comment: "")
- }
- }
-
- @objc func search(_: AnyObject) {
- guard let delegate else {
- return
- }
-
- delegate.clearMatches(in: self)
- lastIndexFound = -1
- let pattern = searchField.stringValue
-
- if pattern.isEmpty {
- countLabel.stringValue = ""
- arrows.isEnabled = false
-
- return
- }
-
- if delegate.find(findText: self, searchPattern: pattern) {
- moveToMatch(true)
- }
- }
-
- // MARK: - Move Methods
-
- func moveToMatch(_ gotoNext: Bool) {
- guard let delegate else {
- return
- }
- let foundCount = delegate.numberOfMatches(in: self)
- if foundCount == 0 {
- updateCount()
- return
- }
-
- var didWrap = false
-
- if gotoNext {
- if lastIndexFound + 1 < foundCount {
- lastIndexFound += 1
- } else {
- lastIndexFound = 0
- didWrap = true
- }
- } else {
- if lastIndexFound - 1 >= 0 {
- lastIndexFound -= 1
- } else {
- lastIndexFound = foundCount - 1
- didWrap = true
- }
- }
- if delegate.find(findText: self, moveToMatchIndex: lastIndexFound) {
- if didWrap {
- showWrapWindow()
- }
- } else {
- moveToMatch(gotoNext)
- }
- updateCount()
- }
-
- @objc func moveByArrow(_: AnyObject) {
- moveToMatch(arrows.selectedSegment == 1)
- }
-
- // MARK: - NSControlTextEditingDelegate and text change methods
-
- func control(_: NSControl, textView _: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
- // Move to next result using return key
- if commandSelector == #selector(insertNewline) {
- let isShiftDown = NSApp.currentEvent?.modifierFlags.contains(.shift) ?? false
- moveToMatch(!isShiftDown)
- return true
- }
- return false
- }
-
- func showWrapWindow() {
- if let window {
- rewindView.animateInside(window.frame)
- }
- }
-
- // MARK: - View methods
-
- override func becomeFirstResponder() -> Bool {
- // doesn't expose searchField field but allow to set first responder
- searchField.becomeFirstResponder()
- }
-}
diff --git a/Sources/SharedUI/Components/NSTextField+CenterVertically.swift b/Sources/SharedUI/Components/NSTextField+CenterVertically.swift
deleted file mode 100644
index d558628..0000000
--- a/Sources/SharedUI/Components/NSTextField+CenterVertically.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// NSTextField+CenterVertically.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@objc extension NSTextField {
- func centerVertically() {
- let centeredCell = RSVerticallyCenteredTextFieldCell(textCell: "")
-
- centeredCell.controlSize = .small
- centeredCell.isScrollable = true
- centeredCell.lineBreakMode = .byClipping
- centeredCell.alignment = .center
-
- cell = centeredCell
- }
-}
diff --git a/Sources/SharedUI/Components/PathControl.swift b/Sources/SharedUI/Components/PathControl.swift
deleted file mode 100644
index 5bdc6ca..0000000
--- a/Sources/SharedUI/Components/PathControl.swift
+++ /dev/null
@@ -1,207 +0,0 @@
-//
-// PathControl.swift
-// VisualDiffer
-//
-// Created by davide ficano on 13/10/11.
-// Copyright (c) 2011 visualdiffer.com
-//
-
-@objc protocol PathControlDelegate: NSPathControlDelegate {
- @MainActor @objc optional func pathControl(_ pathControl: PathControl, willContextMenu menu: NSMenu)
- @MainActor @objc optional func pathControl(_ pathControl: PathControl, chosenUrl url: URL)
- @MainActor @objc optional func pathControl(_ pathControl: PathControl, openWithApp app: URL)
- @MainActor @objc optional func pathControlOpenWithOtherApp(_ pathControl: PathControl)
-
- @MainActor @objc optional func saveFile(_ sender: AnyObject?)
-}
-
-public class PathControl: NSPathControl, NSMenuItemValidation {
- var safePathComponentItem: NSPathControlItem? {
- // click is out any cell so clickedPathItem returned nil
- guard let item = clickedPathItem else {
- return pathItems.last
- }
-
- return item
- }
-
- @objc var clickedPath: URL? {
- clickedPathItem?.url
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func setupViews() {
- menu = Self.defaultMenu
- }
-
- // MARK: -
-
- // MARK: Menu messages
-
- override public class var defaultMenu: NSMenu? {
- let theMenu = NSMenu(title: NSLocalizedString("Contextual Menu", comment: ""))
-
- theMenu.addItem(
- withTitle: NSLocalizedString("Choose...", comment: ""),
- action: #selector(choosePath),
- keyEquivalent: ""
- )
- theMenu.addItem(NSMenuItem.separator())
-
- theMenu.addItem(
- withTitle: NSLocalizedString("Copy Path", comment: ""),
- action: #selector(copyFullPaths),
- keyEquivalent: ""
- )
- let item = theMenu.addItem(
- withTitle: NSLocalizedString("Copy File Name", comment: ""),
- action: #selector(copyFileNames),
- keyEquivalent: ""
- )
- item.keyEquivalentModifierMask = .option
- item.isAlternate = true
-
- // TODO: copy urls no longer work for some sandbox problem so we disable it entirely
-// theMenu.addItem(withTitle: NSLocalizedString("Copy URL", comment: ""), action: #selector(copyUrls), keyEquivalent: "")
- theMenu.addItem(
- withTitle: NSLocalizedString("Show in Finder", comment: ""),
- action: #selector(showInFinder),
- keyEquivalent: ""
- )
-
- return theMenu
- }
-
- override public func menu(for event: NSEvent) -> NSMenu? {
- let menu = super.menu(for: event)?.copy() as? NSMenu
-
- if let menu,
- let delegate = delegate as? PathControlDelegate {
- delegate.pathControl?(self, willContextMenu: menu)
- }
-
- return menu
- }
-
- public func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
- if !isEnabled {
- return false
- }
- let action = menuItem.action
-
- if url == nil {
- if action == #selector(choosePath) {
- return true
- } else if action == #selector(copyFileNames) {
- // otherwise the item "Copy Path" is always visible
- menuItem.isAlternate = false
- }
- menuItem.isHidden = true
- return false
- }
-
- if action == #selector(copyFileNames) {
- menuItem.isAlternate = true
- }
-
- menuItem.isHidden = false
-
- return true
- }
-
- // MARK: - Actions
-
- @objc func showInFinder(_: AnyObject) {
- guard let url = safePathComponentItem?.url else {
- return
- }
-
- // URL returns by pathCell can't be resolved but Finder so with get the file path
- let paths = [url.osPath]
- NSWorkspace.shared.show(inFinder: paths)
- }
-
- @objc func copyFileNames(_: AnyObject) {
- guard let url = safePathComponentItem?.url else {
- return
- }
-
- NSPasteboard.general.copy(lines: [url.lastPathComponent])
- }
-
- @objc func copyFullPaths(_: AnyObject) {
- guard let url = safePathComponentItem?.url else {
- return
- }
-
- NSPasteboard.general.copy(lines: [url.osPath])
- }
-
- @objc func copyUrls(_: AnyObject) {
- guard let url = safePathComponentItem?.url else {
- return
- }
- // convert from NSPathCell protocol to file protocol
- let fileURL = URL(filePath: url.path, directoryHint: .isDirectory)
-
- NSPasteboard.general.copy(urls: [fileURL])
- }
-
- @objc func openWithApp(_ sender: AnyObject) {
- // store the delegate to a strong local variable
- if let delegate = delegate as? PathControlDelegate,
- let applicationPath = sender.representedObject as? String {
- delegate.pathControl?(self, openWithApp: URL(filePath: applicationPath))
- }
- }
-
- @objc func openWithOther(_: AnyObject) {
- if let delegate = delegate as? PathControlDelegate {
- delegate.pathControlOpenWithOtherApp?(self)
- }
- }
-
- @objc func choosePath(_: AnyObject) {
- guard let delegate = delegate as? PathControlDelegate else {
- return
- }
- let openPanel = NSOpenPanel()
-
- openPanel.directoryURL = safePathComponentItem?.url ?? url
-
- delegate.pathControl?(self, willDisplay: openPanel)
-
- if openPanel.runModal() == .OK {
- let URL = openPanel.urls[0]
-
- if let bindingsInfo = infoForBinding(.value) {
- // Note that we set the value with an NSString not an URL
- if let object = bindingsInfo[NSBindingInfoKey.observedObject] as? NSObject,
- let bindingsPath = bindingsInfo[NSBindingInfoKey.observedKeyPath] as? String {
- object.setValue(
- URL.path,
- forKeyPath: bindingsPath
- )
- }
- }
- delegate.pathControl?(self, chosenUrl: URL)
- }
- }
-
- // MARK: - overridden
-
- override public var intrinsicContentSize: NSSize {
- // Let it be flexible when using Auto Layout
- NSSize(width: NSView.noIntrinsicMetric, height: NSView.noIntrinsicMetric)
- }
-}
diff --git a/Sources/SharedUI/Components/PathView.swift b/Sources/SharedUI/Components/PathView.swift
deleted file mode 100644
index c186bfc..0000000
--- a/Sources/SharedUI/Components/PathView.swift
+++ /dev/null
@@ -1,239 +0,0 @@
-//
-// PathView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class PathView: NSView {
- var isEnabled = false {
- didSet {
- for view in stackView.views {
- if let control = view as? NSControl {
- control.isEnabled = isEnabled
- }
- }
- }
- }
-
- var isSaveHidden: Bool {
- get {
- saveButton.isHidden
- }
-
- set {
- saveButton.isHidden = newValue
- }
- }
-
- var delegate: PathControlDelegate? {
- get {
- pathControl.delegate as? PathControlDelegate
- }
-
- set {
- pathControl.delegate = newValue
- if let delegate = newValue {
- let canPerform = delegate.responds(to: #selector(PathControlDelegate.saveFile))
- if canPerform {
- saveButton.target = delegate
- saveButton.action = #selector(PathControlDelegate.saveFile)
- }
- } else {
- saveButton.target = nil
- saveButton.action = nil
- }
- }
- }
-
- lazy var lockButton: NSButton = createLockButton()
- lazy var pathControl: PathControl = createPathControl()
- lazy var browseButton: NSButton = createBrowseButton()
- lazy var saveButton: NSButton = createSaveButton()
-
- private lazy var stackView: NSStackView = createStackView()
- private lazy var separator: NSBox = createSeparator()
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func setupViews() {
- setupStackView()
-
- addSubview(stackView)
- setupConstraints()
-
- // enable iterates the views so we must set it only after all views are added to self
- isEnabled = true
- }
-
- private func setupStackView() {
- stackView.addArrangedSubview(lockButton)
- stackView.addArrangedSubview(pathControl)
- stackView.addArrangedSubview(separator)
- stackView.addArrangedSubview(browseButton)
- stackView.addArrangedSubview(saveButton)
- stackView.setCustomSpacing(6, after: separator)
- stackView.setCustomSpacing(4, after: browseButton)
- }
-
- private func createLockButton() -> NSButton {
- let view = NSButton(frame: .zero)
-
- view.title = ""
- view.toolTip = NSLocalizedString("Make read-only", comment: "")
- view.setButtonType(.switch)
- view.bezelStyle = .flexiblePush
- view.image = NSImage(named: NSImage.lockUnlockedTemplateName)
- view.alternateImage = NSImage(named: NSImage.lockLockedTemplateName)
- view.imagePosition = .imageLeft
- view.alignment = .left
- view.refusesFirstResponder = true
- view.state = .on
-
- return view
- }
-
- private func createPathControl() -> PathControl {
- let view = PathControl(frame: .zero)
-
- view.controlSize = .small
- view.isEditable = false
- view.refusesFirstResponder = true
- view.alignment = .left
- view.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
-
- return view
- }
-
- private func createBrowseButton() -> NSButton {
- guard let image = NSImage(named: VDImageNameBrowse) else {
- fatalError("Unable to create image for \(VDImageNameBrowse)")
- }
- let view = NSButton(
- image: image,
- target: pathControl,
- action: #selector(PathControl.choosePath)
- )
-
- view.toolTip = NSLocalizedString("Choose Path", comment: "")
- view.isBordered = false
- view.refusesFirstResponder = true
-
- return view
- }
-
- private func createSaveButton() -> NSButton {
- guard let image = NSImage(named: VDImageNameSave) else {
- fatalError("Unable to create image for \(VDImageNameSave)")
- }
- let view = NSButton(
- image: image,
- target: nil,
- action: nil
- )
-
- view.toolTip = NSLocalizedString("Save ^S", comment: "")
- view.isBordered = false
- view.refusesFirstResponder = true
-
- return view
- }
-
- private func createSeparator() -> NSBox {
- let view = NSBox(frame: .zero)
-
- view.title = ""
- view.boxType = .separator
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- private func createStackView() -> NSStackView {
- let stack = NSStackView()
-
- stack.orientation = .horizontal
- stack.alignment = .centerY
- stack.spacing = 2.0
- stack.translatesAutoresizingMaskIntoConstraints = false
-
- return stack
- }
-
- func setupConstraints() {
- NSLayoutConstraint.activate([
- stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5),
- stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5),
- stackView.topAnchor.constraint(equalTo: topAnchor, constant: 2),
- stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
-
- separator.topAnchor.constraint(equalTo: stackView.topAnchor),
- separator.bottomAnchor.constraint(equalTo: stackView.bottomAnchor),
- ])
- }
-
- func bindControls(side: DisplaySide) {
- guard let delegate = pathControl.delegate else {
- return
- }
- // We enable the views ourselves but when NSConditionallySetsEnabledBindingOption is true (the default)
- // they are automagically enabled by the binding system so we turn off the NSConditionallySetsEnabledBindingOption flag
- let pathControlBindOptions = [
- NSBindingOption.conditionallySetsEnabled: false,
- ]
-
- if side == .left {
- lockButton.bind(
- .value,
- to: delegate,
- withKeyPath: "sessionDiff.leftReadOnly",
- options: nil
- )
- pathControl.bind(
- .value,
- to: delegate,
- withKeyPath: "sessionDiff.leftPath",
- options: pathControlBindOptions
- )
- if !saveButton.isHidden {
- saveButton.bind(
- .enabled,
- to: delegate,
- withKeyPath: "leftView.isDirty",
- options: nil
- )
- }
- } else {
- lockButton.bind(
- .value,
- to: delegate,
- withKeyPath: "sessionDiff.rightReadOnly",
- options: nil
- )
- pathControl.bind(
- .value,
- to: delegate,
- withKeyPath: "sessionDiff.rightPath",
- options: pathControlBindOptions
- )
- if !saveButton.isHidden {
- saveButton.bind(
- .enabled,
- to: delegate,
- withKeyPath: "rightView.isDirty",
- options: nil
- )
- }
- }
- }
-}
diff --git a/Sources/SharedUI/Components/PopUpButtonUrl.swift b/Sources/SharedUI/Components/PopUpButtonUrl.swift
deleted file mode 100644
index df20892..0000000
--- a/Sources/SharedUI/Components/PopUpButtonUrl.swift
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// PopUpButtonUrl.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/03/17.
-// Copyright (c) 2017 visualdiffer.com
-//
-
-class PopUpButtonUrl: NSPopUpButton {
- init(
- title: String,
- target: AnyObject?,
- action: Selector?,
- delegate: NSMenuDelegate?
- ) {
- super.init(frame: .zero, pullsDown: true)
-
- let menu = NSMenu(title: title)
- menu.delegate = delegate
- menu.addItem(
- withTitle: title,
- action: nil,
- keyEquivalent: ""
- )
-
- bezelStyle = .texturedRounded
- setButtonType(.momentaryPushIn)
- alignment = .center
- self.target = target
- self.action = action
- self.menu = menu
- translatesAutoresizingMaskIntoConstraints = false
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- @objc func fill(_ documentUrls: [URL]) {
- let dict = uniq(documentUrls: documentUrls)
-
- // iterate documentURLs instead of dictionary because order is not preserved in dictionary
- for url in documentUrls {
- let key = url.lastPathComponent
- guard let arr = dict[key] else {
- continue
- }
-
- if arr.count == 1 {
- addItem(withTitle: key)
- lastItem?.representedObject = url
- } else {
- for dup in arr {
- let components = dup.pathComponents
- if components.count >= 2 {
- addItem(withTitle: String(format: "% - %", key, components[components.count - 2]))
- } else {
- addItem(withTitle: key)
- }
- lastItem?.representedObject = url
- }
- }
- }
- }
-
- @objc func clear() {
- // leave the button title and remove all other menu items
- for i in stride(from: numberOfItems - 1, through: 1, by: -1) {
- removeItem(at: i)
- }
- }
-
- // menu label contains the last URL path component
- // It would be present more times (same filename in different disk folders)
- // so we group by last path component
- private func uniq(documentUrls: [URL]) -> [String: [URL]] {
- var dict = [String: [URL]]()
-
- for url in documentUrls {
- let key = url.lastPathComponent
- var arr = dict[key] ?? []
- arr.append(url)
- dict[key] = arr
- }
- return dict
- }
-}
diff --git a/Sources/SharedUI/Components/TablePanelView.swift b/Sources/SharedUI/Components/TablePanelView.swift
deleted file mode 100644
index 6201f45..0000000
--- a/Sources/SharedUI/Components/TablePanelView.swift
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// TablePanelView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 12/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class TablePanelView, BottomBarView: NSView>: NSView {
- var side: DisplaySide = .left {
- didSet {
- treeView.side = side
- }
- }
-
- var treeView: T
- var scrollView: SynchroScrollView
- var bottomBar: BottomBarView
- var pathView: PathView
-
- init(
- treeView: T,
- bottomBar: BottomBarView
- ) {
- self.treeView = treeView
- self.bottomBar = bottomBar
- scrollView = Self.createScrollView()
- pathView = Self.createPathView()
-
- super.init(frame: NSRect(x: 0, y: 0, width: 1, height: 0))
-
- setupViews()
- }
-
- @available(*, unavailable)
- required init(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-
- func setupViews() {
- setupScrollView()
- setupBottomBar()
-
- addSubviews()
-
- setupConstraints()
- }
-
- func addSubviews() {
- addSubview(pathView)
- addSubview(scrollView)
- addSubview(bottomBar)
- }
-
- func setupConstraints() {
- NSLayoutConstraint.activate([
- pathView.topAnchor.constraint(equalTo: topAnchor),
- pathView.heightAnchor.constraint(equalToConstant: 18),
- pathView.trailingAnchor.constraint(equalTo: trailingAnchor),
- pathView.leadingAnchor.constraint(equalTo: leadingAnchor),
-
- scrollView.topAnchor.constraint(equalTo: pathView.bottomAnchor),
- scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
- scrollView.leadingAnchor.constraint(equalTo: leadingAnchor),
- ])
-
- setupBottomBarConstraints()
- }
-
- func setupBottomBarConstraints() {
- scrollView.bottomAnchor.constraint(equalTo: bottomBar.topAnchor).isActive = true
- }
-
- static func createPathView() -> PathView {
- let view = PathView(frame: .zero)
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- static func createScrollView() -> SynchroScrollView {
- let view = SynchroScrollView(frame: .zero)
-
- view.borderType = .noBorder
- view.autohidesScrollers = true
- view.hasHorizontalScroller = true
- view.hasVerticalScroller = true
- view.horizontalLineScroll = 19
- view.horizontalPageScroll = 10
- view.verticalLineScroll = 19
- view.verticalPageScroll = 10
- view.usesPredominantAxisScrolling = false
- view.translatesAutoresizingMaskIntoConstraints = false
-
- return view
- }
-
- func setupScrollView() {
- scrollView.documentView = treeView
- }
-
- func setupTreeView() {}
-
- func setupBottomBar() {}
-
- var pathViewDelegate: PathControlDelegate? {
- get { pathView.delegate }
- set { pathView.delegate = newValue }
- }
-
- func synchronizeWith(_ other: SynchroScrollView) {
- scrollView.setSynchronized(scrollview: other)
- }
-
- /**
- Link treeView with other.treeView and sync scrollViews
- self is linked to other and other is linked to self, too
- */
- func setLinkPanels(_ other: TablePanelView) {
- treeView.linkedView = other.treeView
- other.treeView.linkedView = treeView
-
- synchronizeWith(other.scrollView)
- other.synchronizeWith(scrollView)
- }
-
- func bindControls() {
- pathView.bindControls(side: side)
- }
-
- func updateBottomBar() {}
-}
diff --git a/Sources/SharedUI/Components/TimeToleranceView.swift b/Sources/SharedUI/Components/TimeToleranceView.swift
deleted file mode 100644
index 9040a38..0000000
--- a/Sources/SharedUI/Components/TimeToleranceView.swift
+++ /dev/null
@@ -1,121 +0,0 @@
-//
-// TimeToleranceView.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/04/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-class TimeToleranceView: NSView, NSTextFieldDelegate {
- private lazy var inputText: NSTextField = createInputText()
- private lazy var stepper: NSStepper = createStepper()
-
- var onTextChanged: ((TimeToleranceView) -> Void)?
-
- var tolerance = 0 {
- didSet {
- if let onTextChanged {
- onTextChanged(self)
- }
- inputText.integerValue = tolerance
- stepper.integerValue = tolerance
- }
- }
-
- override init(frame frameRect: NSRect) {
- super.init(frame: frameRect)
-
- setupViews()
- }
-
- private func setupViews() {
- addSubview(createStackView())
- }
-
- @available(*, unavailable)
- required init?(coder _: NSCoder) {
- fatalError("Method not implemented")
- }
-
- private func createStackView() -> NSStackView {
- let view = NSStackView(views: [
- createTextWithTitle(NSLocalizedString("Ignore differences of", comment: "")),
- inputText,
- stepper,
- createTextWithTitle(NSLocalizedString("seconds or less", comment: "")),
- ])
- view.orientation = .horizontal
- view.alignment = .centerY
- view.spacing = 4
-
- return view
- }
-
- private func createTextWithTitle(_ title: String) -> NSTextField {
- let view = NSTextField(frame: .zero)
-
- view.stringValue = title
- view.isEditable = false
- view.isSelectable = false
- view.drawsBackground = false
- view.isBordered = false
-
- return view
- }
-
- private func createInputText() -> NSTextField {
- let view = NSTextField(frame: .zero)
-
- view.alignment = .right
- view.cell?.sendsActionOnEndEditing = true
- view.formatter = IntegerFormatter()
-
- view.delegate = self
- view.widthAnchor.constraint(equalToConstant: 40).isActive = true
-
- return view
- }
-
- private func createStepper() -> NSStepper {
- let view = NSStepper(frame: .zero)
-
- view.autorepeat = true
- view.minValue = 0
- view.maxValue = 100
- view.increment = 1
-
- view.target = self
- view.action = #selector(stepperChanged)
-
- return view
- }
-
- @objc func stepperChanged(_: AnyObject) {
- tolerance = stepper.integerValue
- }
-
- func controlTextDidChange(_: Notification) {
- tolerance = inputText.integerValue
- }
-
- func control(_: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
- // arrow up and down are used to increment and decrement current value
- if commandSelector == #selector(moveUp) {
- tolerance += 1
- textView.selectAll(nil)
- return true
- } else if commandSelector == #selector(moveDown) {
- if tolerance > 0 {
- tolerance -= 1
- }
- textView.selectAll(nil)
- return true
- }
- return false
- }
-
- @discardableResult
- override func becomeFirstResponder() -> Bool {
- inputText.becomeFirstResponder()
- }
-}
diff --git a/Tests/AppConfig.xcconfig b/Tests/AppConfig.xcconfig
deleted file mode 100644
index d9ae040..0000000
--- a/Tests/AppConfig.xcconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// Versions.xcconfig
-// VisualDiffer
-//
-// Created by davide ficano on 01/02/22.
-// Copyright (c) 2022 visualdiffer.com
-//
-
-PRODUCT_BUNDLE_IDENTIFIER = com.visualdiffer.tests
-
-ENABLE_APP_SANDBOX = NO
-
-#include "Signing.local.xcconfig"
-#include "Versions.local.xcconfig"
diff --git a/Tests/NoSandbox.entitlements b/Tests/NoSandbox.entitlements
deleted file mode 100644
index f1e49b4..0000000
--- a/Tests/NoSandbox.entitlements
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- com.apple.security.temporary-exception.files.absolute-path.read-write
-
- /
-
-
-
diff --git a/Tests/Resources/big_file_5000_lines.txt b/Tests/Resources/big_file_5000_lines.txt
deleted file mode 100644
index 1c43779..0000000
--- a/Tests/Resources/big_file_5000_lines.txt
+++ /dev/null
@@ -1,5000 +0,0 @@
-ЩзчБюЙ🌍ьéь😡г🌍💔п🐍УÖнэ
-ЯхБь😡ЮЁ👍шМофöыЁХЪö🎉Й
-ЮзЮъЛ🎉íщíяКН😡п😭öФЕñЫ
-ъКÓЬÉнюЖЗёßяЙÍÍúУщЕе
-ыФ😍аНБЦ❤️🔥ыЮЛИ😂ЗЙчНпф
-ÓÍ😀😂äтЙпюÄХЫßäХМЦБ😀С
-ТФп💔ШЗЩЕЩЯÖЩхщеПЧшЗЩ
-КЦ😭á❤️ЛъПч😎ÉяьснэЭÑс👎
-Д😡фъ🔥ú😀иäчюУ✨ДгÉÄе😭д
-вÄЁкóтТЗжíымХÚúб😀Дßü
-äт🌍у💔👎ßÍЧмтÖэЗ😭ÍхсПг
-нМОлÓñа👎ÄПД😂впаюЭбж🌍
-щÄúЩСЪиоякАтЩфоИ😭ñЛЁ
-вИяüÑьХñХнйншЬБцСЁхЩ
-уе😀ЬупХкüжлäмЮсЕ😡еñД
-😎ÄтЙЖЮыЁЦ🎉яÉЯ🐍💔б🔥ÁзХ
-жÓ✨🎉ЛéУäъцЖРфТМЮб😂З😎
-Ё🎉Ü🐍ñцЕшчü❤️ЁüЗУзв🌍ХЁ
-äЮкÁЪÁёРÜЙуъжсфПбИзь
-ЛхЫмЯёрБКбЪчбИ😭😀ЬС🌍П
-О✨ÁШКцИщьÄАч😂йдуяёöü
-ЬДÁ😡ÜÍг🎉ÍГ😭ккЭоúН👎ü🔥
-вхФú😀лÉдъИÜЛШУФ✨ЭäэМ
-Ль🌍😡чщЖÓ😀ЬéЮу✨БнЫВОн
-ёБжУъ😡пиаМЙäЕЧíущЩóН
-😀ьЛЯÄ🎉хП😭оиÜúЕжÄЕААü
-г🌍Ö👎у✨ЗЬШМНфьВэ👎ÜÜЕю
-ыВуйГÚСúуÓяéЁЬБ✨еÑЛ😍
-üüнАÍа😍😀ШÁá😡УЩÜцщОяí
-ЭуПяна😀Ä😭Щü😭❤️ß✨СЯЮКч
-äВяПÖÉлгÑьÚянИКарÖФЦ
-äэпГПцьчь😀😂рЫдыСöóФ🎉
-ТüФьРфЬЫУ😍эз😡КÚхчмхГ
-ХллфХзБúáИРДмЦÁóхÑáä
-ы🌍рЕМЬФРöЙ😍Г👎оЫÉáсдь
-цÚЮЬыК💔öщАюЭтáÓПé🔥шп
-ёФÉЖъмМъяоЛНцñъ💔хАйЛ
-К🌍ИишПЧ🎉ш💔😡👍ЛФЕÑзБШё
-оЁя😎ФцЗшКРг😡Кö👍цú😡íс
-эРАСгЙхЬХ❤️ртфыÑÑТр🔥🎉
-пмБ😂чñ🔥óзéщá😭👎ÍÓл😡Ел
-ЛбъулÖéЗВúФДíоñÉжÍЁт
-оФ🐍😎ЮÉКе😡втСö👎ЙЁЁ😡óЬ
-ИИ😂ЧÜиЁё😡РавЬñ❤️ТЁчñá
-úУИтéöМСдÉаÄгЪЛ✨ЖУон
-Г👎ЙÜЙ💔щ😂🎉ÍхЙ👎😍äгßэÜß
-ДúХАллÄéÖ❤️БЯЙфíразÉб
-РьТОцÑЗ😍Áк😍Д❤️СäИаЖы❤️
-ЪáíÍоЧ❤️Тв😭лüы❤️ÄéпöуШ
-а😀йждэлúäЯЕóЭТчьúЙТ😭
-ÜшЗр🌍Умввöц❤️бñÚШÍúСщ
-ъЫüДьЩ🌍рКсХьыЁь🔥❤️Í😂и
-óЪя😭тбл😭П❤️😭ХК😀ВёДУё😂
-ЫöёмМчЬ👎🎉ЦдÁÓъÚН👍щÄЁ
-ФñюэÉ😭ÚьтЛßЯхЬъЪН🔥ЮÖ
-ЕÉУЁИуЗДЛЫя💔🎉Я🌍ёяхФА
-тÓÓиП🐍еЛфßпцл✨🔥тИ👎ñт
-рщУ🌍ТьУжßé👍шКжФÄ😡ЪЙ👍
-цП😀ñ💔й👎я😂Ü😭äЭ😭ÚпЩ😡еЁ
-ÁБдКнÉáл✨ÄЪепВ🐍АМр😍Ю
-ШжсЦюЭНЖрÜ👍😍ТэЖÜК💔🎉л
-ЬЁ👎👎фХвКИ😍😀ЦнßсÜАЩÓЧ
-нШЖúтД🎉АМрцСХВгЛК😎❤️э
-П👎👎цлайлюхäыпСоц😎ВЮш
-óяÑСгп😂АЫВ✨ЪжúНеЪяÄ🔥
-äМЮмБсвü🔥вфÚЬúäГ🎉еаэ
-äЕí🔥цКйúщ😡ЭоуЖебчДЙо
-ТыЮÚáЦяÁв😭кфз🌍ú😭👍щ✨У
-äЁГЩЧРÓлЭ😀МЮЛБÁñÍж✨и
-úуиыэÑäяв😎щЮсфРüояэБ
-ъÚнжЧЪ✨чÓп👎ХУ❤️éХт😭ВЦ
-äЦвКчéщ👍😂жÚэЧЪЭлÁäб😍
-Е🐍ныЦЙЭ❤️ОÁЭЙЕщЭнЩ😍Га
-ъóСыЖьéÓ😭ычЫГЩßö🎉Дóп
-😭МЭ😎😎ШÄхЁñЯ🎉рьрÑúщъ😡
-ЪЫнВыр🌍öЧíлáы🔥Ыцйй🌍Ä
-😡хВÄ😡ЬрЛтÉóюгДМЗё✨Гö
-рцЧжЮЙßь🌍ффЙЮЮвÍьöЫТ
-ТКгШ😍ñ🎉зыхóÄúтБНЪаöЪ
-😍Сßзá😭ъüвфЯрё😀жí❤️😀Ä🔥
-🐍👎😍чñДцВМиРЬзÑÖАсÉ😍о
-ЩеГЮъ🌍жъвп🐍Ó😍ъС👍ЬЫцм
-енЪооЯñУьÜÉ🔥ЭШ🌍😂еáñч
-áаыФ💔ЖМ🎉ич💔❤️цЮсЗЬКЮи
-ГШÚЮ😡Ч😀😍ÄНчКá🐍Пу❤️УÚё
-ШбÄжПШЖЫ✨ёН✨Дре😭е😂Éт
-🔥Хл😡ШЮу✨зА👍ДöЯЧЮÄÑЪУ
-👍ОЗ🎉Уп💔ъАЭÁЮÉüÜ😎öБÖ😀
-ФМИЗЗ🌍ПМт😀úíтядм💔😡áф
-МШГзóОДоÉñ🐍НбЩВáбщгÖ
-Лхста👍óдш🎉ÚááЮÑß🌍ГВ😎
-жЮí🔥Д🐍х🔥✨éБкХёцÖжñЕА
-ÉошпИéОÜñжЕцЮжúШЩÉЖЁ
-а😀аЪьÑа😭ИúтáñФéХо😂😀❤️
-УГНГЗ😭ЙÜНГЗí✨Зтаú😂Кё
-🐍Х😂пКмНМрéЦфéÜЕфü✨👎Ё
-öó✨КаñсЬОэМ🐍янй😂ЁñбЁ
-аВäЯ🎉🐍úйЗäТ👍ЭБгэПлВм
-ф❤️й🐍дÁПЙнхсÁЛ❤️ÜЬ❤️💔úÓ
-ьРх🐍еßеäС😭кäзюóñБищФ
-енБжйбгялн🌍спхёü🌍пЖН
-Т❤️П😀👍🌍р🔥хЦ😍👍äуХ😭Г✨Вт
-Ж😀Иóст🔥ÄÜЯТóцЭЯУÜгчж
-ÄцéаМОХэЯЕГкúñáÓеЦХт
-ь😍ЭэгГÜúХэОфКХз😡Ъ😀ЛП
-ÉШуП❤️Ед💔Еъ😍ТРсúнÖÍЬ😀
-дЕ🎉ыВьфЗ😭фЖЙÓ🐍ÓмдэЩя
-Úёоíд✨óИИ😭ы🎉ñШäЗЯгИБ
-🎉íсщУ✨ХÍш🐍хЬÜÄ😂ЮбХпб
-ФЬíßъмъ🎉ÄЫРéУДДЕÁЩÄЩ
-й👍🐍ñфГюБЪьъэÄ👍Ó🔥öИж👎
-🌍😀ъ👎Ерáñ🎉Ы😡Úыь😍БбóюЖ
-í🔥йЗ😭ц❤️Аг👍В😎чДмИ🔥тБМ
-н😍ÜЗААА😂рпÖрч🔥Л🌍О👍ф🔥
-😎о👎ÁИЁ😂хРвÜ🐍ИжщЖÚЫЮб
-еÄхКэНпÉНí😎ЕХÖÄ🔥нёЦЬ
-ÄшКасРЯШзб👍ХÜ✨ЁН😂еО❤️
-ВЩ👎🎉пúё👎ÚККБ👍жЖЫгцÚК
-пАРщИÓЗЗмОаÚАé✨мвЬщг
-Ч😎ÍÚЫЖñЯ🔥🔥И🔥ÉпИдвЭÉЗ
-Ф😀óÚЯúУДпАЙÉЁé🎉😀щ👍öЛ
-ЪЩгаЙÓéáн❤️ШлáÓЁÄ🎉Иéч
-щкÑдОБ😍ЩЭЬü❤️чíßÖЩЗÚэ
-Ё😀вÖмОг💔зжъёУДФгтХ🔥м
-жкВ🐍зУЬбíБЦД😍üып❤️Вме
-ИаЙиЯ😭😭ßр❤️ЖÉ✨ВЦХъпкГ
-íИÜмърЫл🔥ИéвÄсфÜñнке
-ХОчфÍА😂❤️цüóбДüтЩ😍о😎У
-оöхДшхр😍уéгСвÚЦÍшАéВ
-❤️фÓВÜЁюк😡ОП👎ПÑнЕЧ🐍💔é
-РäСрÖвäе👍ÖÖПю🔥юмо😡Нщ
-ЕüñН🔥ыДШСВёнюñПñфü😍ю
-ЪЧХ❤️öóÍÁсÄщСЫüсЙЪВ🔥о
-Яю❤️ÁéöНкюúхö🌍Ü🌍вЭЙ😭ц
-ßñáАк🐍ыЪкНЛЬ😭ОÑХХУХÉ
-ущß🐍ф👍кÖеРáгéйЫóХ😍ÜЗ
-ñБ😂ÁхБцöл😍Тё😡Г👍БЖицЙ
-рпуОсУАЮаиÄМТÄьъЬéЖé
-ßСю👎еопщЬэüОнö🎉ЧШÖö👎
-пзñЭñ😂Э❤️😍тéЬ😡ЧОВЁвъэ
-сТюñГÉóЖуруЭäэлхиФ👍í
-НфхФхЯá🌍💔чплó😀ТяН🐍в🐍
-ЯÑа😎щЛБсÚДЪэАъШíЦЦЪь
-Жн😍😡чиЭЛößХгеШаúБхбЛ
-ёÚУбм✨ТуРЖíКхфЧЛ😂😂❤️и
-ТйшЦоаÖвуюНыжÚ😎З😂лÄÓ
-я💔ХЭссИÍЩЖ👍💔Ó😎Х😀рив🐍
-нпАУПгмЫНЬЙáЪ😀чáЬиВь
-Я💔нÖд💔ъГк😍ЕöЯкÑСÚú✨ю
-БёншÉеАцÚю😎💔эАЁ😂ПЫфД
-ёúёчВЭÑйцÉШЩЩЕ👎гИЮэН
-áЬÄ✨сТ👎ßПÜфдхолЫ💔🐍ыШ
-юлßеэММ🐍ШлñЁ👎Р👎Áé🔥АЙ
-л😍ЭЕсТЭРСущРКщщыУЛрл
-👎ßяÖóЦЬúÚЯÖУ👍ХßицЦÓз
-мСтач✨о😭🎉ЧéЁ😍нИ🎉Ч😡зм
-ЛЯÚщÁт💔аúЧл😂ЩуЫúьИцж
-öс😡йÜЙ😭🎉каяоßÄñДтн😍Э
-ÁЪъ😀😎Й👍ÁхШ💔ыЯÁдАуЁЫЖ
-Ш🐍😀цíöü👎шлФÓфТТНЫяёä
-ЪЩЮдЫВукäкÜ😭тчДчеÍФе
-нБЫтТзДВ👎ÉуßфкЙíмÍОБ
-Ы👎😂ЩТсÖЭÉÜÜийшöÑЮ😡✨п
-НÉХЧэВМЧéЫЕЭгВ👎ДгёХн
-ЙÚЙПТж😀ñ💔👍ÖÄóецоармз
-Й✨👎АЭжиßЖсÄ🎉ЩлГзФÖöó
-üÍÚГЙюляÁуßÑлнöьЙшя😡
-Ь💔😎ЯчúБЖÍАхЭЖЖÚф😂ВЕэ
-Йñе😭НМлЯФЯыкрэЕаЦ🎉жÖ
-ЕöúÓВÉКАлеснЛМöЬЧКПЪ
-ИЮх🐍äсУЩТ👎бИЕщäРСБбА
-н😡Üью❤️оы🔥😍😎❤️К👍❤️вД✨Рí
-ЧГÉÑñÁ😭ЁДзЪмЛжйКйСЬ😡
-щйзУЁÜцфúЛñщсÑюАМХ❤️🔥
-👍üШßüßóмц🔥Ó😂ÚББИе❤️ЮЫ
-мь😀ШаЕÓó❤️óщБ🔥ДÖмТ🔥вЭ
-✨🐍ОÑ🎉оХлвАрНВиüúйЛпЩ
-ЮеюÖгäПсёХгДХúЕфШЙшÑ
-с🔥ÍкЦÑ🎉ß🎉Нö❤️😎уыЁъ😭НЖ
-😍ÄüъринДÖÍПкжа❤️Дш👍ж❤️
-😍ю😭еПиäМ💔❤️ÄЫЭтХ❤️вé😡Я
-лйúФнФäСЧÁпСфтЖ😂❤️🌍🎉ö
-ОывäжÁфкь😎фмÉщёÄÖКЦÓ
-ЗчЭЪЗит👍🎉щм😂РжйЖлСéЁ
-ЙцзбнÁыÑЭю👍öПííЗУттЭ
-хКЕзЭЦншáВ🐍áбЯÑпи😎ßц
-íз👎😭рЧьрурёИЯбЩЬРКЛх
-бЪвÑКоДßБыжРШпáиЖЫзю
-ЕД😀ÖÁЪДУШГкАЁиÑеáоÁВ
-íрЗЙÍПí🎉утХ😍ЬЬÓ😍оÄ❤️Ш
-íБъеНвüвЩúЭёздü😀ШТвñ
-Ж😍❤️😎❤️éÍчÉкéНЬÚыИяуä😂
-сö😂И🔥😎ъü💔👍Мд🔥ЮХБН🌍Шü
-ЖуШ😀ОÜЬСфЩЁС😀Áí💔ЖéВр
-ß💔ÜВыüМнъФ🐍ÜжФшüчиоё
-🎉áЛЁЕиРДТИЁЭñмÓеЙй😀ú
-úнщкЁÁЖБ😡иСÄфъ❤️😂бНтб
-ГД✨ФБú😎😂УТкöБÍéЕзлъö
-ЧЕюштЫñлцмíМЙоавЯъ😡😎
-ИéсоВДНюä👍Аф👍ÚЩéЗÄОЬ
-ГпЕЖЯгЖЦЖБЮЬВИфТОгхш
-хúжМ😭дтЕлОäЙчЧÖáñ❤️✨Ö
-ъХé💔юр🐍ШрЪэьМУЕЧÍШрУ
-влЛЕд😎Гí🔥МЧьчвЖН😡áЬ😀
-тАйгМФЙъ🐍ЕвКЦфК🐍íККа
-чк🐍МдфпУь😎шНъó👍ю💔🔥Кч
-пЦыéлЛГáЩúвШЪéÍóÖ😀👎ä
-вПöÚ😎ёНÜИ🌍👍ÉÑРäмГжúщ
-😂ЭрхÁÄÍгÓгоьÚЯмУШлäи
-лЗÄУоÄáЬ❤️а😭еэßУйуФúТ
-Яв😀ХÖí😡йеЬ😍ñьРÜбьФÁп
-О🌍кз👍😭Ке❤️ЦíЪьПю💔Ú🐍ÑЫ
-сН❤️бüБУ👎ьÚЮш💔ЖоХóÖöК
-ЩоЮФЗаИЗÍ🌍бÁныПÚÚßüО
-íХ🐍ÄьáñДЧÑД👎Á🔥😎😎бЛñЖ
-Щ💔ЙнщЛВЭкЮэяХäКё😂ПЯз
-ÖхАЮйИ😭😍мíÉóеыю😍ÄЬщÄ
-😡ÍФÉОж❤️Тг😂рпч😀СюÉ😭üэ
-ювВяиьЕЗвхщßЙ💔😀Ъ❤️я🌍з
-ЦрОвФйäх🎉éщвюöфогЬ💔Ч
-уЭñÖúÚеГжнЫ😡ДЩЦД😍РЧл
-Цж😎гСЧ💔йь🐍Кö😂ДóХЕиЪé
-снА👎ъчöÜ💔íйщаЭ😀💔ÄцмÖ
-гóБВЛоРЧФОсöÖ😀ДУóЁуС
-ЮÉЭююÁ😀вÁ✨ЙзШТÄЯóóФ😀
-сБÑüßЯьäЦёТЗччжУхÉОщ
-ЮФЯПЬя👎тÍППú👍üыÓГúСЮ
-зт😂äÍÑфзмЙаёдАßüфй🌍Ш
-ыеЫч👎ЫЬ🔥ясЫфЙмэлщЕÜм
-íüцФХХРе👎кжкёÓхöÁжЖы
-иЁцбсЧФКъЦ❤️фОющЦэ💔✨Ь
-ЮööЪб😀🌍ЛÑöщон✨вöÓ❤️óЖ
-ц🐍ÁнАЦт❤️фХ😀ИХáМбшЧЪУ
-роВЛщ🔥😭мцЦзгСмеисИлÄ
-Л😭ЫцББИÚОшáВЭдмВу🎉МЖ
-ню👎ÚсОчÍвттЦУбáóСü😡👍
-Д👎епÜхХ❤️з😂экЦэВПнéп👍
-😎гЪшСйÖÜÄХН😎áРхУ😎ъíШ
-éК😂угЩЙÁ🎉Я😍ЫÖйРÄёёъ👎
-еЦ🐍уöСячйьИДНщ👎ю👎уЧе
-Öоú💔Ш😎ллгЁК😭я🔥фепРщ🐍
-яКЯФ😀áХЙНчдмх👍иÓДÉ😭🎉
-ñю🔥ф🔥Ъé😍íНЬíЛВ👎íОю❤️ж
-БÄ😭еяш😍Íя🐍ББК😡Ьуж😎цБ
-пШЦахÖÁЯЬФщмчÄщЯжÓпÉ
-üäкíг😎КдНАеЗИОжФАОЗ😡
-зüащыÉаФЖрюФ🔥ФЩя👍ÜäЩ
-КфгЩ👎У😎😡ёÚüфЦЩЩЭбШМЦ
-тЯцМяВ🐍сд😂ЫИÍЛЗХ🔥✨Хо
-ёйтЧ👎ЯЕбиßÖБчГСéÓьнЦ
-ЫЫЬЫШЪúéЪш💔штмТßаÑцá
-щÑöнÁюмтфИÍёёжЗá💔Ü👍Х
-🌍ЪАÜбЧВáЩбÁкÍЙН🐍ääЧп
-ущüвюНбÓифЩЯЮвчиВ💔ём
-гъЫЦиÚЦñх👎иЩъ🌍ЕсьóОФ
-зáшéЬ😀ЁИГúöС😡дмÁоЬмÜ
-пЮ✨жßÓЩ😭г❤️еЛÍбобусúÉ
-РÖлт🔥СßрАп🐍Ую👍ñÉéЁüО
-Еó💔ыШтÄНßñщНкяИщЖиЕИ
-ЫВщ😭ÜЬáмЬпэвñ🔥бíз👎Íé
-РеЮцЙ😎Ю🌍зЖБßú🔥✨öнжüó
-öÉéТЁмТьеÄñИЦмчсёЬСИ
-пМ🎉✨рÁпяЩЩПЖ😂ГвЗÓРñÍ
-ÍГúпУбХЗÉ🔥😭хкКЖ🔥Аодö
-ÓíТÍЛШ🔥öФыßэÓкОеИо💔р
-жЪ😭ЧНÉ✨🐍цöанЗó🐍💔иЧМ😡
-😡РуЪИÁфъóХЦБäÄмУЧíЕГ
-ЛóÚИЫХшáкъёЗ😍РМьзöЩí
-бтÑóэйУтЛаёйЧаÁэг😎Ех
-А🔥ßКЛФЯ🐍жäаПу💔ХЕЖ😭От
-éд😍ГХЬоöюэЭЫБпхÚю🌍ÜÚ
-нЭщ😂ÓчКФ🔥е😎фЗÚИЕßс😍🎉
-н🎉цъЮÉ😡аÄЗйÍИэú😭ЩаЧк
-öхЮЩЩÑ🎉о😂юяÚЙÄасДхдÜ
-ЖШíжЕöЙл👍И✨ДхУК🐍ИеЫт
-💔пЭвÉшЪз🐍👍ешЪ😂😡ÄЁ👎Жá
-Хú🎉иäßахьАрчжОцÚГИРВ
-шчоá😡éэяМЮъюжзЁ👍ÉéöХ
-Íß🔥ú💔ЮЛ❤️👍хИü🐍ЁÍщÁпзЬ
-ÑкМьЗÓсЕБÄ😡ЯЪщ👍ё😭ГГэ
-ТЖчёхКюжноьä😡фЪцЩдк😀
-бÜЩÄíиэíцЬÁÉ😡💔😎нИЕ💔и
-КЖ😎оПде💔ЭлЬÍßÍЧВёеЦ🐍
-ё😍ЙóФцлЕÑшÄеЮ😀ЕяКÖ🎉Ñ
-ХЕМррВ😍Ñюß🎉😍рНÉéрñэъ
-хК🎉ßЬёоñтЛÁй👎😭яьЕ👎😂д
-ЪЧаíмДфЯз😂ДЛоЧмЬэичЛ
-гЭрÑÍЬШЖ😂É👍óчьгш😍КÄ❤️
-😡🔥💔РВфö😭юьÁуЭфцъЕЕьЫ
-😍жЭэШяЖЕ😎íÁп😍иЖÍ😡Öаь
-✨ñШд✨ЪмЖЖ🎉Ап👎á👍áВрÖж
-Иöсß😀😂éоЬоЪ😎ÍЛоёЪüáФ
-ёБÍ👎ДспцКкüЯРнъÚД❤️Пю
-äйÖСЬВóйÖУЗÄхä💔Ыúмсу
-тЛпБй👎щК😀💔Ю🌍к😡ÉлÁñсж
-ЯъэйрМúсрдКо😂дЫСьВЬЫ
-лÜЮдñЕе❤️КÉецйÍКвь🔥👍Э
-ь😂ЬТÜчКх🔥чУ💔ЯуШэьск💔
-На🐍УЩуСÑТЖМЭ😡КолёЦ👎И
-ÉáИ😀НцúОлФчЧ🐍áüуюАкÜ
-Э😎уáкюЙеí🐍úФЩÖ👎лАß😡🌍
-😀чЯáКИСñúёСЗя💔áЗНЧ😍ц
-Ä😭яöТúÁикэ👎üÑьÑгЬъßП
-ФíчА😂Ъß✨🔥шЭзХмС😭💔🎉ÉА
-👎ЩуНъпáАÚцСäШüóöñёщ🌍
-РсÜмÍТИЦоÑÄЛГñъ😂ЁжзÓ
-🐍ЦéöйГЕаЫК🎉ЧсщзБтчвö
-Й🌍ЛьúсНиЩёнНс😭ЦКфКеö
-ёú🐍íаИаКЕÑмöшЛвЬÑÜг👍
-С✨лÍзшОöЮХÁшБ😂эмБр👍Я
-ß😂аЯтÄЮ🔥УСÄЕёё🔥áяöЫÑ
-вЦтЯ😍дщяÑЖ😂в😭ёГущ🔥👎Ч
-É❤️ИвÉжЮРТсЗЫЁщЯЁъФУ🔥
-ж😂🔥ÜДЩ❤️íнуНоÑШÑСЦЬлÖ
-чЫñагЕДМ❤️ЧУÓÚÜД🔥Бü🌍Л
-УГ😭уУнюфЧМоВСÖАСювГЬ
-áпкхЗЙъзóÄíяфшбсóЁÚЁ
-Йь😭ñаИМдóßтШЗ❤️ТМъыß💔
-оЗОзÖндАГмÖüхЗ💔❤️✨ЖЩп
-лт✨уеЙКщ🐍хíоИшЕÍ😂кАр
-ЗбíаÍáыгáñ😍üУяКЙ👎шз👍
-ДОÁзНЬéФОÓН😡😍й😀дхф🎉й
-э🔥ЫцöИМЪдйáчЕц🎉ü✨ъÜю
-С❤️ÄЦямü🌍ÖжНзгДээВюЪО
-ив😡сЯюЭнфВОЛзБ❤️хгщэЦ
-ХчеожóНúЦ😂❤️оéÓа😭Р😀Цц
-уÍбЧñÖДÑЗмЧлОß😀бН🎉Зи
-ъЩтÄтЪäгБÚ😭дъТйäО🐍вн
-ЯМфИäПнБф🐍чбНВßÓ😂ЁМ😡
-✨ГУЮЁ😡чцЗтЧ💔ф✨О😂сэГЦ
-áЗ🔥и🌍😡éаЪнóЭХ🎉МЗцыкП
-г🎉Ü😎ЕуЕ💔ПжÓиБипñэЕъú
-Ó👎❤️ёпДмЭЦаФО😡ЯкгенÖó
-ф🌍сэЙкУи😎ä👍ÍухДÖнöÖИ
-ЁфФеиИюБ😀😍юьÓУó😡💔😂кИ
-ЧЗКóЧт✨ЖÓжюлСДКЭвай😭
-юäЪсыЧüФнчдü❤️ФкÜНбСП
-чоЧßшф❤️фЙÉщИщГЦЭаиёä
-яНУúЁЦшрñ😂МкЕМÚВАлВÖ
-аáЩ😍п😡ЁÚРяÍáÚаä🎉ИДГл
-👎ИЛъНъчюауйЧИÚэЕÜúЪ🐍
-иúрШДкХ🌍Ö😎🎉З🌍аßНöьъ🎉
-áУÁШвйОÚыпы❤️ÁНъЁёЦйл
-🔥😡ЛзрÓэНЁэ😂✨йрЧк❤️Кшн
-ИгäЯХ👍Ñьßу😍ыКХÁлс❤️ч🌍
-бг🎉сНÍяоöЖРäЕ😂Ñ👍НúнН
-🔥сАэЫГуÜбрИГФуüЗÚЫé🎉
-üЕ😂ÁЁЦЕ😎ШМéДНмЪ❤️Éэыé
-💔тх🎉щъßñ❤️шШээЬЪыэЕйЗ
-ыЯРъАЗоЛУиЁтöá🔥р🎉оЯñ
-ЫйÑ🐍ЧнúÄЬЛтл🔥ÁéоЯ💔ЙÓ
-👍р😭пЗЖ😍🐍Иé😍üеúцЙДЁсм
-Н🌍яä🎉ÍгаПÖÑаúáдЫрКУБ
-🎉ЁЛвкюяóыÁчБХФ❤️😎ÁЦфф
-ÚаК😭ПЭрЧБшДБюмрз😀ßБЮ
-ÉХÑя👎щхОÜßсйПЖФÍЦЧ😀у
-иóНЪЙúÄрáХÉь😎яÄнУÑь😡
-ХÚáßЖфñ💔кУЭ😎🌍ЪЛßИЦЗМ
-ддäВПÖЛя❤️á💔ÜоОъБбмнЭ
-ЩЬвХщу✨фэЮÁБЗüРЦ😡ЗсШ
-😂✨ыхНё👍ЭТжуúуёÄбДВЕÉ
-ТБЖшУлÓёцжлóФÓйЭЯьАб
-ЗЮюÑСÚÁОЖиäе😡яТ😎КУВВ
-пЛтжЫжеáщЯíюЗйÑЯОцпу
-юбЁñх🌍ёхИсбЯЖЦМÖóеЙй
-ыóъÑЧбíЧущóцФьГ✨НШЮЗ
-úК😡🎉Ю👍ЛПÄуüзЫоÄÓахúö
-п😍ЮÚя👎Ы🎉цж😂С❤️тЛфпСОЦ
-ьäúЬ😭КУзÜúфÄ✨ДщГÍÉны
-бÍíфШМжÜ👍увЫДСНущзВг
-иúГó🌍😍🐍💔чÚÑÚО🔥щЫЕöяÓ
-кЙ✨КЗЮÍИвÄíГ🐍гöéáН😂б
-Úуж💔ЫáАумУ😭З🌍Г🎉иаПщу
-👎нХЦñ🐍ЬЭÍёХКЩЯцйБЦие
-йчиоИÜéбаъеЪäÑпыЦлЗÖ
-😎Б✨❤️йфП🐍ЧíОМлИЖкПжМК
-амКгКЭгéÍч😂бу🐍Ú🎉ЕбüА
-г✨дÉК😀еплéНж🔥ФЁÁíзШ🔥
-😀ó💔дзъЙЙ😍иьÁ😭😭пИöъПО
-цÁеü🐍Монгаñй😀😎Ф✨ЩМБЗ
-чúиНÁЮД👍ЯдокßФбынРБг
-ЭмэЪó❤️ßÖÖтуÖПÉь✨ОШúÓ
-ßÄÉ✨иÄРСХЫЫЕ💔😍кВЗÉ🎉🐍
-😭П👍ГíЙ😡Áг😎ЛЧфÚ😍Чфхрф
-йьúТлНОШßфР👎Я❤️чц😎АКП
-цÄгЮВхЧ😂Üñцо😍Ыцй👍Ñ😡п
-Ещд😀ЭеäДАÁ👎äЬ😍ТГÑвч😎
-ЛОапяш🐍áéъÚЦÁЧ🌍ÜнИкю
-ЛсЩ😎úЙклыМэЫÖуé🎉Г❤️в😭
-🐍ö👍👍АлмÍáÉКÜя😀😀😭яДФъ
-🎉🌍Бä😂😂РÓЙÓЁß🌍иЯЕАр😍в
-ÍЖ😍ЛÜкмÉ😍😡З😡ФЁеÁжзИо
-БäÚШО😎Цщн👍И😭цÄч😡ЙÍЧа
-гЦк🎉ЦУСВЬ😂üУЦьЕ💔😀✨цÄ
-ÁжíЦПпХХБехö😎ЙКе😭п😀в
-ÜЬабетиеÑиМШáä😀х😂ñСü
-ÑцаÉщЯЁцэäЕó😂ъга❤️👍😍Ú
-👎ДбъРКМГ👍❤️йЫЩСЫц✨😀Äх
-СТЙЬ🐍ёРС🎉Ä🔥ЦжéЁУщХР🔥
-ГЯ😍ÍÜРсÁлФЯЗА✨бфНйЛ🌍
-ыТкРчлгÁГыéмТñПёЪч🐍✨
-üВДрРв😭нЯлТÜаÜЯзЭоП😎
-ДцЕЦ✨👍цИбЁЩЪÑёЁÖОшуÍ
-Пщ😂😎ц😎🐍ЧЫЗС😭íгвлАФСя
-ÓТЭ😍ЩЗШьСмНПлñрсБьщю
-С😂ЛÄёüÓ🌍ШЕíюбоАйÁшяЖ
-шдс💔👎Ö😍О💔ü🔥юЭьЦÉЭА😡Н
-Б🔥ßлÄЪсóлрщ🔥ПöйМГÉЪэ
-ÖчгЧЫоíЯСЯУБÜнХШдíиД
-Ñсхóй✨äЖюÚксñ😡цвЗДЩЫ
-ХЕХöБс😀аб🐍с😀ТёУñгяЬШ
-ц😡н😂еéкÑ😂лСОпЕэцБ😭щЗ
-ÄúаМЬввыИÄБÍХэЛУÄáНх
-яÜЖррёщб🔥í💔Зит✨мÍъйц
-ыúэÉЦéюжÖ👎оаЁФ🔥Ш🌍Гäю
-Üш🐍пäЪшéдчЁаРвБöЩщуá
-ТцÖеÚÖ❤️яДбóдюüÍхЬщ👍ú
-КПаЫП🌍💔Д✨тлÖ😡Ñ🎉ЧЭэЙ😂
-УÖНРыЮбгЯоУ😂цйёьлЪ👎Г
-РМ🌍🔥ЁизЭХьэпßÉжцéЖщИ
-ШÉО😭зÖЕ😍ЪаЙчЮъцЫЛЕко
-ЕсБнзßД🐍😡ХéÜгфíУöр🔥😭
-йэуíЙзöЬёВЛ👍ЧбЪéЕÁßх
-жоХГрФлÜуВЩоГюр😎Üя✨И
-сßшÓзßééсЮшШжÑопüНЫí
-üйЗü❤️сзЫР👍✨къз😭июЩЙ😡
-АТ🌍üÑМ👎Ú✨ъВуцШШ😎К👍👍Л
-ÓчиФуÜáОййЮ✨т🎉Ё🐍éЙпи
-💔😎❤️зДéíнЛöущМОСбНмÍу
-❤️Эиърмвъп👍фуЖИЫЪОÁфД
-РХХуúУЖыюХЁя✨óхХЯзяШ
-Ä👍😍ТЯёХЖУШа💔ПЫУБáíбЙ
-áяЖьтПв😭🎉🔥ÍúЖдР❤️Ъч👎Ú
-пóéÜЖ🎉щÁАßТбКШ🐍БÁ✨Ö😎
-гЦОйУáЙёЫáЩФХеÍÄЕßВé
-Е🎉äж😍фЪбáÁК💔ЮéрЦЧ😎Оú
-ъДáРЁ👍и😂🎉ёЕНшъПХугбё
-СöЮщЁВЁü🎉Úüшмú😡ьÖíйФ
-😭НЬ😍👍👎ÉфÉх❤️ч✨✨жЗХосÍ
-Юä✨чÜдэ🔥ТБ😭👍цмдИЛßЖы
-Ж💔МЭЛ👎еУíб😭нпú😂✨👍😍🌍Ä
-ЁéзЫз💔👎ÉМйПмД✨ЗЗЬó👍З
-Ърч😀ЦлсЕí😡ож👍😂ÜФШ👎МÖ
-чЭí😭🔥ОЖёдЫЧИúЮáúитЩб
-🌍чЗчг😎ßСлÉ😂фÄú🔥ÍЧЖ😀ч
-ÚТДчÍлÚТПÁьШП😂аФ😍у💔ъ
-Í👎ÑЧцЪрАЫэт😍вЦЛ😭ñигÜ
-👎ГÁ🔥оххА✨м👍кшпПъФЛЕи
-ызЕзфЗ😡💔ИЗчГнйАУКЮэÄ
-ЁыжЁ🔥йТАуДрЭв❤️з👍ШДЮУ
-ЯВéерщЪъ👎❤️💔цззШчЪдсн
-мГя🔥ФÚÓÉот🐍úЪЦÄЬ❤️😀цк
-ннЬьидéСАÉДÁеóóт🐍сю😂
-❤️ü👍Ü💔á✨гМ🔥ХнэНгВэлщÜ
-áИОАшäÖ😀ЦпЪúóßÜОÓВЖЕ
-спД❤️Ü❤️дЕбяя👍Зé👎ЩüíЯ❤️
-😎ТäЦИрпöъжОБЛáукжÑКé
-Чс👍тД👎КÁкú👎ЭАФМÍСэчÁ
-ц✨цÖтшъöÄúКМАЮЁ🐍ÜЫÉР
-С😭сá🌍Еöäофчт🔥ёэЧ😍ÁáÜ
-цЖГ😍Юóх😡МÓщщяÄ👎éÄ👍😡😡
-úжОзШШЁчуÜжхЭ🌍úÁ✨🐍😂ü
-шúЗßЛМямы❤️н🐍мчСьШáéЛ
-гФёÑФЧёёцЩКщбñДэÁРЙн
-дЫТ😭👍фÉ👎Ч🎉ПрШйÉÄЪзöß
-ткНазÑЦдрÚÁТБ😡ЬÉЩЦшÑ
-йо😡🎉á😍мОЭЁЭУ😎ььÁÑЯЙЬ
-дЖшñБТЫЯЖÑэТмг👎🌍ÓС😭д
-зäхйДÍГÓНÍüТ🎉тÑФтжÉШ
-бВТ😭😍тиЁúи🔥ЦГАáßЛМоЧ
-íЁАíÜщМиÖéлíЧыГÍЧФЦф
-ПЗчУÓЧвТсрдЬх❤️ÄёНшÍч
-раöúр🎉ЛÁПдВü😂мтÍьЭАЧ
-уДЬфБсЬХсЬМéцдЩЧъЬчД
-ьа❤️ГъЙаэ😀кёФЧр❤️П😂Óн😂
-жусУоüиÜОüäВагЛКÁЁМ❤️
-🔥мМФсИ💔😍ЦДЩóÜёНЭКлащ
-ЫяЭбмщЗÜ🔥ÜЯñнРфЬлЛßт
-ÚХüЛБáбÑд💔óп✨Изъ😀ы😀Ú
-еÍррöХЪэиНäвёЖВÓРЩфЬ
-млр😭😍СÑмюñéБЮÓЛщрыТП
-юУéп😍áюМöЁпÜóЧÖз❤️д🔥и
-д❤️ВУЩöМЪаХВÍ❤️пЮíфвÑÍ
-аóа🐍РеъЯИПеÚлм😭зЁÜЩН
-ЩЩФЯЕЮБУзЁТ🎉Я🔥Н😎рнíЗ
-ñШ❤️úПБР😎дáОчкí❤️ьñзЬü
-ÄвцÍО😍ÚЭНлЭВÑХшáНьфÍ
-иóÚнКÄ🌍❤️Ú🌍ГÍжП❤️ЗЗл😎А
-ЁЭÍый😡❤️С😡🌍ЫÍßÍгтÚöп❤️
-ет😍ÑÉíóä🐍зжÁóркöЫыиÄ
-хчлÄ✨П🎉✨ñЁíЕóяТВьъ❤️Л
-íЯДäЯ🐍жсáó🌍уÄрäрßЫáЕ
-úёбíьЭаЙнá👎Äé👎ЯтЪжЯф
-ияäтддíЙЁт🎉Ъ😡Ч👍ßóäже
-äЗ🎉ЛТьеЙßЛóЬ😀И✨✨😂Хуú
-Щ👎🔥ИЧЫЧбáНВаöÑÉД😀зЗР
-ЭÖЖю💔Ñ🔥Ъ😀👍ФяЫЗАáЧÑЬВ
-✨Д😡сАлÓШ✨Ф❤️эЫЯб😭💔Óяй
-цНрХИШГжиХÖßТ🔥éñЮúЮ😭
-😎гоÓХоЮ🌍лычЪсЙЪДÁЖúЬ
-ЬяÑКзРтäфхéПогД😂Н🐍üш
-ИéоуЬЬйрл👎иШйщ✨щлКгД
-эВ❤️ÖЫáй🐍яПФГКфЯЬ😍УлÉ
-ЁЕюКäéХÉñéТТюёÖКзСУ❤️
-Юú👎ß😎ЪÍÖú🐍еÁäуХÜ👍é🐍Л
-Ю❤️😎ß😡уЮ🎉жУпФБñ😂👎Ñäэñ
-👍жнми🌍Аыи🌍впжÄáэñЬ😂ю
-Т🐍Гп😍😎х💔ñЛóЕйÚÑ👎нк😡П
-Ь💔ачöÓпрфжь🎉яыК🔥ыНПш
-ювфуЙЮйлИУхзлЪБИ👎МЫб
-ЗсüÖщФ🔥ЩиÖíЯäя😍😡Г👍ÄА
-éЦеэС👎сД🌍áЕёФА😡еюЬЮШ
-хщÁÜоьжЕубС👍жÜЗЫжрЭН
-ыя😀áЧáё😀😍😭éОашÁСÁ😀Щ😎
-🎉á👍МÍКШ😂üЙэíН😭ЧийК😭ч
-ÄЭАЕÚйЖф😀цТсñÜ😂ÉюИПю
-мЗЧкГ❤️нÉ🔥СБ🌍ииБйúЭЗх
-👍ГÄеия😡É💔РЕю😭ñ😂éÉ👎ИС
-ú✨😂егРуñмЫедßЕАÁЗäЬс
-ёшßЗÁоУÄгíÄ💔ЬÄпВÑъСÍ
-щжщэüЁхЩл👍Нó👎áХпжñ🔥é
-уÍЮдо😍ЬÄКöЖÁхКХЗЙнЭь
-🔥ÑйгдЩЯОу😎йдЁÜßАыНп🔥
-чф❤️АмÜЗ❤️🌍фПглТб✨я👎АЁ
-ЬжВЕъь🐍ТáёЖ😭😀У😂дчжьп
-НкЛ🔥ЁЫ👎мОáЬсЭлÓхув❤️м
-Э🌍гСбÖйЧянБВÚГХПц😭öб
-Вж😂óöЗхáБÁКакт👍оМäйв
-м✨бЁебзБМчоММхоГ❤️Нщ💔
-😭ЫЬфМА🐍СÄТШячУДуíймх
-üУур😎ЪÉщОá😡✨М😂üБ😭👍чß
-Ы❤️ШцÑ😎аÑбЫшэнякгñгЯЪ
-öЗОфЦжуИвИП😍оÉЮФДßИб
-😀ФÖ🌍П🐍éáч💔Йъд😭М🌍фг❤️Э
-😂🎉öхАúСöЭ❤️❤️ЖíыЗсыпМí
-ÑЙьúÄÁÜñÖжУ💔😡ЯÚжаñыП
-к👎яИВъвíИФЕблйшÚ👎öХу
-íф👍ÁОäдс👍ЧáíЦм👎я👍дпé
-❤️🐍жÍжüñТжэгфá❤️ÜпФе❤️😡
-🎉ШВн👎Жлöпзí❤️á💔ыёХ😎✨Ы
-ьíчЖЧПМНФУа✨зОíÁКéí😭
-Лñ👍íÓЦгÚцТЛÜÑÖцоöÚаЫ
-á😡СЧхÖЦóДпюáÜÄ🎉😂🔥оч❤️
-пИ✨éё✨ЁеÖ🐍ЛШ👎КñоЯаЗН
-ÁÄОЬÍñпЭ💔МЖД😭😎уХЙ🎉úМ
-ЫÍЕÚьэфэÄАßÉйгГмÜлэй
-😀ЪßфНТЦйЖúндПсьСэв😀ь
-ГДлÑÉЪÁзтжüЕÖМáче😡ÄÑ
-УьÁЖу🌍У🔥óДЭЭВЕнЮ👍😎кё
-💔ÉÚьГ🌍ФсШцоУюНРФОьü😍
-👎ßÁ💔щь😂🎉лД😂😂ÚжЛЭяü🔥г
-мшЩЦаЬщöщЗВёЪЫЛЦМÖэЦ
-яЗ👎УÍж🐍🌍юзРён😭Вó😍öсö
-ЯшГа😀🎉ёЁБеН😂Г🐍т😎ÁäЗз
-ят😡ÑÓñИКД🐍ЮОя😀ЩУэЭ😭ж
-ДИХтЁжЛГ🐍ÄюИёéечБВАЁ
-пШсоа🔥СнЮЙХЕ😭МИ👎ú🌍äы
-ЦÄлв😍ЪПъРÖцаз👎б🔥Лцжт
-Нщüъíáвúпд😂ЯЮПÁфъ😍👍Е
-äцяфБíф😎ЫäшиúМъ❤️ДиНЧ
-гЫЭÜуÖЫ💔😭ИüЪВÁЮнбäоъ
-щУвЩЫвБ😂ÜнзнпщМвюнЙ💔
-ЦóшЗёóÓкü😡ГЙя🌍😍хис🌍👎
-Äщíй❤️ÓДп🔥ятаОк👎ыÉхшЫ
-и❤️ЫИЕЙрьЭУ😭мо🎉úгЙÍ✨Л
-о💔иРЖ😀ЖП🔥пэÍÚ🌍лкДь🎉э
-😭тéцПРцзхÁщОБ😀ñжшЯт🎉
-💔мЬЕцйéЛвЛжпто😂бйЁÍ💔
-пüÉЕÑпЭлъ❤️áОщгБ🐍✨🔥ыЗ
-ю😡👍😀ЙÍÑмЦу😀👎úÑц🌍🎉🔥гх
-ъзф😭ÍЮн🐍БШÜí👍ёÁ👎ЧйÚт
-ЫсЯзОÄИЗÓЗчКЫйЕЦЙ😎вэ
-😡Шú👎Ий🐍é✨Р❤️тРüжАшШу😭
-🎉💔óкзпГчíяíйХДэÚыÄ🎉т
-🐍тВтß💔яä😡Я✨х😎цеñЦéБЖ
-ьÓЫ✨гкü👍ßЯТр❤️йь🎉СЗлЁ
-чдФКюж❤️нД😀Ф😀Д🎉элéúеЪ
-ЪкäХÚЪиЗйЫгщ🌍КАíнуеЕ
-ВЧлМééЙ😂😂ЗтгÜБЮпвСПл
-Ö✨🎉ХрЫсШ💔и🎉ñóНчóГ🐍ы😂
-Шщ🔥ИпКЕоМЩбЗЛХщфраá👍
-дБюÉ😍👎ÚсÉüФЁг🌍а😡ёЪ😡Ó
-❤️🎉Ыßл👎Гвúы🔥ÄЩíÍзЗуеЭ
-ййЧßíеóЖггüРМЁ💔ÄÑ🎉ъЛ
-ÁсеÄСОкЩыБöШúДчüг🎉КБ
-👍ЕБшЦ🌍ю😡ФÉ👍цОШЭуЕОи❤️
-ÖШУÉГЗЧЩУöДБÚ👎üУЛÑÍЭ
-Яúч❤️ЕЩ😎шФ❤️ПöМ😀ä😂ЗЭзÄ
-аюнñÄ😂🐍ж👍М❤️УщсэСö😍оп
-😂óЩáЫёЙ🎉🔥чУ😀К😭щсОÜОв
-óПЯЁАРКÓхЪИöХП🔥úÖБСЩ
-ÖÄщÍ😍💔ЦИл✨Щ😂хгЯгэ😂д😎
-ЕРРäßбáмЭЧöХцÁУÓ✨ш❤️ъ
-ъЧЫñНщНщККеяРщЬ🎉вЕñó
-😡😀ХéЩВ🎉бáзеБы😎🐍🔥öÖ😎У
-ЮЭöЩй✨👍ЕлбÍíá👎🌍кЪАюä
-р😡д👍üхЭхзсÉЩ👍эüЕÄЦяП
-ТцЧÓлИ👍ТЧух😭жЩсЬзБСÖ
-У😂óÜЯОÁАÁучфÖт❤️ñПмÉÑ
-üßЗихÓüéляЁ❤️пÁЦ😂😂йдú
-ьВÜЙИЙЧÚщ😍🌍ÓБÚÓюсЯö😭
-😀🌍óÄОёЙ👍ЯчЗСрЦхßÓÁАМ
-рсöсЪкОÍЬшöмжнЗüТÑ😡б
-м😡ñГФЫСгЧфхÍÚ😂éлЛжДÄ
-гШñУцбхй❤️мйнЗН✨ГЙ😍И🐍
-ÍсÍР😭🎉йЕА😭шлМф😎цЯüщж
-ÉЕУЖ🔥ИЧМ🌍жуúЙзНшрцН😎
-íсШОа😍💔ÜЯ🔥🎉мФт😂цТÍДü
-ФÚ😎лÖЭёÄЭф😎тЯ😀Ú😂ЮЖтé
-ТüшáзЭТЕАÍГÜЁЮ😀öóщье
-ГüьñßвХлйÑ💔🔥Эб❤️👎ТУÍь
-шÜАЛюЫвÑЫтэ❤️МóСхкíЮБ
-ЯЦыяшБэгГЁÓ🌍ЗÄтОаñÓг
-😀дñМэМñЯебАПиъцУялх😡
-úЗъЕеХЧ🐍úЯ✨ÖмЯÍ🐍гыгч
-МÁó🐍ЯÑй👍😎шийÖИ🐍ГúÚЙ👎
-éВюöШ👍иёШÓúдúл🌍ñДЦßЭ
-Ú👎💔ЗáЧ😀СßÍйШхЫпЛД😂ßЮ
-е🐍Й😭😀ВчЁабл😂í🌍ъÁÖДЫэ
-éОóОЁсоёЩхЯЖäбÉрÉó🌍ö
-жяфЛá💔оааБОВ🐍иÜПЫПЯО
-ц👍🎉жСЭßñúЧñИб🔥МьЪС🎉л
-😎ппПьéПáÓФ🎉🌍йЮФлÖáмÚ
-ÜТÑгñÓНУзШьеЖó🌍ПЧЩ😂ó
-🐍ÖОÑО👎ЗищН👍ЕфРусн🎉уз
-юоМвяЩÑ🌍ЕнÁЪÁí😂мЖ👎úÖ
-🌍щíжвХÄЗТвх😀хÑхíЖ😎ък
-✨öтзьО😡УÖíМ😂ъСпАß🔥эС
-👍УЬ👍❤️еуШÑЖкЯЫÉУЛ✨🎉еж
-ялтэ😭🌍мКкúГüУóвЁЛ🌍íЮ
-па🌍ФШÁгÍÑäБЦМЗДÓ🔥е😭б
-óÜрЦЯÑЭ🎉ЬÜК😂ÄюЕуäмЫё
-Рф😎ФяИтéоСрП😭ДúнлХСй
-éИэóржьзÑúа👍СüМñи😎Дé
-😍жцÄХнЙ😎ЛюялЙкбß😂еЪá
-яСÚбöТ🎉😡Сü😀Ээ💔шüМшг😎
-áБáÁцÁйßыáÑмÖ😭ЙÚЯсöк
-äКаÓзЪхаÄГР✨аöин🐍ЭФí
-ЫщЦй😡СÄНЫ😂сьÑüгЮ🐍кЧÚ
-вшÍуЦ🔥🎉Ь👍ЙÓшä❤️ХтнЩьш
-л👍д🌍🐍бáдСвЫхМю🔥пЬüЦж
-Äфü✨Ч😭е😂ДБöÓт👎üÓ😀ß😡А
-ЙЛЧТ👍Ь🎉👍ÖЖüицШáЫБö🐍й
-ЭюфгЁß😡óХñиШаÓХ😭Öю🎉щ
-НЬОü😡ъñÚßеáíÉПсПчжвú
-😍😎👎ёЗьК🎉ршэяАЕЕър😍Х😭
-äёВÍ🐍О🌍ДРйéъУьпбГЯля
-😂члу🔥бÚлÍЩ✨СФÚ🐍🐍вйСЁ
-бу🔥хщÜÚППъ✨З😂шШсэЙ💔Ж
-ö🎉ыыÖ💔ф🐍ЮеХЭЫвü✨🐍äéМ
-бЛЁвГú🔥иЬÍñ😭Ñ🐍щХХ💔Ьí
-Ъ🐍К💔ñ😡ЫÜáкÚяЕэÍüЛюЗÉ
-щ🌍ÖíÉЦщиÖ😍Ыв👍КеС🔥ЕоЁ
-ъЦлМШсрÄъмНПъá😭ÑÁёЪг
-😂💔👍чшвт💔Á👍СС💔ыШТсаÁ😡
-А✨❤️НÓгккНз😀ХÖéÉ👍Б🎉ßЕ
-и😀КВФвв😭🎉а❤️ю🐍йФшдÜäИ
-ф👎Ждч✨Н🔥öЪЗРÜЭт😍ßтД🔥
-ИТЛпПÑ😀❤️ы🔥🔥😂МЮюиИäяМ
-Р❤️ЩÜАьúпБÖÄфШъÁГéРÖ🌍
-🌍щЗСцíпаЦэрñ💔ÉЭШéРуТ
-😀фú❤️ÁЮарИÍÁжéБÑóскЖó
-😍УШúÖАаúóЗЫКГг❤️ФП✨еÖ
-ÉКйРÄ👍Щ✨Ь😡🌍цЬ💔ъ😂Ыöьí
-лóСЫъßÄЁилАйНЁÖы👎ЬНИ
-ЁАО💔ёÁНГцÍИ🌍б🎉😀🔥ь😀ú🌍
-з😀ЦúÑ💔г❤️ктщзсжьЫÄхЛЯ
-ЁÁ👍ßзкзíиПÓúФыСЕш🔥чЫ
-щэПм👍Гл🔥ÓГ🎉😡ё❤️ЦÄЗщеМ
-ЩьФ❤️öЛвГ😀úОбРН😀ёаñВХ
-ЩАщúÄ👍Ч👍пúлиЯцщÚ❤️❤️ИШ
-ЧМÉüРюцмéЪДКйЕИКбЫи❤️
-вÓÑжЯуф✨к👍ÜöЖН😭ыгЕ❤️😭
-злЪéыÚÑвсВфñпМФИ👎ъ😀Ы
-Фа🔥ТДЕфБ💔МщÜ❤️✨дÑНЧÚЙ
-ЁЫÑ👍ц✨ЛОфíг🎉вЬфú❤️Б👎🎉
-мж🔥ßЦаЗ💔эИß👎😎ФХАИШМр
-ёв✨ШСУнМлТßюаЁЫз✨ПЧ😀
-х🌍Уиш😀Í👎ОВубÁТÍÖкс😎Й
-эьт😍ёÉТжÑÓФК🌍😡ÉбЭцüщ
-юÍßÍÚхЯ😀ГьÚ😎сЯддэ😍Áк
-ЙÚ😂зЙЮДÚщЁжЗсоЭЮщнаá
-😂р😂ъ😀🎉úüЯöéПКöÍ✨ачúс
-üáАъхЮÓ👍😂ЭÁЛН😡хуáÍФф
-ШлЬсРäЫ😎ЕÑЖщГьДьÜÑУа
-р😡ЦШÚÓÍÍЬкÖß🎉жЦ🔥ЫыоЩ
-❤️Тß👎Ое🌍😡ф😡лцявгдщÁнй
-ПпЙъúнИÜЭЮё😂еüЙéÄ😭Эú
-Í😎Ф❤️вЛц🔥пОÍОЙУ💔О😡í👎и
-ÑñьШэ❤️Т😍Я👎тхйтфÖЖАИщ
-Иф😭щ👍ГüРЖйз🌍🐍ж🐍илÄЭЦ
-ßЦЖ👍Ж🔥ÁЙÜТБ🎉ñäüКГю😍🌍
-ХьúБÍацЩ😂УääтÍфшеойъ
-зрвРЙця😎ÍñЗЙПíвЬЖъЦñ
-üвхЫзñ🐍😭БяЮЦäКвЖшЯНЁ
-😍ÑЙ👍ьоúвÖ🐍Квивз❤️жквÜ
-ЁüХÍ❤️оо😡ж😎ЖСßвШ💔öучв
-фЫ👎ьзехЮо💔éчЙЛАНí🔥пк
-😂КюРХüÉüцЫуíЦÉмЦéÁё💔
-ФщВщ🔥🐍ПÁéЬ😭ехТ❤️В😡ЕШУ
-Я🌍😀иБ💔ЮЛЕууБкМхÄкЩПЧ
-ТЭ👍ЪСоЖЩю😂😎фÉ🐍ЙаП🔥Вй
-ш👍ёöХЬ👍ОНжкУфШРцüáыГ
-ЭЫзбБЦ❤️шзáшЦ😀ЮЙ😭😂вЮ😀
-👎НИТнúЮмя🎉ыжйАнÜ😎💔шэ
-БмоÖьГóЪПíЁТäИúñä😡Ее
-ЛÄбЫÜП🌍Оá😡ÜД😎Íé✨плÚä
-ЬотдñöОж💔Д👎Ä😭á🔥ЗдПúь
-😀ЫъьЫ🎉о❤️Оáá❤️ЗьЬÄжщíБ
-жоёЬ❤️ъКÍАр😎чÓвВчÚ👍Ú👎
-тРЛуГу❤️Ъ😂тüДТ👍ЭУЯцмК
-ЖБГÓьТоуЦчÉÚ👎Чúпгíув
-ЖÓöáеКНОкнъО🔥у😀ПОЖО🐍
-ЮГН😡тиьцК💔äЯ😍ъВЫ👎Мшш
-✨з❤️лВнЮйíн😂тшюПпр✨Üз
-ä👍ñÑОÖц🐍БфвтÑáыьцоДñ
-ЛыОБäУю👎айш✨щпВ🐍эÚ👎А
-ЖГО❤️Нц👍á😭с👍ВЭшофнъЭЦ
-мÜШ👍ЁцсéÁсПи🌍тдлÚэаЮ
-😭🔥эäоЦ❤️ДдÄУШ😂ЪМСЛхпÜ
-ЦЯ❤️НвäгъéßКЙНу👍ДНЭэÁ
-🎉кíЪуÜЯТ💔лв🐍чÍ😭🔥🔥ъьá
-ИЫÜ🐍ÚöзТ😡гпЮнúиых👎фТ
-ЬёваÍИÓ💔гяэВßВщАóЦрг
-😍иР👎в🎉фёаäжüüЗыЛí🔥ñÑ
-🎉🌍ЦгШ❤️ÓíчвБ👎кÚКСÖéУЁ
-шЕ😍иЬ👍уШЭ🔥РНЭйИыъИ✨🎉
-ьЯьТщщв🌍сеюБ❤️фп😡чГдг
-ÍИЯрÁЁÜЖсúлОрÓÁÍв🔥лй
-гäÉÍяогы😎ОыßцúЬё🎉вчэ
-éÚ😭лó😂ÑЪгúЖщрЫкОсУуС
-кАцАюöЕáП🔥ляГ🔥íüБФыы
-Я😂ЬИбúкСÖúГк🐍ИЫН😂🐍Áü
-ä😀íгэЕВч❤️мЪё🐍Сёнö🌍Í🎉
-😀Íь😭ЦахъЭ💔ГиЭВ🔥ёоцэÑ
-рщДЙВЧъОÍн😍аЧяПЬéжЬÑ
-ЁЬцлцöÜНЭÖлÑЭдтИЗéжг
-ДßсщаóÑО🐍шЗЖПь❤️хúÁßЫ
-цкзТ😍áöьЁóедЛАхоДВ✨😍
-ö💔рÄ🌍💔смШбЮМЭевшБуЛÜ
-ёÑёÄушÜЯ🐍🔥🎉éФаöРЭСГ🎉
-äлЬжАпЗ😡ЛОб💔ЛÚЧМнътУ
-ч❤️ЛЮÁ❤️лжЦ🌍ъцЪúóюсцÁó
-ВрГ✨мЁЫб🐍😡пÑюÑÓфЗ😭😍Ó
-üÉкЁúдЗ😡дÉчТ😡óУ😂ц🌍Ъö
-ШРрРйñ🎉ъи✨нЗóфÍЭл😍эä
-ЪЮßзЖ😎аóТбърВёх🌍❤️í✨р
-ЦшВлбÄ😎😀Ü😍😭ГвÁЯ🐍щиёЮ
-íáßШЩЫЩдц😎ГуцЯХёЙцБш
-ßКЁВ❤️ЮбшÚöщñишЙÍÑÉÑТ
-ЙТжТСэб🐍аХФкцяЮ✨лЕÄТ
-éАЛ❤️ñ😍ГßßжМ😡ЭрДфТ❤️Хс
-ЦöацЮАсИé❤️öзúшф👍Ь👎ку
-Шц😀фÑíÖóéиЬЗ🐍Жх🔥мíцэ
-Х🔥Иг🌍Зе😎üш✨хшрЩщиЭЮЧ
-рЧюП😡л💔ЬаБ✨ъвúэÜМ🔥ЙЭ
-😭АÖЬЫСьé😍рРДг😀öИ🔥👎ЖЕ
-вЖАэыéРоОÑúДцЪАэУгнС
-чÉäклэßОдкЬöкБоДбЪñф
-öбръл🎉🐍🌍б👎ЦÉÓЫчÜЮ😭ЪП
-КоАЕЮóбДИЙъхяхжл🌍Ö👍М
-юÜжДУßдаííö😎á🎉я✨зú✨ü
-ЁÑшЦуд💔нц💔ÑРьñюв🎉Ü🐍н
-эо😎❤️БÚ❤️эусШьПХн😡тДÉв
-ЪЁЬ🐍💔аАóЖЯЦ😎жЁÖвеÜЕЭ
-😍ÄИИф😡😭гНüЫ😡ÜÄдШл🔥ёз
-ЦЩдй😡á❤️ЮещФгаВРчДЖфа
-ч✨üпЗÑ👎ИтзÜ✨🐍ÓУРргäо
-ÍкяÉЙАкгН😍Т🌍ЩА👎ФИ😡ТЖ
-ЛЕТá😀тчёЪÉЙТ✨🌍ГУЙЦъä
-РьМáóши🎉Э❤️ХäИМÍЮЮТöС
-Г😀ЕЪхН🐍бгЛÑГÖб😀Ъóыб😭
-яüüфбЁß❤️ÜьÜпßХьжвчЮЪ
-р🔥🔥💔ЛюВÑñоИ🎉фВßгЪСÁд
-ÖСЮ🐍ТЯЩüäХЙЪьЦР😎хÉэх
-Ь😍лá✨🎉СзГÉ💔лßНдОТкшд
-цз🔥ЁЭßкеОáМЁупсчöÄá😡
-хí❤️❤️ÜЪмАурэкЭШпчишПГ
-Ñ🐍вäБÄ👍щ👍САсÚПáЕЖЧ😎И
-ПМе👍жтЫчёъ✨ЮС😡йП👍зИП
-Ыб✨úдйКФЧчЖяЙ✨ÍРаГФú
-❤️юаиЬсдЯхэмАÖъъСäзшэ
-ФчлцЮÚе👎щьВóÚÑВюúВмм
-лСцж💔ÓВвßуЩггЦÜíЙ😎щ❤️
-йёЬ❤️ррЖÖÜÖЩЕэ✨иБпЯ🔥😭
-🔥Лт🌍элЕúÄФОЛÓэÁАлЦ🐍😎
-É😭ОЁ😂РЁЧÍбЮЛИÍЧó💔чцщ
-😎üыАс🎉ЁйЗ❤️🌍👎😎евЗхЯПП
-ßХяШтЧСспИДЫфЫúйШФчЩ
-ЭА😀ъГоüЪÚФИ🎉АаеШРЧÉ😂
-КгáП🐍üñ😀óЮоúиДНÉö💔с🌍
-аХртÚхáцщíÖ😍ёНмÑХЁ😡и
-óыЦ🔥ЧхИÄ😀о🌍йЬшоñвáзЭ
-ÁуГёЬШУ😎Л🐍шч💔ХЭ😂вПäД
-ВуоыДäáоцглеОущ😀чбЬЭ
-нг🐍ЩУ🎉О😀чПЫÄззú🎉😎ы😂Ш
-еЗОчцÍМñÚЭхЮООЧПЁÉ🔥з
-ИОáБЙäйё❤️щнФЭАиоУб👎Ú
-ÚíÓМыИоßй💔кóФТ🌍ыюЦóЯ
-вЁАиышБЬСñрúбяЙёсÉ🐍я
-🔥в🌍üнтЬ👍чрхщдУЪрбЬх✨
-н😭ÍúиИаöÁÑгп🔥ы❤️Эгьн🔥
-ÚбЪäноÉнíнюёиí😎вГЬлЮ
-М🔥ъЖöаÑ💔ьúтя👍ьВСНчÍФ
-шеñéñá👍вМЁпñИ🔥ОШ😂Íáн
-тóúуу❤️😡ÜирäéДßжаФшФб
-üТрЭчÓ😀🐍Е💔ÁУ😎ХÁСЦИчЛ
-ЖеЧпó🔥Ñ👎ЩС✨ПЩХÚЕÚÍфр
-мъЗС😡Тä🎉Л👎эт😭íñАЩíВы
-👍🔥ЫЁЮÉФД😡🎉лЫЯ😍ЫÖ💔ёÚÜ
-вв😍жнзÄЭ🎉Хц😎ЛÑБчÚнóг
-🔥ЫЭМХСОСüзóяийЁТжßьУ
-Жуйх🎉😍éьх❤️тпГЬюЪ🌍😂БÜ
-Й🐍íщЮ😂мЦАГЛжЦГ😂ш💔üб😂
-йШф🎉ыёШмЦъццÓÉФг🐍ÁÍБ
-😀Р👍ЗуИ😂ЕыСЁó✨ДЧчОмеК
-ЛмЗßЖúЛó🌍ÉöРáй🎉ГзÍБэ
-ШЪШЫ💔ОсЮтРáмХüхúЗЭЫЭ
-ÚПТЬтÑОЭУяр✨Ачл💔нТ😍щ
-ИИЬЁАáуцéМóкуж😭ñЛЗЯф
-ьК✨в👍лÓ😂ЦЖíÉнЖМБцЩег
-ЦъÄчыÉ😍😡дМнУЪпгЭЯдЁ😎
-Üд😂ФóдÉß😀НÉАäАйлУÄ🌍Е
-мИцюЩСжёйöмчЯШэ🐍уУУИ
-кгФ🔥щúвхíЕЕöсЁЩ🎉üё🐍Ö
-Бó👍ё😭кпЗА🎉ТÄфÁЕ❤️эЛÓс
-тЩéüПАФöТУаÑЮНжИñИУЬ
-дЫ😍ттёэВ👎дйüууЗйдúЁ🌍
-КГю👎ХЯзоИЕн🔥🌍ВЯЦÁ🐍нЩ
-Á😎áя👎ЛУÉё🔥эЮÑа❤️ж🌍ЁХП
-хкУÍ😡ОаЁ😡ÉÜлУВчъоЯпю
-П👍É🔥😭ЛДЪМÖсЬЕüВ❤️üЗоУ
-Á👍щй😍У💔сдéíЙЯцоñГЁнÉ
-❤️ЗИёКме🎉щÄп👎ГВÖыúюßí
-б👎Ó🌍АФтЖБ🎉АáÜÉЯМúцвъ
-ФепйЖл😀пКВБ👍👎пШыЗКñб
-лИ😭👍ÜОлдЭУнЮСМЯЯкющЯ
-а✨😂аапБÍёаЭки🌍ÑсХ🌍Л😭
-öз🐍пкж✨ёüÓА👍к🎉áШЪСñ😭
-ХчдЬ😭шбЙÜÁ😂ЪсÉю🎉óЬм💔
-ВТЧЕтккГФ👍ÄХъ✨БÁÉЙЙ👍
-ЦацЫлúÑСл👎шй🌍ъйö🐍😂УЗ
-😍😎ñÓ🌍óьÍТхЯФАЫ🔥фыТфÉ
-ИЫЩтÖÁЁЙÜКйдР😂ГЭЗü🔥🔥
-ЫХóЖ❤️ÜБЦхÖÄнÉШ🌍óщхД❤️
-á✨ЖШöнКогдÚíърä😡у🔥Зу
-ГЕлПñяёМЛ🌍юзчу💔üéб😍Ä
-щ💔мгЗЫвКшÁ🔥ЙщпзÜ🔥ЛЭЙ
-❤️ИНФ👍сэ😂Ч😍😡юВДб😎кпЭÁ
-Á😭ПЙ✨🔥Ъа🌍ёäЖмоц😎ри🎉🌍
-ГпшхуИЗÄХтУКÄЯЭя🌍вЖ😭
-😡ЫнСь👎Д🎉Íк😭У🎉Ö😀Вц👍áЗ
-ЮЮоы😂дёÚИдВбяüТкьюмП
-áДÉЁЯЭсл😡КÖ😂ЕЕЭ🔥úл😀ы
-Ó❤️НÓó🎉МШьЭШПаЮвúР👎лЪ
-лЁмщШ🎉Юсßü🔥😡ÜОÖ🌍с💔Ыí
-хеäÍÁжжыЧьиÜ🌍óЯяГк🐍Ц
-ХЩЁáшд👍цГ😎вГíояЗЛёЯд
-рксÚОЛü😎Я👎ЯЯРäЭуСнáЧ
-éЁЗТÉоС😎🔥мßс✨чнеñУáК
-дЭчüÓЫ👎ЛвШОÜáДлчáюÄх
-ÚóиÖЬй🌍В😎💔лБЧПМÚЧшТÑ
-Ш🌍фЮшЪЭОьÜñЦЁшЭГН😭Áц
-ИÜЯээШд🎉ñыёЭШсоééОч😭
-тИüрÑпщдЧúщлЧЯВéЯЙсЖ
-БхгщыÓпÖöÁ😂💔ТаСхОпШ😎
-ЦгЩñЁЗ🐍ÖТя😍ЭмП😀ЩЕß🔥Ю
-óрÄчЮдрглыыÜЛхмщ😎ьРе
-Мнчж🌍Цм❤️хХöÉФЪÑНÁÚУц
-ЕäÓлмСг🌍иФСшЭ😂😎😭ÑДцж
-äаЗÁСсú😍ыАöäзУющбсñы
-ÉÁюоä😀дгИ😭УХЖнЩЗЭтÜ🔥
-чттфЙЪРавЮгöСÑЁÖÄиСЖ
-😭Íé😡😂❤️ÍаóíФБЛШЯё😭оТХ
-ыы👎üРдэ😀аÑЮсыгЦäБÓЖß
-гÑЦíБрЧé💔о🎉Ф🎉аыщ👍Уц💔
-фéр😍ЮЁдЬЯБнÉжзиЬуЧЩы
-уХВаЖЛИжЭ👍М😡еПчеÉúт✨
-Áэ😡ПЫюРУ😡ÄПФХЖХсЙкзÁ
-😡яН😂тВйЯöЧßíÍЦщРбÖрУ
-😎ГеГуеЗй😭шÍяÑвъъ😎öщж
-🐍пфИ👍БгúÑЛöтТСы❤️аюмм
-ЯзДя🐍ЦоäЁ🔥хшЛ😭пЗ😡ЯРО
-пИырЫёСгпЯПóÑАУхЭ🌍😍У
-ёКШсäЗüроьМХЁю😀üЕЁЙ💔
-пÄ😍🔥жáФГ😂ÚаФфпБШßÍщ💔
-💔ЪдЧаяЁí✨ÖУÚт😎Ьбп🌍😡И
-ÄБЪÄьЧ😀С👎éМх😎áÑщьдрÄ
-ößМмд😍мÚЩ😍йПёЗöмЭíáн
-😎дДЕпÜЭхíД👎ътхóъüЕф✨
-🎉у🎉Эáзг👍иЁщ😂éФúиЦГ😭í
-фяóеЦЭШÉПÍшыÉжшцкóЦЖ
-ЭÚПРТбЯßЩкж👍á😎лс😍🔥ВЬ
-яжÓ✨кчЯЬÚЁХЕЯÍÜч💔фЬД
-шь🔥👍юá👍Ъэñ🔥éМЦЧщéотЬ
-яа😀ыэжрÄüъНЯеÜжГüо👎я
-юíЫдЦЬÜюгЭАä🔥😎ÄЩрЁтИ
-ÁафПыÍäтяХфíйМЕ❤️😭тГЙ
-🔥жш💔ЪЖЖдОд💔ФÚиñ😭éээ✨
-со😂😍Хс🌍НБрГАóñЙВВыЫй
-ЁЪм😡уÁöáркаърцэó🐍ÁХí
-жуЦ❤️öЩЖ👍ÓñйЬÍжлГ💔йЬИ
-💔б💔ччэудоäэ🐍Ñк😂Äч🌍✨ы
-ЪымлЗЗüÓÉхü✨Üр🌍юУэФд
-к😡Зог🌍лПäÜшлН😂лш🎉ЁфЛ
-еÄбШöÚБзЙх😍😀üкíÄпАХТ
-АещЬäъГшвпуЯйÉüЮклЦт
-ЯöвсЕóЁ✨оР🎉íОВтаÖßТЖ
-ВХ😎💔з🔥уВрМОаЭбиЯОмсС
-и😡ъñУйиКуöццФ😍ÄЕПЮüй
-УЙ🔥тэоЯÍчГ😂КáНШП😭кЩЖ
-ÑщлЭэГ😀äвыфрУЕг😡🔥🎉ЙП
-чслЕгÜßУ😀ФЧгüí😍ТШэЗз
-е🌍цоэтöрÖбúиЮжöóГГу😀
-вЪ✨аöЕиßлЯЮЭлГб🎉😍РÑñ
-жШржС✨😂дéИЮуЁЩÍЫгСйб
-шГí😭жоВьАöз✨юЁäхБпПш
-👎😎ÄМЧÜЫФ👎🔥ЯМРбÜÚЩХüЖ
-ЖмоЦÉ🔥ÄÖъ👍Й🐍хПОÜЩё😀ß
-👍жЦцЕИЁßÁкÑСгüЬéО🎉ёи
-ьВцÉмüÑпо💔😎ФНЁШкбыфУ
-рÖщЬßчзäщ😡ъЪ😍öэЩаР👍ы
-л❤️ёцЩъОп🔥в😡éгткСñнР😡
-ЩхбтДéóÉöфъ❤️éЬ😎😡Абоá
-ÄÓу😀дВ😍чеЦШчíНЧчú😡лв
-сШüÄнЕЮЬхБпЗЯ😭рцщЭЪ😡
-нэ👎фЧХ🐍НЙХпЕÖ🎉МСзОПП
-ÁИ🎉🌍❤️АяЗёКкЗЩ😭РмáХьР
-ÄДычЩЩЩТХÍÑ😡ЁэАñßРуя
-éрПñÍäШЁáнСäНпЫМЗц🐍Ф
-ф❤️👍ЭЭúйí😂цЭФзЭДгшБчж
-ЦÍÄЖФúижёТНИеяÉьуÁча
-äúъевфвтÓХДБЩвОдъхаа
-юЮ😭я✨МАЙЁКÖм😂áйф🐍😎чр
-ЧúиЬÍИ🐍😡🐍ъЪö🔥🎉ШдН🌍Äы
-АЁу🌍гэФü😀ячхЫ🐍ьИсЦПъ
-Ыр😡😡üß❤️üшÓМЦнцüъэá🌍Ö
-н💔ÖОхс😎Д😭еиЗÉ❤️вние👎Г
-ъЖзСбÜер😭ЪщÍТÁСцелиИ
-üéúИй🎉уяÄ🔥Íъ🎉🐍ИГЮП👍Ñ
-ÄзгИЖ🔥шуМё🎉ЭлМБФüгОÖ
-уáПääЫБМХрЕчпфОáß😎аÄ
-ыыЬщмМчДтЖРÑРЧр✨ЧÚ🐍л
-ЧАСз😭ВГтЫяыúцÄ✨ОФбÜ👎
-шяЮНЙ😎😀áхÄíэЪР😎ÍИ✨ЕЙ
-ÖЪ👍íВК✨éЯ🌍нЮЦ😡äÜмТÄñ
-😍ÖЭШъЁÉÜИшáБъ💔😡ÜПí🎉п
-У👍Р💔👎ÚÜ❤️вШйÓßёÖßЩХщК
-УзшМТщлаÖЕЛАчэыéЫддЭ
-В❤️ч💔💔ÁÍё🔥Эó✨КЯЪñсЦщ🐍
-КñвсäРНÑÉвЧÄттиíеБГн
-ЗэФиш💔éгÖ💔✨жцХмúд😀АЯ
-👎ТмддбзÖóÁжЁёÚК👍ЩЖЙМ
-ПлнЦóкчцбЪüлНäñ💔Ыапк
-МКéМЕчУÁ🌍ЫыеßыКÜжп🎉А
-🔥ñЗБаúÑШÍэ👎ДВз✨Á😀яхг
-Áп💔ñкíÄС✨воÓú✨Д💔ñÚЮВ
-ЯХЪМЧцñлп👎óфáШКъйЁñú
-МО😡íЖñзь🌍éüöДюñхЦблÓ
-ЦпКЭсЕÍщЙУшÉ🌍оÉХЛ🌍Ь🐍
-о👎ЪÓтхäóъМДЮóЗÚцÁЭÚÓ
-óАЪß👎ъчфЁчАп👎ÉтЖГóеЭ
-ФАЕШäÜщофÉнÓ😍ЯВ🎉з😡á😂
-ÑхЩРЛЗ😭Ле👎ЕЭюбÚ😍э😂Ръ
-ятÚЙФеЩ💔ÖЦъЬуоУаО😍Ш💔
-ЫÓжДб🌍аТбюШПТáРГРжть
-ÉЫЧПÍнÄóйнлрúéБяíüуÓ
-хлЫыЖúРтьУыБЗЭвДнЖн❤️
-ёúСд😍АДüÜщннРЬЁцэü💔э
-óöСюёшеш🔥Чб😍ИÉмып👎и😭
-🎉ёуЭИХЖш😂юм🔥гШёоасяÑ
-ÜчÜЛöХВ😡Лвн😍ТеÉñэБМЗ
-😀КчБ🐍ЪÜлыХ🌍хуРгкМЮÄ😂
-ю🌍Т🎉Ыч😡н🌍ЩеР😡ЕТ🔥Éч💔ü
-😍öЕЙäÉкззиЦЩыЕñуñсÜí
-щóриеяхКЩÜфЖáпñáЭъ😎р
-чÜецдíкАéдУютЮ😡мЬлъд
-шАаВрРКьш😂АÓÑъсÑ🎉ПГп
-ДЛруИ😀ЮфЬФтЫшДФъáчíъ
-😭úñмÖ😂ÖкаÍеúтЪВГШ💔Ч🎉
-КЁКЧ😀з😡👍тТöä😀гНСЮЫÑЛ
-ЫНÓйЖУÑЖßЧÖгкЯуäУлдё
-ЬчмЬГёшßЧдЬцнäяюЫВЗ😀
-ю✨ЬйаЭЮиШУÑМнЗлÍЧЮшÁ
-чñКзрнБУ😍ЁЪÉМ✨АхßñщÚ
-👎äщЩОвАÍВсМ🔥ЕЛиÓ😂ёöт
-уКüр👎х😂ÍДбóЙ😭😀üпИ😎ПУ
-úÍОё🐍НнЩЩЗйУÚяЬчКсЬю
-ЩэкыумДузЕТЖННкЫъäЮы
-ЪкьЩХИгноЖ😭Г🐍БФчÚ😎Эж
-тМ😍ИзДÁМнСБэ👍гЯщ💔íе🎉
-ÜГы😀Ñ😂✨💔БФáлíжшÍъ👍ÑЩ
-яЗПЕíЬéХÄОéзПьÖÖфдßУ
-лЩвИээфÜÑсйюцЦüÄÄ😀ф🌍
-сыЗДЮÉХДЮ😀гäáЙáТМАЛ😍
-д😭ыт😍✨❤️ö✨НеДтÍХиГФмЧ
-ц🎉👍Р🔥БúД😎🔥Жоñ😭ВЫФушъ
-🎉ОЛ😭👎ДэÉЖё😡цхáó💔ХщÖш
-íщудОЙб🌍ÍЛШа💔ъНЦЖ✨фг
-❤️пéдяüКЁ✨ГО🔥ЯфßаёЕЦУ
-уКО😭дТЮх🌍🌍äÚЬ❤️ДУúиúЙ
-❤️йьИЪ😍ЫÚьшñФ🔥ь🎉Б👍юЪч
-✨ЧкбÍЕÍХюрÚяÖЭуМÓÚьЙ
-а😂❤️УеУТ😎УГуИъ😀ÚШ😭ßёЩ
-ÉчфСгОьмЖиФГßЯТöЦвэÜ
-ыÓÚШÁТдшяМöЁЭд✨Г🐍😭уп
-аюд🎉уЬ👎Ö👍пКхÍ😂ЪпюЬмÚ
-фÄонВХäЩютñАßйХнПЖИú
-уЩÉИНíГáцИÄ😡ЖмОМ🎉íВэ
-Пп😡💔üЦéÖÖЁÍñЛÍЧы😀нр😍
-íемéАгНЁ😂Ä😀ÑÖáдКкОэР
-✨ЙЧПДБЁЯюÉЧä😡ОЬШÁäн🐍
-В💔Ó😀Ú🎉óДÑпÉ😡уДЧ👍🌍щЪё
-и❤️🔥ЭЫЕЭßХ💔А🐍КбЗуъЧЫ😭
-щЧйЪЪщÁЙü❤️❤️ПßюТще👍лЮ
-áРЖх😭ÉэÓФä🐍иÄЭüЦзцüÚ
-лМрЁОíÍЪЧкзÓñыöÓКУ🔥💔
-É😂МÚ🌍ЙзГ😎👎оÖ😀ЪОЯМГÄА
-😡✨омбхуИÁäЗéкÉвшен🎉Ю
-ЬаßРлÑ👍мПА❤️уßéуöьПГí
-ШЗЖбрäгуз🔥Íя😍НвВíЁЩÑ
-ÍЛÍЩщ🐍Ш👍ÚööяЪ🔥Фíб😂😂ь
-АФМ😡шсЙТфйыЦ❤️МЗÑМс👍Е
-😍ä😡цёБХñФáР🌍АЗíВУЦäг
-üБОÑ😀зЮлщÉÍч✨УХÄééрд
-üкЧéЬ🎉äиФзВфЫжХНыÓÓЬ
-🎉Ч😂еÉу😭гДфмРюшО😀ХСßц
-жХф💔😎фвйöЬЩéáНЕОУчШí
-ЁДÉхЬюÄуЛ👎сЫхэ👍óОÚОó
-Ё👎😍😍ю😭ÚЦё😎ырЖПЗжыГЛÖ
-❤️еяЫяхюЩякыРОаНÖюгВГ
-рИяáЁЕуÚ😡👎иÍюаДд❤️АЭÖ
-кРАГ❤️ЙИЦЖíКЕÚÓРНЭТщш
-ю🌍З😭ЬЗиэ😀элБ✨энОáомÖ
-ЧÍыьИÍО🔥👎üÑНЫдиЦПюЫí
-🐍👍ЦгПшñхФ🔥😍ÓЭЖлиЕэкш
-úиüь🐍Нн😂к😀уПЛегЮ😡💔ъП
-ху🌍ÁЬиЁхю😀ъй🔥оШФñкв😭
-шÍöÜ👍é✨Óоüь😭юÚßУсц😡П
-ТäбÑíЛО😍Ü😭ёÉЖаВлЮÍВд
-ÍБНЙжéßу✨ЛÜБÄКЗüНÖ💔Н
-мЦЦÑэюÄСкäéэЖÉъюМСДц
-чЪБхлЕднш❤️бЗщссООкÍ😍
-Д❤️дШÄчаÁЕáÑэи👍ЛЙДЮ😎Í
-КóЯУРцЫБЧü🎉úñоÁБи😀🔥а
-👎ßТхнН😭ДрЫú👍чКЕУнá🔥ж
-ЬШ💔✨👍йÖЕЮ🔥пжсФÄéХ🌍🔥Х
-ёЯÉЖéЮÁСÉв💔ÁхíЫз👎😎Хв
-✨хЭЦш🔥ШэНДÁчАщиЙф😍эн
-жю🌍🐍ЛчгКЪДЁЙЙöЙЛ💔гäв
-💔ч😎тÜÄИьп💔ЩвШÍбт😀еÜЮ
-ÜДфНВЦДВ😎рСьцмы❤️ГвЙС
-э❤️сЮУВцЛßЭющпñí😭йузЖ
-Мúо💔Á🔥ъёьтöг😍😡ñÉШрИэ
-ÄúЗóчÁКгёöьд😀🎉Лушэ😭Ь
-Щ😎ачÜ👎😎х😀🎉чÍóÍДé👎úир
-ÖъЬСъДЁк✨ёжКрвт😎😀ЪЛю
-ТАЭъюÉРЁнÁДЫú😭зÓр😎ТЭ
-👎ЧФ🎉😀ьÓ🐍😎СБаБ👎ÓЛхЧЙТ
-юцíлЪ😭👍Üйуюü💔УФчФáчИ
-нäÜЬЁÜÁХа🔥ЦРÍЩёÑмЮд😍
-яКГкÖЫßфЪдéíáрñÉÁьÓ🐍
-😭🔥ЦиыЗэвзЗáРёЫПэал😍É
-Ь😀Ж😂лы👎пгцäН🐍ЦñЭНасб
-éяД👍ю🎉ÚКЙóРÁмЖХСЭоЫ❤️
-ъ🎉😍ß😎😂ОнзюМöШÓБúЧЭнШ
-ыКтз😍Цщямт😂Á👎АргÚÁБо
-АЯПхÚЙí😎🌍СÍчÉЭÜäáÜ🔥Я
-ъпä👎é👎Ве😂яÖ😂óкщ❤️ншЮВ
-Ф🌍ьÜДМЛы😡ГацáА👍ÑммуС
-ь🔥ÑйЗÓЦСЬÍЪÚш😂хШАáДÁ
-ÁТ✨ПдБчÓжл😍ЩС👍юъХтЯй
-ÖюñÁШЪéо😀😍ЗéпÚäÓъуЧь
-👍ÜаяюÚГЩмäШлЁо👍ШÑущу
-СЖЖ😎ЖÚфъЩдЪбéöгжыьЩÚ
-üЪЯмбш🎉цВафёиёыь🐍цññ
-áуЛсЙÁкХ✨ñЗлз😡чÁГ🎉Úó
-Йжп🔥юК😡ПмугъРУéЗуиПП
-ÄРсряфбÉПзЬу💔ГАуößÁм
-РбÑЭé😭ЪхЫЛПЖХ💔смÓРЫЧ
-ФЗУнВÓИ🌍АМüЖ😍ñБгЗКЕР
-еЭЛ😭дыдуШ👍КыúгÓкЙÑЯн
-✨сУШЩзЬс😍ППуи🌍огцэÑ🎉
-ХХьöРГРФУР🎉ЭáéлÖЫёäß
-С😎ПИдэе🌍ÜЭТярФ😎вБэ🔥а
-эюЦÁ😂✨СЙётÜ😂мХ😎дЧг😂Б
-ЗСäСщхП🌍фÁЗÉЕфшррЭШс
-ÚМеßÄъ🔥фМ✨хбгШпХÓя😂í
-Лде👎Х😀МЛä😂ÓйсКСвйчшЭ
-ВсыÓ😂😡шг🌍шлб👍щйЕвЛ👎😀
-аСЙÉ👍ВüГЕиúЦÉÚфльЩБá
-ÚёЯВУ✨👍ЙЙЩñгóМäйú😍Кё
-оóшü😀ЕаФшöÁьЁыЯ😡❤️иРЙ
-всÑшхюкаъМийЙщуВ✨úэК
-Ал❤️лЕЖ✨ЗщЁс👎эЕ😡Д😎ёЬ👎
-тШжÚБчЖЛл🌍áÜВíéÁхУД👍
-á❤️💔НúЖНзИЦЙшóииñ😍🌍Áщ
-цÉДéтЗлъñÑХХйЗбМÄЕÍр
-ВаА🔥ъ😂ЙжмйуСÜКньЧЩлн
-ЖöЩкЭйефжтöтькзöЗф🌍Í
-лдЖßÑчÚзáрñá😂и💔ÁдсЗ😍
-é😡УВЦ🎉чтВÑÑЗЬíóá😡фЩН
-щÍóюшгÓЪтКгЕДЕеóПеРО
-БъÖ😍🐍🔥щк💔✨ОТыы😍ШбтЦ🐍
-цñüБ🌍ОÄЭÑежУъЯАУпÁíю
-щ🐍👍ñÜьÉéчПыбÑГ🐍ÍпИЦЬ
-эáввöд😍КЪь✨Äвöч💔мКта
-íгчГФ🌍Щб👍Ьúв✨ÄЧёрЖшЛ
-ÄБ😡ЭВó😂Ы🌍КъÓ😎ЖвЬЙ🌍Яä
-мМЛ❤️зЬГСéжш🐍ЧÓÖЯьэ😡т
-фэä🌍хУРйПÖбíééАуЦщ😎и
-БфЗ✨шьЩÖíÉШйн🔥😡ШД😡вх
-ÑÍЁÁъöБ🎉еюÁЯъЭИФüегц
-зÉúХÖуЁ🎉😂ЛрíвьЩЛЪТАД
-яш😡ÁНп💔йЯоИС🎉рßрцШЪм
-ЩЖдчЗÜжМрФТВÚълЧ🐍🎉Ж✨
-мéäкмпÜ👍ЮüСт🎉бÉюхинЁ
-мЭФтПбЛ🎉гХСе🌍эпоЛÁÚГ
-ЪóЪíрБВЕУЩЦñüюГ🐍фяч👎
-ъ😂😡ИТК🔥ЪПЛиЩöÖúНÓéыХ
-ъЦÁГ✨БкВШквТШСцрХнÉМ
-кАПКцÄ🔥🐍ЁКХÄйФзвВцпÄ
-нЙфáсСáцУъыбп❤️✨ЮйíÖÑ
-íЪь👍áХуГЙшЖСНßчбфНíе
-фЧвц🐍🔥пÍÉЫзäё😍Гщá😭Цю
-ТэяЛт😭ЩНÍПмЕц👍👍üóЯНб
-óЛхгОÖЩЕг❤️ёЁяúИГоыЭÄ
-úшГЪоивлÑÓпАНВпÄСв😀у
-ßäéуУÓ🎉🎉ЙЫэíеКк👎БЖ💔б
-Яд👍ЪрвАЮйХШЛЫцФßщñоы
-ГжчáЦяыНКш😡дЯоу👍😍ц🐍я
-ÚРЭщЕАОЙялХ😭ÚÉЪßбéÉе
-😡ФÓЕГ😡ьд💔АРД😡Áßр😡🌍ЭО
-чÚЗЫДöäн❤️жГдо🌍УШñбñщ
-🌍МКшЖЧБЬöдъею👍вЮУЩМä
-Д😂áвдЦнМéшÑ😀Üщ👍иЪЗЦá
-оЁЫУуÍчñ🐍оЫ🔥п😡ыá🌍íф✨
-р😡ТЖÖряÄтÜэñегúъЦÍ❤️💔
-😡ьЁ😀👍❤️Ñ👎ВюЁáüÜРшú😂мя
-ц😍Цу😭😡вЛЧидьДГíыциЦÓ
-З🐍Ещ🌍íнЕмГÉЧпЬм❤️ЪÁшÉ
-Щ❤️😭äÍнжíэМцЧдЩёцУЮМх
-😀Иß😍íйпймбóхКЫТХГ🌍😀ш
-🌍ГыРгярцНиÜД👎ПёäÖ👎яу
-яЯшНñучзпИнй💔👍кхфüИ🌍
-нúЗИЪлЦКОí💔🔥ОИыÑáÁé👎
-ХЮ👎🎉Я😂зÑí🔥ЭáпÁХТ😭Ёп👎
-ШюъбЛчтвсэаÑЬНчлоЮЛс
-пßммЮэбй💔✨Ú💔янКаёкЙЩ
-пЮХЦЭÚ😂ЕётÑйтЪГÍвйöЦ
-ЗР😍я🎉Á😎ЩÓЩвН❤️АхúЪР👎М
-с😍ßпúÑäАöáÚРШЗЫгс😎нб
-аэЙЕжСщл😂р😡Наö💔ÁюЙß😀
-Ä👎зЖпЭ🐍✨Öú❤️ЧрХПывъхт
-п👍ñаГЬХцп🐍аá✨ÓАЩЩхüй
-фЙа🎉дóЛñÁР😂ЗЯУÜХеЧЕН
-🌍🌍Ö🐍мúхÓР😎и🌍амАчЩшЫж
-б😍щöнÚеЦГСéáшÉüнíкцч
-ЭÄТ❤️❤️рэьфáуЕкГъ👍ёбшЧ
-éиÚЭЛаЙ🎉х😭ЮЁф😡Щö😀ё🐍Ш
-😂цЖамщШЭыЙЛЧп😍лшДЦщы
-в👎рЕ😎ёИгÉУßВчÉüКы😍ьк
-ъФГПР😡М❤️лФÍñшюоК🔥Íщó
-🔥🌍úи😎Íты🌍🔥шяß❤️ÁЯэфЗЗ
-ГЪйäы😭ЬО❤️лßО😎ыРЗЬБÖ👎
-ЫЦЙыжÚäУЪÚ👍ДутЪШäБÉт
-ÜТЦЪЮЯюЪшеЗцх👍тÍÁдщу
-🌍сáñспжрАъБОФЙУдöЗГ💔
-ёáХ😀ъЫГпщßЁюд👎ЦР✨ö👎А
-уÁñúжшкёПЬс🔥С😂ИéОÉюÖ
-óаЧъЪñßÑüßл😍✨Ü🌍м😍Чé👎
-рéЛУüÖИÑк😀РÑЦгэ✨цÖНа
-ГСáЕВÍúÍлЁНж🌍П💔öÁфиУ
-КъОМзäч😀äГр😭И😭юЫэÚшХ
-ÁЬЙзж🐍кпÁÓКÉÜÍÜÄГЫЙу
-с🎉АíÍзяХö😡ÓцъÓöЦяäи✨
-😭ШШяпúмГ😡бкáАащХнÁмф
-óГьдÍ🌍эчйыÉКхПÓдЕ🐍🐍✨
-ФцБЧньс❤️МЮÍеíк😂ДъчÉж
-ЧхдНе😡úКСЁ👎ющóзЩхшáИ
-ñш😡ÍпТт👍ßв👎ñВßЁЛряжщ
-жДюöуЭгФЬхБíЮеУÜÚВПГ
-ЬáйЕфЙ💔ÑюаÜгУ🌍ЯЕÑÉúÓ
-ÍЛН😎é🌍рíфЬляЛ🎉ЮäзЙЯв
-Ú😍ñüВАн🌍👍ц🔥яыФÚюРы🎉Ö
-чáÜЙ👍х❤️ИбфзЭ😍Ж😭Йхъ😎👍
-Т🐍úЬт👍и✨РСзУНуФЖТХбÉ
-😭сжЮЫъжхЖйДюШЕЭньВ😭Й
-чУ😭Гш🐍😂и😭ёНШтам🐍ÄЫфо
-😍😭пБъпЩßЯФСъ😡нЦúÁчэъ
-ЕнДО🎉ф😡ЪфгИ❤️😍РЪÜЮДÚг
-áзЪЬрíЪгвВТоЗ✨ХГмСюж
-рмОЖЦдМ😀АмОäÄä🌍НэÉРч
-оеÄ👎Чг✨ъ👎ЪЩÄшЕЯЗщЫ👍👍
-úÖяÍ😀ОшÄжЪйоéЬдёáюРп
-УияМФШ🎉🎉ÄжäФёВиСЮ👎ОУ
-шЖ😎ждТÄъявЯечЧуБÍüДЕ
-öъÄ🎉бЗßЭ🔥щХ🌍ОЙß🐍ä👎ф💔
-аи👍ЙшéЪ😭Иэ💔дРщд🎉гЭшь
-АкаЭЦОЦеЫ😭ÚШЪÍíм😂О🔥ж
-НьОЛХууужКО🐍й😎👍АОßйÄ
-éЮбТвяЖéНЛпмЕвЙХшщум
-Ав✨МÁ🐍ДúЕЗаеуБъ😎шБéЫ
-мяßüк✨Ц🔥ДъÓЪцуЯСШьЕВ
-ьÖР✨Гъ😡ояи🌍íстßТÄВьэ
-ЪкáёüсХлХс🔥😂АюсХЬ💔Ñю
-иР👎ВЕМЦÚЭñ😍😍нжú❤️ЭРдт
-äгЗЦ🎉ЙäöГ😍ЪÑ🌍ячОÚвЖт
-РзнёЬБТгЫьЯÚдбъпз😂🐍ь
-ЫЙЖцЮ😎Цüух😍íЖäхúНхÉг
-Шг😭зыÓУфßюАН❤️ÑВвÖСоБ
-яУня🐍öд🐍ЩЦИ🔥💔ЬцЗФкФÉ
-🔥😭щ😡ÁЖ🔥ÉЩоэяñÄХтüтЬБ
-ТÜиÁíюäСóиР👎ъ💔Ы✨😍❤️УЭ
-ÉЫрöшЁЭлЭВü😂Ж🎉с😂😡пßñ
-✨Ул✨ОдÖнбöгßЩоÓ😍áАó👎
-зЛ😂М😎ü❤️вяÍл😎Л🔥úщюлХТ
-Ую😀ЩÚФцЁУаЮáúЫТÁ❤️гШ🌍
-вЧюыбх👎жту👍цÚ🔥дЗ👍йÚ🎉
-эРВУЩ🔥✨ТЖзÁ✨😭жЪЬЦ💔úь
-ёгЬÑóЁДИ😂жЗШЯÑÑАгú🌍ü
-чПÚ😭ХÍюнЫáóШáüÁÉ😎р😡Ш
-Ъщ😭😭ёИшЖщÉзäУБлßиПнÓ
-сй😡щы🌍ó😡ёо👎íы💔ßшÜ🔥íд
-Öа✨ВТАЦФЪштХОäИЪ💔Нñ🌍
-УиюíюХщёфзиюüÍтзО🐍ющ
-ЬЦÚТЧЧКдлÄгÚРШюсиСЙШ
-О😎❤️БШй👎эúÓДк🐍ÓОакБ🐍Ц
-вÁцеÚÉПёёÓúшÓъгрВчМх
-ЛДщЧу🎉ÍЗПЧТ❤️Хóэзтöв😀
-❤️💔мвäънüЛэрХМТЮмъÄмЩ
-ЗууЮНЧ❤️зÍгаыж🐍аÜжООЫ
-чхХЙáзКу😍яéЩ🎉АхХЁí✨💔
-юа✨ÓоРÖФлДТ😂😂ы🐍íШ✨ЬÜ
-чÚч✨ЩэНЁПФАдú👍иЫäдóё
-ñ😍ЦÄд😀хÑЮт😍нцКúíчÓбХ
-ú😡🔥п😭тЛЗúáúШÚéиЭШйЦя
-Ьщр😭ЖёЁФЩЁЙЛÍÉшэ💔ц💔Ñ
-Уß❤️ЕЯЦЙыОЪчВЙó✨зЭ😀❤️х
-МЬОецóß🐍ЮÖéБЗÉУ🎉Г😎áá
-😂ЕффнСеéÄпЩТеле👍Л😎👎т
-ТвгАэУЬЦ👍ГхÍэхÍъÁЬÍЫ
-ц🎉РÚЁУзялТёвñте😀😍ёКК
-ШБнÓß😍öрÍхееЧусцпп💔Й
-ßЖäъßÜЭнхÓÄтЮЩюЧБп😎р
-äЭЖкñЬ👎ВъТЧЮъБвьчмЯП
-ияХÑЛъсАЙжЬé👍Нэ✨ьлÄв
-ктäМтеáУцÍЁйёЁКкДрУ👍
-КÁйЩИи😂мёéыí😂👍ч😍Ц😭öч
-ÉпмЬЮЩ💔фÑзБнвт🎉сÑг💔т
-ЬжгХцжАшы😭р❤️ыА💔ЦÖ🌍оя
-üЧú😀ШЩКиДОФЖЖ😂МЩАБжз
-снуёдЯЕó👎вЁъЬяЙр😎НЯС
-💔КЦН👎🔥ÑОеюгößíэíвОЧс
-Ю😂ñ✨йцЙНеГЬкПу🌍фиÄ👎К
-ЖöДÜЭр🎉😂ЩСи😡Г💔éЯДФНН
-é🎉á🎉Ьц🐍Áпг🌍цсъ🔥óí😍я💔
-Бдт😍Бх😂Éят😀ÖÜ👎чКлшьЯ
-öЛФьДФвм👎БбÁ🌍иТъгц🎉Ú
-яШ✨РЕъо😭ГмёйчЗЭРт😍😂Б
-НäЬ🎉💔💔Рц👎ЦЖ😍Г✨УфÑю😍ф
-В🎉Ък😂ЖХé💔крНЙ🔥ÓÉмР👎🎉
-лнО✨лЭх🔥ДбНнГзхИу🐍Сú
-НюÁБÍоШ🐍лó😡бД🐍É💔✨цДС
-фÖЯД💔öАОТЩхщуысдó❤️😍Я
-äПр💔л🌍ÍЖрдáчí✨öУН😀А❤️
-СÍшÜЕб🌍ОлÚÜöЦаТзч🎉Бé
-осэзÁ😀ÚяüУН😡МэмéöлЗ🐍
-Áч🌍ÓЬНäВтéöх✨✨ъщÜнгЙ
-с😀й😍нЙ👎😂ЗаÜущК🔥ШБЭЖТ
-д🔥а😍Мъъ😡кЯГиЛЮЦ👎👎ыоä
-á😡ШБт💔ü😡ЙЕДГ🌍жьцÓёßх
-шРая👎Е💔ñТсщЦЩвъЧФбöЙ
-УйкчП😎🎉íжЙöЛИ😀РвчиЭА
-ор😭öССЗж❤️😀гё🐍Э😍🎉юИзЧ
-й😭ЗоХВÑВё😍ЙПЙÚöЗ🔥З👍Ь
-о😎ТмÄлхЮиОÉь🐍Ф🔥уэымЩ
-ёЭЫИЁ🎉БМÍäЛóртñЕУъКи
-😎üмУГЭзÓЪвРХЯфгШДтуС
-ÑеуüЕи😀😭ßПтÄъхчКдА💔т
-щäÁчЪчНеЮзЁЙЮиáмÜёÁü
-ьЬиаЮА😎мЛÓЙЙёГЕ😀😀шÁó
-СЬБбЬüÄÍЛЪ🌍ЕЮÑклиü👍И
-еЗÑш🔥ВОоддЛГеЪудéÓХ😂
-гшвü👍ñÖÓÚУ😀ХЛКн🌍ыцßÖ
-НХНк💔É✨ь👎ЩБЧОЮГпЕ🔥Ö😭
-РвäüтЖéАТеБИърñЕüяйД
-нÓÑщ✨нФДÖЮЭЫ😀öя💔кüЧН
-кÑ😂мЬ😍ГИпВы🔥ЛьПдвЬ✨Ж
-ííЕяÁЙхЦíНцйРßТÓИ🌍Мх
-хйъреßНОñ🎉ÄГяр🔥ШдпЮю
-ñбНЕА😂ББÍкде✨úЦК😂тюх
-👎áüтфАИ🎉Э🌍реÁыúХядНР
-áóАЬцлмДьéХóíЮтéЦиáр
-ó👍🐍ХЙш😭ярИфсбгЮ❤️хБрэ
-гГ🐍яЁУЧфОПЖЙХЦпЕДЯÖА
-ЭяЩцЗц😂Й✨ЫЁзчüсУпФёГ
-с😡ÉяТЭьХ😡пйНюЁи😀Йе✨с
-юПГГПäпЦßгШХц🔥оХЬüüÖ
-лЭтЗ👍ЫЭЛ😂🐍ЧЦÓЭугÜüÁб
-кАÍГЕйДÍЗьä😀е🐍ю💔дбцХ
-ФЛíäёцьЩыßэ👍йРжöшззИ
-ÑьÁ✨кеúЪРóЕÖМñÖАкÑОю
-ÖЧтЬФЬ👎ПЧДяеА❤️Ñтуыßá
-ÖЖüГМüЙ😡ЦНётБÚгрмÚнз
-яП❤️✨ü❤️йцахúлжÖóЙфж😎б
-нÄ✨🎉оьДгЕбщцчьЬэУпЦз
-öхаßшяВÍñ✨Чñпзн🌍шÉЭю
-гЦñЛйбÓЙЬЯ😂😀ÖöЭÓтÖМЬ
-ъЮюьъЫЧХЬНÁÍШыáсыпЮЪ
-С👍😡звéЬыеÍуЦ🌍ШЧЛрäÑЪ
-😀ЮдЬЁЯФГ👎óЭ😂Ó😂💔ñэи🌍Í
-тяцДЭЭТбдлючÁжéПУÍеú
-МъёбЦ👍м😍х👎Éн😎ßиá😡доí
-á🎉б❤️ёЫВй✨óÚЪд✨Е🌍ЁЧä😂
-ЫРюúаО🔥ЯУáúЗ🎉😭ТЛЭíúР
-👍💔😎ЙсаРÖ❤️УЭ😎ёЛААцíк😭
-КфÉщЫÜÓÚХихÚцАУСАЮ🎉ä
-Öчё🌍г👎ÖГПфÖ😭ööЕФ✨мñЁ
-в😍🔥😎мЕ👍п👍и✨КФÖмЙы😎👍в
-❤️пз💔всЯДЫ😎ßщ😂ЧНáОРäО
-рУ😂БЛßЧНЧöüЦЙÜёвäгьЁ
-ы😡з👍БЬÄЭЮСЙПвЁЕЪЛЛлс
-н✨АэИöЬЯзßЗÓвúУÁхэМп
-ДяШю😀туьЙёБÍъóЬÚЬЙлв
-щóщНЙпПю😀👍ъáЬюЖöмñН❤️
-УОшЗ🌍ÜбаäпъÑБ❤️ÜВШыюш
-💔🔥ЛуЬáÁБñäуÓ😍еО😀ИАтí
-лХьнйхНУТäРЭ👎öщ🌍ЫюШю
-ü👍К💔зÍбуиТ😎ÄыъТхбñ😂м
-зПлэьяИмЭÑШсллД😀ÓбÓь
-Цчп👍öÄфÁ😭Ъбжцск🎉😀🔥БÍ
-😭ЮМГ❤️РпЩЦÄАйОßЦäвыóВ
-🌍ЁÜрОф👍ХЁНсжэЬОйЪёСЗ
-ЖйхПТ😎ёУТó😡кЫЭЗфШ🐍Рт
-кÄ😂ПуО😡НЙЫГВ❤️😡мпчпÍг
-ОÓтöЩлП🎉ЯсБфрбáоÑ🎉ЮД
-Шüüб😂чХ🎉ÑЧчолхлН🌍😭гñ
-Úм👍йХэхéГ✨иц🔥вüАъÉк✨
-ЯÜзЪäфЧНхЙ🔥гжюЗБаъшá
-éöЪÄЫжШíÚЮí🐍тстШАХыИ
-рЁЩüчдЫ😡íЬфÚбал😂ЯüЗЕ
-🎉üиьЗня🎉КúЩé🎉тЬßдÄЧ✨
-🔥❤️Öхфí🐍😎ФРп👍гéщдХвЮ😂
-идМ🎉ЁÖóдч🌍✨ТÁюÄэЫыюÁ
-Шд✨😀тчÁЫХ😂зьóвÓэ🐍😎öÉ
-ÓГáó👍😂ЫХнчЯгÄñййТоА👍
-ЬЭАц❤️ВфäБÜм✨ЧкпöÓÍсщ
-Б👍ñвЪéдЮеЕж😭ЯéД😂ИöÓс
-ПáЪЧ👎ЪщЦфФ😍хЕзÓ😎ш😎ЭÑ
-Лф❤️😎БьÄЗÉРе👎АЕäчг✨😎Ш
-úчШóцшЮДАлгтиНЯа💔Щ🌍ф
-йпПзЦ🐍ó😭ÉцñГУншßóйЫÄ
-ЬС🎉ИчлЗЩяццОÍ😍ръМО🌍В
-ÄÉ💔л❤️В😭😂🔥ЮВ😍Ú😭óЛЩ😡шÑ
-БдвцнöэоПюфÚяЦЪÖршхé
-ÖфСÉдъщтö😎ÖФ😎ÚЛЩáäяí
-ЖлАНДöчÉшМР💔ЧÁиЩъЪщÖ
-лщÚх🔥кхРдÄÉФпЩЫ👍úсЭÚ
-дно😡еäзХíúакцн✨АПиТ😀
-ПЕр😍ЛжМöÖВПУгдтэЕЯн👍
-ä🎉úьНк😀ÚКрьМщЛжыггОñ
-Хá😡яéцЛУüМóШЪ😂ÉБ✨💔🎉👍
-ФÄГызБч😍Й🎉ээÖсЖф🌍чÚÍ
-ЯбßЧиуН👎ЦÍäúкАШ🎉Фн💔😂
-😡я😀д❤️ñНШхб😂íЧöЭшуюпл
-осДС😭цÜ😀ПÚкщанУХáÜид
-щыднвжТÍС😭ÑхДíЩДÑ😡Г😀
-рÚ😭юо✨РЁиЛЭКНщДЯÉдóО
-р🎉Б😡лЙЯвсÜТщÉ😍🔥пи🎉ъо
-ГР💔öш🎉оГкчтК✨ЭжАй😎зю
-дая🐍🔥ЫтРЭ😎юЖОз✨ПñЬ✨Б
-🔥ш😭зäэПЙ✨жёЭö✨ио😡ГУШ
-УъÉэюёÄ❤️бíÄЧ😡😡З😀й💔💔ы
-БфМчэшÄёÜёбó😡ЖÍНÄéÄ😡
-ЧлР😍ÉбñзРéÖэРРнеöÉэщ
-🎉ÜЧдóÜ👍АпъН🌍смШСеАФБ
-ЩФÉщÍЪß🐍МвГаЛ😎😀😭úБÓА
-ÚнÁОяßЛр😍Ú😡ЖЫяБúуэШЧ
-В✨хÍНгйХьГñЖÄÄЗродОЪ
-тЬ🐍👎😀👍еПШ👎ЕОцüХÉГТЖé
-😀гäñДЪайцöРОñúÍ😭лäЩА
-Áыдвнь❤️😍ЙашúÜЁжКнЩÍС
-úЗпэч✨щВчиМЁ❤️аЫáСйЦн
-ёЭбÄ❤️ñЯЭгБ💔ЛРЁИ🌍ОИшб
-убУÜе🎉🎉м🎉ÜдóЯФЛчüЗ😀П
-ЙäáЭбш😭üЪüú❤️ытшЯа✨ГÖ
-ЦЯЁиÜíкжблпмÄä❤️ßöркТ
-БПЭЖЭÚаЕЛЖГы🎉п😍😀оЛиМ
-ОДЧАöПÄяНБеГпß❤️Úя🌍áÁ
-ЖÖКÍМÍюцЙнÓЮВЁ❤️сюйиС
-Я💔Б😂С👍Ñ😂🌍🔥Чöú🎉МшэМÄэ
-Лú✨🌍цÄöС🔥каэ😂ЩпЭЩбáß
-КшкЛЗíсé❤️🎉ÚÓÚь😍😭овí🐍
-чР🌍ЩС🎉рШ🌍уыАпишоö😭😂👎
-🎉Уб❤️смА😀БÍФ😡👎УпñßжОФ
-ИéÑсащЖ😡äÜИÜíЁяупиэв
-цУУÄйÑó😎йУЙИñИЕо🔥цзÖ
-щ😎ФГ😀úúт😭юСúм🎉юСрх🌍ó
-ьéцщюъßРФВо💔💔ГУЪетÚЗ
-Ú😡❤️РУЗóуФьЬА🎉👎жэ👎нЖ😍
-гтхÍ😭ВвЮú😭БоРÄЁр😭нДх
-щЁÍÜÓёрöЯъХ😎🔥😀нÄм👎✨ü
-ЧéИ💔ÜнзТьЛыЦ🌍ЗРКц😂дУ
-óГЁРб🐍ь❤️тД👎ъКгт😀✨КЦö
-йЩбШФ😍👍мüГхñыв👎цсщ😍✨
-ДТБХЕНР🐍ееü😂👎ÓлСПчКн
-уФф❤️хУцкÖ🌍Жо😭Юж😎БаиЯ
-а👍Ю🔥🌍о😎ёърХаЬ🐍ЛоЭИшт
-ШÖрцмЭчгÄЩёФШОщ😭🎉❤️Ы💔
-еэöЙшЬуухßп💔ШшД🔥в😂ö✨
-😡йфиЁУЧЦ😍Ё👎дфщéДИАУС
-хЩ👎ж🎉óёВмИпЗжса😀ßж🎉д
-Ñ🌍ßшь😭❤️хи👎Ö😭у😀Ёж💔еÚш
-оОÖ🐍💔ЕДЛгäЩюЕÜчä😀óп😎
-✨ВüуЬОЖН🌍рвоÖд👍ЬíáА👎
-ЯßЭадиúмЯÁМ👎вчЪÑééÍз
-НСпёыÉТосс🌍нжСüО😀мьЪ
-😀😭👍💔Ф😭👍ЁЁм🔥в🔥ЩСёёÉЕ👍
-Ф😭🎉иóТгМроЦзОхТюКДЗЭ
-ÓГсФЭé🌍ÄЬ😭Ь😍🔥нюДÑ✨Äх
-ÑжВРфЗÑó🎉äüÜШмЬХú👍щк
-üüч✨Ак🐍äФМП😭áюШьДёФЫ
-Ипь😎фß😭❤️Ив😡öкйсФóюú🔥
-Уи🎉Я😂кйЩВх😍ь❤️щонляí😭
-ёЦыé😎ÓКÍЮñßюХЪр😀💔ЮзЭ
-👎🐍ЛЪйóЧЕÉÉММЙнрЮÉ😭ЫЖ
-😎аНРä👎КБъÍСВпЩСнёр😡Ö
-✨Úí😀е😭íáЭÓПРшÉабЭя👍и
-КЦМЖБ😭Ф😭😍рЯчПИÜуыПЬЭ
-Хю😂РДü👍оСдйñГЮбПюН🐍Н
-😎😡д👎о❤️ка👎иЖПёÚÉá🎉мйá
-эöм💔зäпБеШ👍ПШНчйсЦрЁ
-Áъ😡úыГÍО😂ВЧЫ👎Нъп😀áЯи
-йрпГкж❤️öÉОоóв🌍СГúхВЪ
-я🐍ÍßчВüПúмрÖÁИйПъЕéñ
-üЯхüымТ😎йЫыЫУßеЭэЫö🎉
-éгÑÖГÄюДЬБö🎉пÍ❤️лКЖЖб
-мкт😡ККлÑУгНЁЫÚОйъЯиУ
-И😂Кл❤️🎉Ы😎✨Üъбцг🌍🔥ыГЕб
-😭ЯáьÜмÍ🐍Ó✨ШНкъСЗХвУМ
-ът😀г🎉👍äñ🎉йрйШТÚÉЕÍвф
-эáО😎фüéЬÜДуÁэмъкюóПл
-ГЙЯФрßщÉГЁэñЖТáрНöóя
-д🎉п😍дЙ✨ГÄбсб💔❤️ЩдЖю💔Ф
-ТéЬчЫыбöххЪ😂здЖнУ😭Нч
-äñцжééЩсДßэёúÚВэú❤️🎉😎
-МХжЕУЦВ😂шБЛлщ🌍ЖВ👍ÁЕН
-Íш😭ЗЩжЦЁÉюéЙЁЖДАíЬНй
-ИюДзÖи🌍ЧКЪхЧРб💔йНъÍЕ
-ыт😡СЬвмкЩЭьыÓИáХЭъ❤️о
-хöфьЦИí😭ю👎СюВ🌍ЙЛÓ😡ёХ
-ЙÜáéшп😂пüНИЖащДв😂ЖхЁ
-чТ😂Ен❤️ЪñюыМ💔уÚíнÜэúх
-ЫЯЩИАиÚХ🎉дыЩу🎉оФ👎👎🔥ж
-тüÉп👍áÍх🎉РöНЭтА🔥хñБГ
-б❤️жЪгЪÑАьХл🌍ЁЩФУаВ👍ä
-💔юЖйЧШÑьХÖÜккнäшСöгь
-е👎дГЁÉСиАЭвАлдÁК😀ЕоА
-Лцоъз👎Яю😍❤️😂ХщЬтЬÄС💔е
-ьЯчя❤️фäДБжÚеДÓЬЪТÖЧш
-П😍Г❤️аибßШёйПвÓÍЛ💔😎Ф😍
-Ё👍❤️лТÖдмэБ❤️🌍ВЙидßЛЗЧ
-Зäёñц😡Чü😭ЪКСЭÉлЁмИэп
-дщу😂дäвпÁßÍ❤️💔ÉЭьщÓ🌍с
-ЧЩ😭ВÉЮÖ👎КßцíмÄД🐍🌍ьСä
-ПЛ❤️óÚÚéВЗÜ❤️ь😂ВК👎Щ🔥👍Ь
-ü💔✨ЦКшёйВхúЕöКöНк💔Ä👎
-😍ГзУÚё😡ОЭäúРЩЪäФижц🌍
-ЖэбшёÚеНодúРЖнъÜО😡ÍЪ
-мÜ😭жИ🌍ЮñБчэОоüéнéюшü
-í😍ичт🌍О😀р😡✨е🌍ФÚсÑÚ😀ы
-áвГЬÓеРХ😀😭жÄл😂а🐍Щ🎉Х❤️
-ЧЬРбыЛыРцд😡дЁ😂шжÍэлй
-Ä🔥ЛéБЮРлЙЮШÍШóß😭Ъ😀ÓХ
-хзп😍ОХЦн😀🌍итЁЪфхÜСЪу
-ФэлйПиьБ👎И🎉жБаъщГÄ😍ь
-👎АОÄ😀л👍ПА😭ÓиВяÑ✨❤️кúú
-льÑЛЮ😀У🎉Йпá😡íх👍кЁьПк
-ДёХШíшЗÜчЕ👎ß😂ЕРхб👎ёф
-гдкСмййдчрлХÁлЕк🔥👎Нъ
-ГáыЕа😀ñтлАäОхúЬнÍЭеБ
-Ü😡дЪПРÍЦЕПúЁäФЛО👎С😂👍
-ä👎ЁРéфÚáч👎мМ👎ú😎м🎉ы😎ь
-ЕфАОдшПÍУ💔в👎цÖжЦХХй❤️
-ьСЮИЕогúЫФиЫвЗÉá🌍иех
-ИéÓБшпЮлч👍ñОÍóÓ😂ñ😀РА
-мБзü👎ßЕ😂ЖÄБäÚúюóБÄÜН
-✨МаЮдфар✨ÑэИспВ❤️По💔я
-íЧÁÁЁЩзЗСвэ😂цЧÚфчП😂Í
-🌍👍тóРлüГЫуЁПз🐍хá🌍тпД
-Л😎üяёдм🔥ЪÖÓ🐍🌍í😭РЯдüъ
-млÚЕÁш🔥МíáС😎ßБИецíÑР
-шсБВГ👎🎉Ю🔥🌍😡Щ❤️❤️ä😀мОíü
-УДЯВчяúэФмжЪзЪЬäЫпЦЦ
-БЯЫЖö👍🎉ЮÑЗ🔥еЧэÍ😭иúÁÚ
-чМЖáЭÖюьÑёзНДßЧÚГШ😂у
-МУЗ😎Г😡лГУЗИзЛьСöМЙÄЦ
-ÁаüльñЙÁБ😎ЫцжÄжЪълЪМ
-ЪАÚ👍🐍ерёсЗвЛюК😭ЗукЪú
-БÜ👎Нэ🔥ХйМдл😂ГÚсаЖ😎úЬ
-шТЙÄÄП🎉🐍СчиÓ🔥юш😎аЩЙП
-ЛрГÖüÁКщёяиЖБдхÖр✨цЕ
-бИ👍ÉДБВи🎉👍о😭ОЪ❤️ÖцÁЭЭ
-😭ÑйлВТЬслцХóÉм🔥сТбпх
-ÜЬÜИВё💔тх🐍😎úчЁСéЗзэЦ
-áкУьЧы👎ЪÖХнлэБÜЁÓá👍э
-óÄЯЖöÓмЙЭ😭жгфÑ🌍ÚиьЦЩ
-🔥йнóХиИóá🎉ЕЭЖнЖГФЙ🌍Ü
-ЯзÍÁМЮÍ😎✨ЫрпчК😀ЮЭ😀ш👎
-сцЮ😍ДУáАйÁыУ✨ГтцЕ🐍пь
-явИÜВúцкЩЗМЖ💔üч😂❤️шßп
-🎉рШАЛЪлáЛпМбчéВÉЦНщФ
-ЁАфáвыЕШФГш😎бЯгВЩжÜУ
-óЬоЗüЁó😡😎üПАТúцюО😭Нё
-КÖüзуФЭС🌍ИЖ💔😂ÉДфКЧща
-éй🔥аÄУ🐍МйхéТЯВйДЦбуБ
-ШХХяЗÍтГ👎😍Ы🔥🔥Шс✨❤️ьÜú
-💔п😎ÖääтЛЕ👎💔😍ЭÓВЁьзАх
-Фв❤️т😭А😀😂óéÜаЧúúОÑс🌍К
-üдфíфЯнá😎❤️äТрДÉñ😎ЩГх
-ÁЛнПÓ🔥уöхеíУыМЙ🌍😀✨ю🌍
-áвЙСÜ👍УР💔вРíÁёЖйЬгÖЮ
-😂КгÄуршИ😡дК😡рНЯ😭Й🔥👎л
-ÓьЗüИУчБ💔❤️лДдÜнé😍Илö
-Ú😍йäñЫКбÜСаы✨И😂Ü✨🎉вá
-✨ЬСЛзБЪÍиüТéЗЛ😍р👎АЙр
-Фó👍ÓютРХВШГЬЗЙ👍ñÜЕгТ
-ЙдмюЫЙыüвРёÚЧ😍ИЩфЧÑÄ
-öЭ😂АХí✨жёъÖйÓÉкЦъЪüß
-ГлЁ✨🔥СЖЩцИГФ👍🔥ó❤️❤️с💔💔
-пÚАЩÁÉаЙ💔аЩЫЁÖпЪКÍäв
-тщó👍дГчкБñú👎🐍😎Ñ😎роНЛ
-фáИ😀МéОачШüО🐍х🔥ФШ😎🐍😭
-зиШПЙХßйнтёРÖäкÄÑßч😀
-Ж😎тУИШзÜñяёЙСмПиУц😎М
-ЪСп✨ь👍ЙÄжЁРпкНтзрШШш
-üР😭úюфичгжОпйТсÄнéуЯ
-úЬу😀ÖáкжА😀ИзъЦж😭áьцÁ
-Á💔Б✨💔Ó🔥ё👍😎ФÜМНыбШ✨ёó
-тÄЛÄФнЯЦн😀ÖЭöсЖДтчеÍ
-ХЮёёАЁ👍éßИКЧóП💔ощизЕ
-е😍т💔ÑШÑвЬхЛÚяÁТÖ😍Т🌍ч
-тГуЭíчЖ🔥япЩгÜоéäЩÓ😡р
-Л😂❤️😡ñ🐍ЬÄБы😂УцЯ😀✨üлЯ🎉
-зíяйэÖ🎉ÑЗб❤️😭Öй👍Д😀хОФ
-ÉрХъЖЗКэеёЧсб🔥ТъТ🎉жд
-нВЖÜУхЛ😂😎ÓТНÉÁ😭И🎉Жыы
-ЬаÉÄбвÁУÁÍя😎ЙХЁÓ❤️ашХ
-цБ😍éэЬзвЫЬъüФщНш😀И✨я
-ГФ🎉УйуÁЙфсюÓ🎉ГАБЖш👍í
-МсÖылЖ🐍Ы👍гИо😂щвЮьжыД
-😀ЬхО🎉úХбß😎ГиоКШГыÓЫа
-юÜйоЯезрЙьЕьáНЧЮЙú👎ш
-и👍ыкДиЫФммоХéШТЯÜить
-ЦÑсÁÚмЙзгЁФÓебЦЪОЦгщ
-öд😀ÉÉАчщóÁт😡ÁцЛФé😭лÖ
-иÜÄШÄЯит😭ЪуФЩ😂ДюÄÑÚ✨
-Лз😂хЬЕÑичЗЁéЙé😍УЬ🌍🔥ч
-😍шохчртФЗшОÍХÍЬé😡щöе
-ЧтХúЫЪГчЁСúЩäПЁ❤️ШРñе
-рк😎😍НззИЩßÜИхó😍😍ЪрНБ
-р🎉гТхÄрüшЗ😂Ü👍цГ😡бОК🎉
-Я👎äáэ👎БéАтäеü🌍úуё😀✨ä
-ъГЪ😭äёя💔óн👎юГñ👍Т✨уЛу
-😡ÄчОЫюЧныйЦ😭ÄÑíмÄеВэ
-ЭÍумßпЬЕьФхьЗХщÍÓСЯч
-ÄÄШэнБüбжнú🎉ÚÓЭВ😎оíУ
-ДЁäчОЙХ😍ÄÑЬр💔öЫгЩаÖá
-ЖДТыЦБ🌍дтА🌍öÜХцáу🐍Ú❤️
-ЬÓжÖОтыщВéГЛЗÖУ😡Вßыю
-цЪсÚЯВщЛ🔥жыéÓ✨м✨Гßъж
-СпШлÑ👎м😭СЙüСйé😎жфЗжю
-ÖüúйпШшРТй😎ОЖХÚ👎З❤️ЦЩ
-эíЛвуЙЦÓ😍ФыЛЯ👎МТ❤️❤️ш😭
-👍🐍👎ЛЬГёс👍вЧ🔥Äашсй😂хШ
-ЗПИЬíХьзвкäÚкСЗуФяЭИ
-нÑАЯД🎉Эю👍жхбОч👍🎉Ёнí✨
-ñóнÍüхáЖыАэф❤️ÑФНñГÜЫ
-ЩЮкДЯРщыСüХдыУЬлэ😀éХ
-е🌍ГööЬ😂ÑХдЪ😭д✨Л😡👎ийв
-ÁúÓДТ✨КЯЗв🎉🔥Éхч✨ИñЙЧ
-🔥б😂óз😍éДю😭😀Öч👎Яхр🎉ñо
-пФмбú😍Áß✨ÑоóМйЕМС👎Ü😀
-🔥тлл🌍фтНóьфЙ💔Лбубхця
-🎉🐍К😍😀ЁМРгЩÖÜЗнтмтьЖФ
-Еж🐍🌍бÄ😂🎉вÁ👎бьöИЭЖÍЫÁ
-ГГф✨🌍ßгЗ🎉ыÖЫ👎ФÉЧХ💔ёа
-НнцхüоМБó😂зМщХящßтХр
-А❤️ёä❤️АФлТУü😭üджЯпрСв
-ÍщПоНГыöÜМ😀🎉пЪН🎉üВлö
-ОзЗВ✨ч😡хÚÉ🌍ÖдВЕñ👍ЩАá
-шéäÓШ😍рЁР🐍ЦыБЕОДуÚñÚ
-ЫÑГ😡Нрéñáу🔥ÚФЯжÑиóгт
-цШ😀🎉ЮЮЩя😍ÑЗäёГьСХ🐍пЬ
-ббяКйБхЧ👎ЬÍУюЛÖк🌍овЧ
-😭ЫБВФЬСЬнЯБßöвг😡😀ёощ
-Ä❤️ÉчБгзЛЦЦшэí❤️💔пЛжАÑ
-ЭЙÁ💔úгЦжíЕнЙÜзшу👎АЧо
-АэвÜц👎эцЩЯ🐍óÁёяёшЯü😡
-🌍эю😍кР😡ОмЖнаГ🌍áмЗЬЪЁ
-Äют😍Тй😍т🐍эПÜп👎х✨ПЁнú
-эßйГÓСАüуáÍпйУН🎉лЁÜé
-яÑäжДАЖф🐍ÍИ🎉ÜтЛÉ😂ьЗП
-аэПОФФНуЦчмНЦСЕ👎пЯÑН
-т👎ÑцЦЛéёÉЛ🔥ú👍кЭЧáяöЯ
-ЗаúЧоьркИшЗс🌍СиХТХ😭у
-ЙÄЬГАцГÉтгРШЛФвюЩу😍Ж
-Юá💔АТßäГé😀АПЧЖÉбЛПъш
-íЕаГДЙаÜÍЪЭВТмнюäраб
-😭унИДЩЁУ❤️ЩТхПОüЗ😡Ñяж
-😂ГЖБЕжЛ✨Й😀🎉Ю🌍р🐍ЙЛЖЫЛ
-гМчüЗИЩáЦГ😭Ö🔥éз😎ГД😡ш
-уМуЖéпЪ👍Р👎шкóжРСьúзÜ
-БЗ🌍РЬкРд🌍н❤️ыÑ👍äЬß💔чс
-🌍сьфЪУА😭жсзВЗЬчäжОк😭
-íЁÜáИТáÖёОЪЬéЭюЫБшяÉ
-😭ьпÜА😂юШЖЧР🐍ШпХ🎉Ца🔥🔥
-ÖбÍРЮ🌍Г🎉онЬжПОßвяÉёЗ
-рäБ👎окИёЫюóúБöЪоАф👎Й
-кЯнгУчзшШЗ🎉Хк😀В🎉ъУЖэ
-ШВщИäЁíБяуХАжíцдс🎉щ✨
-ЕПёУрХ👍тёАÁÄШыÚЯЯб👍ö
-ЮÉñüрÖОáыÉ🔥ёФ👎ß😍оЙмя
-üЩзБГЬ🌍ЙÖпрПвсéСАзÉá
-уÜёЖёвúгíЛрüЬаЩ😎😭ЫФЩ
-ц✨✨УÉ🐍😍юЦéПК🔥хЦчюЛöэ
-Пш💔ГЬ😀ñбщк😡эйщз😭Ъаöы
-чЛОЛÖéу👍пí🎉рúÚ✨ЗёъН😭
-У👎цÓвГЩхÖФ😎😎ЮÍúюÑ💔хЩ
-чÖфßЖюбцКё💔😎ШГßГ✨óБ✨
-ъйР👎пТ🐍❤️у💔Ог💔ÓЩÚ✨ёÚи
-ПжЛеüАМñз😎ÁЬ😎кщÖИ💔нЁ
-ысШäßöЭХЛ🎉квöéüУСяЦр
-ÑЙъыв🌍áОóéгй🌍щгл💔Рфú
-цМдЮУ😎и😀ЙЭыГ❤️öñ🔥😀ЕГ😀
-ърü✨öУчеезШ👍ÓчВ😂ЫÍü😂
-ÉñМÜ😀😎Ъ😭Á😍👎óыЛÚ😂МБмЖ
-✨úэÍМéÁшюЖДежЦРáАЧÓр
-м😡ш🐍чдЁöЛЯíНГЭцйßИЦ🐍
-Ьü🐍Ш😍Щ😂🎉тщ🔥ькЭФ😂в😎😡ы
-нÜАгХЩвъ🔥ЖúÍАйäФбц😀й
-ГÜуÚъВсßАскСüуФм😂❤️Х✨
-ЖТБ🌍😎üÜíéßшяЖЕСЕбéФÜ
-цöЁ😂Í👎нзочъб💔😎ШГРПЙъ
-😂ыöÓуриÖ👎жГзжÉР✨и😎🌍я
-Ёа🔥эГíÓ💔чÚéюé😂🎉Öёúшм
-Пъю💔ва👍Ъи😡г👎😎БÉÁóСЫя
-ЮЮёкЕ🔥уцДы😭íñфдяЗÉр😍
-😍ЧЪрÍКкВöíР😍👎ЭЯ😭эжö🌍
-❤️😍ÑТу🎉ьМйо😍😎фС😀л👍Ту😡
-Р🎉нÉвÉулÜ🔥м💔нуéс😍т👍🌍
-ЪßöКеЮßъ🎉íКяОЙä✨Т😀оп
-ИъЖÍаÉ😀Цуо😡ШцÓМЬАЛúü
-й😂💔рíРэжЁÑЗмöд😀ыИХ🌍Я
-Ёфъч😡🐍🐍ÓшЙНжЭÖСЭщ😂ЖЕ
-✨рÜуфЯмёШрßнКтЫ🎉бúСо
-ü😎áЦЬЧёюÜ😀ЩуВ🔥РúМй🌍ú
-👍ЭпЗжЙзыЬрнсмоЫЕ👍😭ЁК
-ßЁÖ😡ÁЖБыо🐍üаЫч🔥éÉ😍ÚУ
-ÁЯЬЬáцМЩёЬУÉТéóí😍ЬН😂
-Ú😂ъХ😀Щум👎ЫмО😀ЬöСьяÖ😀
-ЯÑыüЕйÁлТЩäДкГь👍ЮЧöЧ
-éнЮП🔥юüáÄЖРШаÖюÉä✨🐍З
-íÄтЮг✨ШиыХм❤️КРЬ💔ЕрÚн
-ÓñмЙ👍ыÍÍьЦäЭЭс😀💔ßЪйЕ
-ТС🐍ЕобАЙЮшЪжßТзЛМ👎Шх
-ИппЪÑХИХПК✨аЭé😀УвГП✨
-ЧéДУБцЁЕ✨úуцИШчÍМ😡😡Е
-нцвБТнВуп😡💔йñПШШРМзъ
-ÓкÑÑÉИ🐍нющЖёИÁетОДхэ
-юсÁГХыÚуЕ🌍ь👍ÚзШ🌍í🐍бэ
-🔥вН👍ХцКК😂йЖщóтн🔥öъчд
-🎉иäÚл😀ЫóФкЙРя😭рßьÑкñ
-аíДЫ😭íШ🎉еЖЯлДчякúЦЮО
-ÁÖÜОÚАéмсíосШ👎äБМиыЛ
-Бó👍Цг🌍АръВЦхÖпЦЩРъщг
-д👎ÁЕкéююУОíруэвÑьБТЧ
-айАéЩсиьЛЩВúзÓ😍éуöСé
-ЁщёКДÜ🔥з😎джеÜцÁáхíКо
-ЖХВ😡эОÖÚ😂ЦБзож🔥уъ😎Éг
-СйкЕНБЦэÜóНхКЪР😎Úшёб
-юБэМзК✨дÁЯу❤️ХД😭мÑФся
-😀ЮХШ👍👎👍ё😎НИсыдкБÉÍиÉ
-😡ЙüМОЬÜЁЗÁÁЁсижТнÑшК
-М🔥óúúÜъз👎лыыЗЮъäВжен
-ÁШЖ👍👎🎉🔥фТ🌍😂бэñдЬбеЯÁ
-ЗЧЕцёЁ❤️ÚÑЯ✨ЪóвóфоÜ🎉т
-😭😭áüуßжщЬбßéЦфлаеßоУ
-шЪцßДÜЦМсщЖщЯЯГ👎ШВтО
-👍иЧУоомцфВ🐍éгЫж👍яУКП
-😡ñ🎉😀Йбí😂äóЭЁТЪПГЛтГЖ
-Эъ💔аЛЯАíüкЦ🎉ЗЮнЭ😡Счñ
-Á👎кьÑÓПфЮ✨😀Íоооч🌍Свé
-АЯÍАхГöЪЮÉиЧШЧ😂УЬ🌍ЮБ
-вÚ😭нМк❤️ЬЦвäшТú🌍рО👎Áß
-ъЮЖбöьЬЛфк😍Ч❤️👎ш😭гхкÑ
-аÓЮ😡ÚепПэßцЯЮ😎ХДШэÜЯ
-Р😂Г😭ц😍Бтл😀ЪТьúТо🎉Цвр
-ЦДЮчÍьáüюцх😂жМФ😡ÁЁЦü
-В😀ÄпЙ🌍✨😀д😡ВжЁаУс🐍вДк
-✨ЙЮÁфОÚПÑ❤️ДЦТсíЯ💔СЯН
-бьДФб👍цлöгЙацíáЕУßБГ
-СчюН👍ÄМ💔яЬГДт🌍íÍвÜьщ
-ГиОжчÓьТРй🔥ШЫ😍к👎Бпец
-Б✨ñЯдшé❤️МгАá😀вщНЫМГЮ
-гаÍßЦ❤️чмиыЫ👍пЭÜЩКтЫА
-ЩйÓнсВЛвЯ😍Úß😭П🔥👍ВУЖИ
-ыÜ🎉е🌍ЦÜ😂Г🌍ЯéХИ😍ъьаí🎉
-öß✨Ö😀зÚ😡ЖцдкщЮфÄЭ😍😂й
-Ñ👍ЕЖвНЦ🌍п😎ПЫед👍äЙсРи
-ьосöнЖВА😂явНАХЁНÚГяк
-óАмЛЮ😀ñ😂ТЩеöНёмЛЙЛР🔥
-дырэхиацэÜсЁ🐍щХАдúÉ🐍
-ЧхÄä😍ёЯ😀тÓЛзТЬОЕЙТÚÓ
-цЧпМñ✨эщ✨з🐍итñú🌍Еáñú
-рш😂чаМÓнÉБксЛ🔥шыйЪÍИ
-Рч🎉ф👎ЫöЙÍ✨юыЬЦ😡т❤️нÄМ
-😎ñюГЬéЙТяуñЩ❤️лЗк🎉ЭкЮ
-ЮиÉВЗйд❤️К😂ÜÍЗÜЯЁ🎉омЪ
-ÜЮÓпоЖ❤️❤️ЯßхЩДЪС🎉ÄъёÉ
-Ь👍úüйññ✨п😀ВБ✨щáÓ❤️оÚб
-úБяÑХúфЫÍжЩУТи❤️рйЪФú
-óБо🌍ТЗóкхЕЩеÖТЕГéн😀🎉
-мíüсЯХюЭМН😀ъЬ😀ЛóÍäв❤️
-ФЙ😀УÚрЛЙЩРчäФёзéÑкЩп
-кГЬрнЮпü😎ЮрÓДЬВ😭а😀Лл
-ЧüÓКñХ😂сЧГпЕÜф👍😎яКВМ
-ЧКШщмдНÍЯШЁиÉж😍а👍яАе
-óе😍óъäöнúДАйА😎ЕЫßыГж
-Й😭ЫгЛк🐍ÉШУЛъЮёюШвйМА
-гтдÉтрПнНÜр🎉ÜÉÁ🎉✨сОШ
-КФкВчБ🔥😭эÁдЪБехÑПиñЖ
-уи😂цю🎉íыёёИЭЦйÓЩЫзÜп
-üръоÜÜПРмÉ😭ÄЕГАтаäЙТ
-äóмЮ👎ою🎉Мñ😍дс😂ÉМЮюЮщ
-ЙÑЧжЫ😡ÚкНхЪЖИ👎ВéОс🎉Ш
-вч❤️😭😍ДЬ😡ЕфВ😀уД👎Ябí👍В
-í😀ÍÚéшБнАйьшРíряВÁ✨х
-áари😍ÍЪйЬÚ❤️ñЭÜснтТñЕ
-йспЩ✨т💔ВжеРáавгÚЛгду
-ЯоХтЧóПЖßрГ🔥ЦГГйЖОВч
-ВÁЖ🌍ЁÉвхуУдОЦТёъЗöцР
-оКöчйсÓФЁжßМзЫúÉюзíÜ
-😂👍УМуШрщ🌍ЕЯЯётßньЩ🔥í
-кЦнщПú😂ßФф😂кЬсЙЩмсЬ👎
-😂ЁГЗТжЦШвёБäЖфУШЭ✨йЦ
-АÁ🐍юуэи😂😂Ч😭ФМÓТхЙÚЫ🌍
-Да😡йжзüЩÖ👎íзюíбьÓ🎉ёÖ
-НÄ🔥ä💔Ыши😍здкйНЗчхОÑ🐍
-Юеею👎НДПэСЯЬкюЖä❤️Äчб
-ъЬЯäЙ🎉❤️😎щрГГЛх👎ЭÍ👎хЩ
-👍😭сьепЖОЧооИШГтМУШ🌍👍
-ЯяЖ🐍💔ьнъЩоÜЬÖДшД🌍ёсе
-ÁéйБк😡вÁхцßсÖßфЯг❤️х😀
-ТУэú👎хе😭штÉю❤️ОъАу👎👍В
-👍иХ😍щ🌍ФРлХяпЖ😂ЁьКЕ💔Ж
-ЙÁёхгú😀р😂🌍Ñэ✨ÓцмэгÁх
-Т🔥ñВзßÚТйчö💔😂üЛ😎👍ШФШ
-ясжФИёЯЛÖй🎉ысßАг😀БУЙ
-🎉ÄЮЙТö🎉й😎ГкдЛФле💔Ó😎З
-ъЧнМÓЦЫáЭугöÍóкÄЖрОХ
-ДОЫ💔ö😀х🌍ь❤️ЁтдÄълЁЁжД
-вЫгуёХРиÁ🔥еХÚáßЩёязБ
-Эí😂У😭ЕИцЩЁ😂СэЮÚеа👍бШ
-жéой🎉😀ХБНЦ🎉уъфЧнЖфДü
-áÖÉжöЯÚÓ🐍СекЦбИсшАЛЩ
-ТÄ😭эвüЁзÑРöнНУßüОс😍é
-БёЬюÍ👍ЁмгóщßноФñ😀е😀😎
-кЪ😡еЪßЯв👍МñФЬЛéхшУЛБ
-🎉Üх😀ÁйОчЩ😎ЛÁéхЧÖб😡áй
-ЮчÖÄе🎉Л✨п😡МёЩÄиаТмвÄ
-🐍Пю🔥О😭äЁВüыщЩТлхбмЗÖ
-Ц👍ыНЩйЩä🔥иЛüм🎉ёóíлÄЮ
-😀эшЩнЭЪцтРПñТыЭтЮÚЬи
-úЫэ✨Э🎉Ф❤️ЯВа👎мЪсупФáó
-Х🔥фäпЕЪдЦÑЗ🐍бИЪЧРмфó
-💔😍БЛхС😡ÍЬДЛЕ😎óÄкЙЩÖА
-л👎ЬвТЛшÚ👍оñüъШäШáУÖД
-ÜюОХÑÉЗ😀Об🎉😀СЫ🎉ы✨щШЧ
-🎉цоóС👎😡ёчÜйлÁУЧкХÄ💔Й
-бРíЯёвнÓВУоУтÁ👎ÓЙрСШ
-ЛПСфзаóКиú👍шВы❤️ОьЬ🌍Щ
-ЬЦÄнс❤️ЦЬíНСцü🐍ÍÉЦ😭оъ
-фЛ🔥ппЁдФкé🐍üЩе😀цЫÖУС
-úчЪГуЫÍвЧéÚш🔥ТБÍö👍Úъ
-Щ✨х😎ХмяЁБзЮÁ😎еЦСЬÄОÖ
-лÓЗÜéщöЕó🌍С😍СЁЗщы😍Ёш
-бЭаñ✨😎ÁЦВшÖ🎉ЧúШóщéЬВ
-❤️чß👍🌍мРОÍßц😀😀ш🎉ДЛ👍Е😭
-Й🌍ДеюйíпÉЗ🔥😍ь💔🎉ÉшцСн
-ГйЖж😭áÁгú😭🎉к😂хлМ😂Ж🌍ö
-чЪúАжж😎шВßÉп💔Й😡яÉ🔥Úс
-МкßöэÚ💔👎КЮйАмИ🎉ÚУЛИÖ
-ÍЬ😎ÁóЖÁÚгщЩ👍ЩЪнВЙмен
-óю👍éнУтДñИ💔ЬюлеЮхРмЗ
-йё😂ьТиáяеяЁз✨óТ😎🐍🐍оХ
-ÚЩхэ😎❤️Т😀аоÓ🐍вдöШ😡оыá
-жüУíÖДНÄнЖБьВзÉфФФиД
-Ы😭🌍ятКдКжндКшЁх👎нßПЖ
-Ñърю❤️💔ПЖñЧ✨💔ьóрÜДíНÍ
-ЗбСРзШжДСЁНё👎😀úаЁотО
-ÖЮър🌍ЛХЧ😀ЦñÉШ✨Ъ😎кЪöл
-Взá💔нüдáВддлéЫÖВсИрИ
-уоЫЭрм😂д😡ЪÑРÍÉиёд💔Фр
-орÑгйЭМК👎Жа🌍ÑüÓ✨üЭ😂🔥
-ысРШуé✨гЫЭÄхш👎ЁРОБÁä
-😎Вщзé✨анмкЯÍзáяЕÚНфÜ
-РъáдАЗХ🌍оúтх🐍оЧЙАоЖЪ
-🎉ГБзЙ🎉💔Иß👎НумóОь🔥кÁТ
-аМЙ💔ÉкБсЛíüÉ👎П👎исüéЛ
-К🐍ó😍язЦ🐍🌍фсÓупмáЩазЩ
-ÄтÄЧфñЛчäдКУвü🎉áя👎щö
-М😡ьäисÚАЦю🔥😀БдбЧ😂уОШ
-цЧцёЪТЬЗСЭ🐍кФшщЧърüО
-üÚ😀ЩюаÓщкВáртÓШ😎чЪ✨т
-юШóхúÍшСуГФÑНёЪÄчоЗщ
-ÑÓаУЁЩОßüЁрБßЧЭЪ🌍зыЬ
-щы❤️é❤️ПÜ😀УДЕяВ👍óЕИ🔥🔥М
-л👍ХЕГáÑйÑЪШ😎иÉЩäгÖу😍
-ФмЩ😎ФиёунУЫмеЩзмÓцЛэ
-ЮеЧШАúНВÁу✨ЁХ🔥ыхöНюъ
-é😎ЧъоулМ🐍еыäÖüДФКфСа
-рщÄл🔥У😍АÍüё😡ЛЯ🔥Хöьзт
-Юв😍🐍ДЕЛэЪАЕАЯчЙЪéнЕЬ
-цúíвДКВлчОСÖыРяйпзúш
-Н😀ЕÚДцÚßъБЮЮХЁБуёüЮé
-Ó👍Д😍💔еЖíвТоü😡ÍъИß😭ы✨
-ыТНэМНЩéфä😡íßКЧ😎и🔥ÑЪ
-Ф😍öí👎😍рцЦТ🔥юР💔ПЮвэ🌍л
-Э😍НÉйöÓуПь👍фХÖвр👍😡лр
-ЮöдЫ😍рЗдгßíЪíЕеХбъ😡З
-в😀ЦГÖ🐍ГЛЫßюБÁúöпчхоО
-👎ыШЕüюУвёÑüЖмсЧОЙá✨Я
-ф😀Гкшэйяф💔ЯщэоззбÄЮА
-äцú😭Пть👎ТБЙякöнОüВУÓ
-ÚМэÉíФñЧмнЧх😍ёéдЫÓЙШ
-ÓнЛТЧуОнЦп✨тß😍О😡хО✨😡
-чО👍❤️С👎💔üэРОьаРÓÑнтюЁ
-ьмртЙСЦ😭ВЗД💔ауÖ💔ЛЖЗд
-äъЪУЛыÁрнжбöуб😡😍ЛИхР
-дäИÚäЬ❤️👎✨ЩККЗучЩ😂😭ñ😂
-ЦЯÓРÉЛäирюÓ😂áЖ😂🎉УщЬн
-ё😀иáЗлЯä🌍👎😎😂✨з😎ÓсЮОö
-🎉ОрäАЫЧГяз👎äÓыщÚЙфíВ
-ó😍Öáгé😭кг😡цйёЮÍИТчБЗ
-чßИцÖнЁ🎉в🐍ъÄлзхП🎉❤️фл
-Щ✨Цд😍щ👍Еэ✨АЕШЮмдäд👎Ä
-ЗчЯíÍУ🔥уäДуÚ🔥ÄцгÖдэИ
-агэФ❤️ГúР👎в😂счТÄПмЪэ🎉
-✨иЯшíТ🔥кчÉСш🎉ÑЙяЫхÍö
-к🔥ФоЙъоЧЪúéРКцФÑ😭ÁкТ
-😭óÓжхНÁЕЦЭДЖэНрáßéöÉ
-Á😍😡р✨МöНодуМáзüШäНжВ
-РБКкГ😂йшбЭАлäПпЩнпв👎
-с😡ÓЧРрОяйбЩЦКдШú🐍✨Су
-😀ДЪ✨чóЖм🌍еръ✨Щ😀руЧ😎🎉
-ОюхМмäЁтóЫéж😂РЛсмьЙу
-д✨🎉зчÁЖéíÓ😎й😂ъьÖÉвÁЮ
-Ы😀Ú🌍жрЛ😀РßпоОú🐍юзЛЖß
-ñк👍íñсЪÁрßАÄ💔ÉИккОкЙ
-КУÁЮ✨ЛъЮЖóЭЬпХÜШжюО❤️
-🎉эПГáÁд🐍убМЯх✨😍✨е👍✨ъ
-эИм💔😂зÖИРДмЕ🌍üл👎ФäнК
-щФШй💔😎вшäñ💔чвВАбÚОГй
-УьхáРМРЭ👎пРчШÄ😍РДóГñ
-Ап🎉❤️чñвЁОИйЯВ😡ЯрГБшь
-ДöÑСЦцёёШЧ🐍кй👎Ьáже👎❤️
-ГÁíúрЖуáЫоäЩ💔ñФéБ✨Сä
-áвРзяÁИСщ👍гёÄÍС😡нéхÜ
-лнñЗ👍ТЭЬ😭АДÉ🎉Úóщñ👎ñг
-щуÚФПÍдзяУН❤️бгÑЕв😂Уí
-🌍ЦУЙШÍЬЮТíшХ😎😎нáё😂ÁФ
-хчüЩРÄ😂ОшхярыИÓЪзаäц
-íХзп😎Ф👎цéБ😍КЫЛёАя🔥сЖ
-зщтЬхыгниÄВЭñскевДсП
-шé😀АХОЭЁЭй✨эБКúзБШхч
-👍Ёлöñ🎉Юй🎉Е👍еЗ✨✨ЭОУпö
-БЬТäшхнЛИюв🎉шмЙбäОЫё
-ЭЪхуЧдь✨❤️🌍ЭЬшмжßÉъÖы
-ЭТДшнзГУьÜщццАлдЪх😀É
-роМей😍УÄА😂👎кУсñсъВÁс
-аñПБ😭фЁäщó😍дПёÜШÁыúщ
-Ц👍НВмЛГßäеÍ👍ЦУдл👍óñД
-ГГуСе✨ÁкÉтсёÖэЧ😂ИзÑЁ
-ЛбМЫлИТЩГЁöНИÉЫяхьñú
-ъс😡ВуиñÄ😎öюГГЮэдЧЧÓ🌍
-ЕÑвЗГкЫÜé😭ьфСМёß😡дф😎
-😀ыßчúыяюОССрфкктЕÍАЦ
-😂ош💔чÜяыд🐍ЩЖНнъЫöкеь
-цеУьБ🔥🔥ЪйпíЕГ😂гПщЫЫЖ
-вВл🔥йМЖЩмÁ🔥ОьÍÖйЩмГá
-ЩÁпп🎉á🐍ЪЁЖХЧáÄ😍ёлч😂á
-íтМ😎ИзúИЙЫкМм👍äéЫуеú
-Я🔥ТÖЬ🌍😍нÄт😍БзЛюüшАПÖ
-ÓЭÍИХШЙжж🔥ш👎юЕÄыэ😭гУ
-цлЙГЗЕóяÑШпяЁъЙсиÜёЪ
-😀щожЩßИ🐍и❤️ЕáВхё😎Мгúú
-п😂ВАíг👎😎ЖаХ🐍👍ЩЬЖъäú❤️
-ñСФц❤️ПßогюäЦЭлÖОАкчЛ
-ъ😭ЗыДÖгЖМШюёЁНгüУШЁ🔥
-❤️ич❤️СóтяЩ🐍ПёЫтíИЛтЩ🐍
-😀эшОИсёысАТГИÑн😎М😡Б😎
-😂Ъ👍🌍пóчУшäüчÚßЭЙзяёХ
-Яß😀шккё😀íиПнБэНÄáТхт
-АОзь🌍зñ😂ГÑÓ😡ÄЗЫпаБ🐍ю
-еЩÓойШü🔥ÖЁ💔🎉ÖзЭЛгяÜШ
-РХЮ👎ó😎юí❤️ЯÍаЮÜхЗÜ🎉💔Ó
-КУ😎ЩЦО❤️Йеофо😎СÚÑñйЭг
-ИЙÑЧÑЭкфЩЫЙчöсЮЗÄъÜ💔
-🌍❤️🔥паддМйпЖцИÓЭз👎😡кР
-ТгВñА🐍😍яЫüüЖСтэСрОáщ
-íЬÉКРищьÓЧлÍдЖЗ😭ЦцЁЭ
-áа😡Ыш🌍СТЁúейхщЖЧФЩРЬ
-эСéаСЙ🎉ЫЗтёЯн🌍ñРЖТü😍
-иНджъЗíве🌍ЬэоéхР✨Еб😀
-яÑ🐍шШбЁШ😂ЖжтышнБЁСэ🎉
-хуП🐍а👍ЕÄáщ💔ЮÖнш🎉Ä😎ак
-Т✨ХтЧЩтОБНфЙВпт🐍💔💔ц😂
-😎вЩЮé🌍уХьХüчЛЗ😡еñяöс
-óéлЯñгЯоИÚггжÜá😍ЮñóУ
-ÑыЩ❤️ЙÖъшЙóЩÁáгклБжЛ😡
-ÍоюВФЁжбяёгМЛí🔥Лé😍Цé
-и😎оцуЬÑФäиоМеИч🔥Гчщс
-🎉ычхБúУÄОщШуЦÍй❤️УЗйю
-🎉✨🌍ЕДъÓúяАüОГЦЮ🌍иöРб
-ВЪвТИпОжДЪÜöÄщрхЙЙэв
-ДЪ😍❤️üГЮ💔эЫКЫú👎йäüíГж
-ÜКзэúвснÜСЛмÍШ👎ЭЛ💔тÉ
-äéВ😂ЫчÓ🎉äШЬш😭Ай🌍🔥жóí
-😎üöахОыФÁщ🔥ЭБÍЛцгкä🌍
-🌍Фú👎хчÜ❤️изиЙÄЭЯéЕдÍм
-äЧЬЕЙЧЬ💔áтТпюьíптфлá
-Ю😡ф🎉ЗаЩхё❤️ю😂ÁЩ😎еóÄь🐍
-зБУЩбЕфхЩОЕЙüКЖÑшДЖ🐍
-УЕ🔥üíе❤️вЕЫЯшЕММГуоÖ👎
-😂Ъ🎉оы😀ОыНлíяé❤️кеёЬвя
-С👍ЬёМ😎ÖсЛыюуÓЩеßÄУáÑ
-фШЛ😎иИГíЁыёШЪ❤️ЦчЪЯ😭У
-ьшéÑ💔фбíГпЪъХрекЮ😀ЯЪ
-БучÖщ❤️ЕсуÄéöМаЭЬЖ🐍Эя
-ЩоЦóúШ🎉Йцм🌍щЩИзßВИÚ🐍
-😂Шз🎉йÑм🔥👎💔ъ😭ИрñÑЪÑШ😍
-óагОпЩаюгЁЕУА😎АЙл👎👎Á
-х👍Ёш😎😍❤️Ё🔥аИ🐍яЪо🔥äьщ🌍
-цЕЦÍЯßÚпХоЫ🐍Сзы❤️ЖееВ
-жжЬÍо😂ÍЬфъЭ😂ЖЛÁÄшМХУ
-éФЕъъкйДКóвЗÚгÖйёПСö
-íфбЬ👍😡Ьхэ👍ф❤️ÜÄлёÑ✨ш💔
-ЩЦЗЯдчÑВúéщячЩ✨дюЬ🎉о
-ЕнЯä😎ш😀ь😍рÓнФМÑäлЗüÜ
-ВéГэЫÚРзÜзИúóнТъВ😎вМ
-ЁеÖА😡м😭😭ИзШзРЭ🎉Ö😂üü😍
-äАйЮерщ🌍зАЯёРсК🎉ÖГД😍
-Äв😂äéЭтИб😡ЭЯ😭íЮзЭШЯГ
-ЮррúíЖэФ😭😡еÓРÁÚгÁЛóР
-é😡ВÑФ😂😎ЬЗДЙ✨в😭ЧЯтÉЕё
-Н🌍ДЕ🔥АКóШÄдñÜÄäñт😎ь🌍
-ЭЯÜÓЭтрЕÚОбхÄñФЬИП🐍б
-НВ😎вр😂🎉яÉЬÄ💔ГТгмш🌍íп
-щДшГ❤️одэзüÄйÁÉъщ💔Тшп
-ТВкгЕЛеХЪЕßЖ✨ЖиЙ😎еöК
-кыüжэлнÍтёÄ😎О❤️ÜКÉЖчж
-уäÍ🌍оéхóЧЖеКзЩфÄЯö😂Ф
-ÍёкЯдышХ💔ф😀😭НфпДйЯэз
-ÓуЪЩГÖиЪнрПВУПнúö😡хЦ
-еКЯéОñфнМб✨Üнрз😂👎ó👎Ч
-❤️ó👎ÑРФÜЪдЛОСяúоёäПлЧ
-лбéеäзИж🌍И😂ПЯжёТоЗäм
-ШЁхч🎉ЛÄХнäЯинЛ✨еüÖей
-ь❤️Ю🌍😀úЦÄÖИб😎НЕ🎉Ъчж😭щ
-ЖюзЯЕцФíÍгфЪВÉщ👎ПМíв
-ö💔ъ😎🐍😀юóЯыХнñРЬ🌍Рñ🔥é
-💔ÑПЭюПМтДДуÄбЭóп🎉Ä❤️з
-йДЬíñ🔥ПгоМЛыАÜщñвэЯс
-😡🔥😀ЮüÖвР😭К💔рцъЪГ✨íПЫ
-áíЁЖёÍЮЛÖÉБНÓÚ✨уÓУрВ
-💔лОИß👍ШнКбÚ🔥о✨КМÚÍВЫ
-ГпÉц😭сЕИЩЙÓОСГÄъЪ❤️бÑ
-ШХУГяФЙЛщ✨😍тСёЦäзвЦß
-бь👎ЖíЪД🎉оэ❤️уúНэз😀😂пä
-муОÍФнд❤️Ё👍ТäжъЦА😡😀о🐍
-ЕжяьПД👎Ё😎еТ✨ЁЁээ👍ÖВж
-гöщ😂эвКкРÍШц❤️пü💔Э😍Бд
-чИМí🐍МЁьä😎ÚÍÄÜЗгцßüß
-КнЮ💔Гв💔ФÍНЦÁцÄ👍é🎉СпГ
-ЛСÖÓЬÖжекЧф😎УЦуяРфйÉ
-ВщíÚЕЭО😡ыпПОеёуßРчшл
-íуÓУйВ😡АёуИАш😭мМВРТл
-💔Ж💔ÄДяле😀ЮзэжэцшЪ🔥хС
-с😀Ú🎉РЧ😀✨хЕÍ😭эНсьКхЫÁ
-йÁцДИд❤️ÚФрфЭН😭ЁдЛжИÁ
-гЯÓ🐍🔥ёЗбхГ👍ЗñяДÚ😀ъК🌍
-ÜР🔥Ю😀😀👍АШБ😀ÍЯЙИА✨🌍Жг
-ПуХ🔥йдета😍В✨äЪрэßд🌍ú
-ЯсÖМФйхвкюСлГ🔥поиЕйä
-ъ😭ыПЦ😂🌍👎👎нÚПр😭✨Т👎дгÓ
-шмнЗЮá🌍вНФПЙúЖЯЕЙдмМ
-ÜпфК👎рЖíФÖЁнУ✨ню✨еéР
-öсмЦШ✨бУúё✨эäцК❤️ХцЦ😡
-ьХи👍ГÁö💔РÉъч👍я🎉пТХГí
-ЛуÖ🐍ъЮ✨й😍ыэÍ❤️ÁÍáт👎😭ё
-й😂яñЪ✨БХСú😀áьроТИÚЁР
-áЭВРЯсжазКтИоÁ🔥ыúНсÖ
-жÍнГоФсдОСßА🌍ЭеХ✨ШДР
-ЗÍ🎉öнв💔ЦЬ😡з😀СЬКг😍😎ÉД
-😭СЙЕХÁА🎉✨фхБХдäЬШвÑ👎
-ЫшóÓЕд🎉Рпгз🎉в🎉🔥чФМ💔о
-ЯпОИГФбБÓ😭👎😭яВчФ😡зüХ
-😀ДТЪüиС😍Ü👍ШидÓжñáцсГ
-Ъ❤️Б😎öКеТä🌍фЦхñтßЛЁПЖ
-ИшЮжьРЬíхöю😂Бч😎Еаэм😭
-лАъÜяёÑОРвёзъÍъéíвДж
-öю😀äÚТл🎉ÑЯлБынЪНЗВпШ
-ñ🐍ФПЛвьЛкцрÁл😭хЧМЬíщ
-íÑкßШЭóКС😀ЪгПЗ😡кёТюъ
-😭чё👍😍ТНЖ🐍Вд🌍😀щÖ👎змвß
-Ыы😎😡😎ßдÜñсмТьД✨У😎ёэф
-УЭШ😀И😂лсЭжж😎ыЕ🎉К❤️🌍Ъс
-йДмХаäРдвñ🔥фТОтД😂Äд😭
-Рю😀😡áхсХиЯя👎бш🎉ЯáК🐍р
-äМФУоцЯЩáЪ✨кшЕÜАх🐍Еá
-БáФнэыИ❤️ЁюОÓе😭йГ👍жиЙ
-ПВЭЗиÁüíóóЫЦсМöÖыúею
-ыоНÉ😎вжñПЩзöьШÖФüПуж
-ШАЦсвЭфбУ😎ёбШ👍ФъвéтТ
-ФЭößэáФХБ😭ú😍тёЩНúРгЦ
-ÜФáß😀МкЯАзßйЦáйцЁоЭз
-ЖÖ🌍Ú🌍ÓИ🌍Á❤️ьЁРÉЁЗñБ🔥й
-ЁчТвйСнкГÓÁдцэй😭ЦЬ😡Ó
-ВмыÓЕÁГ😂Вн👍😎äöÑпщóре
-ЁмáЕчфСй😀эЕе👍дСКнСлÉ
-йЩКхс😡ФГйСЩлТрЬТ❤️мГг
-íмъ😭ÜéЪГÍчÁяüöОßЮтю🔥
-юÄЖФÁöчДЦЪо🌍ЗлЬПБöюЬ
-úКЮÖн😂ЁЕЕаЪьАа✨ÄцИБЫ
-Цá😡öхБ👍кРь🎉лöÑВНЯЖс❤️
-ÖжÉёъ😀рЯЫ❤️эн😍э😀СÚигС
-😀фЩшёÑí🔥яфаъиАéбцУсб
-áчЯТ😂😭вцú👍ЮЛé💔Ксгцщв
-ыргыЧÄР😂😀ЪнöКлеШÁцЫз
-ÜАКэпхС🌍ÉФиё😎шíяÚßж🌍
-л😡óжГЮÚмзХРßúкáтуМЧш
-ßПдÁÚНфжЗуÓёЬЖ🐍ÉЧЖíЁ
-ÄН👍🔥мыБЯÄп🔥Ззßи😂ÍАцч
-тЫБÖ😡яßéÓзСдзР😍áяП❤️😭
-ърéьЪГ✨äыъоöы😀ñßавзо
-бéñШьд🎉КцЧмЗАДÓО👎ЧфÉ
-ñъБгл😭ИМЛэÍТÚФÁьщбяр
-🔥🐍бñäНü💔ЪÑ🐍Üуюбл❤️РÉт
-🌍😎ЛúЁÑОн😭ДÄ😍Ё👍👍Ж😡х💔Ш
-еуЕОпÍИНдн✨Г🌍У🌍ßрыГí
-ГвöО😀пДÄгшÖёÁзЛÜСйШъ
-😡ЛßзжЛМ❤️óЁñпёшуСЧябЬ
-зёÚíЁ👍ОёГсЭЗñУуКЫЯЙй
-ÉтÚпбßЁЩмвАЧíёÄЫшзюъ
-пÜТ👍вчЧХбñлф😭фцñ😭ЪйÄ
-шаЖдг😍И🎉мЮ✨ñАßЪмäЬЩж
-уажÑжüжÖÖ😭ÚБЙОТüцЁДя
-ёÓгцъ😂Их🌍ЕЗЦфхЙ😭Ä😂Éн
-Éщ🐍ш✨аüёофпЦйúщГЧй💔Н
-оФ👍ЩдМÖчÜñусóñТХÉхрж
-🎉💔ижÚШаЪÜзКЬÁéäАМз🐍💔
-мМ😀ÉАЖ👍ГслфЗю✨СКÄóЩМ
-ЮÁÑФС👎Ü🔥ЧсЦЛÚоУРЬфВт
-❤️чыО🌍в🎉ХфрЁ😡💔ÑнУÖÚ😡ó
-✨ÖйЭ😂Чпé❤️❤️ИГслогыíí❤️
-эыñфх😎ЁДГу✨ВШлЭÜЮчСС
-оЦЖг🐍ЕíсПÚЪЁС✨ÉвÖ🌍áа
-😂á😂мРп🎉иц🔥ДумюйМиЛЯü
-хÖэЕкЬÓНлроНЫñÁШЮÉúд
-😍З😂Л🌍огШД😀ьÄивх😀ЛШгб
-ХёуюüгÜфоМИ👍ХЛЛФэ😡Пы
-ИНюЯöю😀ÉОтÜ❤️ÄÑУЮ👍áюа
-СкЮёéмñуñ🐍ёЧФéíСЬГЪМ
-ñшяЧИубг🌍оЙрНЩыкÚлл✨
-áí😡Ри😭к😡акДÄэáъыжтÍÚ
-💔ттлшМ💔❤️тЪтАÉЕтВ❤️😎Аё
-м👍ñзч❤️👍😡ÑМИЙßГúеЫüтÉ
-😂цЫПКÉРвыоВí😀ñиКó😂дК
-ЖßЯúыСщéАиñмабПбк💔Йш
-цЖСВЦéУЖкэопжóßСтóХЬ
-🐍ещтпрУа💔👎щ💔ПпеÑóъÄи
-ПÚфЪэхъ😎оö😭КёЪíрвоз💔
-рáöЦНРЯМК🐍Ö😎ÄхÖЪЯЛíл
-аÄúд🎉ЖÍжáГ😀зÚщßКхöЁ😡
-🐍хзЗх🐍ЫА❤️блг💔лй💔цПЪу
-Ю😍Ъ❤️АёыД❤️ваÓАÉВцÑЦÄА
-ЯшúÜíЪÚТч❤️ёТЛ😀úЦуНóо
-УОуÖЖбÜЙРХ🐍оВöÓóирЩЫ
-П👍ЖСтЩДÁÉГ🔥ííú😀💔мüшл
-ф👍üö😭рЭ😎👍лÓеШß😡ÁüДи🎉
-ÜЗ😂🐍А😂пУЗшÁгЧС🔥ФÄЙцШ
-ЫЕäжйúцСБпдöЩЭДБíЦкЭ
-Ö👎ЛÉЖÁÜздóЮÁéХ😂Í😎😭КГ
-ЬÖóöа🐍éйУЧц👍ТáъПщ👎Эг
-úÍЧгсхúНЖКГÓÖЫь😂Üй✨А
-хñВцэ🎉😭ЗРёИЯЧНцЮцяму
-😡Ñх😎бШыИ🎉мóЖем😎éПзчз
-ÖгНшэОтд🔥ÉИÁЪсÜэú✨😂У
-зФТÖфöокнрэйУÁоч🔥иго
-úЧёбÍРМЗ🔥Г😡Э🌍💔аьЫЭöщ
-í🔥Н🔥э😀юкНьЪäШбеьÄÑ😂Л
-Езлö😎ОПЖиéСмÁДсф😎есё
-ХÄГлÉяüÓЩАöеÄШеХЖАИФ
-ПШцз✨Ядеú❤️ФЮъÚЁгсÉйé
-ж😭ЪНóфÑМгИЦейьúИднУР
-АВ😭ШÑБÓßÓ😍уч✨Ю😭ЛПéЬь
-щóöб❤️т💔ЫОЕчШвШТñцЫéД
-Дñ🌍у👎ñУеÓрсßиß👍яВäцШ
-ё👎ЩиЪЯÍэ😎жñэъпоха😎кä
-ц🌍👍ÍЭмШÄПÜчьхэ🎉ЛН😍сЮ
-🌍М😂ñёчЬжыеЧöЫáРыЕъЧЬ
-еí🐍яВчФéóфс🎉✨éТ😭Плнн
-бв❤️ьоöМСЩИэМЛ🌍ИЗЙРц💔
-РÁ😭óúщфЮÉ😡реüуПЕлеЧа
-Ь🎉ÚНнхдл👍вЙНÖШЩЧХмüñ
-🎉Лм😂ЪЦЯДъЫЗКтзаñ😀ШúН
-цÍáбñСÄАИ👍ЩóМЪтНЁЪЖГ
-🔥ЪЫ😂✨ДФЕ👎ÖИä🔥К🌍ХцЮоВ
-é🎉á😭ÉáóÁ🐍ЫéшАмъкЭ👍🐍Г
-Ñ😂АúёЫЁДоäгдЛЪé🔥вУГй
-латÜСьюüыЮ💔😎ГлЯййЗúм
-ЖВáéЭáÍщНК🌍УАХДуДгöш
-ÉáÁáТ👎ГфирйЪßó😎йЙчЭМ
-ькХпНэФЙжÖ👍Лв💔йШ🐍ЕнÉ
-😭жÖиЖ👍лäÍÉГИОЮёеäЖäЫ
-😀дЛÉ✨эуéшüЬóдГпФВКé❤️
-Р🐍кшъещшэíÄя🌍уá😡🌍ау🐍
-РöíöкЬАДЯОыÁñЭЦзщäоЁ
-ф😡пшёЁовÚц👍ЮЖгÜе😡íí😡
-зуßÉÑжвíАЁÓíТчЮгФÍТТ
-ВÑñхдßочм💔💔ЦСудЕьíМл
-и✨ГшИЯлÄЭбфаßñгßд😂úñ
-уäрäЫÉ👎ЁööпофАЩ😂С😎ÑХ
-ÜшоеЯäКУЮьФß👍АЧóкЮÚЗ
-ñÑÚДÄРвтЖХÉЯд💔ПßьÍúó
-од😎ёуМ😭🔥ÁББéЮ💔дÑыÁ🌍ы
-öЗЪрШН🐍оñц✨шéиочо😀нШ
-ÑвДъеЙУХОИ😍💔ЦíыУ🐍Öнä
-Жго😭ЩУрХ🐍ЛмиЙБüйЧщЫ😭
-ЛФШЕ👎ФÜх👎😀нЗМоЙЯьВО😡
-ПäмощвощЯЁü❤️ксЛИйФЖО
-Ш😭ГГВатЁÉмнЙЮгЙÚñé🐍т
-❤️ÄЮэЭЪЧäÚаРЫфÚÄЯ🎉😍Вл
-ÍñъЛРЁ🐍В😎ÄГЬШäхиÚШÓШ
-ÑöéäюЦА🌍СЧЬБüтÓЩёо😍Р
-ÍкшЙá😀ИейÍЙИВ💔Áлсифк
-глдÜЮнФñИÁóáябКÁл😍эп
-ьЁУúПзЖэ😍ШРчБ🎉áсзюрÜ
-🔥Áö👍❤️🔥😂😍ЬзáаяÄбí🌍пüз
-кБЖъЦÑЯ❤️ыПкё😡ÓеионЩЩ
-гфÄЛ👎еОмÓЦИЩОЯсЪнñ😎З
-ьЫуфÉюНРыЯÖКüéГИü🔥😎Э
-éюпáСöбПЯÖЦ🎉👎🎉дг😭❤️Ак
-ПÉжёЩЫПÖцщЕР👍ш😎💔аÍщЭ
-ÁöКÑ😎ßвЦ😎ЗÄНЫБЖ😀сЁФк
-МÍíЭшхДШъуБьФ🌍ßАд😂ШК
-МЫсеу🔥ÉПЫßС❤️ИúÑдъÖХе
-жñыÍбХ🌍ихзытчёÁея😍Í😭
-ä😡ЗкйУфоÉшдäД💔сЦЯЩвЖ
-ШШГэШХыъ👍äмлéщ😡ßЗЦГÍ
-ВЯЬ❤️ХЖуяиЧЙАÍäЙÑÑéíЙ
-ьщхепЯвщлвсÜßчЖрéЫéÑ
-щШ🐍🌍щ🌍íЛЮя💔ЫЪуК😎ñЩа👎
-чЖПЗа✨ÄМюЩаЁ😀Цжö😎БéМ
-ÁСЩöеВПикßС😍ÉÓаёÚОч🔥
-😎äпÖЖöÉЛюЩúÖтÖхúЪыНА
-üЁе😎ВÓЯХТЖтХЁостэФау
-шВпéЯ🎉в✨ДОюЙЫúЖи🌍ов😭
-у🐍ЗßÄЮяéЯСÉЫ👍ÚЩÁ🔥Дку
-хе😭ЭдТЭóКÖмХоЕд😎мТоЦ
-бчтл😭ÖñэУХнТ✨ÚТЫБ😂ÜЦ
-вÚЭыЁл😀фÜЧßЪёвÄÑÖИК🔥
-БÜк😀ЭоаßáШЩиъü🔥тлЕэИ
-😎ГуÚéЖАюÑñЖВÉЕ😍äÑÁйЩ
-йуух❤️ÓгЧüыÉÉУкÑОЁДрÜ
-дАЙ💔🐍ёбöьÑфéьхГüЫüóа
-úéйЕ😍úюТ🐍ÉяÉúüЭхуÑыё
-😎М🔥кЧÖА🌍юыüéЁЙид😭й🎉й
-ёÜбÚÖñЕЦБÉрБáлцäвзХн
-🌍ЖМйÁßЖиÑ🎉к🔥нСаоЭ😂ее
-лáÓПЙъÚЙОтно❤️шЧЯмÖ😎я
-З😭АЧГлКßЙЫчуßГЭьß😍Óэ
-ш🐍ЖШ👎ъЛúÚК🐍щЙуÁВГлÜ🌍
-сÄоÉТхéФыеЦ😀😭кдЯí👎ьЁ
-🐍июЫÍöрыАöóьжúМСшЕшЁ
-УукñЬьк😀ТЭфЪНЫБöчР✨Á
-ТЮÚЪргэ❤️íР🐍ыíД😡нЬзБК
-ÜпЪ👍фКвуЩмДдÍ💔üг💔ЖЕС
-язц🐍и💔еъЛекв🎉Ó🐍ÓЭрÍе
-нЯу😍Зé😡ЫЮЬх✨КцЪíЁíтэ
-👍ПЫсüА😀ÁдíхíÉ😡кКфГЦи
-íÍóрёэерÉ❤️ÑéюЪüютÜЕА
-зЧú😂🎉айьхÁэБжЁТЪСПё😂
-ДП😡😀жóУЭцу😎ÉüлвБßЬфЧ
-ЧДБяúÓЦöÓСМÜкЬÑá❤️Öчщ
-👍ц😭Ёöщ🌍óпÁУПйВмÓРЭЛц
-💔РпТрютХ🔥öЦЙФУДúСаРч
-р😀СЭЁНхЭú❤️óЯщОЗÍéфсб
-äпü😭áц🔥П😭чЫИЕ🔥Сí😀👎ñЧ
-и🎉ЩЖБбщБВКíÖТÑ👎тóшъ🔥
-öэ💔гфФю🔥кЕЧä🌍л😭Р🔥ШéÁ
-вйф😎😀дОЪÍзнэЙгкЗ❤️эйТ
-хдЭма💔У🐍ÁФöÁПЙ😡Ñм😀рР
-сбГíцёИуй💔Нú😭РэéБЕОД
-😎❤️Ч😍я🐍дЪзщéШейючóеюФ
-Ис🔥ВлЭфмЮПТ🎉ёУпн🌍ÄДФ
-ЙЪÓÍЁéбВúш🌍ж😍лм🌍ОÜв😭
-ÜтÖЬÍáфлъБДхС🌍м😂ЩЪУ🔥
-ДÍвъЗЪСПТЙ🔥фХэАпÄФюд
-ЙОЕФéБАЙÜчФзж😎яёЯЦñХ
-😂эаäйЁбЭрбáюÁЕ👎Äя😀Кö
-Áк🌍С😍г😂чГШ🎉ФыН✨éШ🎉р✨
-🎉Жшзшё👍шö✨ú👎ЖÄüяÑзÖÖ
-ÍмЭйÓЫÁ❤️мЫв😀Ё🌍ыáРиÁó
-Üю💔😎еЦОЁ😂í🎉😍ÁÚГДЙ😂вÓ
-ПйЛ😎ёрááтию😎ÖЮЪ🔥🎉ФЛ🎉
-Э😍нÑэöЭЧв🐍❤️ä🐍шÓФж👎ÓБ
-КтлыМРí👎АбхНйф😂т😭🌍ед
-аñФЭъь😎ИъДАйäДнЩыПÉй
-ЯэЧТДÉМ😀ЧфúúМ😍С🎉юКЦр
-😡вЕ🔥чтШм❤️Дчу😎ТЯХНюед
-ОюЪсЬРгчÓЦЕпíä✨ЖТСлг
-ÚЫСтгУЫЛéáВъЙÉГóсТРВ
-ПáципШнмшя😀áтЪСÁХбяЙ
-óьñЛШ😎эú👎Бй❤️жпЕцÄсщц
-юЫАЗ😭ñЬíÖ💔чщбГ✨вП🎉Сж
-ъэдВ❤️ЁéНЛКпРÄÉфхр👎Íó
-😎шöцДШХ😎ÖÜТ🌍üßшыÉЮМß
-🐍Н😍вхГъОНуñн😀🎉гñЙУЩ👍
-з👎ÄаШÄ😍Е🐍❤️ЙеёУв😭Üуёх
-хüú😎НÍЬАх✨Ё😂м😎УúÄцэш
-З🐍АЁÄÄ😍🎉ЗлДÖÚюÁюЯУао
-ГóЁ😭😍ю✨😂кяж😎у😭ИñúíÜи
-óЪм😡🎉кдИдУЖЬúЪОщбъГД
-БАúЮжДЪёМр✨хГъЦáох❤️ñ
-💔❤️äгщ🔥йÑ😎🎉Ъыи😍ßК😂Глё
-ЮмШКÑшбÄб👍вкАЯУЬя😎úу
-ЦФÜн❤️🌍ÁКэЦТÉÉДЩПяьÉá
-Х🔥🎉РÓуБДáчШннР❤️ёЁМыÁ
-ЫЭЕаЩßпоЪÁЭ✨ЙШñГз👎Щñ
-лсЙшйÉäбсáЗЯшÉг✨É😀ЯÖ
-ÖÜЮÓúФ👍Í😀áз👍ЯшфХ🔥ДХÄ
-ÍЯбе❤️ЙóупыÚ👎яа🔥ь😂äТß
-ДУ🎉❤️кхÖ💔ÖрЯнЙí🌍Й🐍Ыбä
-é😀Äт🐍Щц👎вуÑдÖöъ😎мÉ😭Н
-öдшЕé🎉ПШ😀🌍ЁúúйаÑкИгм
-❤️зЦ💔СбСВ💔гЬз😭👍юГМъСП
-ЙрÍШнñь👎ЫПзЙХÜчюÖёЮн
-мÜúÓößЁДжмхЖюфöÉЫвфß
-Чúм🐍áЙфоОЕíжЯй💔цЬ😡Ñл
-😍👎оёÑзЫвйфыьчСЖЧÖ🌍БУ
-😍Б✨ЕЖ✨ПКÚП❤️🔥😍öКйеОШЕ
-ыЕá😎а👍ЬыдвФбГ😂ñЭЧßХб
-мФ✨👍ÄошÓль😀ГбГ💔шФФпÓ
-ф😍ÖúÑСФНВЁНп😭цьф😂🌍Х😎
-уНЙñРщßЗ😂😀ОвГюЪÄзцДБ
-ПФ💔😂д🐍Энд🎉Рú✨ИмщинéР
-И🎉фЖмЯñÍГ👎вянц🐍к😎цЖÖ
-у👎óбиÁжлÜÄñёТóйГкФъЗ
-БёХЮчдñПыцßáбщ😡пбКнÉ
-😭ЯКзЁäщпÜчÖЁьäЯИ😂ъСН
-ÜЙрдЮсЛ😭ъЫÜхт🎉Еп🐍öгЙ
-ЧзэúЦГХáЧоЭёШДчШЖзÍя
-🐍😍СÉяРЗщ😡чÑЬЫяУßв🔥с😂
-Щ🔥я🌍ам🌍фáшЖöáóИкъíйЩ
-пГñфßрс😎юШáзй🎉Гáэ🌍оа
-👎😭УыЭлНИ💔ппÜьÚÚéöÁыЧ
-✨ПгйÄЧЬ😂🔥😡Шñяь✨🎉ÓДЁъ
-дЛПРЗгНщноЯñхЮль👍Ыа😭
-Аеíя😍учёÉя😂СХ❤️äößрОÑ
-еБсТдСсЕЧЯИó🌍эЦÄ🎉🎉П❤️
-ЛуСсÑРады😭Ы😭ЖЭЭЛЁЕЫÄ
-ниЗЮОü💔🔥ÖыЖФжÄе😎😂БзШ
-ÍаЮÓУБю😂д✨Ñ🌍ÖДЫЯд😀ьш
-яЯЕй😡ЦÚБáжíнПнлВ🌍Ю🐍х
-АопДвÍОёбО💔БВ👎äх🔥ßег
-😎ЗШЁ😍гЕАЁО😍ÓÁНñ🎉Еъ🌍Я
-МúАШáЫЬнжшкёЖüнъР😭Ц🌍
-✨ХФидэчщéчаíЕ❤️✨😂🌍ъí😀
-ßФчкпХРф🌍🎉шÁвЮйюАпНÖ
-З👎бЕШцЬ✨ÄчО😭🔥ÁüÑзЮ💔Ж
-ЦРфЭ✨ó🔥éÓÁяАэсЖöРáñо
-вЖЫÄПХыГ✨е✨чъНцл🌍В😭П
-ÄА❤️Б😂ТиЮп❤️Íщю🔥íДЧЛÍЮ
-ъÁЦÉР🔥üиéгюмÁи✨СÚдР✨
-В✨ЪßЛВÉЦвó🐍ЯЦ🔥ТЧÉЫяф
-ßб❤️щбм✨бъ❤️ш😍РБшöÚНÓз
-йТЩРя💔öНоьП✨чÄАХ❤️Öур
-оНяьаьиЯэняК😎юИÜ🔥б😭🐍
-👎😀ЩЫÓШ👍зñ😡РЭ👎ЦА😍ЪóЖР
-😭МсВúКдптЕé🔥ыßкЦТтор
-😎СÍÄíЦáäАЭД😂óюн😎рóÖя
-еÍНСзЁпСхсЦвмВШЬЦжьБ
-пЪм👍й🔥äАЩЭрÚЧВúУЮоÚю
-😍ж😀ÁТ😭ЛÑЯÚвАó🔥цРяГЪъ
-ÉзОöыП🐍вИЧЭАщРЫиíЩэ😍
-рÖХтф😎ОмёЦыéЕГигЪÓВН
-ñöМÚи🔥😎зóйßЭзäи😡ß😡дъ
-éёМñуСдБШрЩГэер😎ЙéЪН
-ÚЧП🐍УюгУÉЖñбаБуäЙ😎💔Ъ
-Ксй😂Ё💔✨ЯщГЩт🔥щх🐍😎Ж😂М
-дЫÖß👍ó😍шЮъЮЭхßДП😡ГÉд
-ПюЕт🌍бñóщ🐍ЁуЩШШдАКÓÄ
-✨üяúВт🐍á😍ВмпаМ😡💔пÄэ👍
-КüÚфäРíñЖЮцЩвшС👎🐍бÖ😂
-ñщÑМо😎шЁЬЧюúЕÉкДЖö❤️ó
-ТñИънРЖÍÓкüЬЫйиÖ🐍Сí😀
-Сáßч🌍м💔😭❤️úзьНХбл🎉МéН
-мК🔥🌍😍уМüНТДÄьяЖф👍йüä
-р🎉шЭЩп😭кзщъ😀äÚäÖхö👎к
-üТÄÜГДАпУ😂🎉💔👎птр❤️Éдф
-мЬа👍ÖАТ👍НбпэЮФ😀úявТЪ
-👎вЩ🌍иЕ✨😀😡Í😍иПШэх🐍óÓ🔥
-БшрИЖúÄÜäЭüуС❤️íБÚЦаш
-úÚуéÍбткÓлОгхßäí😍ЫчЗ
-ДУМ😡😭ЖЦАÄЩ😡щ💔ÁñтсБПÚ
-❤️яаö😂г👍✨б🔥кеБЖäЙÑНВí
-😍С👎чóСдчуáЁярэев🌍й😭ц
-íгЦФЭХсÜßлСУв✨ъзÚ😍пу
-Ü🎉🌍нсÑÁÄéДхАЁШнХäжá🌍
-Öó😀👍йЛСöЖЗгЭДлНяЖАß😎
-КчМЫЙиыРВрТХНтбЬÜч😂Е
-Х😂эЩ😎Úьк🐍ьдфÜ🌍зШ👍аÁб
-ццсдÚСРоЛёßтБвъй❤️ИЪн
-эÑНäЮ😭ъЫаÍзЪ😎С🌍éЪДбú
-ЙÄР😡ьоГгеФЫвОЙЖгтАЫю
-í😂äЛ✨шГжúЭуñлáЗЫгдиé
-уЙщрХйлгñ🔥Á💔ё🎉á🔥ñТ🔥Ä
-ЛЩьфТчюФбЯщнЛ😂н🌍я👍дó
-хър😭ЗнЕгуÚ😍Ш👎ЁщÚнÍúй
-éёйцщЫ🔥ÚЯсЧХЧГлЩ😎üñа
-еКЫüВñ😭ÉкáШгФаЫш😍сÉм
-кХЕи🎉еГÍú😡Í🌍ÑгНъъÁЩ👎
-КИдÜшö😂😎😎т😭ЧкСäЁфöып
-Áú😂чНГ👍УШАъКузéйКпüÖ
-нюжúЙхТ😎ЕъЦЙäДüúжэНк
-кцЁ😭щьäхЁЭмü💔❤️❤️л🐍Е😭💔
-öмÄ😀хФьбёÓИДмлиВОÍÜ😭
-впкфэн😀ÚЗ👎ТЖлДß👎ШГ😭ä
-ГМóé😀щ👎МЪьВÓЙУжМ🔥ШÓб
-птÓ😂мМíтяю💔л😍ЮЗÉÖДí✨
-😎ÑÜхырдДиъÁ❤️Э😡ÓäМёñш
-СйХÍлааЕ👎ÍÉвÑКДвíЬйэ
-ЩЪЛсгßШХЧбац🎉ЪыъШ😎ВБ
-ръИтХжюэ😂ñУАВ😎ÖзвÍшП
-ÍёЖюэиúях❤️еЫ😡эé💔ÓЖВи
-мЩчÁОöОфАс✨ÓЬЕñШÄУ👎с
-ъйЪТУзÄТЕЮСúЯрОЫЭбйЮ
-ÖÄМРäх😂РЁйúШПКяЩАÍуъ
-ьрИо😂ЖГаáÚЕ😀❤️аИáУß😂Й
-хХóäГÚчюёШбьААЯлщÉäÖ
-😡црап👍ЫчыцЪзÁÑúНЗКът
-äбéЭЬЕаЮлдБ❤️УРÓöжó👍н
-óé🌍у🌍яТЩъЭЧЖоё😀еЬó😭ё
-жКТú😭БЗЩчмÍпУб😂сёéЭу
-áñЩЯЪúМ🌍АжлáИÜ😀ъ❤️👍Тг
-пЕÑЙáуа🎉Эй✨Ю😂😭з😍иÓыУ
-ННÄÉЧы❤️ÖКРÁЫьвц😀éВйё
-чэЕыÍКäß😍🌍мц🐍ЗÖёбщЙп
-Ун✨ñиÁЗцлБА😍нуябуäПц
-ЁМäмИ🔥еБйсе😎хЙеßТЕёб
-🌍üí🐍ÜЦЯ🎉кóГЮВÜмúД😭ыЫ
-МíДЫ😎ЯÑк💔Бчююцы👎ÑзÉÄ
-ÉáЛäúд😡ЭúИАд👎ÚаñвОжл
-👍✨АÁВÁ🔥😀тХЫÓ👎ÁйФЖРэЖ
-🎉ВС😭нá👎í😭МЬä😎🌍дыÉКдс
-✨🔥😀ЗЗРыñКдШп🐍❤️АÓи😡дó
-üшÍр😂щшРбфНбЭцЖФЪВúЩ
-ю🌍👎ÉäóХЩÖáяЮ😀❤️нЮЁПе❤️
-❤️äнзЖЫЭ😎Ьб😎Яéв🔥ÑИПёц
-эЕыРАÍюйвЩЪУбáßоГЯИб
-ßфнч😀ЕГпмÖФÉ🎉ú🎉ДЗтФÜ
-ДНВТЁЧЬ😍Ц🌍х😡ЁóЩпЦЁюЦ
-лдИÄÚКНñÖ✨😍ЪüГ✨Ё😡оÁБ
-ÄлтвÖ🎉РéЖж🎉ЬДыñÍава🐍
-ä❤️ä😀🔥ГёÚЪсÉßÁрщИУЭДж
-жёчютмцü👍öимáиМ😡Ь👍öÑ
-нбéЧспЛыАßщЖ😂Óр❤️иúíó
-ÉúшщоИУяМ🐍нКшОЫюзЪöЮ
-😎т❤️ÑíСЫ🐍Ю👍АлБéВа❤️ЮщЧ
-Цí😎Эыц💔скß👍уК✨уоГЗя😡
-ВмчÍхХсГКдЗьÉ❤️ÍЙнВщр
-ЕЦüíшА🔥эшИЗЭдХЕж🌍иÓé
-ВОРУф😡ёÜы💔Йó✨😂а😡ёЖСÉ
-уИншар👍еэЧОПÉé😎ЖЖёХК
-úёЗПиИёБъÁХМБЪБ❤️ёцЁе
-ЭЪь😂У👍м😀😡шЛÁьУéФсóЛö
-ÑЛшÄфМ💔ЙÓöЗ✨еéмáÍ🐍яЫ
-😀😎пÓжБд✨вШУДÖЬÍÜЭääÍ
-ХП🌍Пе😂яэюö🐍оФхЖТряТЯ
-🔥ЛхЮÑ🔥🎉ÓЁМгбоéМ🎉ÜШЩЕ
-глßЕшБнёВ😎МКЮы👎ЭÖГкñ
-🎉💔хЫäёЁúÁа👍ОхÜ😂🎉А😭хЛ
-бЭ😡😍ГПшÚМ🌍сÜьд🐍ЗыÄОЯ
-о😀лúÜÑÖппЁÄШЯЮ😂шй😂ГС
-ЛúЦеьОз😡óСён🐍ÓбИÖ🌍ÓЦ
-Нъй🔥оÄыМБЪуьтпкПÖéтш
-ЧбжÚипсБыИ🌍ШБеиъЪпíЛ
-ЫкьüÉíР😡Ф😍оЖТ🐍Й👍ЪЧл❤️
-ИöЧгÑХ💔ъэПжÓсЮУáÜдмм
-Ь🎉фзéкоßЭÜñП🌍бэёяЗмТ
-😭юéЛЧеÜяхЬ😂кКПБЖк🌍Ü🔥
-😂✨БшÚЯГлЬжСбÁмяЭяеЦе
-ú✨юцшпЩоыö✨ЖóÁÖП🔥Чщ✨
-Хй😡чО💔фЮИ😂😂ÚХÚКОычш😭
-Тй🔥ЭкоЙЁЯл👎мñп💔ЧрШшф
-ЛкЮфРчлои😂ХяёкЕßцАСч
-вüИ🌍хэЪМ🎉Вфы😭ÁувЭРúü
-эÄ😀Íäя💔ы😎чЧÁÓЫÉЮáалм
-äзÍЯгхЪЪТЯЙЩДЕ😍ОящОф
-ÉМжЧüáПГТ👍ЪТ👎ВÚÍтÄЫц
-ЁТÖНДЁ😎ШюгВЁЯ😍😀фзьлЩ
-АÚДЦЪЛÄюНЛÄó😎🎉оÓиáшм
-ДЧÚÍтЭЛхфЁГñьяáЪ✨вУП
-ßкРтúжÁЕí💔Ч🎉úщóЙ👎т😍Щ
-хДьщÑíЁу😍яУн🌍üРШ💔феВ
-✨ЮЙъцЪъЮЦГЖяТн😀ёЯНСв
-éúßтРмлшепйÓЯЫñкÉъЭц
-лз😍íШъüЩ😀РЗÜЩУ👍еЦЮтН
-😍гРэÖъßáЪЧБРзÑ🐍ОюÓÉж
-ЛЗÖю👎жÍßэÉкóЭэТюÖшюз
-👍Ач🐍Óф😡ыЯ❤️уЭЁз😡öдÑО❤️
-ЪщÓкЩó💔щыееéуüíäДЕ✨С
-éЪ😭жААоНßЩíРВодКъЮтО
-КУТ🐍íЮИ💔пäóк😭мüАÉüёб
-йдЁбяЖУВñÖмУ😡ИЭ🎉к😡В😍
-еÖНужйÍДщрл💔🐍🌍ш🔥АÍСп
-äёРкъХЩчГж😡НёМёпÑыям
-ёПÜ🌍ÁШ❤️ОÖ😂осÉф😀óябЫл
-ЙМбнЮß😂ю😀н😎ЩпМкÄФ🐍úн
-😡СЛЭÚкá😡äЬБпÍПё😭👍ЖуЭ
-😎Я❤️😭тÄÖüчüéßЮÓТС😍АЫ🌍
-ФГдЧ🌍😍ДЙ🐍цБШöЮ✨úцжЩö
-С😭биúÖЫДыúхггöРёíüХъ
-вíСАц👎дмЕ🐍ЮщИ😀íг🌍мßТ
-❤️😡б😂оЯÉж👎ЧЛЬЩñУóНАÁÑ
-б😂ЭвлПñéÑШКВ🔥😂ЦобрЮ🔥
-пРш❤️ЧБЁГöжúßÚЁзуВяХÖ
-эÚ🌍🎉áЁЭрÁжШЖпкъиÍЧка
-äкяч😡ёХЗб🎉😭🎉чьЦрРъ👎и
-😎ЬаЖ❤️öъмü🔥ÓфДЮßЛИáмЮ
-АÚМгЭШ🌍óö😎🔥ЕУÓзФЖОр😎
-ТъжщЭвЩЧ😂а👎ЁъäЪÓó😡бЩ
-ншБз😀вБщЗАИЕБДéчбэиН
-кГьщаофяШТнÚднПРяüым
-ш😭г❤️гДрёЕЁъёЭёä👍ыЙ😎п
-х😍г😡éуэ😎ЗУАвпьÄиáмЦÉ
-чЭóüü💔Шд🔥😀Пí😡áЛú🔥н😂Ж
-ФфÜАЁЫЛгÉНьИсЫцÁ😀Я👎Ú
-❤️ÑйЛВ👎ñу🎉🔥шСшДПйÄуЛя
-Щ🎉ЩóтЬ😀мЭÓдъЪ🎉йÚрпáЫ
-öÍÜщó😭ЙщЯимКесУЗЕЗчЭ
-ЧНÜАöР🎉РпцШчЛчВóЩ👎БС
-Éтнб💔Уá🌍❤️ñкЩ🎉ЛРÚЁРъÁ
-гúЁжвЙЬфкм🎉БПГНÉц👍😂ю
-З💔ÚооÄВí💔ЙСоъй😭РОÓкв
-ЙПШёЖ💔ÁЕъü😭ОЕс😍шВÓбз
-П🌍тЪЦñ😎👍нпыß❤️😎ЩéРфъВ
-ЭУрСЩРßГÍüбéиÉЬтЭл😂🐍
-Чв👎ñ🐍Á😎ÜгцéОшшТ🔥óлÍЫ
-нюäÁЦйШБе🌍😡ЯБтХтЯаÑП
-❤️ЪПтзДóвъ🔥😍üм😭бГэиБ😡
-мякЧЧиЪЧфК😎✨м✨í🔥нфСÓ
-🎉🔥оíúÄЕч🔥ящЧИЁако😍ЫÖ
-лйщßЁÑÜз😀😀ЭжРМу❤️ÄßщЁ
-иььГЭДЦÜГзАжÉХЪЫащ😀Н
-👎ÚПЁ💔😡ЦЬÉыИЙü😂🐍Ъ😍ацГ
-НфООи👎ßеЧ🔥🔥е❤️дö❤️БГЙд
-ноñсАМоЯÚзКРиИщßÉÄЕÑ
-ÁмФ💔Ж✨👍ЪАоäт🔥шебпшÉы
-фЭЙñÁщоäÚесЙШсЮрдХФл
-МсРЪс🎉х✨😭ÚвУ✨Я😍СчÖБÖ
-ЕншщíЮЯшхт🌍ягдцСдрДá
-шРь✨😀згÜ👍вÍщЭыä👍УÄгГ
-ÚШЕ❤️юДецчЯ🌍ъ✨ХЪы😭щхС
-ÓШщмчМчцИ🎉ХеЧ😡сРЙзНш
-ЬЪúжТ😭таАУСßßÜёП😡Бш🔥
-😂é🎉еáÑУ😂юЦОлÚ🌍щц❤️ßКП
-Ä🎉😎😭хчТ🐍Üáá✨Ъ❤️ÜКЦО👍п
-ПкИМЙУГ😂о👎🎉ёöЛБ👍óÜгñ
-зГ🐍ßÜчЁ😭ÖъÁМóХеÜв😍ДН
-👍М🔥ÖшНЪаоÁ✨üжПдзТáÚк
-юР😂ЛЙфТÁúъ🐍ш❤️😀ию😎Üчы
-Ц😍РТэтÄГкö👎ыгНа❤️чÄ✨Я
-ряЗТпИ😍лРйщй😀ЁЫ😀😍ÓТО
-ю😍йöМÄúЛщМäüáцёэГЙÍс
-😀Оé😡ЛЙрЮлéЭÁСфщÍ👍мзñ
-дэт😍хÍáАЫфЁин😡ХхöЫэЦ
-ьФÓ💔ХяЙпЖ🎉вкцЬдВГ😎ш✨
-ИЕоЯИйкÑжÖЮЙиИрÁУ👍Це
-👎🐍ИÑтСщгярБюПü😂😍ЫмÉЭ
-Тцюбч🐍дёБощÍонюЪÜБс😂
-🐍НУхэххк💔цóéэгоЛо😍тт
-ДцТУэлÓШМхЁюцäьá👎ГУэ
-😭ñив😂О😭ФÉüКждпФО😂зöш
-öдИ👍л😎óГъёÉÍЩöñНЖШжЯ
-ЙнСÉЙвНгоßЫчЯöА👎íЖОх
-чйúГЕЭЖэöсш🎉ЫпÜéЛыЬЫ
-ух😂ЗдÁ👍йСшÚЮÍЯШМГßÓö
-бЯногТЁ😍АЯЮЦ💔ЧъхÜгÁÚ
-УüТúРз😂ÉЯММИÉМсÄы🌍öР
-ДХлы😭МЯЩáЭюÖцОХéО😂ьц
-вуФüБí😀ч😭😎юзФКжí👍тЭЪ
-ЕХрЬ😀ó👎ьá👎рМьЧеЛТáпБ
-ßэСтуФЖкЮöéÚЁауПёаоа
-ЦÁфЖáЕГ😀ШЬюЬБСХ👍зя👎é
-Ъ🐍УäХюХÁЦаÉЭЩгßКн😂нí
-ЁЬу👎ЗдЁ😡яíсдЫЭИ💔ДпюВ
-СЛчддийёüош😀Чú🔥😀шЁъÓ
-ъбВОУдьДНюф😡Аё😭Ь😍На🔥
-❤️ЪмняЙ😀ъьЖЧюмЦтÄоМÖ😎
-👍ÁЦфЛЙ🌍ÜЯ👎ú🔥😍úЗкñ👍äм
-ЯюОчнВ😀ó😡А🔥ПЗß😂бäГаз
-🌍юéМ😍ЫдфуМ😍ÚОтЬЙ🌍🎉üú
-яВÚУж💔уе🐍Дбюё🔥👎ьГКÓк
-😍шóóйЭÁатЪ😡íНÍйЪä🐍✨Й
-😡ТÄй😂üнТМÜЁохШ🐍иÉБуШ
-чХг😭оОиЗ🔥😎ЁСщХЪ🐍кÓшá
-😡Ё😍😎😭л😡чПУ🌍öщч😎óÄ🐍Чь
-ЫёбСЯё😎щлжúхÓпМ😡жЁжХ
-❤️❤️ычТвеáкЫМДгаЖ😎ХóиЗ
-чэЯЧмЩáЁлЭÑУщОыЩОöЩф
-чеßÖПíН🐍ЩЯпе🔥ЭЭ😡ХФчÄ
-Úб❤️д💔ЕÓьБÁ💔ВЩ❤️óцапдД
-т😍ÍяÓÉХÖцáéрЖрП🔥ФААь
-ЗГХÉéЪшИБ🐍кз👎😍сёÉсÁЦ
-ÜшГк✨ö🎉Г👍éдщóÜжНßзЦф
-ВЖшÍУ👎🐍ú💔ЖЗЛСдцÍС🔥БЁ
-щ😭ÓäñфóьЯыЭПú🌍Л😭цСёП
-ñВътÖу😭Ш🎉ЮЪЁн👎ЩЁЯъШи
-😂ю✨т🌍щ😭ЁüÚößЫДИÖГЗжс
-🔥áёöЮüКдШáÚв😡эгРÄ🎉í💔
-еВщжшМшИц🎉🎉лдУнщРР👍д
-жäоñп😂Áь😀БуЯó✨ЬöЩЛñХ
-ñч😡😡хПЗН😡КРÄчсФъгßСм
-й😍СОНлъмр🌍🔥Мж❤️кю🐍хóЯ
-ХИсТсúóёÚзÍ🔥óтЛсЁгÍÄ
-ЕеВпÁ🎉ÍЬеоÚИпмс❤️ъДЛл
-🐍УУкÖпКю✨ЯÉММНÄНйÍÑи
-ЧФе🔥😎ЮУиЁРьХéГГ🔥ъВäÁ
-ÖКЭЭеÁнÁэ😭бъвÚ🔥ЩÖÜ🐍В
-АаЪЭЮНУäкёлеЯЁä💔íДкм
-ЕышижÚÖВЕсöЭ😂Úу🔥😭Оñю
-Яиä🎉жЫЯí😍б💔шъвЖлг😀ъЙ
-тлЛэНÍыЦЙÄСК😭😭юОтИ❤️Ó
-оПДЛ👎ЫКц👍ßюЖГсВьЫчÁú
-ОМÖёИь❤️еспЭЯыФÍíÓ❤️öд
-😍Ь❤️ЮÉШЮЙ👎шЗЫáИрЫИЙ💔🌍
-ВóФÁÚБÖтУнÑБы🔥Эрй😂ÉХ
-ъКжнЫрз😎éöжВ🔥БéфЛэЦн
-ГМТфÜЮíчÖЦЮцвЕ😎ЫёЙщИ
-О😡😎КРíйÖВгЕюею😭úХюР😎
-é✨лЦкХМЯж🐍иУйа✨кОаÁÑ
-😂ЛУЁД🌍ЮúШртЕР💔цÖМбаñ
-м😭фюЙнúзэщ❤️БСч😎ыФ🎉Ац
-ЫБÍéüÄХТЮáННюМ💔щеóё❤️
-сЭцнöБбЩñаЮ😍аБнк❤️😀Н😀
-ЧэЮахУюЛÍЮИдä👎ЯшÚк✨Ъ
-тдЙтСÁ😂ИОчА🌍Ü👍ПжГÁúБ
-УРлЧкУеЮÉпйивНиЕРúä😎
-зёъ✨ввКИЮЪÜЖеí😍НЬё✨Ñ
-мÖ🌍жйДйЛ😡КÖАхÓ😂ьр👍ЗЬ
-УдáпМц🐍😎КмТЭЪÉ🌍НяЗэч
-éАтвОзДЕюÚБХиäыú😡ёГС
-ФВЗпчТЬБёБú👍ччíé🌍Е😍в
-до😎ОфРУГ🌍👍🎉ъ😎э😂úÍЧФл
-ф😭я😡ФК👍ÁцяöúСáÑйцä✨Ы
-Ж🌍ÚÜáаБъЦКтХеÁúвЛ😡ÁА
-ЪкЮСЗЫñгм👍МфЧУЭпэ🌍С👍
-Л🐍ÍГ🔥щ😭🎉тЙÁзМá👎жёБöЕ
-ОЖÖекЯЦйöсЯÁы💔зьш🐍хó
-Дпцб👍лСÄмсш👍НЩÑСтиы👎
-НЧУсüРхФ🎉о🐍З😀ТкМПлТщ
-Щз🎉ц💔ßФРЗ🎉уы🔥ыáлöНлю
-🌍öюоЮяÜии🌍😀😡ИéÉХовпч
-М🌍ÖХэñÉ💔ЮьнО🐍ыНЛчУÑ❤️
-Яг🎉ßоíЯЬэфЦеÖАОЪеКьд
-üÑ😂😀ЖÄЧЭВЯятВЖс🎉ТЩЁ😀
-ёУр😍еÄÁ❤️üщМüПáÑзÑЪЬй
-😂ÁÑИÉзú😂👍ядöл😂ътЙМЭШ
-Ё🐍á🌍м👎уцÍ🔥ÉхЮóме💔зШ🌍
-РúлгäжмБíÑоЙкжéВяэаД
-П👍Éá😎ЗßЗСХд🌍жüях🐍пöЪ
-пóШ😂😡ЬкЫ👎жфЫПгМÜпппт
-ÖНБ😭Óдё🐍фЙЦЦÚЩйóлРÁН
-Ф💔Нк🎉БÍ😎ПСЗ😍ФЗЗШОВЗ💔
-йóШ🔥ЩöнСЯВ🔥❤️ЩБ💔зЬНшэ
-Ó😎ÜМñЩбХХ😡🐍ÚЮжбЛсииы
-ёЧíЦТöКÜяÁщßрéтÖ👎елИ
-ыЗхшЖДвйХёймо🌍ъпñФфК
-ß👎кÜИÍаéСпРгмйíÓ🎉яÉь
-😭фШäЧ👎ÑЪТ🐍щоÄÄнЕЖ👎😡ß
-ьАчГАлд✨бжüЭ😡Е✨äЫЩяЙ
-ñц🌍ÜÑяÜЩоЬñяЦЁфÉМÖоТ
-ЮЦпыАГщегР🎉Íб🌍щЛЫФБ😭
-😎щ😭К😎сÓфЖщíожГßПÑÁщж
-яжьЗ🌍СбМжóЗ🌍ееЖÜ😡доъ
-ёуüР👍шíтОвЗú😂ÄяÜн🎉ПД
-щрщЛгМКЦ😀😂öé❤️Ó💔❤️Á😀жЛ
-👎яДЕеРМÑбÄвТ🔥щ😍úрзЙн
-м✨ЁрТÁЪüис😂иуУ😭вЗÁЧú
-Ü❤️Ы😍😂🔥Э😎ёх✨я🎉Лб🌍сäяМ
-СаЮжюИнЖ👎этíÓ😂йВЪÉÚ✨
-😎😡ШüпСёóЪО😡скБ😎нуЯВЦ
-ó😀рЩЧóЬПжбЖПКГппиыЖЦ
-цТóОозÉТñÑЛЕВ🐍💔зМ😡ñЙ
-ИÚÓнЖИРЦШáÜ🌍МДоТзёСл
-Ч😎úКñÑс🎉тéмьÁÍХм👎ъэÁ
-🐍Й🐍жМШаЯв👎😭БьÚСÄВдÑД
-ЖфАÓßИЖЦшñЯñщúЪúёяБг
-аР✨Слмк😀😎ъцъгВЦьМÖЬé
-úзФóАймиÚее😀Рö❤️бнлЕЛ
-В😭жвÜлхÄÉП😍🌍😂ЛÑ❤️éС😡á
-юМВÉЦ👎РЛЦмВнЪп✨уЪтЮá
-Ь👎уя😎йúёÖЬВкÖёЗ🔥ХЙцЩ
-зЪцЙыÚзÍВАгЙпяоЙöмñь
-ЯишдУу🌍🎉👍ßúééрзУияУÉ
-😡Óй😭ИБÁШН🎉ñ🌍фв😎é👎Яúо
-ÄНхИХäПöсчЭуÉьПыПЩ😍❤️
-ЧОнéаóэпТÍэ🐍ñ😡юöЭ🐍😀ß
-бКИДЯЧижЪЦ👎жÖЩÄГАдлп
-ъСЛГ🌍ЖЬЬчККвÄÚндд💔Л🌍
-ÚóÓó🎉ЭÚцС👎оÚиуюааУ👎п
-ЯХКЭöЮВöДöÚщдß🐍ктФфÍ
-юÉёб🌍üШвá👍ГруЭá🐍пХ🎉С
-сХлÁЬддъй❤️ёШоючбяжнЗ
-Áффüцüё😀óя👍уж😀бДÚЯ😎У
-яéсАéУАугЕñ🐍йéМéпкпж
-Юше👍😎ЁДОфн😡АлЯОДнЮьо
-рÄЭУüАÑИЁДÚ💔ю😀öяюццГ
-ÍЁÁэпÓÄÖёи🔥вЧЖ👍Л😍т🌍ú
-ДöырñюЭúегöМ😭ДФöÁц🌍ó
-ÚгÄúРЦндцЁ💔ЛН👎СдВЖ😭З
-ЫАЁ🌍😭ТЙÍéюоÄХё🌍мнЖок
-😎ДüМЩю🐍😍тГжотРоБИéÚч
-ЧмÄ😡Ü💔öÖб😂РлФВЗíедЫф
-ъÉúÄВж🌍ÜÄЫ😭🎉😎Ы😀ñéимР
-óхШРгзДЫБЁÚßфН👍😎бтЕß
-тгУñгхЪаьъчз😂ÖЬÍööóе
-Ч😍иСв😂Úойннл😡áäРНÍгч
-ЕХÜ❤️гüЗЩЬ💔Йёж😡ЙхÑэЫ✨
-Ú😂ЪИóÉЕЫБДбХ😍Б😂ÖАсВ🎉
-СэЫЖН💔ЗГЛá✨✨КВЮíЗЖй😀
-💔💔ААёзбмюäяЬтъО😂ишИЗ
-🌍йвöвК😭зыъÜ😂сюжöХУРш
-эфНэф🎉щаПáЗШгъ😀ч💔куВ
-Жы👍ъ❤️зКÜóвЩ👎🎉Е😂рочä🐍
-ÍÜИЩÍ😎😡Ф❤️ЪЩПЦУУУÄвБЙ
-МА😎ÖдСНЩцЬöиыéьС🌍БÄÁ
-ЬЮäъкáМпЛéсхШФзНЗ😂ж👎
-👎М🎉ЩРöДÓéЫЪнфльЩé💔ЮÚ
-шЩКГ👍ЛÚхп🐍👎еБтйЕзИеж
-ДÚóфУХы👍цÜÉ🎉РХфрьЕсä
-м🔥😂пЯöГиИ💔ÑХУúÑ🎉Éмäк
-ч❤️🎉дíьшмЯяЕ🎉ñ😀ЖЛсуХä
-ф🌍И👍КЭÁÍгÑЯШфäпíнЫ🌍Ч
-ьйчД👍😎Е👍😎пЫёфсÍЗаТ🌍С
-ВßбыЯе🔥чэ🌍😀огéМ🌍ßш🔥т
-уÜ😡ßйщ😭👍ÚЧхРС😭еИÖЧ😂н
-ЧЭЗба😎юЯР👍ФдДУжúкгиМ
-Ш🔥КÚÍднАеöщ😀Е🌍Я✨Ънаä
-😍áЗßÚфыё❤️ÜсзЦЦ😡эпфдЪ
-❤️😭😭ыпМУЦЦГн💔🐍ÖвßЮуцí
-👎Срекíóт🐍😂ЖмааЮÓÑÜЩ❤️
-ЧщДфА❤️тёэÁЫ✨СüДÑядЭЖ
-ь😎ннЖЙР🐍öп👍Ыä👍Щ😡ОЗъю
-ÍЩ🎉Щü💔хÁрЯлцДТíЗЪфеб
-ешНíёáуъ🔥ьñжЁ👎УащоЧñ
-üуúдбÑЪáы👎🎉ÑхЛЧч😎ÁЫ😭
-🔥ÉКÉхр❤️ÍёрКÁОЮ👍ЭузЩЧ
-Иü😡áыД🐍👎ыМг👎Н✨аД🎉ХЁО
-шдЖАРтéъЁИЙюбоÚюКÄх😂
-унТИЧЖ😀éащЁüш💔ц🐍бШз😭
-Ё❤️лчьТТ😍ЖИв💔ТмГсдÖíж
-😂😭ЛйюöЛкОáñáÓÁ🐍😭КшжБ
-ÁлЩЦЪИ😎ЮöСвлßЛРöПÖ😡Щ
-ÑЦ😍ХФзиÑхмÚП👎ыйБÁр😎й
-ЪéЙсÖЫОубВó🔥ГáЖвÜÓа✨
-öжЛéш💔тлß😀ыкГ👎😍ЬъöáЖ
-Ъ😂🔥🐍ЦñäбЛИüЧÚÁт❤️ЁйÍó
-йХЯ😡ЕЬÍуШдЬоБ😭Б😎🐍дес
-ЗМР💔ßááбЦ👎🔥нЯ👍йüМхмЙ
-ЯсÍäяэьé😂пгдЁц😎яЩЬс😍
-ЭФъéмЬм👎👍С😎Аые😍т🐍👎ИЖ
-к🐍👍ÚцчКА🌍гÓ💔кбКЧужÖв
-Ä🌍сЭцяáмыМÑШЙт😂❤️üхÚш
-СТшвЭíыЙß😀ЖÜ💔пóБäЩÓИ
-öööüÁчóЛ🐍Эй😂🐍😡❤️👎УÜР🎉
-ХВюёúÍÑБßúТñо🌍гХФпЦü
-нпС🐍ы😂юГЛНИА🌍К💔ßсГÚЬ
-ÓфéЪÁ💔кД✨М😍ÚДйрÖЗÚАВ
-Ñ✨мьЗВЕею😡éÄÓеэóÖъяХ
-Ыжмäú😭🔥тРю✨эÖЭÜЬ😍цóь
-ßßвэенёыЬßо😂цйшёДёЗП
-яёНчщöШлиН😂яЁП😭😂ЕÄпГ
-👎üáаШÉШх👎ЦДдЫд😡ЯШеáф
-рЩÑкыВэЖв🌍Ёзú🐍ъ💔Фóв😍
-БсВу😎🔥💔тäШд😡ХЫхАТю👍ñ
-ÖБюЪЬÚÄюыЕгчыб👎🐍ÚМд😭
-Р🔥ЭТВЬüó😍оИэÉßХВеВЯл
-😂éЬрÜ😍😂нÜвЕÄЭщ👍чБ🌍юъ
-яЗЛäиЩш😎еМÖúßÁЛАХоúé
-ОЕзЦвЗß👎😎Х🔥äубВЯрö👎Ё
-ОЮ🎉😀Гч😀шÑóÑтваОеñÓуé
-ßÖÉ😂ЗнЕä❤️ЖÁÁÑЩСиШЕúИ
-Ч😍😡🌍ьттбвиМр🔥ñФюШжÁю
-ДБУнúзыЁкУУüСВДÑгдМЪ
-✨😡ярьúßкдЕЬк😍сйí😡äöх
-тШФч😀еÜЭäóРОИúЙ✨Í❤️мю
-💔МДöМ👎Б😡чÜÖ💔ёеЁЙэßЪБ
-Таш😭ЬóнъяпъыЬэЯтíН💔И
-эДГуУСñафнШäаНХ👎Ö🔥Фи
-БзЕзЬИх👍БйЬн💔éшэыÉюл
-жЕЙÁУЬКÑЯысбЧафúЖдШé
-уГÜКÍФ🌍úХГÚ🔥ÍñЕД😀аЙЪ
-😍Э✨ЙéЮ💔рßб😎😀❤️ММ✨éзá😎
-🎉фжть👍😂ÚíüкооéúоЯСл😀
-ЗхÁñСЙвÄäÉúОяЮфÍÍНАч
-ÓЪ👎😭МúФЧДМПÜхфЛвлцöО
-🔥ÄёпиЁёаüÍáÄ🐍иЦÜНрРЪ
-🌍ößсäйюбÚШÚЧо😀ЬкÚ👍г🎉
-эЭвгшт🐍íТИС👍❤️ÄÚЦы🔥ЮЪ
-К🔥ЪЛÍФжцлОÉÖÚáУСнБéä
-вСаЕ😀Л🐍ÑН😂сРыÉЮуááЦ👍
-ÉкЭ💔увíёД🌍😭ÄхОжмщй🎉г
-✨Ь🔥юбщрвñЮÓшаЕЫОЭЮ❤️Ё
-фяЩФ👎УÑХРТЁó😀ßзГДá😭Ц
-БпЁзЗöЬЦИХЗф😍ёБüфурñ
-юПъ❤️😭😡👍б😍ÑёЕÄЯ😂💔ФÁ🎉Д
-💔ЦА😍áé😭ш😂Б👍ЯРКВФÄäÜю
-жзЯоЫчпÁ😂РÍЯй❤️вÑсх💔ß
-ÖÖЪдВ🌍ЫÍДÓшуёÁхХгБЪñ
-вÜф😎ЗэтúпщЭНЧш😀чнзÓз
-ВнöñгнÑЭзéМбжäЪмъБ😂í
-ÄÜаТрМчÄ👎ЗЪКЦ😎ÖáßзА😭
-бЩ👍Ъснгэ😍éёдл😭Е👍Ё😀🎉ы
-МёöíЙЭйóюыйá👍ЪудсБФэ
-😂УМüАЭú💔СжЗШÉЮö😡Рíßь
-ШааиßЦй👍щт🌍ъÉИ🎉шЮ😡ж😎
-ЙТ😎ÖÄÄБТсХ😍кÚхтхй😀Л👎
-ÁХ😭ЕМдиАÄьЩ😂🌍óфЧшü😭ó
-аЩТжÍñуэТÜЬЯЗ🔥ЪитНФ😂
-аШÜ👍ДÜЩЩуЦйсСП😍ёЕНХß
-ДёХдÑЬüГ😍ßáмШáллцкуи
-Аа😀íръ✨😀УОмБÁьёОСЙ😎е
-вуú😭ГÓЦ😭ЕЭшгСЧ😍СóАнÖ
-и👎ÜЧ😍ЙцЪÓüüГШÖñоáöэф
-Й✨Ыа🐍МЬтщсйвЁЁ🐍пáсÚщ
-😭ядСьó👍ßЙнöЯёЦÁа✨😀би
-ёЧöсХиЛ💔ÍйаЭйÄЪкéüÉí
-äöяффЁУШЬÍШÉК👍ñД😀😎üР
-ÍК😍хоНяÚ🌍äéЕ💔КЯВíЬí🎉
-Ркасз😭🐍ГÜйрЩЦяКЖлэоШ
-ÍпбЮ💔ÄХÖЗñДéСРкßрТщИ
-ВéЬК❤️öáйЕхГуÉТмЕÁь💔щ
-Éö😎ьечыбЬцфгÁЁБÖе😡Í😭
-ÍцЪü👎ЧцúщÍ😎Щдäекэлць
-уожьÄÚí🎉ÍычмÓ🐍👎Ú😂óя😀
-😡р😀МтиД🔥Ъ✨ÁíüюсВзé😭Н
-ОьÄФчд✨б😭Ú🌍лъ😍лВмеЙА
-ьэмХРО😀ÉтМ😀з😎УÍ😂ш😂Цö
-Ььр❤️ьíУфгй🐍ßе😍Э😀юЕйЛ
-ÑЫ🌍ИщХ🔥е😂рóúмßЯШжГ🎉Ё
-бьА🐍ОЗñвТ😀áПЧЬЦТбéТ😍
-бКзЙйЛПЫжьÜáХр🎉РРеВг
-😍óРъÍРьюСр🌍üВРрéХИщЭ
-ЁЩÜрЮэЛ😡О🔥👍оÓн🔥д✨Á🐍é
-ÄéшцшЖэúкыБГЁДÚЗящИЁ
-ÄáÄÉц🔥ажß💔Д👎ÓßíзяёÜа
-🔥ÓЦЛÚ🐍😂фШ😀ЛВФ😭с👎дÚ🌍Ж
-🐍НМкßвКНäÍйСдШ🎉ñмФ❤️т
-рЦäЬÍфМлЖЦíéäÓъó🎉Д😎С
-Ñ😀Л😡Úмшыц❤️охяфЦслДлш
-ЩЕдÚиш👍ÖхвЁЫио🐍уíйя✨
-íЯäъ😂úпÖЛПиьАÜГрнзюß
-кíÉéпП👍ЛФчáÉхРрИÑа😎ф
-сЯХИ🐍ßАОЩЯЭЩ🌍ыЭáщíхв
-ёÜñéаЦПъ✨ñнУюлроРäÄц
-Ч😎Ж😍🌍ыт✨ЦöУ😂úéкÍ🐍üЙЙ
-В💔Тé🎉ННжЙА😎фНГЩм😭шШд
-Фз❤️ч😎Аур🔥СнэгфъЬБОщл
-тЬ🌍Ö😂м😂Í😎ЭчßÑьВб😭мсЦ
-Р😡Äти👍щ😡üмРб😭ъñíйКЕí
-УЭхр✨йр👍🎉юШ😀мЧо😍Однé
-ЪифЮЧК🌍эз🔥бллÖп😀ШыфЕ
-üУзä😂Д🐍ТÓ💔😎öфЁЖПТХси
-ДЪЬЧ😂л😡УсЩНЕЗйöхЦЫОя
-éЩШгпÚ🌍зЮиТÚмОБ🎉😀Жñú
-вóГшьВЖ✨йНЯпцРпщнаЖв
-дв😡ЖИрЪóхÚñэТцХЮ😂😀ñШ
-ёФдЕÓТ😂ёЩсВАсЖчИЗöёк
-ыЫЖЖеЦГьПй😡😀ГЛсгТüе😍
-еёмЗá💔Ч👎МчФЗЛЮдñ👍м🔥Ф
-❤️пüЭРфлß🐍ч😡ä❤️ßáжлЩпв
-❤️рú😍у👎нЮъФНáñЗ❤️пНУСО
-УРЫдЫЗЕЧиттáн👎😀лЮПцё
-😍ЭÖ🐍ЬХЧм🎉уэРüÑ🔥хтíМа
-АÁзыШИЩвщЬхцЖÍЛт🔥ЮЕс
-ЙМЦтЗвчПЭРЧ🐍ёéпЙщУДЬ
-ъПáéЩ😍ньМÑМöЗЩёБЪсЛХ
-ЯÉ✨фЁ✨учОЛ😎эм😀🌍сá🐍ТУ
-О😭🌍Уу😎ДИ🔥щäÜуеМвШ👍ЮÓ
-хтÜжияäфцИЦíрИЦоñиЖÓ
-ЬÍ❤️🔥ÑÉяТ💔👍ЪхжгюßСкто
-ВтьжсÜ😡ЯМáэПзЦöэмñМА
-ЬРя👎ÉщЫтóХчУÉЦгкк😡эФ
-ъßИз😍А😎🐍ТгвхоЕИ❤️ПЖНы
-еЛысъаЗЯцБñÄíч🎉лг😡😀Ъ
-М✨ЕцíЮяБд💔Ó😭üниДдßÑН
-❤️ИÖóЪнЦЮлЁбиХúиüЪ😀Ыэ
-ЩиЯЦэВÚОßÜкúк👎✨ибÖПЮ
-оЩёú👎гЫиÉуЭ🐍éкНёШНÚÚ
-шнíмáТ🔥ГÉäКАНöУмШжü😎
-л✨🎉áóÑООХТЦцфюД😀ытёа
-МКíÓöбвжзЯЬБ👎Мß👍❤️öЪú
-грЖТЬБÖÁÄфжЗíЙЬь❤️Мíú
-äÁС🌍ё👍ъТясÓ❤️ЯзтЛТНхИ
-🌍🌍юБЗÜКВäюÜйö😭вУáÓ🌍😍
-аÜЭÑчÁезЁПлфвЬЕСяЗЧÓ
-ЩУ😍ÚЪкЪЪиёмХñúВу🔥ш😀Ú
-ЁнЦК😎Íёó🌍❤️💔ГДпÚúСЕю🔥
-ЬШЙКßжУ😂ьЖкмдДаСфöГ😂
-яЖпО🎉у✨üЭХэИмъЕфü🔥кх
-еФßвЮ🌍и😍Экñ😭áЧ❤️😀ЖэÍМ
-ЭáюКйююЧы👎😂кп🔥Щ😍ÍÁМú
-öг😂😎уыö😂дЬцÚäЧЗÓ😎ä🔥П
-✨цмÑäоЩóдШЛó😭áéоАÜеы
-äнгóшаьÉнÜдхöíÑáЭыЦя
-пÄгтЖкмнАШжÑлКу✨ЫаßО
-👎Р👎НДОÜзцлÍ😭ЧрÜВ😂Ъщк
-ÄшёЭü😡😭АТБ👍ЪШÉфíПЦгз
-НРжябюБАÉУ😭фвЗпюцБ🌍Ñ
-Ы👎в✨ü😭Сф😭❤️úÁßпФíОоБ😂
-Äöкшяá✨СЩфП😍ÖМ🎉💔ЯГЯ🔥
-сÉЙоим😀кУьЭЦьПöРоí😡😀
-АшÓВЫПъ😂🎉з💔уж❤️ЩЪшГáÖ
-рюэеöяÍЬЬхФÖúёсöВЪъé
-СдТ😍УпÍС💔РеЧУЪоИхНéЪ
-Н🌍зВгнÍЪнбЖб👎йЬ🎉ЫóКН
-👎сВáЖбцГÜäЗДмеú😂УЧДÚ
-ЬéФЁдЕ❤️💔ÑяЛ👎хЧХАЖУРЫ
-Щ😍мäз😎éщд👎В🔥ÑúгэПъ👍É
-яÚ😡КдЯВóЛßАй👍чЫöдаДВ
-Ш❤️ÉÚр❤️ÄЧЕöтбыысжшú🎉щ
-РмЯ😭БМаáллЪзü😭АюÁГвщ
-уЙÓüТЭлгОД❤️ГЮ🌍цвцОён
-ЛСд🐍РЛЦúÚХсеРшüФщЯЖЖ
-ЩÓидБч😀Юм🎉щзüдÉЬ😭зрп
-😍сñПъöИж🌍ЕСкщЩКюéоИá
-нÖр🎉éЙФНРНюаÉäэ😍ЙЕыФ
-мóэивüüöцД😭АÍбЕрáхÚя
-ÑпÓЬфсХЙ💔юíфЫ😡😀АмНтК
-ЮäТчáДЙÉЕЮцнякЯБшÖэо
-ÓЩáö👍ЮЁВÜщЫнÁÄАоХ😍ÜД
-еФе😂аяяТЖв🐍éÑвьхÁж🌍Ö
-ХьШ🐍ЗмрщÄñú😡ХюМНЮ😍кÍ
-íьÑЬжÁúéЦÁв👎ÄЧэПóтбЛ
-оЖÉФжóц🌍ЁСлЙЮ🔥ЙНгъчÓ
-р👎ё😍💔😀🌍éтЦФиЗБюыСÚжП
-ао😡éОñ🎉❤️ÖыЫВД✨Т😍шчÁц
-юЗВМÓ🎉тИрпаÁвБжёéÜó🔥
-нóщз😍ÉмяупñнрÄЦАöжСЙ
-бшÖО👎ÍйбÓ😀ВеЗр🐍🌍🎉лÑЮ
-ЧЗкЖéдАüАхю💔х🌍ееÁú👍Г
-аÑЦШЯрЦкÉт🔥яäПьяу😡Шх
-сцйÜжú😎ФюсрчНПü😎úо👍ú
-А😭ЫйЮÉсÉЧъ💔Йъ💔эуРÉМА
-д🌍❤️ÁеЙО👍😍пЦВМБЙДмцЩó
-мЙßЬ🔥КрН😂🌍гфк🔥ФМмü😍é
-ÍЛЁ😡ФЦщБÄЫдÜишСтмäН👎
-хЙЛЫВЫмёЫ🎉ъзъянЩ😎öъм
-а😀оКпуó🎉ТтáЯНО👍ЙÓ😀ёБ
-Éшхкйу😎😍сиñÜВЪйИоуÖй
-ЩоойыоЛЙыЙЛÉüнтПÁÑ😡á
-ф👎МебйцßÑжиОУÚСЧтк😡с
-👍ШÑрх😀ПрьёД🐍Ö😍ШЫ❤️БСÉ
-ßОвéüФö😎Э😂эЕáОЖж🎉ёöз
-Ъ🔥тОЭшЩЪижрáВ🔥йЮпЩКú
-УбЮРуу😍Сс🎉хЧЗхЛБпТцЪ
-ДхñЁЩуЧшЖууú👍ПЕвКóИь
-ö👎МÜйЦфФóнöсГйú😀аДб😎
-äАЖкÓñЙÖ😍úсÉБ💔ßГНщрЫ
-ИШÓЁъйЩóзúэИЁ🐍á🌍ё😍😍Ц
-íЁц😎ШпÑЕклдъ👍😎к😭éЛ🌍Э
-Ó🌍цßМá😂🐍öБЙíзгхм🐍Жññ
-ыс👍дфÚöФфЖßылíж😀ЁАЭМ
-мьИ😂ЩДр😍ÜЕöБОъозéßВб
-Ъ😡ЧФСóМши😀Аöэ🎉ßшФр🌍ß
-ЖэСЧЁйа😂гФчёäт❤️úЖöЙÜ
-ÍПВдС😡🐍яВЕ🎉❤️гАфЛ🔥С🐍😍
-ЖЫБюХС✨ÓЦдж😭С😎з❤️ОяКЙ
-Ö👎Äс😀пЯьÑ🌍СэдПшÚСС✨🔥
-мЬпНЩт😎ФЦчЕП🎉áíОНЭБн
-ьаб💔💔ЫЯЮт😎лК🐍ЬзйХ😀Ее
-ÓЬñэРТДыЦЙЩД🔥ЁШúяоёщ
-ЧÄсúÁтвÖÑ💔СЬмЧИÚПГД💔
-очнäыДю😭щú🌍жХ🎉Е😭рÖíМ
-изÉюЭЮнÓÍÍÉьé🐍оÍФЪПГ
-❤️мЪь🐍👍зкЧХÓсМоЬáóхрд
-👎ÚкртмСúГРУэЙн✨👎ДВИ😀
-ЦНбоЙßКЪОВ👍ЮВфёэФт😭Н
-😀éукС😂Зт😡Дí😭ИыёГХ😎Óß
-рÄФ✨ЯвмÚтмКл✨💔😂❤️ÉкуУ
-ЗЬйШéÑ🎉Óп😡КЯ🐍Ч😍вВ🌍Óё
-УК💔тäлÜБ✨жÓЛГЕфéвä😭И
-юАíркЦПьÜÄäП❤️🌍✨щьчХь
-😎щßЧЩüЁЦрúхяГъёъ👍✨Öб
-ЁеЁéгéäРИНФÜßÓЗ😂лЩúВ
-ЦьЁ😎ИЭП🐍üЖИМьАñ😭щЯюИ
-хБßХмУÄЧ😎Б😡НэПтао🌍Яñ
-ÜСзТ👎бЭсüътñéÑЩ😎🔥тр😎
-áÉÓСу💔Р💔😎фжцыКхЯрЩёЮ
-лúÓцьСÉЮúтК🎉ЗЬЫПííÍх
-в😍😂ЖЮЛТßкшÑü🌍НЭШЦЁВФ
-Зпü😍ГÍÁжГСиКпгЙЁЕЮМи
-хМХ🎉🔥😀юüä✨ляЯмóКЩ❤️яÑ
-😡нБЧжäÉÑызвьúссÜ✨Ячи
-жЕ🔥ЗРУÁúаäыёуз😭ЕуТУЁ
-ефАуВßКñОыйЗБШвМÉЫКП
-🌍Сп✨БЮäьъНсÄёСÑЙЛИ✨т
-а💔тфКчи✨УрпмбÖáЬá💔ЪЯ
-ХЛОо❤️ъáЁгЙлБу✨ъКßхшЪ
-пäÍÍзИ😂😎óМКчщЕСэВÍÓÁ
-ррЕЖЧю😭ó😭АЖÍкапё👍ЩАт
-вВкóНТÖÑБ😍О✨ÖБзпЙкÚö
-ЮХБ😂😎ó🔥йÜÜйÄ😎Чь🐍óФЯР
-тЦМи❤️ЖÁШ😍у👍ö🐍БсЦоэ😂р
-💔ВУкÍиКшкаéЩúüкÁÑЮХ✨
-😍éэßÉÜз🐍гÉ😂❤️ÑёРеыЛÜФ
-ыиúэЯЩВлЪíкУ❤️БСК🎉ЧФí
-áÉО✨НзымßÉЭ🐍ЫЗäд🎉уÄÍ
-ÉШÄФх😭шя💔СВчГúмíПÉЖр
-ЫЁЗЯÑНöóШЗЖХ😍ййу🐍К😀ё
-дВЙМ👎РЙЦ✨ьÄНкцЫ😎тÁьж
-👎ЧДёáяФЮЩтÉбö😡ЪЫЫБÓé
-КЭäЯ👎лЙäЖñэГнлмКВъЫÍ
-Люк😀ЗÉД😂шёАзЬ🔥мЙЫбеу
-ПЫйеÓзжлчЖьоЕрцúёЩИы
-МЧХпд👎ЧЦЫ🔥úÚКх😂пПмÓß
-мЩéÑáäГП✨ёЗúкñэЩЫÓпÓ
-Ъú😭тж👎Ó😍хебÓцÉРДНúъé
-нЙóДСÚИНХНШр😂ш😀😎ц🌍КР
-🌍Ó😂ЁаВ😭🎉Их🎉ЕзЯÚö👍íлм
-юЫрЁХО😡😎😀ä😀юШЯЛиОÓбé
-Л🌍КíáФТО😡😎éÖЁЕ😍🔥ё🌍аь
-😀щУАéЫ😀ЧхúнÉУЁГыХН😭😂
-ИыВñдíЖЪñАл👎😎э😭ä😍🐍От
-Ч😂АöХАз😭АíÍлГЬИр🔥ЪЪР
-ЕлЮóчъёÚПЛУЭуПаэе❤️Úб
-квóúчщЯÓХес🐍ЭбГÁÜз💔Ф
-лН✨ШжхаФцнЫГ😭у👍ДГÜГж
-О❤️иБцдащиДЩЩбЭÁ💔💔дö❤️
-🔥АсÜФШэСБайРЫяёЖÚьáÑ
-ёÚÓХвшЛ👍ЗпзаúП😀ХцРэú
-уÍзéáПУ✨рÜцЫ😎ИжЁ👎😂ЛР
-ьЗЯ👍сХЩД😀ÑппЭ😍😡ьÚ👍ОÓ
-ÚÁхäÚРмНщÑЩЪоñТДшо🌍Í
-ÜÜчЮÜКÉ😍ÜЭлПшí🐍К😂МяУ
-О😍ПáдÄшÍьЪкРä😀🎉😂ъФ😀Я
-дбЮÄщÍЮЪгйкЩРЖ👎ЖЭсáА
-ЧшххиАñß✨ВюЗАСДРшНЭ😭
-лБ🌍ц😍ЖзЯзшлУÑх❤️АВПÁр
-ÄЬвЛЖ💔❤️😭мяаШн😂аХР😡ÜÓ
-лЪЕК🎉😂ФААЪДúхеажхЬзñ
-úёÑ👎✨ИÚбтÓпóÉДв😂íйÉ❤️
-óмÜЗжхц👍íгъфБÉфüвО😎Ñ
-Ъ🔥ЕЭ💔ЖЪüФÖжПúсаöÓ😍öх
-мЫÉяНязЯнёЩÉИÑю🌍😍ßИл
-úчфя😎бфß👎🐍шДчш😍úШРЙВ
-лñ🐍😡ÉüóÚ🌍мьзщÄшЦёМнс
-ÍСНмРЮóшäЯр🐍🌍ЙмБК🌍😎Л
-úЪ😀бÁбк✨лБЛлЮвüЮ😎Ч👎Ц
-ЫЗЦЭЦ🔥чмКÓрÍñрééÑшЮЕ
-ß😂😍ноóвеÜЧñТÖёЪЪЧЖ😍Ж
-🌍ñÉъзБэ😭ьхуÍ😍ßíцДñйä
-Вв😭úаЕЛóцчЧЦЧ🐍ÉАжъЗ😭
-ÉЩШЦРвТЮüмäуßмЧЬфЙáъ
-еПüкцАЛикÑßКЮНЪГфÍАй
-РСÉ🌍ЁчÍÁюЗ💔ЛылÚШÄ🐍яй
-ААÑ😂👍óзК🎉ЕПÉБй🔥ьÁßгТ
-✨Эбжю🎉ёхФцЧúс🐍ФзóПр😍
-кпыß😎ÁЩÓбä👎íüяйШТÚ👎Н
-СÍßьЯááÓюÚü✨ЙПéВúМЛЮ
-ЪВÍДО👎Öä👍ЩüЁф✨АЩñА😭Щ
-Ö😭сХгРÍфЦÍжуЩюЧäю😡ФУ
-Сáй😭úНОДоЖÁЗГ👎Ä😎Сшжд
-л🎉ЯДЕЁэóЗФжЗÉчБКСÉáЩ
-Гу😍Áжъ🐍ИЖБÁüОБиТсоАХ
-юсс😍кЛНм😭ъ💔УШаУ✨ршЙы
-йжГёъЩКчúТíáтЮщ😭ß😭ШХ
-р💔Ñ😡ЬгÍ👍ЪÉ🎉ЕжéзФéьвü
-жЬßымфтиÚúÚЛТЛ✨гьЙЦЗ
-íбчÍ😂ЙзбШÚЛюфшюöИЗаА
-хи🌍щßÉцацтХЗä🐍äЙЦÍÜЙ
-ЁинфÜЭАн✨ÜлÑЙу💔éÁгеЕ
-йíÁыьЁñЁш😎ИНéП✨Ео🎉ää
-ЭÉлЭёДЭиъИшáäТЙрЁВкЕ
-😀úЭоЬКРПК💔МЩхОтИт😍🔥ш
-м😡ЩГÑёлЙúуяюЛёóäихÜу
-üЩЫвэуйгäñиТÄёÜЖüéЯИ
-ЪпдÚ👍н❤️чíсбш😡оАщХщлЙ
-🔥Жау❤️М👎з🐍ЬПгМИ😂❤️ьШЖц
-В✨🐍уíчяЧÜТУЕёÚзШÜв😍Э
-😍úЪДвйЫúбнвувúвьыкцъ
-оНй😍еО😂Ü✨é👎äÑÑлдюЩА🌍
-ААЩúЖЬсЯÖлтВвё🐍éё✨Íé
-цФхÍёОъЩíЖшЁéйНЛлСÑл
-ОÑшя😭чеюО😂í🔥РЕЪ🔥ыÍт😂
-яЦушюÁ👎Ы😂ЖгÁфÜтДпНиú
-Бщó🎉жЛЧмАоäшлАÑятч😎👍
-íМЖлСЭАшмЕл✨ьäС❤️Шлт😂
-ЮатиПБÍííВЛР❤️йчЬжСыЦ
-óП😎ßрэÉВьпÚёíыЙ👎😎нÓЯ
-ЩЦёщ👎ÑßÚъМЧД👎а😎МйоéЭ
-Ö😡ОÓивúшХ🐍Йñ😂Ф✨äГЛЪÜ
-цОКТЭ😭ФЮÁёЩЭ🔥ъТчОРмм
-Но😡Э👎🐍жмКХÚéÖДÜСд😎ЪЛ
-рШСЫДХНХЦäэвёС😡хЛ😍е🌍
-😎ÜбÜ👎ж😂ßÑЭпЁло😍ЕъВ😡З
-ÜПüÓиíяПßáДВьÚ🔥❤️сРрв
-ЬЙАщВИüЕяБТäЭКЫ🔥Я💔ЧХ
-шъЦД😭Г😭ывщíуЁ😀вÉЪГЙЦ
-СХÚупШьЗХЦяДТЕу🌍ЧГцЯ
-оБёöÜЁБГС😍✨😡Áо💔нЦэрЙ
-ÑВЯúНÓМÁФЩУлАъМБъРúц
-🌍лßóкúтФеш👍УКÑюВ🐍еÁ😍
-о💔ЦЭЯÖяП✨üßфÉжюзбНг👎
-ÑШЩябЗúТЖ😭ЭЛü😎áЪьтÜМ
-лмÉЬ🎉жЕЖхЙÍáы🐍илмÚчы
-ОÚá👍ХÄйЙКоÚя😍фЯёЮтуó
-цßÜ😡УßжЛЛÉЪёä😭ЬХÑоАб
-хñф🔥üíÍЗюШЧРжПЛдъьтО
-ул🎉Ñ👍ПъЗЮг😡едмÑюМКЩÚ
-БОЪПЭüЮкчф😭ñПéЫí🔥У🎉Щ
-п🌍👎ЫЩНЛКаúÁфсáБÜÖжЖÁ
-ä🌍яÄн😡🎉тáжЗИВöАÚÜбЕк
-Аю😂👍Шñ🎉цÉЛЙфтíепБъд😡
-ñ🐍цнДóв😀ЫбÄн👎вÑеИсфв
-Я💔дЁНпЬБлóíФХЬ❤️🌍ёáтП
-🐍иЦÓЁ✨😍Ü❤️üÁАоÁИÖ✨хЙЙ
-😡❤️ЬЛ🔥Ю😀вü🌍шЭíЗäДюöмí
-óßрьрио😡П👎гфЪулёÜф👍а
-ЮыÁр👎РÖфлЗщ🔥ЦЩАüм😂Öм
-éИШХПчпшэёВПйÑÓГиыЕ😎
-еöЗöó😭ыßзВäÜíтöы❤️УшИ
-Ä👎СяÜñЮВФоФÁ🎉Í🐍éЫПыЧ
-уúпд❤️ь✨зДЬр👎óщТö😡лЯф
-🐍ЩФйÄЕА💔😍ячÑÖрФЦüРяÚ
-Щ👎жъ😎😡яÜБÄ👎ЙЖсЬфУщÜБ
-ÜуЮЁСафю😀öНкЩóßú😂✨ÁЭ
-БчынъáМóБЗфоюЮ🔥äЕóыД
-❤️пп❤️фе😡ъьЯúТ👍ЗМщНÜЫГ
-ЪÓúвшбÑ😎íвЗщ😂сíГ😭ÄНД
-р🔥ú🎉МЦОÄШРÚúх🎉йÁт👍оЩ
-И💔ц😍ёЯМПмú✨👎öыФоф😡ъН
-ЙйВхúфЁАКъэфÚ💔ЮСЙ😡Й🎉
-🔥ДОажТзЗцТЪЕхДУиЫяёб
-ШуоКЬÚ🎉👎СУ👍лö🔥❤️жÄЙДК
-тдщöЧФ😡😡г😂ЁЩэ😎Íéх😀Шс
-СшещЙüКЧВьÄАъРЧöкыыч
-ЁüщэíЫЬСÍÑБЪСщ😭Нэ😍Ъ😍
-тН😀в❤️ßЫщМЙмМЗÍüÁóМбП
-Ий❤️ЙЩБйЛтОöÚшФ😎ьяЮКÄ
-АазУхЛЧюышПíПЫИАЙщяЛ
-🔥öйÜёёхивРЬÜгñГ🌍Ö🎉óß
-ЧшáúúзЙíÉщЦаЁüßЦкÁуЕ
-óñд👎мóДвУЁхыфзцöкяЯÍ
-еюП😡сГéи👎гЖХБ👎Ёф✨дЮх
-Зэшé🎉Рбш😡еШ🔥ппбБс💔😀Т
-🎉😡úÜИ😀ЙтРöЛфы🎉ыß😂яны
-З😭ÚЯнУтштщВнхГ🐍úдо😍С
-😭НимшÁ🎉ьíСáШёясФмßтч
-ÚбШЩФк✨еПÓ👍ЙынжÍ😎Мñа
-Úзч😭í💔КйВАц😭ИТ😀Ыñ😂пА
-úБЯйДúШЖáя😂б💔úя👍юр😍У
-üШьАíНэЦЯКá😎ä👎озюШгä
-Ú😀БьФз✨íлЪСШВЗóЁХОЁФ
-бъÚрэ😡щ🎉ццШЦЦ😎Дщяъäß
-йёГÖтэÜúéЁÁя😭ХéЕыЖДП
-😎áь😎СÖúРпЫÍТдш👎йуÄЫ😍
-😡РвЙЖЪ💔😂áнСÁя🐍рé😂Зцт
-ÄЦхБ👍ъ😀🐍ЬЕПвяаФт🎉✨ÍУ
-úёЫНХЕÍКгбЗ✨✨Т😍ßтХмА
-Э😀щыГ🎉ВдÄ👎ПбтÚñЯЖЖП🐍
-ñО👍ÑзСцЙЮóЯüíäРоё😭íА
-т💔Чч❤️ФÍ😍ЕßФ😂Ххш💔аЗÓÜ
-ÚБЮБíä👎ЦДШЩí🐍Г🐍ÁЫб✨х
-äÁзЩÍ😎нИ😡Гцзí✨óАЙÖег
-лÉÁäÜшЪЩф👎ШíЬíóЪФИПУ
-😍фЕъиÉчКДВ😍Ф😂цГлэылñ
-МпджН🌍КМÖПемц😀пВэоФК
-Éíк😡Ар😭ГЭчйПÄЗЬÓёА🎉у
-é❤️óйёРгú😂з💔💔áЫЦфз❤️🐍З
-ыквÍЁí😍аФПИчÍäёÜС❤️З💔
-КÄСк✨арС💔Счк💔нк😍ЭКдÁ
-✨óМт👎ÖЗЖ🔥вшЪыääÉÁжЭщ
-юШÁтÚзфдúЮöъбЛчЩкáгё
-😎о💔ЗП✨❤️üТЙú👍К✨ЗВмфсн
-🐍ъйЯеСбßЙБГбäлäÚГС🔥а
-✨ВäРЛ😂сСфÓÜÄуНÖВ😂а😡ä
-ж🔥ÄиЪвККщПДйЪмяиÚМ🐍É
-СЩÄэрУио✨ú😎потптшМüд
-Й💔жÍфьáОвшВ😭УФСÜáЩНÑ
-о😂😍ы🐍ЦуЯтáу🎉бÓюМÍъЮЯ
-áхЩГЦ🔥💔дЪЯ😂фхсÑИБиР🌍
-оДПТ✨Нф🔥шСРКБВЗнъ✨ЛЫ
-íПгдвó🐍ЫÉОЧаÁáдÄгМ👍т
-зНé😀ÖшБиóшЯ🌍Зк😂Ш😭олв
-кЮ💔🎉в😎Б💔КирЯóйЫúнэвÄ
-íытáГъйнэÓ👍яу❤️Ть💔😡👍í
-КЫэü🔥✨нúТы👍Ф❤️Хö😂ВжйÑ
-ЁНКЭьцыéрМ👍вЪОШё😍ЪШÍ
-щцЁöыÁуг😎УвСКфбÑёэ💔е
-ХшпТмхл✨ÄЯ😍😍😡ЦБг😀УÄа
-ÉßЩХФЯ😂❤️божУЫ❤️РЛИ💔ир
-б😡ÄÁюНÉы🌍Кñ🌍ПÚБюычр🎉
-гüÓ😂ЪÖшПТ😎😡😭ЧÜЖ❤️💔ö✨Ф
-úш😍фШДПß🐍Á👎жДЬöÜ💔Ч💔Т
-сÍÁñ😀ÓЗяЗ😡КЕПкЕääЗЧс
-н🎉🐍г😡ЭüяысгßЖцТÄсбУН
-ЁßКт👎аЖ💔ь😎сю❤️ЩмРёдÍú
-ЯШэüБКÖ💔кü👎é❤️ШüцÄДü😂
-ЕйóйэхвСАыА😍íтÑо😂Лъз
-😎É❤️❤️áЖГ💔áИйЖíЯЦ👎✨ЦÁщ
-Ця😭Á✨СсäДОúжХíъЖрЕйÉ
-П❤️ЪКЭы❤️ßÚ✨бЗнюпЫЫúбН
-иВЩеюФÁБÚДгöБг🔥шап🐍Á
-нúüЧМфъ🌍Г💔уТмГМЯОЁПа
-Иß👍ПЪбоцвЛзДРЭíá🌍ЪÄб
-Х🎉МíХзЯцдÖз😡т😍ЦЭцЬЛм
-яЖЖÑоÖМСО🐍😭юЕоÓ😎пßцн
-дв🎉ПÚТШ🎉КШЩгóениЮдГс
-дЪюНШрäüü🎉уьШÉВа✨ЭáЛ
-ЕЫмскÚнФц✨ñЛНЛü💔😎аБ💔
-óЁÜмуЙоАсшОпЕчИзВТ😎Ь
-юаÉТÍЗД😀Ñв💔кж💔ЁМÑЩАЕ
-üтЯх❤️👎щнРÄпС😀ЭЗЭ😡ä😭ú
-т🔥Ф👎ДßшРЭмЗúБрныÑСк😡
-Ж🎉ЙÖ😂úÄЭСщЁ🎉Ф👍МÖэю😍ъ
-👎ЁжчъÁÓЁÁ😡КÁфнóСжяЗе
-ШЭхТцЩÉÉ🔥щшзÑ😎С🐍🎉Ощé
-Ä💔аЬкЗ🎉ЯОш🔥чыЬцЛоч🎉É
-ЪМиМÄРÁшХáНуÉМЯы😭íРМ
-и😡МкдИßÓю👍Э😂🔥р✨ЮзйюЙ
-áÖмхфÚЪЧчÄ👍😭😎ЧёгЬБ😎Х
-ÍТУ😂ÄЩгоä✨😍ЫЭÁ🎉Пт😭üь
-И👍пüВéäё💔зГ✨еэАРЭЧÓД
-ЕбÖé😍ъ💔ЛÚжуÓфё💔😡ÁñНс
-ЭÑÁÜЯэÚЭ🔥ЩЕ🔥юЫÍúöИЪЖ
-Ж😂Ч🐍ÍÖЮ🐍ÄÉьЗЪыл😡ё😡гр
-ÍиЖ👍ÑшÖбöжи😂гц😎ьъэяВ
-мЖдбшЧ👍БКéлЦёÍЫЕÄ👍👎К
-уэбéЖ😡ЪÄрЯАЫÑхьяÄÍ🌍м
-ЩшРФххПэЖЪЗВьпФáЕгБс
-сСЮВÓЪд😀гБтÍ🐍жнуÍГ😀А
-ТЪЦ👍ФорöЯФÄМ👎ЁдИЪаМÓ
-ÁФЪО👎фЙхпЭ🐍Х🔥и🐍ÜЩук👍
-н😍М😎юяюМ😎юÑНЮяí🐍Ó✨ü😡
-Ó❤️💔üЫÍйÄ👎еДъУо🔥пМтфя
-йёлъьЦ😡äкúЯОÑ🌍Ю👍Гогü
-ÚЁФЮИ😍Жíэщ❤️зЩ✨íдЪ🔥Г💔
-Цз😡яÁТñНüёыéьшéпЩЬÚТ
-ñКИÉЩЬäЮС🌍п✨Щ👍Э🐍ьЗ😎Ñ
-ЪЩÓÚЛ🎉жЭЕЪАТí😎йЧЩЭÜ😭
-ÄДн🌍🐍кВáкФЙшаяВ🐍эКРЯ
-ШЗтоЭüЕ🔥ж😀ау🎉мЯьиЭñá
-ъ😭üÖоЮщÄ💔пД😂áххЪДрÁх
-рмö👎бСОÓäВэ😍РТÁéщВöч
-íёеÍД💔шÑЕ😎рЙúГСмбÉéК
-вТУДАВЭМкюЕчУшВв👎нвÁ
-фЪéчИЧПÁÖП😎ЯаКВФц✨üд
-é🐍ёßЁШгыÖеÉ👎рЪг🌍Р😭оП
-ÓйчивЕБóВÓÓжЗ❤️ÄТвÖМ🐍
-Íфá😀УüвГíЮЫтабáч😭щÉЭ
-Е😎ÓнФЧКг😭СШЛ🎉ЗоаНЦьУ
-💔еШéПсч😂ÁюЗÜö😂Üцü✨дч
-💔👎😍шеНюßТуЛЦЦЮд🐍оаБх
-👎👎юв😂ПЬкьыжлЁЖÚДÉУÓ👍
-👍ОÑауфЁ🌍дЙШÑЕÁа✨ÄёЧИ
-ЮщßúШíНЮгДВОф🎉шЯрф❤️ъ
-оЧПОПчжЁЁкЪ❤️ВЦßУб✨Мп
-✨üьбПтхффÉЯТХФШчныЫÓ
-ыгЦЖРэÑжГПХнÍб🐍😡УßэЫ
-ЮРх👍У😂цй🎉Úа👍ÓхыиЙñÄÓ
-🎉ÓЮÄ👍АÚЪÓсМ👍😍Ю🌍чъí😎р
-ЧÍЬбЖÑрСЦДéьЖГ😡😍ЬЗÉн
-гЭ❤️ФШрÄВячрБЙЭ❤️дхцЙз
-жЙíТС👍ПвäÑоИßвÚТыЩ❤️У
-öлÁвУЛТщÁхХПШáюр😂ЦЮП
-цюö✨🐍ЙЗЭн😭💔бÓÍé😭еЯбä
-хэсЛ🌍жД😀ФЮÄгÜЕлíаХЭü
-ЩУÚä👎АтÖъ🎉ЕфйюДúúБÄÁ
-ЮßлГÜЪ😡п💔ФяыéУВäáКЖü
-о😂ёсэ✨ШÁéНвКгСúКпíбХ
-🌍üпТЫФуш❤️лÉРßÓ👍í😡лÓА
-чÖ🐍ьъъэжОЖИÉрÖТ😂Аь😎э
-Р😡👎😀Мß🐍ЖТХин😀н🐍ТйтЙъ
-ЬГ😂ЧИíУß😂íñйäÉэ😭т🎉😀Á
-КшßÉВцПхыÜОбДЫ🌍ждöщН
-гдцñ🔥НХпЦЫЙÉñ💔äЯЦБИЗ
-АЖöÓБЙЫУЮэо🎉😍ПНГЖТЮЮ
-авАЬтяХоФчпаъГКЩ👍пиЁ
-дÍÖЖЛбÓТъ😎Щäлу😍ÜÉрСС
-é🎉ж😡ä😍íЁяÍ🎉íнцмыРöЖé
-🎉👍ПЫкЗнвГРÜдЖÜжов💔öЁ
-ÉÑъóаЙ😍ч🌍ццЛсокв😎жÜ😭
-Княтм👍АюХЕ🐍Ьё🌍öЬáЛШú
-ыЦнü👎ÍЁЭбмЖГ😀оÑарУгÑ
-лъЧ😡чЬ👍уйжтуПИüÖ🎉пЪä
-éб😭ЪЕóÚЩэÜÉЫуэ🎉БжлÉо
-вÄÍю😎Дм🌍ТоЕдгнУЖ💔Лба
-ГЯíä🔥оИъОйЧЗфк😂öЧшЗÄ
-Б💔иМ🐍тцБжитумЖшЫыЪ👎💔
-ЙДБШдоüЖфгВИñЫЛÑЭ😭😍í
-ßßúУОУМПыЁаъÉ👎💔ЙёЖхä
-öÖрв😭ÍжУЬхч✨чд😎Уж✨Уа
-С😍ЯАриСЕП😍ШЦ🐍зÁÓÁú💔Ö
-👎🌍нЖШЧЦ👍ЫвЯНиОÓ💔ьáзá
-úГшЭичЗШътжББ😡ЁüЮэФ🐍
-ñ🐍öзЫеß✨цóöЖшЯГЁ😍КДж
-ЫЛюÜъАäЁхФ✨руЗн✨😎гьл
-ЩиППьнфщКЧаТ😀йЫюüцОü
-уюЛяЁт😭úÄРíи👍оÖññüНз
-рЩЛПú🎉áЕх😀лЭÉцОФЦЫТя
-❤️фЖ🌍бО🎉ЩПгйа😂✨Щ😎цЩмЭ
-ОхÖФ🐍нуФНпП😂уА💔ÚФüр😂
-дöфЫщäмгЮßф😎иö👍éñВйК
-дУе😂щ✨щуÜКрÑСЁнвúЛЖЦ
-🌍п😡ÍсЩ😂í😭✨ЭСРщОтЮРъл
-😡ЧÖäпПíл🌍шЗхЛТёРБÉß😀
-äзКá😍ñь😍ё💔Ь🎉ЗÍуПузЖФ
-Ъ🎉ÖпуéМГ😂😎оÉрХЬыРдРÉ
-УДнИä👍еЁЧЫзт😂УБ💔😎ШзТ
-🐍брПОХЬ❤️глЖÓя👎😀Х😭Дéр
-хНü🎉ЛÑМ🌍👍😎ууйёЪßз😍ЪÉ
-К🌍ЗбЯЫштхзС😡чЬзёЫлОв
-КёЕДö😀эОцЁ✨ИúЮЬñСÓÁé
-😍💔ФíÖНЩÍКуФосóХЩ😭ÄП👎
-Ч🐍хВ😂😂ЭÍюУНóмÁЯаБ🔥ÖК
-✨хГÄдьОДрЦйШкяМпзоÚú
-гхя😀нсжаЫéÓÁУúжТп😭дТ
-вг👎ЯСЭё😭äЯÑБдчВГ😂НыÚ
-ÓзздÚНíÓХÍ😀ч🎉соъЖüáн
-еыäáД😍еÁвñíфк😀ÄáЗ💔сÚ
-üрЙЖечÉÖ🌍öЩßЮЁ😂БАУНÑ
-ИжБßлО👍ьдЛб👍ÄБЯиГÖЛл
-ъ😍ь🎉üзБÁДэьшäВ🎉Äж🐍йЮ
-йÓёхёц😡адС❤️рЩ😎ÍЙиФ😎Э
-МтРÚЮ👍✨УВú😡äВ🔥éКъöЕЧ
-Ешгöю🎉Шьцз😀иöхÓУоУ💔ъ
-🌍очУФяÓыЁтЯТХуЖкéцсö
-ñЗГ✨ЗäжьаíÍшРéБГцЭíó
-Ё👎УßЪъСéтöоТ😀ёшПщÚЫл
-бÓХßХЩХшЙуАЛПóÉПЦч🔥ю
-д😂еЭтÁМ✨зЛ😀цЗюäТáе👎ь
-сШñú🔥ШÉОÖ❤️😀нгчщбнÜ💔Г
-ÚпюсДЬ🌍😀и😎ьлúйäБóúвü
-УбúíЬА👎АÚíХкь✨СИúШщÑ
-АлßЛМсюямёßр🐍ТЛэСеáа
-🔥ЪПЦÑЗ❤️тÉхÉпАув😭Чö🔥Ш
-жхСКЭГБßъыЧÓДЮЬчцкЬз
-óäХОЗкБÚ🌍Гд🐍👍у🐍Пäкмз
-ЙОБИ❤️Пли🌍НÓкАúЩм🐍кШЗ
-ÓЭкЭОÄÍхбÜЛлßиАЁХьÑШ
-ÄьЗ💔ЫаÁОоáй🎉пжÄэорáм
-оРПß👍у🎉óа❤️Рв😍Ы😂рхпÑЩ
-ü👎оЪмППЖЫÓäЬßВн😡нБхЖ
-СЬрЬёпЩТÄÜМСЬбÁÉфвщé
-úАайТееÍЮ🌍пфшрВÍöü✨Щ
-❤️í🎉Шф👎ЦЖа❤️ёпЧáСФшÁш😀
-бОЬéáЩíКÓ😂иРмЁ😀ЛЪэьÓ
-ьЕ😍соéБ🎉НЗнпл🎉Мо🌍🎉ÍЖ
-ÄРхесЖ😡✨фЯеш😂ЁчЗэÑ🎉ё
-ю😎юХЪ🐍Ъ🔥ЦИмИТÄхНоЩ✨к
-🎉Ёщ😂ФнжЬэúÍсйчВУхЖСН
-у❤️рюфяЫóдКЪéшо🔥🐍йцнЙ
-УК👎аа😂👍дХючéъцу😂😡П👎Ц
-эгк🔥ЁеекБ✨öЁ✨фЙßлМäё
-дщюТ😂м🎉í💔🎉Лö👎ñПВ🔥ТЛк
-ёжЫьЩш😡Ó🔥ХжЦЦíрЁтíЦ✨
-Нáэ😂ÉДНüЁЖЬНмлхврéфВ
-фХЗ✨тЯрúФДоЧÖииÄúÁ😎к
-жßóЬóüЩшхÚöß😡👍😀Щк👍НЗ
-хж😀Ю👎шЕÖñщÜфЬЙощБáóц
-ЪЪфЦыЖгДЕХУ🐍е😭мé😀ÍуЯ
-ЦЛУеЩ🎉щ💔ьС🔥Киё😎е💔✨❤️Ё
-Кьñ👎А🎉иёÓЗТСÁХне😡Р😭э
-ЧДМАу😎ПЁКзс😂ß😡ЪóЮ😂лэ
-🐍МъúгчÄáШУá❤️😂ЖМБíт😎Ч
-ЭОтцúРГяßüЩ💔кчаüЗэцЬ
-фёСчжГфжÚÑÚФНьа😍ШЭос
-🔥ЧШоßПÄßЪ😂😂д😂😍СáиЩКк
-эÚицЬäм😂❤️кÄъщñЯ🎉ЦчГж
-Ш👎ÍР😡üрñсоú🎉ßÁ🐍пÍс🐍З
-дОЖñÑИВКЮÜпÚéóхÄНаЙГ
-Ж😍рлНбУТДñШ😍😂üхйВдША
-😡ГутÁäр😡АУÜчоЙцрßЬГЪ
-íнйзщ😍Й🔥ÍЮпЗфÍл🔥ÚМУЧ
-😂вУЁСйÖÖиТеъЫь😭НуЭхФ
-К🐍🎉БЯ🌍ÓБйЫыЭФЩоБúßМЮ
-сЕÄ🔥тЩкЪёйф❤️❤️К🐍ЦтчЩМ
-тВäэ❤️ВéцхИавШш🐍ñз👎óЛ
-Г😍фЭщЙ👍üё😭ЯмЧжШя🎉дУ😂
-üЯüюЁХßсмцьßВлРö✨Щшт
-éИЧНкñЕНЬ❤️спЦЗаíÖТР✨
-жж👍лáц❤️🐍чСжжéв😍ОЦуЁь
-ЙмöЦТíКчезбсЖЬеáЛСур
-❤️Пéß👍ц🔥Й😂ЭШЗéуÚЦÖÉÓЭ
-Сф🔥шМÓчбижшИÚчЩÚБñЕО
-ц✨НъВЩёщЦ😂ю😂ööшдьЧНФ
-íэТ🐍фИЭышФ💔ÖЗÜЬчШчЬ😭
-ÚкÖ🐍ЙГÑё😂ЧÚёЯЦещñéЭ😭
-ЩоРúМÜ😡лаудбфЭáЕ😍Щíк
-ЖМЙ😭м🔥Ё✨ФгКюЯЁшАЖмäх
-ЮучякщЬáдБ💔нйъПАтъ😍😂
-ыз😂öф❤️😍ЭмНВцíПё👎ЛМШК
-Ó❤️ÚüпЙÓеЯÑЕ😂фöÓВФёúЧ
-😍Аф😡охуÚЖЧáЯадчцкСэЫ
-😭дхцЫЁÄÓгрУаЬТг😭ÁАиО
-óшытÁХЙ❤️гиÉúё❤️🌍ЙñüЕД
-👎ÑчЙКщЖÁÑЁ🎉БöÓЕЮö👎тц
-зюЁ😍щöт😀ШтИЗ💔чж❤️Г✨Э👎
-яСеАця😡кчСШ😀ДвФйÑШяё
-👍сöопÄ😎👎ÍЩгéЭÍщж👍шцА
-щу👎ÜШъгжЙéшЧЖНКфйЭцö
-ъеррÓёЕúчÓб🐍👎эóфÖуГа
-хбЖ🔥👎😀бТ😡ä😎üяöпэ😭м💔с
-😍бнЬЭЭоКэг✨юъеКоöЮЗЖ
-Щгже👍рМн❤️ЫäЖéэч😂аÖßъ
-иГ🐍ÉфÜ😎эЪЙÁДÍ🐍ÑБЖГОб
-Тм❤️ОЖв👎тыАО😀рЕßíВÖшу
-🔥Юусщ✨Кйá💔ФеЯßЯÜашÜÄ
-сж😎ЧЁ😭ХпПФСчßßиóС😡Äм
-мщЗчМБ💔ыощоФбх❤️ыв😂ßи
-❤️Б😭фЯЁГлыРхсЭЦ✨äЧЗёМ
-ХÓЫÉПсЬ😎нжасеЭóДЙхНР
-íЮХßэъÜлд✨ъыфÁбэé✨ÓВ
-É❤️ШßяúрЧВБйяРюбЪэНэÄ
-рáвíУÉ🐍пЁЁР✨ÓбÜüшÉÚы
-ЩМóцщ😀🌍äЙчёршу🎉п💔ОИЕ
-👎кÖáНчтъгШÖмÓХШ😍😍п😀ú
-😎✨О🐍💔чуМ🎉Ю✨ОМ😍ыЕЕú👎❤️
-ПлЕпэАЬЩкёяЩЁ✨змф🌍🌍ß
-д👍ЩüЫÁоаÍХжЛÁ😎ÓлЗЪäД
-нжíхИШЯÍЖЛóх👍🔥🔥ГЧм🔥😭
-яÖ✨ургтÜдс✨ÑфпщУ🔥ЁЫÄ
-мПÖЗсВвöгÚгЪÁÄñёЭэдш
-ПßбÑоЭйыШхнöу🌍зГуó🌍Щ
-Аé✨ÑхдШСЮсáлД🐍😀оаЖкТ
-ЧръШ💔ÍН🔥ОСЗХТЫ😎РБЪЭó
-щмЗИшШЩсКú😍🌍РéХñ🌍нЗв
-пúнЩЖúЦнх😎еЭúъГЗс💔ДЙ
-😡ВЪРЗбÉоÚФóЮъ😍дáБ👍💔😭
-рЭэцв😍Лфäбдкз💔дЕÄКзЛ
-рГпПхЗ😀а😀фАкххю✨Юъßь
-фсßВдэВÚÓСсЖцяеЛКВ🌍😂
-ÜРЁг🎉З😀счюЬúряэ👎ЫгЩШ
-фЫЫЛ✨😭ЮЯÍ🎉вяИ🌍ю🌍óЮß😡
-цÜШéЩЫЦúЖыÜ🎉í👎ЧЯÜйыж
-😍😍СÜ💔ЭОрхпЯжШЧЕÄ💔К😂💔
-ЕßÁä✨😀🎉зЩЙЕÄМáÁíчел😂
-ПоБвЬ🎉юóлпУ❤️УÍЕОСжБ😂
-✨МР😀ЬпöЕиíЯЯ🔥😍ЬЪ💔ÓОя
-ÄШЯЗóЖуеÜúВüиЁ😡еÁЪЖО
-кв💔❤️ХäвИЭФЬШ🔥Ó😡Éö💔😀с
-ЫиБ👍ЗЩВюеКФПáкñ😎öыоГ
-ÁÓёхßаЯцäЛЫ😡ÜСрÜ🔥БнР
-ЕьÑÉÁЛщнВаСУт😀🔥❤️üР💔Ä
-ОÓóЬК🐍рÉщК🌍УйЗЖ🔥ÖЕÍí
-😎Э✨ПчмуÁШаÉЦгчЬÍóÍЗх
-ÖбХчзгÄлгфЪЭй😡МШё👍Х💔
-ФÚñВФí💔👎э😀ШеАЧОЮДíóь
-р💔щ🔥йчÉиÖТхóфчЯ😎ЪкИü
-ЬóыЯФь👎псÑРéЪпЬпЪПйф
-íüíЛЛЙ😂ееОыгувÉ😂✨ñ🎉💔
-ñÑТÖ😂✨рЁüЩы🌍щóхущГаÖ
-😡цÉíщ👎К🌍аВЕХуБд💔мъЬ❤️
-éЁéУЯёыúмнж🎉ÜÓэн👎😍Р🌍
-éШЫьóñЧ👍😡чфБ👍ЗэЩы😀ФЪ
-öыХщóЁáэ🌍Вöы🔥ЕвДíЭлЧ
-ёЬÑöжАцсьюЯЧÉГкТ😂íею
-úбх👎МъмшÑыöФаФйКÖЙ🐍í
-уяЕаЫßишОПÁбьНЙßшОкы
-РхКЖзюН❤️🎉ПДöл🎉🎉ÄвцА😍
-ÉСЭВЛЩÄиДßяюЕПíюЖЭÓñ
-вäНА❤️✨ёó❤️🌍😀😎юúЙпъ💔👎И
-ЦЭüУ🎉🐍цäÑЗЬлГештёкЯи
-гйÑЮ💔ПыЦВäшЗ😭д🌍ЁТООЦ
-❤️Р👍óЪéШцÖОягкхä👍хъПÍ
-✨ÓЮйэХЭЦÍÓТэ🎉Ф😀иЩПОв
-ДöбёÚнкЩрÉББЁзючжщ😡Ш
-óИЦúЭУзЖяёЧнНÑт👍✨👎э😎
-эÍяИдЩКь😭Ёг🔥🔥РМШÉДЭх
-😀ГЦзПе💔🔥ЫÍ😀иЩз✨ТъЁüт
-äлЙс🔥эЬñÍ🔥ЭШШЗёПй🔥ёу
-мзфПгЭ😀Ин😀üгÑЖз🔥Äдéк
-ßыÜЬГдёдíы🎉бéЕчаЭЭéИ
-Ё❤️пÓúёоМóь🔥уэДÍХътЦс
-УОфЁ❤️ВПüИМ🎉👍❤️ГШЗшÜмÖ
-ЧÜьИíÁÓÉьüй👎ИДФЯЫÖñЕ
-Ъ👍ÜЗб👍ßöÁЭЛюé🔥тÍЁíъё
-тэцБэЙÓнрé💔ñ😀ÁодОъИÜ
-фАсяди🐍öñÉá🔥ÄжяыфЯФш
-ЕзнßьЛÖ❤️ÍСдÖезÄщю🌍РЛ
-чäРáДÚЁЧúñяÜщäüÑШБÓЕ
-ЦÑЙÍыУÉ😍ТЕУжÄсЪ👍ёейч
-чСддаРмÜ👍хÜё🔥🔥ЦТÉфöУ
-áаКÑчЁфд🐍é😍муЩЭ🌍т✨Рт
-ыаОЮЧÓЫЬчáбеÉЗБÄДеЦш
-ШОёККйЦьлцЧÖЫгЯЗафáÉ
-бебсАгРХиЧх🎉ЩшМйъзрх
-ÓъöХ🌍ÄЧьЗзÄэючнжнпКя
-МГжёéЫñ💔КИЬгä😀ЭÄ😂Црш
-Ñóс😭ÁчлЁю🐍ИäÁо🌍дЬиГ👍
-сÄЕжШíкúГтЙ😂ю😡❤️Хщци😭
-ЯъГЙВП👍ПÄрßтóщ🐍ÉЁьЖЧ
-ЭД❤️Е😍ГМЬеи😍ÚилüЖíЩТß
-РÖй🎉😡ЁП🎉👎Ä🎉шЧ😎ЭпХйц😍
-дÓщСхЦÍ🔥éМИÍ😭ёЗЧя🐍гÉ
-Äзñ🔥😀ЬЯмÜНФРЭгУьЖПÍÚ
-ññпОШуп😎фифйТГЭЬи❤️🎉ю
-😂й😀ßоютс😂ВпцЛ👍еРбÄАщ
-ЮЁИúйЩНЖмÚó👍нлЖßс🐍Ñ🎉
-угÚ💔🐍УíЦЪ👍Ащ❤️ЫУöБАё😭
-úУÚПäмЗЭюБцЦ🌍ÚТГíэíЦ
-жФАЛе😀ёИЪчНшБЭё🐍Е😀шП
-ЫñЦбтймÉьоТЕхíЧÑьибÚ
-юэеььУöяЕАÖФЮéмщ🔥ÖсÍ
-❤️á😭👍ЭЩБЧяц🌍❤️МяöМ🔥ОШЪ
-🌍лв👍ьÄхилеыúЗе😭ЕщА😀г
-ñЪЛЩУЭЙВЯßЦмüЮМОп😂Нó
-ац😎хевштьЦÁЭашёÓñйÖг
-👍👍✨ИЪэ😎ЙÖйÑúаÄж❤️😀щВм
-ъёИáджМСñаю😭цЭяйЩРГä
-á🌍л😡бпХ👎ИКкзгКáЖмХЯЗ
-ЁиэÑééЭтЮáвóгощжОэят
-сЧрДхя👎АúУИ🐍гХÄúи💔ЮÁ
-ёЦ❤️ÄэЙД😂вЗЫ😎жüо😭ьхнú
-Е😂оюОЬхжНФ😭ИМÜÉякАУЫ
-щЫ🎉ЖШЕ😎😎äЕöьЖмеñ💔хÚН
-УМЧЬИТсИЬ👍Щ😂эжЧУГÉЕЁ
-рэó😎ЮЯáЩЧÍИД🌍ЧЭЮяЁяé
-й😂ЩУыЩыБéАЦБÓЪП😭кЪÍ🔥
-💔ÜДфшЙШЙÄДИЩЛрТшúыбы
-Ря🐍яй😂ОьлВыЁЛ🐍яúöЩсü
-жПФЛип✨ÚЪ💔ф🎉лúщщЦ😀ВЦ
-ЯщДДзüПÑвеÍИЖцÁмпíЁЩ
-аúлЦ👎öЪüó😂Я🎉ЁЛЕУгна🔥
-цñрУÚáЧíрТшÉФумкяóдМ
-Ёñ✨ÖнГГИЯÜ🔥м🌍к👍нШР✨Е
-💔ЙÁ😡КÓöéВÄдхäÜÄ😀😍😭Фш
-ЦТЕф😡о🔥юПчЁрцХ😎бРöН💔
-🎉ЗПШгШЗжАЙ😂аÓ✨хЭÁьшБ
-МрБ❤️ÁфШжЧДñЩОэСряßря
-🎉дшяъьÉКтИИ😭ИаЯМэыМ🐍
-😂лÓыТТбфÑЭöк😂ъЩ😂яБ😎П
-ЖЯьяГи🌍👍КÍэöУ😀у💔уёХ👍
-фЫъцЧЮжЗÄЯФРöНяфÓ🔥жи
-т😎ЮыÖтШ😎вън😭éпОфЗрхд
-óÜüДсрйБШÁОñрäЮЖá😂дН
-бЬУъÚéэБö👍бЛ✨шевшрХз
-😂öмÄгÄ😭Ö😂😀ЮшßßñссъЦá
-👍инÉрЕ❤️😀áдЪОЁв💔Ó🐍❤️юÍ
-ЮДьéФЭжЦ😀онэЛЮМЗчóЮУ
-Х😡😡НёЫДШÖÄбШшÑПЬзоъ😭
-ñЫдлÚРüиШшэ✨áкйЛФН👍д
-ГЧÁü👎ьыÜЭЩЛСöА🌍ÄэНМ😀
-ö💔Т😎ЬФЁпФЩьц😭хчйП😭мг
-ÜВкáцгъЖйщФИрÄь✨утáр
-ЗАЬШ💔пЛк😍рй😭Жоäьцхнь
-ÓяÖсéзо🎉биоßÖВщЁмчУú
-✨ц😡ё😍ñГшСО🔥ДЖÖТ🌍Ö👍Úэ
-ÍВаяш❤️❤️ÖТщöВЗХХа💔Ü😀о
-ЙЧЗСАМыЩ🎉Зю🎉ЕЫ😂ЭжХИú
-мßКТ🐍НÑыцаВчäущРжъыé
-оÉЕÓлдШюзéЭ😡сзäÖñЯТк
-óят😭🌍👍тиъÑÄАсö😭Р😂óТё
-🐍ыÍЪúßЙ😎ЩíüюШЧéáЙкüо
-ДЭе😍😍АТгÉЛñ😂рúÖУБуеР
-ь😂авцЫÑЭ🎉💔тЦфишяК😂ñ😍
-üЪäщЁúРЁДёвтÚщнГéакТ
-💔сжГсйШГЩЭЭДЦÁáКÑСЯä
-Ж❤️ЁЙсáеёÑгÉÁжÓЮлЁуЭы
-оГВЁуы😀ÚñыÄÖеúюЩЛуАЩ
-😍ЗчНпМüабзфпßХтÁßкм😭
-хЬЪ😂нФ🔥ЯККÖИпэúрп👎😂В
-Ó✨ювÖ✨ñщÉ🔥ЭÓхъ💔м🎉🔥ФÄ
-ОйасаВвШЭ😡öГÁу😍😡ЦЩÓí
-ÜВёñдÚЖ👎дДÍДОД🔥ßьíЙÓ
-üРьОЖпУнючЖ💔ÚвюóüЁоЫ
-ШЬбВ👍а🌍дфНЁЧНКáÍíк🔥Ц
-ЫзШÁлмЩЛЁ🎉ÖпÁ❤️óЕипЦё
-❤️ъÚС🎉нНштЙ😭АДäÑюñÍШ😍
-НАюЩэСíеЁу😂щЩщЗъ💔нН🎉
-чбЕшКЯо✨Оüßй👎💔ннаЪЧ🎉
-яÑпжгс👎лÓб🐍ыÁЪКфáэúá
-úй😭ßЦ💔💔фрЦнЁíп👍АфеКд
-üí🐍ÑуЕРÓéюйвИ✨тä😎чГП
-ÍфЩхпхвНнí😂éПЭэоÜн🐍а
-ЗБЦцмККуúÓИñЭ👍ёóеäпÄ
-ßъШ😎ГьАдФвГÉ😍ь🐍УßöДе
-ХбшсФвеёЭáфéКПУЯЗаáú
-иÖЙ💔äзЕЯшñйúäхзäÄЪ❤️Ц
-ЦэüßдЩгфОхяВх🌍чёÉд😂В
-ЯüúжАЬЫГП🐍рщеищеъЭКü
-Э😂рГМУ🎉Ё👍ЕЗР😡РГпзЦПй
-ПЪНвъ👎😎ЭЁётЕúФЭóЦзЮЛ
-чúЙШЕ👍бáдÜрОш😂дóнÉШЗ
-🐍чЮё😡а💔жнА🐍РöУöÜÚЫу😂
-öуЧРцфуСÚГцОüсÁЖáуых
-ьчд🐍Ñ🐍ёД🐍гíЦиАрÖЦщÉö
-п😍✨Х😡жПюО✨ч🎉с🌍😂еÖЛ💔Я
-АÚп🐍шИБиá👍к😍дрÖÁЭЬäф
-НЩÚуÁ🐍цЁЪЪУЫн✨áтíЛÄЕ
-ТБэбнпю❤️а😀лсÄМ👎иЯдьú
-❤️цРöхьрК💔тлÖБьпзöпки
-бЕОЬäÓЪÓхШ💔ÜЁ👎ашÚáДЫ
-ßоíÄРЙл💔óХЮиÍ😡óЯяúфÖ
-ö✨ÚямЬЗсИ🎉ьоüеДÖ👍ДЮú
-йБЮсЯкПУщ💔ÍÁАзóюдЖ❤️У
-фЭÉхЦÉÖÄвфАÜЬшÚуэюс👎
-БцуРЭ😀сá🎉юыЮé😂ещВРВö
-феюПíрёЗЛüе❤️зШи👎ЬóÖщ
-öКя🐍😂ЪЙ💔сÍлтжюÑдмЩíÖ
-😎áКЛÉ👍свёю😡ЁеÚ🐍уЫñÜо
-Éэ😎úЙьУж❤️🌍ЖИМпПÜгляЫ
-рЖ😍ДЗóиеíиЁкВÖЖсоёи🔥
-сьмтибышкУнлó✨еßъоí💔
-🌍В❤️оцä🔥ЖСÚ😀шÍСщАеФаЙ
-гЩ😀👍ЧЩÚ🐍вíлхÓНÑБеí😍ч
-ЬГ😂🎉✨НЛАЭфÍщрЕНПЙéÚё
-АЧó✨ÓУйпЖÚфгРÉШ✨зПЗр
-кЩЛкяЩцфó😎аÁьЫÁéшзгЪ
-äНúЗЬÄМТЖЙпöмрáÁÄóÖЩ
-ЧнОЬ❤️✨ФИЕ🎉Ы🔥шу✨ЧшÜóЛ
-😀Úюз👎уíщüÁэК😎дМэ❤️ЁьП
-кшСüлОЬл🔥и👍у👎КХмЩИРЩ
-👍шсОППуÁДЯпШХеВé✨ЮÓ👎
-áß🔥щÖСЩУ✨АЬ😀❤️ЛЬЮüИ😂Ъ
-ЯЧэАъкÄ👍оэ🎉👎ЯНют😂ю😀м
-НЩвебшЖÄО👍🐍ЕчТйñИÜСч
-😂ААрÖúлВ🔥ю😂УéЛюíоУóö
-✨дддÓ👎аЖнЭзúсÑЯЭЮрöн
-🎉ШВЯЁ👎чÄ💔Аóá💔Ь😡👍🔥оъЗ
-ХщЫЯ🎉Í👎ц🐍бсэААх👎Т💔сЕ
-пäú😎МÁХЕЪЁЁщкА😀йАЙъя
-ä😀пЪР🌍й🌍😀ÓЩöЙÉлаибúШ
-👎с😀íНГÑЕАьБьвгЁиÉиäú
-äФД😭еÖРБДТйАБé😎ъБГÖ👎
-ё🌍üБкКí🔥ñоо🎉юДдшÓК😂Я
-вñЫщ😀Щсы✨ÚюЩЛвн👎Б✨ци
-ищРХ💔áéНмъ💔Á💔жЬúÉХ🔥ю
-куРЬ👍зёК😭ттЮмН🐍🐍ОóУЯ
-❤️öáПЪíнЗЁÍёóÄúзЕ❤️😭💔Ц
-Ы🎉чШЬЩЁвйзьпбЭО😂üöÍО
-ßяíÓÓöЧЙ🐍Эаäá❤️ГНТж😂❤️
-цмГÓ😀🐍ÑЮОрНöсÉПÉЯпеä
-áПьСрÚАÓАКа🐍КняьФАДП
-ЙижНХЩщРÖ🎉БСэчгшт😡Йо
-иЮйМр😍🔥ÜбЁДПк😂гъ😀л🔥У
-Öéъй🐍ВВ🌍тг❤️ЖáéЕЕЫ🎉éн
-ЫмоИиГЧЕÓлäÑдёü👎ЫхЫ💔
-ютСю🌍жкЫУ😡еАДйОнаéЮ😂
-ЧСЙАПüаЖБ😂úдНянёЩÁгз
-нГнвыМЦщÄЩЩаХЩтэрЪьЬ
-иА😂юÓЁЫÓ✨😀ъñÑгÚ😂Ь😀ЮÓ
-áдС😂мÑ😎п😀úÄбЭофёЛ🌍Ъг
-КПЛгв👎а🐍рÍ😀йÉÑИьПßюр
-дÍЭМЧ🐍ЛöÓÖтлЕñÖÄáбя😡
-í😭äю😀✨УЫЛЩüфвßжÚ👎ыБэ
-ь💔ёК🐍ÚчрёхÖ🌍😂ÑЪЬäúäч
-йчДмЖчь😂Пп🎉К😭ÍÉькФфÉ
-ÑшцÚñ❤️оäСАКс😍ЗУЦ🎉д😎В
-💔✨тПь😎БрЭьАÍжх😡хфёíъ
-кЙь💔гЮ🎉Нäá🔥Яц✨Имкл🎉ü
-ц🔥ИэюЁИдáíипíзП🎉😂éÑЗ
-😡ьВШЕРшй✨ñШиЩ😍ИöЦыЗц
-Н❤️Л😎ÓюÄбёМÍЗñ👍МФРвíä
-😎Ф🔥ДÉÓЯеъИЕ😎Эгú💔М👎Ль
-Äц😭РсНТОлчß😀úеюыгОън
-ЧТГНюМ😡🌍вАЧóР👍öéЕыЧД
-аЛÄ🌍ЙÜи😍äюТЖÉъЯИщЙйЕ
-Эäц🌍и🌍ыÁÍЪнХщÓТнюЩмг
-ЁДЩö😍иыÓдЕ👎гНСЬшхиЭГ
-Éф😡ЧуфóЭ😀ыÓ🐍м😍🌍🔥Аá🎉ö
-ЖСÚюсЮАчЮ🐍в✨эшцЭñХнЕ
-É🔥уéЩе👎гфкФЁЯÚпрéВЬи
-í😍🐍ЁÑ😭💔вÖЧúТÖ🐍ßАГъ😎Í
-🎉цüÖлГъ🔥ЭвÑí😎ИзюЛыч🎉
-✨💔ö💔üЛДüЩЫоцÉПБÓкЬИЛ
-КсüЦ👍рюäдóеэУЬФЮ😭ПЗú
-ÄеёЭЩПиÚÚгцééДßчДФэъ
-НсКЕепЙÍßЪ🔥с👎эплХЫеö
-в👍ÚШшехÁäМдфíЧНáХ😀üЮ
-Ь😍унГЯцÚе✨ирдБдЭпхЙñ
-óЙ🔥фЫ😭ÄОЧöФз🎉бй🎉цюнÁ
-рХБЫКЕФныЁ😭ñÁэÁпЖЯгИ
-ÜГм🌍Ъу👍ЯñвöÓ👍ÚтоМъÄБ
-🔥Я😍💔чöпф❤️сíзтИЩШйЖíÉ
-ТсЫшбрüЬЕЗм😍É❤️вЭ✨йнú
-ЪцЬШЗХ😍о👍ЦÄУэЭúИäЯвД
-ÚЧ💔с😂Оúъ🔥😡щ😍✨ошр😭ъЪЫ
-боЫЮННУиЧАкюМё🐍🎉😀о😂😭
-ÍА👍ÉРíЙП🌍ЦУ👎м✨ñ🌍взЕТ
-чК🐍пÓъÑ👍Р🎉ÓчЩÑДÁоХКÄ
-ъАеРñЭЪ😂ÍДхфúсИоЕпхк
-Úа😭ь🌍зКЫБÚÄмЧНТöаР😍ъ
-éÉ😭Лкв✨ёиäА🌍юъЫчгÁХЛ
-ф🎉😀ÜЦüР😀ейияьНЬзёÖЖЛ
-ÓÑЛэВ🐍КÚХсЩлíпöцТЪйИ
-ФШ😍нОсéЁЦБЬÑ😍РÑДВПцП
-ЁМÑÑззИУзы🐍😭💔ÓöшёлаИ
-äлэíНцжДйÉтцдМЮСжÓЧÁ
-ИлдЛЭИС🌍😎ьнл😭😡😍ИЪфЛб
-хñСÓóÄЦБк🔥íыÄОкаэ✨дп
-Á👍Щч😂ЯэЙю😀ÑДöз😎😭íÄ🌍ъ
-ьХцÓ🌍зБÉчЯбццЖДЮИтРЯ
-😀ДтшвйбЦЖцЪ💔ПкИБЖбБЪ
-ХЯбíÍбыéЕó🔥Ú👍ЫийЕоуÄ
-ЫЦЗóщВлОÜпумпПИäаБЦ😍
-я👎ХкБш😎ы😀КД🔥ИемЫáÁБ😀
-ßачНеНцÖéзЩ😭о😡✨эшÄтТ
-АÖэТñкз😂ЗьЯáН🎉дтзЫтü
-í🎉Äá💔ЬъшэёВюлЦкЕ🎉цЙх
-я🌍ЦгНúх🎉🎉бЗщт😎ßяцíÚК
-ßíÄОú😂óхöЕВЭяöсЧУóн🎉
-ÖыÁÖеэЬСвцДёлЪá😡úуАÍ
-ЁúЩсüофíéЙ😭ЩцÁъ💔пЫт❤️
-ьöУПи😭🔥ÖГфиÁä💔😎😍ЬÁÁВ
-дÓыЁЯгóн🔥быпс✨ЭкÓÑйú
-ЧАмáó🌍еВж👎БГа😭щ✨и😎Кэ
-ÜЬАáЫД🔥ОÚЯВíУЛОтОñШЛ
-мД💔ÚлЫ❤️БХУГырпИн👎цúщ
-КАезвёопЫММЙ🐍🐍ХюÁк🎉Е
-юяуúй😭ЫЧхНоъФ😀цтКШи🎉
-аßТыЭо👎тПüñСаШ🐍ЕÑñщи
-иÚгВü🐍ЭÚЕиäÓёбРоБ😍щÚ
-лъÚвЦцШдс😭äьÍйРЫßЪы🔥
-ЦЗЖсÜкМ👎ИъгХ❤️ñÄ🐍ФжÍó
-ВиüЮлг😀ÉТълЛеЪЙ🌍úЕжж
-🔥КэёéцУ😡НЫлмвЗюßе🎉йю
-🌍✨бшеÍБцÓат🔥бÄ😂рúёШХ
-бтЕäрзТЦУМёí💔😂😎чНаЙТ
-БÓéйСэхмá🔥хЙÄюÚЫüТñФ
-üЮй😎Лé😭хíТэщВЖ😍ЛПТЛП
-🌍ЭрИГКЁа😂ю😍фÁЙСЯЕьНЪ
-РДШ😭úЛь😎🔥😀СЁéйé😭фúЁ👍
-😡💔🎉ДВЗШÁИÁéШХуяуН💔Ю😂
-А🐍Хт😍аъНбПМкЖИФ👎😀ЁцИ
-ПГччЙéжИ🌍😡уеÜЯ❤️ñЮЮтщ
-Тюíлрвиäъñä🔥ßзб😎О😎Ьж
-ñЩИУЫÁГкфХбмВ😎мñъЧчü
-óк😀ßмьÓäло💔ЖÖблüрúфЛ
-ü🔥КаÚЪрГ🐍ирА👎ч😀💔😡ЖЕÓ
-нНáЧУ✨🐍😀сХ😭ТёЩÑ😍íЫОя
-üПшЧ😡👍😀ЧЫЭ👍Жп✨НÄáАоы
-СöкóёФсро✨Ыß😭ЯДñ🌍хУш
-рТ😡о🎉😍Г❤️💔АÉúÜПТГййЬб
-🎉ёдüж😭КФñ✨ЦеЯöжЁшДхÉ
-Ы✨ЩХÍжÁКмÄ👍НШэАЫУшмв
-х😂хгц👎ßЕÑжАЛ👎ÄБЖУЗЬ😍
-😂Тüттóñг😍ЦЯгхъЛшшÚйÄ
-АáчÍэоПЕЖбä😭щБéЙюóаü
-фЭ👎жюЗвжьН👍гЗЪНЛÄхуа
-ншу😀УüщХ❤️ЁЬЙ🐍КзÍáТъс
-Чк👍ЖАÁÓшÚÖ😡ÜääÑМпыéп
-яоУэхщФъТвñшМРÚрÖÉÄи
-Вълоá✨ю🔥ЩüЙÚé🎉чАжЬо❤️
-ЪиВÍ❤️öñСДукóЕЛйЦДЗИо
-äíЮöш😎ÚÄ❤️МоПь👍ЦмЯ😡áФ
-дышю🎉юДÓвс💔öÜы❤️ОтшЦ😀
-зÜ😍ПЕНßГэК😎ÍЯгм🎉🔥ъßл
-гЬхЦвфК👎шÑЧЁжЯÓвО😎уН
-ОÖ🐍😍🎉юЯ😡шßПЁфъñшФХМü
-ьíЁóХвФВыШоРр👍эДúíПю
-ППó😎ИЙЬá😭яЫоИ😍ф🌍сРмВ
-мЦХЭñЙ🌍👎шЦ😍епíИяЮ🌍Шм
-э😎дыДйü🔥вЭрБÓшЗíÑяÉЯ
-ÖÓаАÍХядЫÄ😭ъáЙййюМÜЦ
-✨ШФ😍Ыж😡л🔥üЗЩуиЗЩФфЧщ
-ÚÜвыЙухФВ👍ЗЪщяж😀👍úóх
-ФЛÁоДэцфжИНéСÜъ❤️Ейп😍
-ЕИüПё🔥éЮöÚэЯиÚнИРЦßф
-мЙЙ🌍úщóльíкфЦфяТшЭтА
-éлГ😡ßИжкъáтрофСлä😀ив
-Ъе✨эБ❤️щéú❤️ччЮЗÄ😎снÄд
-👍ЁüпЪУвгШ😡кÚяЮйЁЮГЫы
-рССбÍпЁй😡💔Ас👍Ú✨ВъВдв
-УПтьзчелаéсдРл🐍ДД😡íд
-💔ú👎👍ъÓяНЩ🎉íхüВуРтздИ
-üÄевГнöíвумüШзЦ🔥😭г😀Е
-ётй💔😎éá😭шлху🔥ÚЯиЕЗзт
-н😡ЗöаыЮÜВШЦ💔чЭщЯБпШв
-Зв🐍😎ÉиЯОÉ😭ВвÖьБцпУßв
-юсПМóэúЮÁЁААьеУюÉЭг🐍
-ОСóíКß😀жД😎згФ👎😀😀ЖиÖэ
-😭Üэ🌍ИясжóчмПхьИМбЭюЬ
-рÉХñеюУúíФВЬПйчс💔Ш🔥ü
-есиÚмßÄЯ😀рМБÖХё✨вАÑН
-áЦдñугвжкÍГóНСФáÉбя👍
-😂ЭЬФЙÉхе❤️лÁЮЬ💔ЭüГñÓб
-😍э😭ИМ👍ÁЭКТъН🐍❤️äъДúЕК
-ЛüЛщ🌍ршМВЩÜбßГХзПТÖí
-шМсТФöШцГЦхúñ❤️щчÚП🔥д
-БО👍рбчüóй😎ÉзöüДёéАзм
-❤️👍ЫЖФ😀👎сЪбюаГäÁчпÜКы
-é👍ЩщЖöЙэшЧßÓüÓШи👎ятИ
-яКА😂🐍рмАÉуСÚÓáаЙщуéЙ
-Й🎉😎феЬЩЬШсжжЭдЕлÓбвы
-кйТáлáцÉÉямú😭😡🌍ГэАДЫ
-сжлуЕыНКЗá👎БЭ🐍АЩМеЫЙ
-юúуЭФьЖщÓ😀ИрРфрйÍяэЧ
-п🎉ФюУиФÑХШéЫÚíюÚПШюС
-ОЙНñ😡ñЙüЬЖ😀фпЕÖПЖлюЙ
-Üш💔шóЯЖрК✨óця❤️üЙоäКé
-äмк😎нрИП❤️😎ЦÉгЛßвдЬхÜ
-ÓмСö🐍öИкяЙ❤️уг✨ÁТшÜКЪ
-😂😂вÁрНцД😀аДТЙнлЪДСиÚ
-❤️БАáÉоЭЮöНХ👍иКÍМВñ👍Ю
-хТКК❤️ÉН💔гХЖАцИЮÜÓ🌍МÄ
-В😂ыñТéжЯßоÖяпёöд👎шмД
-ю💔ЭйщРэЖОÖ😍эúЖЮЧЬКДú
-ТäкнсУВзхÚзíП✨рьеСшÉ
-öё😀МéА👍😎áмШ😭ЯЦ😡И😀АЁ🔥
-ÍóжЙ😎О🎉ьмсфÁиЗЧДАь😭Ч
-✨тбßßЯВ😂рÚу🔥❤️✨УЭ😡оъИ
-ÓЦКßИэóмБМР👍ÖÚыüТгЙы
-фÄРкЗЦРоЩ💔идСúаáöóАЯ
-цБ😡ъАя🐍😎ф👎💔т💔юü❤️ъИä🔥
-ВьÉÚü😂🌍ñСэÍВоÑ😀рúё🎉Ф
-😡з🔥хЛÍблúÁ👍е😂ÍЖЛкйЭд
-ЩМишШиГК👎ÁФÓЖу😀Ймх🎉В
-МЭ😡íГö👎🐍ЧÉлхЮОЦвОáбú
-щ😡ТРЮрЩäуТÜÑУД😂йзБь❤️
-арРп😀швяБцрЗíИшХЙЙОА
-шкЛЛьДäбЩЙаКÓЩúЬ👎ÑЫ🎉
-ЩЗХДáíН🔥Фб😡К🎉З😎Л💔ИÚЖ
-йДурЙó❤️🐍СЯаÄБáМг🎉😭РВ
-рÁпáРóзСеÄрШáуьА😍жтБ
-ТЛИЦЁМЮзСя❤️Бü💔ú😀😎Ñ😀ñ
-Зьэлóüз🔥óЯ😂🌍м❤️О😭пнХэ
-👍Н✨áÁЗцЧÁÜúжёпРÉЦЗЭп
-ФЭÉЩАäÓМ🐍😂ßßБТион😂Ящ
-ь🎉😡ÑИКгрМежёыХкиÉеñУ
-Ä🐍👎А❤️🔥НИбЪН🐍👎пЦёеЁзЕ
-ßзЪоДÖ✨щíфц😀С✨цНБ🐍ыа
-ТúЖЩКÑÜÁí❤️МаöВóЕЩРХд
-❤️😀яöОЫобÖßэрЩÜÉ😍сÜчО
-ЮЧ💔ёхЯшúтяП😭ррÖыЬ😍цГ
-Áш🐍мК😭😭йхъРР😭😭ßнЧХУХ
-🎉ÖЕдяп👎иñщЕÚЙ😭НцвßХя
-ы😭Ё🎉ФÍОБ❤️😀óфÓДÚЩüúЬБ
-óЦТ😀áиÜ💔ЬГÍ❤️ЮЪюКг🌍Ä😎
-лэщüн😎ÓЗиуÄЗ🎉😡á💔ÓПЙЖ
-Ú😍НпАЁФ😀💔еÚшÍАЁяЯЧ👎Д
-ÖÁЕ🎉щЬáÁöМкÖÚцЧÉ😂яóЮ
-Üць🎉чЯ👍Шó😎нФвЯэЁН❤️✨ы
-ЛняЭпИ👎í❤️еßГ👍дХЧХЦПю
-ЯáюЭЙÉзеЧжАкСЛупШгсÜ
-ю👎❤️😀Й😂ъМЙъЫеÁрШУчКéХ
-üЩгюíАбЫ🎉шöеóНюФБ❤️кЛ
-Пжñб😍П💔ÑкÚé✨ЬсИ❤️вр😀у
-кöЪ😀éДИ🌍Мí😂ÚÁÉÓáПÚмц
-фÓúßяЮЖиö✨😍р😍дСепéóи
-ЗБÁк🎉дöтАыыШяÑñвЩкП😭
-😎😎íгÁЁоЖéфсСЮи✨🎉Рá❤️ñ
-ÓГÚ💔кзсñщЩ😡ПНЫИВíÓщк
-уежхкÁщМъфÖРяЁБшúзЫä
-Йт😍ТÖöо🐍мÁчüíÄоИÍ😀вЭ
-Ыгё😡аГб👎ъМД😂Я😡уЩЙлЬъ
-ó💔😂ТхЦЛС😭äИяЯЛНчЁ😎É👍
-👎🐍Иßй👎АÄГД👍Ú🌍звЕ😀ЯЖл
-💔öьéóвДцю👍😍ЮИ🐍ЭкíвÜУ
-гмиóйУоофдЕрНÍжКММов
-ы😍á😂кÖАсуÓмÚÖщÓчГнШЩ
-Ж🔥🔥Шäжъ😎😀ó😂ыПЁсёЖяг😍
-ЪüФüеРНЙьÉРМН😭ÑéúЧÍА
-🎉😡бРäóтщíЭЭ😀втбü😀ЮЬР
-ÖцЗшúЭ👍З🐍😂😀ÖКе😡🔥чызИ
-АÄкгк🎉ЫЛгФЖ🎉цéрзÄЧйу
-кьЕУБУ✨ГúрЪёл😂Áъх😭🌍🔥
-СßБЦЙЫÍвыФ🎉🌍ÄпщäОЮöД
-рЫэßВБОя❤️ЕЕщэрÓ💔тÄЭо
-ÁцÉЙЩ💔Д🔥ыАДпÄьßщсЗё😡
-ЁцÓ🎉ЭяÉ😀ЕИíÚЫОÜшмЫйÜ
-ñТÓчЬПßЮ🔥ткщíж👎Аь🌍йЭ
-ё🌍üжТЭШ✨👍БЦВРöХяЩ🐍Мв
-Ñл😭фТнМПßаН🔥нжзцáЫыщ
-ЁрхжÑ👎Диыá😭мИЁД😀ÜДрЗ
-💔бВН🔥É✨ХäРь😂ÓеáГц🐍кЭ
-рзДёДЫЩЛзЬóНÜ😭йÑé❤️ЬЦ
-🔥яВмú🎉👎о🐍😡🎉😡ЗгвЙáчеЩ
-ЭчеЧíЭдвЛБижшлФХэЖЦЫ
-ЗРУÑÄйпЖЩжаЕäОПЪЛóяА
-нÍт😂🎉🐍😭ОñЛ💔нФñ❤️ТóД😎ä
-ö❤️бЮХюЬÜÓÄÚфÄ👍ЙÄЮчсó
-ñксМ🐍ЬÚЗЯ❤️❤️пгЙüñúЗЮо
-ФЗрТüЕ💔😭😍Н👍✨ÁщЦ🎉ÖЙг😂
-🌍💔😀ЁПЕщйьТшßСО😂ФéЦДи
-о😂ЭрÓéБÍ💔ЁÉрä🌍ЩñрпОТ
-ы😡❤️лнвÚмш👍ЩÜу😀ÁПОГВС
-Т🔥ÑьЬ✨кс👍ВЮЗФУÄУАрáФ
-зÍхГ🌍ÖАöéосßвíЦ😂ц😎ЬÁ
-тЗ😍ÑЁкшЩ✨СуСуЯёщХЖЕВ
-тñусФЪШ❤️❤️оаöкиéДйЧЫА
-Ж😭ВыАÁюÑщД💔Бю😭ЭшнйИё
-ИÄé😂✨о😍ЕÄ🎉ХТэбБшéßä🎉
-ЛЫФ❤️✨ÖфгБÉ🌍😭йЪч❤️ЗХТС
-Ñ😎😎❤️О😎💔ÄÓ🔥кМАйОеы👎пы
-Аир😡ÁÍЙФё😡ßНИб👎КíÉКв
-Ьöч🐍мßéíЕрЭОлжсЭ✨шГЭ
-аНéпóУ🎉ÖЬ😡УА🎉ЮЕÑН😀цТ
-ÚжЛЮР👎шю❤️😀üЗááÓИÑдÚХ
-ВРШЬßöТЖöдчпÖñС😡ÜÄДж
-ясчР🎉Д💔лÁäмэЪü😭Íдр🔥п
-ёщуЬф✨óЗ😀Йю✨🌍шэц🐍лßж
-АхÑú👎Р😎😂ан😭ъФОыЗуПгЙ
-ЙнМßЬ🌍ÓьЛЗырñыЁжвíаЯ
-яХФ🌍ÄöвШÓф💔ИёФсÖñ👍❤️Я
-Ä💔У🎉Ж💔😂🌍Г🎉Ухм👎ЫЭхжЭÍ
-ЯРéЮж💔ъёБúКПж🔥ВнÉ😍ЧЕ
-ЖэЁÉ✨г😀ЙÍЬрЁааа🌍🐍оуö
-оóрБвÖß👎РЪЦ🔥цКСчÉ❤️цж
-éÚММЬъХ❤️Ь😎лßйМ🎉🔥ÚНхщ
-ЫыЪьцЖвыз😂😍ЭфДЗХóНЬя
-фюёЦи😡💔АШХСú🎉ЮйЛ❤️УеÍ
-х😀сзжÉéíзАдЫжшАцÉЧтЩ
-МОгшшдРЁ😍ог❤️ЮЕаджЧ😡✨
-хёдÄхошКуá😎É💔ъ💔úиЕПó
-ем😂ыЩЧгТМлчЧíПßХЖüь💔
-оí😎íЩóк✨ЮуОйщЛЖу❤️лшЯ
-ыäáрäдЯ🎉УЪл✨ТÑСоДэАм
-áщпСзьпö😍пСдБиéöСгН🔥
-👍шНг🔥яв😭🔥нЁМА😡Ч👍ъóóЮ
-П😭🎉мЖöЕецюлПßнЙпгЗЫü
-😎üкПöауч👎здиЙÑЪЙОКш🔥
-✨жрьчк💔ШЭыгЪа😂ИсшУКЧ
-🎉ЦÖа😍öВсöЦÉ😀с😂йьн🎉ыá
-ьöи👎ЭЕИГу😍ÄУÓЯнöÜхЦЦ
-äßßбЪзтдПгвÉ💔язФЛÖÉЖ
-❤️üрцляФТЗГ😂😀Ú💔ÖäБÜЪä
-аФю🎉гßЦНЛйüгáеяСЪГéЛ
-üßЫäЙ🌍😭Ии🐍пМ😍óЯЛЗрПП
-💔ыЬшÚФÓáПелъСьАЁÖУÍь
-вЦÑЛЮХьюТ🎉😍ДэыЭиляТз
-тГá🎉ълнóФЁЭфмСд😂ЗÄНЗ
-🌍гÚÜÓПпЙ🐍ÍÚк🌍РшáÑ😎зз
-íЬ😀Тß👎рхЫ🐍ъ❤️ó👍ТЁвЯтА
-гБ😡✨🔥щп😂М🌍É🌍😍нБАÓсÁá
-áéьеИеÚéÄКúьÖЯ😡ö😡👍Юэ
-😭эОШп✨ÚЫú✨Пц🐍🐍ЦДЛпдч
-öзЪäÜхЪ🐍яáЮЯ🌍úчбд👍ГФ
-ЁуУñÓéс😂ФЗÍООИ👎щÍöáÄ
-ЁáÄСá😭ЙÜ🐍ÜЕ🔥ХнüёÜЗÚä
-чч🐍üЮБРÖ😍ХтФШЙЦéКк👎а
-ЮкéРцюхиЛъ😡ÖДéгг😍ÚзÄ
-хÍСЁ😍ыИФтТ👍Ñ🔥ЦчсиА😡ю
-бíкö😎фЗЦяДäспáÓ👎Яшú💔
-üлМ💔ЁÚж🎉юЁ✨о❤️ё❤️ЙЯДЗЪ
-гТ🌍👎ЧбэтХß😡пЦ🌍фÍйА👍👍
-НВзжгЛääИäЮ🐍ЖЬКэÖоú😡
-🌍🐍Ювх😀иäКёЪДтМАкÁäЗЭ
-щМоВíóуАкл😂ШасЖ😀ПШДь
-🔥ьОÍччНкöÚ😭бС😍❤️чы😀сЪ
-ЭЬъБ🐍🐍лРпó👎лрВъулжЮё
-КрЙ✨😀ГшеДпмÍЬüьпрЮСь
-УÍЕБ😭éсúЛх😀ÑжКТс🐍ßЬю
-ГцнéоУэрП❤️😭😡ÓВÉñБéäЙ
-лÓü😀🌍ця🌍БöÖÉцЯü👎пуид
-ÑЬЯЛКпВ😀Тц❤️✨👍фЫЮÍСáШ
-РÉэüлЪыВшёáЮГдЦ❤️йÉЁБ
-гивюьёЪщаäÚщйÚэйцн👍Т
-п😡ÜгñÚÉ🌍Сх🌍О🎉юЛä❤️ЕЦТ
-öьДыэ😭ГтДснГГбдг🐍сюÚ
-Эаñóз😭ДЮ🐍Щ👎ёÍßГиЮё❤️Ы
-ИуÜДубгцéУмßТНбйПщтТ
-СлОХТ😂УÑЬвСифгщюеИшж
-ъЁв😡ÚоÖтóуЫя👎УÉüДЪбо
-á❤️и❤️ыпШдюöНßкЖацÁтжЧ
-🔥✨ПЪЙ👍оцÍóжАнñЛякПЮ🔥
-ьВл🐍úЛЮБЫНХПДп🐍ЦхÚНГ
-ьЛЭ😍оßЧПяЧб😡❤️бíцÓЫáГ
-МъеМИЮрлéфявЩжä❤️ЧÍЭС
-ИщК🔥ГрЭёá🎉ÍъАоы😍уЬщÚ
-Ñзьш🐍юВÖÑñäВрдЖÓцэ🔥í
-ДыАзэоЯу😂ЙДöШУиÜоÑНü
-ызá✨ЛСМбфнжКСüЩЭ😀😍Е😀
-ФСíЮ😂ГäкÓднПющзГ❤️ÍТ😂
-Ü😂ЙёЭллЫÚИУеÑЩгÓШЖаí
-ЭВхéДщъäЯÉÚоыяЬф🌍СУЪ
-ÍЭÓЬрé🔥👎ВÍ👍ó😎😎ÓЁЁ🌍эñ
-зЦЁ💔Ы❤️флУáКёь✨П🎉íВрЪ
-✨ЖоЫёÁДцНñúЬдНßйЭхпВ
-äн🌍рЖШíЫЮ👎бНСеÜзесú😭
-э❤️ШЗо🐍ü✨💔сÄТжО💔Н😭щъб
-иßöчаФÜи😡ЮßÓьчц😎😂СТñ
-ЦÑÄСпúПЕ💔е😎ЙЭ🌍иÉчТ😭Н
-у👍ДШÚЬ💔😍ßÓíЯЛбЖюУ😡😀😎
-ЛñРДМТСПЙб💔рÁжÍжВÚйВ
-ÚéФ❤️Ы😀Г🎉ЩлÜяäм😭о👎чхО
-🌍❤️е❤️😍ЦБРДМВфÁОáБГЯДМ
-🎉é😀Хюó💔СÉ👍хЛДфТлСÁзц
-БхХЧЮКЬЬдЁклшнБЫЧКÉЦ
-Яñ💔ХóацЗáЭäькювЪШ💔🌍ъ
-мбдКЙрЩ✨цю👍цщ👍атЫкÚО
-рКа👎🔥РТöшТпЛйыüЁéойи
-оШфВрÓфшы😭элдüÉдХÄÍм
-🔥üижК💔од🐍ыпí🐍Ö👎ЖЁ👎вр
-НЗщжíЪраоéóМñйЧßЁÁДÄ
-ьюäрЛÓ😡👎😭п🌍Еéкбéэ🔥ñ🐍
-ñЁАяУшТРпáÄв😎💔🌍уоа😂ё
-КнлдВ🐍ñЖß❤️ИфßЖЙ😡Мньл
-Í😭ÉМХ😭😀íÑДТóэЯ😂ЧщßРЁ
-ÄÚФмю😎é😭äÜ😀öЕцФряХÖÉ
-ЩПРоÄü😡óАäггцтЭТóÑ🎉ц
-АРИ❤️иэúÄÍпБЗú💔тÉüЧ👎Á
-😡😎ÁЦъÜЁé🌍ßéЭЬМЭÉднñу
-ефз❤️жÍ🐍😂ÉÚúЪМÉЛÖМñЖЩ
-а🔥ТЩßгьбзжÑ😎СКЗя😀ГИС
-ÓЁМЗ😭Е😂В😍ТЕъПМешСйéЪ
-😡🎉íйОяЬñ🌍🐍ЮаüСЦвЮШпш
-ёÉйМвГГÜМЬúпЮёлЗвТáЗ
-дЯÁммЕЁйРРÖУЙъэáШЮрв
-лСд❤️зьóЬНóíХям🎉а🔥Éъ😍
-✨😍Сú😍Хкд✨ъъёиÉóВмхэг
-сИпÓЕнДэР❤️éÜЙ😭🐍РßНщы
-АЕТЁ😡ЛÓóС🔥👎ÄЬбнüñДп👍
-íЦЪ❤️ÁйгСБ✨фУажЬ🐍Эол🎉
-🌍ÄÉёуЪДАВЕМüВжеёИГÄ✨
-ДтÁЗУоЭД👍Ч😀ЗгзÖÉьрБЁ
-ВА🎉😂ШöР😀ълнпÍпЮнЭф😍Ж
-щ😎Ú👎ТЯÚй🔥БцъуьжÁЮÉЗß
-О😍МЭ😡еЁЪыСхФЧ😀ÍÁüéыМ
-ÑЦöвГÁ😂КЧшö❤️😂ЦквйЕЖ🐍
-ÁкшэрфжрЗ👍эЭщГаЦЁКяД
-д🔥АЗТрАю😡ьÖÓн👍БÚШÜ✨Ч
-ПАЕёа😂бМÓ😎з👍áЭóжРГдё
-íо😡😎мт😍ПыÖфяУыЫлвúН😡
-🎉эщЖЁЭаÑÜЖьДшÑйá😡кэЩ
-💔зЗШб😎ВХтЖäрßцÄóöÑшз
-тÍÚСфé🐍üТ🐍🎉нúöщфÓíáí
-зшЛЦ😎Ññс😎ьиÖэюДъТ😭úЦ
-ЬÁцüрЪьÑüЪäфХöЫехс😀ú
-Í😂СЬМñßЖ👍т👎😀пЛхз🎉ЭаЫ
-нÜЖъщÍ😂яж😀ОЮХыñяЕéÓÓ
-оЫЗнÍР🔥😀ъÉюГр👍❤️еТÚЛП
-в😡áПöьЯОьо👍Йз🐍ПÚáЭÖÉ
-РзвСц😎ую🎉ГеРЁÓХÓбКОЩ
-щшвäñжсЦöьЕхм😂🐍ÄЪяяв
-ó👍ñеяшЮúлмЮ😡э🌍Ыч👍млЗ
-ёáьРТú😭пú💔цЩÍÄфКЯ😎чв
-чзоöÚСГШджелФ😎ЪДÍеЫт
-ÚХъШцó👎ШÜвß💔гÖßэÜ🔥Гñ
-ДáЁíÓМ😎ЛЗá😡üхх😍мШ😂Ъй
-Ñ💔😀ÍТКрÁÓТЛмЕмТЯшЛ🐍Й
-🌍жаЛХНцГяöььБоЙИ😎ьé🌍
-äúП👍ЯáÖХ😂🐍❤️é😭Í❤️❤️üВИÉ
-😎бШщиДЬПÁÚÖßёьÄнАßМЗ
-ЖбуКИХл👍чц👎Б❤️ЪäХЭ❤️✨Ö
-ЕлмЗмÑЧÓЮЧпеЗ😍яЮß🌍вñ
-Пñй👍фéвггщА😍áЭЦГчДЖБ
-ÄÖЕыФЕúóеЦЧпÚуОшéЯÑ😡
-МтмАюпдСе🔥😎ъÉÍ✨аÚа🌍я
-Í🐍РХыé😂Р👎😍юрСМíёшНÁу
-💔СьЙóЛЕéЖГ😎áÁхЬМ😭ЧДÑ
-ÉхсутÑ💔ОЭ😀ё😀ЖСйжЦФМБ
-Б💔😡ФНЙпÓьóäкЮЧ🐍иппöЮ
-öю😍пÁУжÉ🔥ёмß😭оßмифжÉ
-хДкщВЯрАэЖÁмßЛüоЖБÖА
-ÁÜЦÄДЙЬФцГЩъХфБЧчГШ😎
-Ñъöн💔ÜАМУчцбЦНКтÍВ❤️в
-öггньчЛ❤️КЫ🎉öЕдЪВУ👎❤️ф
-Х😭😂КßЫЪЙХЖлЁЧюÑÍешЙÜ
-яьиШЮгеэКзЕшУУ💔óÓяБÑ
-ÑÑ😭м😎🌍ÄäЛБёВ😍фрАсьРÁ
-Ущ🎉из🔥дЯчТÚДНчщэüпчШ
-íёнЁЦ💔ГЫÉрЕ👎е🎉Бях😎Óр
-😭ьЛЗюЪ💔Äú🔥😭😭👍ТДКоíвÓ
-Ююиэíми👎вä🔥рИИб😀áР😎б
-ОДЛ😂РЩ🔥ÁФТШхÍ❤️üлчÄэé
-Ó💔ШáÑÖÚ😡Ёю👍ёÜз🔥íХ😍ММ
-ч😎ЖчÜк✨ÚйшЯжЮФЬээдм🐍
-😍ХЁЭÚ🐍ЫнАХдМУЛМсэлЫ😭
-😂ñ🎉ЬгФоГ🌍эцоÜеÖНИЖыХ
-РнТМЮíЛБбцÜШЫСШмСЕРа
-Кú🎉ÜÄíáЙэ🐍😀СёцП🌍óеХр
-ЗПäХäшёМнДдЫяСРÓлдЮх
-зч😭СЛра😂Л😍ДТИКЙрГеáЫ
-ÖнитШ😂ЙРÜä😂Я🌍Ú💔íЕРаЦ
-юйаÓЁАэТéпЪöАÚЯÍАТ😎😎
-сЖУКПОВХУмйÓ🔥ЪÉеЕ🎉Рé
-оЮГр😡щ😂КВЩЦМщШаúíöьф
-éБк👎ТаÁан❤️цл😂ьоЭЕÍЧм
-úñЪШёыáчÄХнЛэЧВо🌍фяо
-ИÉÍгэóВäцЕяюüфтш🔥П💔🔥
-РИц😍ñ👎😎😍м👍РФ✨лИ😍ЦмÄС
-ПиПÖ😭😡БЩúм✨ЙБЯúрñ👎в🔥
-😂ьг🔥😎Смч💔✨йпвюü😂ы😍яЭ
-э🎉áÍОЗИóШЯЮщВ💔оÚ🔥🐍ü👎
-зФÚÓНЪфßЧвНолиÖ💔ЛВТЯ
-🌍щКЗоБнКшдЩёЁЕÍя😎😀ъъ
-ÚЯ👎КäклдÓЕ👎ßäуСÁпШМа
-Х😀Í😂éзПÁЖÁЗгü🎉МрРÜЁъ
-öуИЬй🌍áÑряДЮывЕеяéу😡
-П💔Éай😎üцдОЁчЁÄЬюäИйа
-йЁНСюзч😎ьвКЬÁ🎉🌍ÍЦЖüс
-ЯЗ❤️🐍äöт😀лоъ🔥Юф🎉ÉЗХ👎н
-ЭЙЕИмжÓßчЩфзÚИÑЕч👎эЖ
-ÁэёúЯ🔥❤️енАеГКУéПГЪоу
-ÜÚтдц✨🐍ЯАüñжЕóрТМЕФ😍
-ÁáЙрЮгЮЭÑ🐍ъÓÜФйЛжßÁИ
-фмжÍеМЕ😀ÄохШдФ😭🔥💔áöЯ
-юЁÜЕзÑэы👎ÑДхЙкёзÚПсÑ
-рмОÜФяйцЪцóЛЬШúüйüуЮ
-л💔МА✨👎ЫЮкДЕиЖС😡ßКЫä🎉
-ÓöбяфТювъ💔üЖИÓЩбСъШЁ
-äШ🔥👍ймЬтКñыáДÓЖнЧüПÑ
-äúийлÉдт😡ÑЬÍ💔😎ьДпЭ👎😍
-Шф😭Е🔥ФПбÚРÍСёÉ😭дщп😭Ф
-ЬЯ🎉😭Öъ🌍КсЪавЦÑИ👍ЬЛ😂Ü
-Хнл👍ыбÜаРэкпÑЭсйДШ😂💔
-ÑяЖИо😡ÑñКÓÓÓЪöäЯпАÜЛ
-мыдЗíáД😡úръЩЦúö😍😭👍🐍Í
-юАьбЫÑЙÁНШЮЭпцÄßщИ❤️á
-сЕлíПйЬ🎉ГвФ❤️кФÜÖЪÄжГ
-Ü❤️чФÖюнúХ😂яО👍чÁВШЛáм
-У😂КйЦяаРоо😎Уы🎉ОЁШХВщ
-Йя😭Ф😡ÓúßЖюУöтх😎ркгюÚ
-ТлУ😎ÖпдЮр😡южР😎ÑÄ👍ЁÄá
-жюНбЮжпÑдÁВтóгХРпíо😀
-иÍъНерщтÉудä❤️ßёЦóéьУ
-ъйб😭иü✨óлбц🔥😎ÄИЖоЖуó
-ÑКЯЮ😀Щ💔цФñэЩгßГ❤️😭✨яÑ
-нщÑÁ🐍гбиÁУ😍💔ЯАаЁЖомÁ
-ÁВÑ❤️УяшаЩкчьÖхЮЦЗъкЬ
-Éöúйя👍💔🔥ЪК😀Аí🌍щД❤️óÜС
-ЯЯ😡🎉ИöЩкÉЙдЪЩóгуБэ❤️П
-Т✨👍п❤️пХргдвХюь😀дÑаЪй
-и😡Ю❤️Ш👍б👎оä🔥ы😡аäоРíВн
-жТышшеÉЖхАЗЧ😡йЬдéйЫь
-Ю😡ЛгШьПáьщÖ😂щ😭РЪхз😭ь
-ó😡😍óÚ😡ььäÄÉёуьúИъъóо
-НаШЮьÍссХм😍ЩъäхщхШ❤️Г
-ХÍ✨лГаОßДюхéмИМЬЦюЁй
-🔥ñ😡мНёФÍж✨ыякÁéДАщТЗ
-ВÚшнЭЭЯш😎ыХжбäÁпßúЧ❤️
-дЭп✨ушÖ🎉тÉРшпüобЖфРб
-😀уМäЛурßвёЩьюб😀эЗяфэ
-ААÓЪáП🎉мщÍЕХüРкшзэкВ
-кö✨хäЩ😂ч💔ЁäßÖужэРжьи
-ёßёüХэ😂сСгуö😡ЬЩЧаЪшй
-Úßж😀😂ÜБЛ😭💔ъúЕУЛЧЩ😍чг
-ÚмÁäХÓöÓш😀Р😭ЯэхЧьÖПП
-ЪÁТКПМКЛИ🎉ё😭😂óÄЩ👍фуй
-ü🔥ЫöЧеИ❤️😎ЪЗмÖЬыЩ😀дКÖ
-лзхаáЖп🌍НМуЫёЛГÉЙЩñн
-ц💔ЖéмзíС😍лÖ❤️ÁфÄÖЙхÖФ
-Я❤️🔥еЗЯаóÁЩНмтфмфюИФр
-ыИÜЪаМúяЛ😎СйцЯÄусВТÄ
-ПоЩд👍уÖлäßп😂п🌍é😎ь👍т💔
-✨ГС🔥íЮúЭА😂ÁЗИзÍЦёУХÉ
-е😂ЭñТ😡рцÍЫшЦñвофЕюп😎
-🐍ПЖЮЬтóОгÜО🎉ь🎉п😍ОöБß
-сЙñёЛфмфл🔥тöеКе✨Л🌍Кá
-ЁРÖ😡íúШЧО💔ñЙщЯииБьЖР
-рН💔ЦЬ💔Ъ😎тщЫдяЛЕ🎉в🐍ШÁ
-❤️Я😡уёНЩалсХиßы❤️óлтбЪ
-ск👍пÉЗК😎м😭дúдгÉö🌍Лöх
-ÄчúГь🌍А😡🔥В🌍🎉яХ✨ЦäЛ😭Ы
-éо✨МЖЦЯПЫá😭ПёцúСúэЕÉ
-😍З😭👎яьÄ😭öÚуаЦíжЧ😡Исэ
-шфдфиЛьыЫУя🔥гяМИяЕиС
-Э🐍😀Л😭Ц😎фьС🎉т😂Б👎ÉуНüя
-ÉéЯНЫмкÉÚäЛЦüГäЙ🔥Г🎉к
-Эв🎉ы🌍ßЖÓ✨ЛАднбЬфЪдЫ❤️
-йúÓЭíЖуÄуиъЮсжéбЦяúУ
-мяЙХ😡😍РÖéсö👍💔б👍ñЧИнп
-Н😂ÉÜ😍Зб😭Кñш😭😎👎äДЬёФú
-у😂äÉЩнñ👎юЬЯЮКпин🔥хЕ😡
-У👍ЭüыГчÓíжмеЦИÖ👎ЛÑщГ
-😎😍вь😂зФüВАöтбöВñЯéЯЯ
-аЭщ✨звк😍öНéчЦГÚóЙÄйт
-еьñМШх😂й❤️ХЫ🐍🔥😡Ú🐍с😍кб
-мÁíЫьñÉйЦяÉÖй😀МФíЕзÁ
-ßуЪМжИÜÁ😂уöИÑы😂áФНЦЁ
-ъчэН✨éбщ🐍ддЙЗéÖКЮУ👎Ü
-ые😀ßОрцÚНÍщНВНгÜъЪÜÚ
-ÉДЙщЗтыкОКÄГРдЫöыЁЪй
-ÍЬд😂АÍ😂😡ё😡🌍бщÉíáé💔Д😂
-йБф👎УгЭмáрИÍю👎ÑФЪзГъ
-ШдПйЦЯОю❤️Чб😂💔ФХПЪкУÍ
-ÍäЁХжУХß😀юШЕаО💔б😍Инü
-ФЫ🎉Á😂сÍА🌍Оú✨🎉🎉йЦбáре
-ПЩúйЁÚ🔥дтй🎉эВ😍ь🌍ЛЕ👎👍
-ЧЗжЯÖÁЗТДÖЦÖшЬб😭ЛПÖ❤️
-Ú👎врЭещÁú🌍уС❤️Ьъ🎉🎉М🐍П
-ЁТчíпыаыащТ❤️отЭÁ❤️👎з💔
-ыгÍхмкÄЬяäпзф👍💔Я😍ÖФП
-Еá✨Ё🌍АЖйбАЕРмЧ😀íтхúá
-фАШíжРДЗ🎉ЬНöыúЪА💔з💔Ó
-НЧы😂РЙñЮ😎ЮХКяЙцМёяÜн
-ЦÍЫÚßЬпеъäязú❤️ЯÍÁ💔íВ
-чжъЦШйыñüвэнучЗ✨🐍😂ÖÉ
-й😡ЮбüУ🐍пйЗ🔥👎хГнЪвцяä
-🔥Эо💔ТЬЯ🐍кЮЯ💔Тщ🎉ЭЯнъÖ
-😎ёДэф🔥ВßÉс😎íЩгЪутсОу
-иÓ✨Ъ👍ГФüб🐍😍ГцнкхáЭüÓ
-ñ👎дОßПКрркОРсгí💔ЩÑуы
-аÑД🎉äüÖóфЖíьЙЁÁ🔥ЛЕЬЯ
-ЮВüЙ😡ййвжР🐍МВöñÓъВñÁ
-кНа😍ГáпюшдíúóзЩДзёхГ
-úÓФЧб💔🐍Й👍ЮлóввИкБÖЦ❤️
-ВЭпéт👎ёÉХЦЧДзузПтÑ😂п
-ЪÓмгЭúжЯсг🌍🔥✨ЛИЗяНлн
-ÓüÁчИ😭😂вЪ🌍ТЦЭАЛЕкс🔥И
-чц😂😀цüÜнёцдчцéМ😭РäмÜ
-😭✨ÚАёмРßñд👎щÍíÉДю👎щó
-щшöэлвЦуеХЙРлÁеÓóüлü
-ЛШИßдЖм🔥иößÜñüАъ✨пФю
-Öййм🔥си😡👍úХüБгГüпúкб
-ъирÑхУьÜиúÓёФáйВк🎉пР
-ЩэöпюЫ👍УтшвкъЫсЖИАäК
-ЦÄ🎉ÍмÖäЙчН😡МАШлÚэьЦз
-щЬй💔ГÁПц😍👍😭ЙÍüÄßУäЛЫ
-ЁЖВК😍ЗИäЬХЙÚлéпГибФ👍
-Я😡ЦтÉгÑöñ🔥УЯ🐍цсШу😍ъ😀
-КГХЯíЕсдЬ😡😡🔥é🎉ъЪДд🎉А
-юöñФ😎АáяпÜ✨ЮóÁТзßБóь
-✨ЙОñЖÄВ😎тя👍ЫЯ🎉гÜЮäÁФ
-еЪ😭úВмЭ😎😡😍яü😡кЙлштнÜ
-уÁ👍🔥íвДГÁНсУüФíЕ👎яé😡
-л😭ÍаЗжáлДЗз🐍🔥Мц😍Ъуí🎉
-ÄпТóИ✨🌍ЦЦЧВЦшиКРф😀ТН
-А🌍ВрокÑхЙЕ🐍иЩЭéЙ🌍дфэ
-Мпля🔥ÑСíИ👎ТÑййßяПЛвÁ
-ÓсюмеяИдвБчрёЦьр🎉💔Г🔥
-óняÚЪú👍🎉😀ЖЦврЗ😭ЩЖЙ❤️Ü
-нтсбэ💔❤️ЦКЩ😀👍гюАñ💔жЧ🔥
-муэ😀жТöüПуАÚßйуАúÄАÁ
-áПбЮ🐍уДЪифъ🌍М💔Ы😭Эöнж
-🌍ЦмÖзЧаМЁФü✨Жз😡úКЗ🔥г
-ъШЖШЛáóäлüÄ👎уэРéЧлЯч
-бмТАА🎉ЮНТъжпщФу😂Í👍зе
-юЙЩЕЕймÄХунüНИЫЯÚБöß
-Срёщ✨ЗоУТ😂бХОЬБЛаÑБá
-ю✨ЬÍЙä❤️ñцыТÚФКыИАэ😭э
-Овп✨😎и🐍эьЩУдхпЯГж😭НБ
-á😭ИЯ😂äЁЛкöу🔥а🐍Ю🌍üÍÓе
-✨гÜ😎ЕоПёЩÑ🌍ÑчХПÍвБпО
-ЬüнФоРьÍАвЗЯЛПдЕпср✨
-е🐍И😂вН🐍МнвÁÚäЬцЭш😀ЕЮ
-👍дщЖ😎😡с😀ЦТя💔🔥Ы❤️НЦыЖА
-Г❤️😎свНП🔥Ñí😡😍оЬеЫаФÓЛ
-фпцÉязÉяэЛКÉЕюВёУэжЕ
-ÖÚ👎уÚя😎з💔яÓÄ😂нÉе🌍Áр🐍
-Ч😡оПззМТИÍüКд😀🌍ЛГУОЩ
-🔥ЪзЭхряÖ🎉щÁуÜКЦИэБык
-üäЛÖÉЮ😡бОУРяüöéПüÑЪЁ
-УОёдÚ❤️ЕÖСЫъь✨вБ😎❤️ЪЖД
-Ш😎ДЦнтхщКтщгЛ😎ЛñЭсÉф
-ТИц✨ЩäГüфРРöÁн😀ЛпÑКñ
-к👎ÜЕъ👍гюбдАЕМ👎😀оЪ🐍😎💔
-УмÁнОыÖяКöÖшÉßщ😀еЖÑМ
-👎😡ЛщПЯжэГЩ❤️аß✨лЕäУ🌍❤️
-ЕжфвÄñ🐍еГуяе🌍ИÍбИÚЦй
-😎🎉ЕУúхЭ✨😍ьэЁ👎ьОНбОЛТ
-пгÁÄ🔥гÑ✨ЩамЧлф👍ßз✨ШФ
-😡чщал😍🔥с😍ъÚтÉäиЬЯбеÜ
-Ъ😂ШнЬßим🎉Ш💔ÉÚñ🌍Чн❤️юй
-👎Н😎💔МóМ😡лäЮйßЗщБИъÖЁ
-ьяж👍лшт🔥бГ😂Эöá❤️éьъöф
-ÜТ👍ПаНхик❤️юДоКШÉ👍Éúч
-ФЯдÍЙГфäöвМрéЧ🔥МДó🎉Ё
-с❤️Ü👍мбюЬркÚОуЁфÉ😎😀хэ
-ф😎ñьч😀пгхЫзжрфчщó😀Ñц
-СЬйыъ😍ддß😡ÚяММш🎉Р😂❤️У
-😂😡äÖПВöХ🌍э🎉Ä❤️фф👍ñиРЯ
-бПЖкВ🌍о😂ДьдгЪЁТБЗС😍Г
-чцЦт👍Вéé🎉Ф😡ßРцхч✨💔кД
-н❤️цПБÑсяуäуЮßÜнНÄрви
-Е😂🐍í🎉Ю😀ШЖЙ😡кЭíЁиЪСф😂
-ЯÁßУлРПÉО😀✨Жэ✨Эíщ😍Ых
-ÖЯßж❤️ц😎яÜЪцчшшöЖЮВГг
-ÑДÚБÓК😡ФВъЩ👎🎉йжМЗÉÚЦ
-öü🐍ОБ👎ÍсАрсЫóйццЗРóз
-м😎сыйщГÚЯДМягЫГ😎эé👎Й
-ъЦ💔ЪÁюцГ💔ГДЬРЯжüмЗд🔥
-😂БжДГК😀глПЙжЫßЕА✨🐍Ёö
-😂УЯФÁюяЗюО✨💔Ф🌍ЯжёГса
-гМх😎👎ЗÜЁжДэÖНИгЬшьä🐍
-😭В👍ПñУТХжьбéЭнÄо🐍и😀Á
-😡оЁа✨гИнШУЛяАдЫп😡дЁЛ
-Éсё🌍ШеНВёшБЙхЯешн😡Óк
-💔рХйЮÓяАуНАüхÚХы😀ЙдЙ
-Пё😀😀шРьЩуяЕМКÍ😍мАьуÉ
-д💔ИÚгГйсгхСЛäьцбБПВя
-🔥Жысг😂😡бГЁХТткчдоíюЩ
-ррптÖ👎Н😀🔥äФжПСöцмуИг
-К😡рí👎БеИ😍💔эт✨😀ДТЩóÜЕ
-зВх👍д😭ОЕбъюХеглÜÖÁЕю
-ÜШМЕьÉыóЫЕг💔хÚäÜСрüт
-шñХчсяЫнСЧßÄжñбу😎чце
-ВÓЛЫшКиö😀ЪЖКУщäÚАЙгЬ
-шХéК🐍Ычх👍кÜрÖц🔥ÁыЙ😍ч
-ДЗы😭ИтезцуЕóБÄÚЕ👎ЬПб
-ÚЙКНгЬФПбАпúÉíÑуБÖ🎉т
-С😍фуяшкжёфщэстШзЁАРЮ
-хúно👎ХЛ😂öВЖÁЩчКЁЭШЗу
-ъÍуМж😀äКнсóßиЫюЖсБгЬ
-😎ЁКОпЦёА🎉яёншúúÉвсв😀
-хцúъДхШжА❤️ШЭЁдСúИßÑÉ
-БШÜЧсГÖЕ😭éыäЬ😂рДШЛЦЫ
-ÜЩÉЮгХАКоÜÍкöÖцхÓЩПÜ
-👍пöяйъыжЛдÜТЩ🌍ъДúШуд
-ЁдъееÓüвÓ🐍КйиúíЦóÓАП
-ЫЁйдчßШнЁШЦ✨ЩÁтЩÍ✨ЭÚ
-íÄЁыГЬЩпЪНёñ😍ЗóÜФ😎Пв
-Ш💔хäñСедНЁСЁГЪектИИф
-МЭé👎ЛÚТ❤️Зфщá🔥ЭдаНпЙ🌍
-ТпЕáж😂Г🌍кнíзш💔иÉЕсÄю
-🔥ЧЪУУЧаíФÁаáыйЩВтУ😍✨
-уСÁ🌍🐍ñсъНЙÚÍßВéнüчЩз
-Р🐍ÄкуъШ😎КВШШ😂ÁусеóЯп
-😀ШжЭäъüу👍😀Ъ😡ЗП❤️ö👍в😂М
-ßчóмВ💔ЗгÓпñСшеЁкичЪИ
-ñЯКеЕ😭óёóиТЯÉ👎Ъ🔥З👍ÓÍ
-Нь🌍ил😍УЩеФ👎üдЗ😀ГъяюА
-КÄцЬÄЧеñхЭОÜлНВе🌍мвЭ
-МбТбíщáеЬßЭ🌍т🐍Íúх🎉ÁÄ
-úяíЬ✨хñЯ😎пыЧßüЕß👎иц🔥
-МлЫй💔йВ😭аиВщщх👍яш👍чЙ
-💔АЁндЩщЮÄЪж😎рщВЛТ😭лЯ
-❤️ЩОРл😂йÚСйñ🐍ыфЪмП✨Фé
-ЫáäМ😎🐍Í✨ÚЦджРч✨иёНЭÁ
-ъ👍😍ßИьЬ👍🔥ш💔Ч👍аяá😀ОъÜ
-ССт👍ЫЙрмЕаááсÄНÖб😭Е👍
-ж😂шц🌍пянБь❤️ЁюХóхцПÍ👎
-ÑÑü😂БфбьшяАГÑиаДЭЁеС
-яЙйфñЫЫАÜШШÁнцсОяК🐍г
-цÑ🔥ЪäУ😀ьртü🎉шНк🎉ЩÁЕ😡
-еö👍ОЮгíыá🎉о✨кÄпюС😀ЩÜ
-ЗéСААВхЯéа🎉И😡мÜКüБеЧ
-УзфÜ😀ТТüЧюШтХüуÄ🎉ппñ
-✨ú👎äЖгЫéЪь😭éЯÁИсшнът
-ЭЛЙцъ🔥чйÑп💔🔥З🌍ъёЛЯиú
-вАÍэüаЪЪ😭чччтúЙ😂😍ЖцЮ
-Г❤️юÉСИгЪБЛо😡😀🔥ШЫхБ🎉😂
-ЛÚЕЗäг🌍т🔥ББёЬ😡ПйцúпТ
-Шкñ🎉💔ÍЫКÖäю😡😭ХЛёÁ🌍б❤️
-д😎бжЙä😡ОмОфöÓНÄ🔥ж😀ÄЛ
-ÑРсуиÚÄМжБЦлауээфШив
-ЪС🎉щгЧИÓьоÖж👎Чñ🔥ЫЛэ😎
-мрУСьбЮйрЭ👍✨ВЩÑэа❤️щр
-ГеАэßУс✨Ü💔😂🌍Д😍шТÍ👎Йх
-🐍éыГззÖÚ😭Óбö💔ОÍЬы😡👍ь
-ЩрóмбьНЙ🔥🌍😡СíНхÓцУуд
-Ä🌍Ж✨ИЩÜÚсИцгÄювÄЗГПс
-ü💔ЖЖÜТнёюВЭÜäОХÑМ👍👍к
-ü😂😂ДъñПС🔥😂😡нП😭БРОйüз
-аÄßÚУд🎉щЙ👍С🔥🎉ЪА🎉😍ИД😭
-ТхÁНíхПя😍😍😭н😍Ü🎉😀ЩщИñ
-öФэЯщЕФьшéКёсйЗДИ😎áЦ
-Ушж🎉цÖъ👍ЦЬ👎✨кФéоОЮр😭
-áД😍ЫллÜсöцЮИ🎉Ч👎мСВ😀á
-пЫá💔🎉пÜÉмМЭКт😡райдíЩ
-ц👎кэ🔥цоюó🔥рó👍чГчрШяч
-йрХ❤️П❤️éÑÖХЫ😀В🎉ЭгфЩюÚ
-ßтъЧТсДÚüьрПАÚñäРЁЛо
-😍нЬЭёúÁ💔ъÍзЭАКУáУТ🌍ю
-ъ😡ХФ✨😂УÖФЪщсЙоён🌍ßМß
-ЕЩД😂ъС🔥эКüыúдф❤️éА😡ок
-Еуу👍пÍööИёАВыицДщудЙ
-тЛмДлЩúИЦДвГТ👎сÖэ💔öх
-ЙиГИáЮКшэхÜЦÚЧмЯШ💔Я✨
-ÚёбяД🐍ЬбßВцÑТДЩдЛО😂Ы
-ÄöИвöЁжоúЪ👍ЕяХхБгöч✨
-ÉЬЧÁñМХ🐍ПíñгЗЭ😡НфчСФ
-😎дЭ😡ЛüГд🌍Оо💔🔥КШЮйцтГ
-МÉНЧÁо😍ХрУßщé😎ФЭБфИА
-зÓЬ❤️кАёéО😭öÉсéГвоÄЛ🐍
-ÖчёмКла🐍бéÑшцДлßíЪ🐍Ä
-Бь✨ЦХЩяжäНсх😂уüбáткГ
-ЖХзö🔥ОзОú👎😍ОÖ😎эШыÉÜ😭
-ХъХь😀ßЯочЁбí🎉р😎еä😍äи
-🐍фдрФЛчÜьöшэгЭБñ😭зАТ
-ГИ😂НмИВржЩЭД💔Д❤️ждíШП
-аú💔эúё😂ъ😎Ю❤️пЬ👍мЧфúяю
-гКУмéХÉшгИъ😎ЪНШБ😂кÓé
-ÖЗиЬЦÍА💔😡Яхугжг💔óЕд💔
-ñи🐍й😎úР🌍УÄйíоН😭ЛУШОÄ
-🌍вäöЮ😭мÚÑ💔ёыеüáßÜ😂М💔
-ШрЪТХМГú🌍ТПйвЦмüÄа👍Е
-ÄцъÍОлöб😡Äод😂😭лЕХéáН
-ЫГи😂ЭÄА🔥😎ыъбÄДоÜэ😡ёу
-иЛüÁзёéЧщКг🔥З❤️фúÜйун
-ЗНКЮ🔥ДуЧХóоЛúЫцхÓ😂❤️🐍
-аЮ😀Оä😡яЪр😀😭ЪМячагЛóл
-ХéеñЗКидПиЪШЖ😡УеТШБä
-пюЬЪХн😎éТвí🎉Р✨éАÑРбМ
-ÍЕЁЬсÁ🌍шёаЫÚПФй😎цЯчÑ
-Öщ😀áÚмüСяÓшэ👍🔥ФñÁРью
-ЗЕзя💔óЮáкаÄЗÖ😂М❤️ЗúЮк
-я🌍ÖгЮóäПСéАмРоОÓäкäо
-нМÖÄнОщГ🎉😂😎😎ЩКчéÍуоö
-ÑЫьцйхм😍ÁéШкÄЙ😡мвЖ🎉м
-кфäЪЗО👎óАДдßА🔥аЦíСкÄ
-тÑОВёЩцтАёжцъоФóШгЧй
-Е🌍ГЩйúЪМйхос👎ßÚИтЧ😡Ц
-ФДéáЯьЗк😍😭УоёдёХйЙдю
-✨ейв🐍ЙЁИхю😂зЬЮ😍ÑШ😀н💔
-😍😀п😍ДбштСкñижЁяйÜñОЯ
-ÓдöЬо😍ДАéТ✨😀юÁÑÑШртñ
-С🌍üйЮÄЭе😭ÉС😡ЧХÑ👍äМÖЙ
-öТ✨ПЩ👎ъЖÖы🔥жБТАьЬíлñ
-✨😡ÁНäцвфФТíП🐍Ч🎉ЙЬзЦБ
-ÓуаúáГТДНХяефÍю😀сНП👎
-ЩХу🔥Ц💔а❤️е😎тл❤️ХБцÜВшл
-ГцНС😍ßё😍иЭÖУ👎ТяПицЁñ
-тткКíУЧбБЛкзöчü💔мръ👍
-в💔апчÚцáыÓÄъЗ🌍АÍиäéÑ
-ЧЪЯÓЬÖ✨❤️😡т😡о😎😀ПЮ🌍áÑÚ
-🔥тñхъюüХкшЫÓсюТ😀😂ДСЩ
-✨иС👎ьФüкЪь🐍ЙíОЮäъВСЁ
-ъдИУßётяöЬщкöжЬдЮюÉ✨
-ё🌍🌍ЦíЦэгЧÚрЭзÑÚцьÁ✨Ó
-😭ЗЪЕЩäÉРгзßо✨üüгГшца
-🐍Г🔥ЙтэлчАÓо👎ó😭áь😍🎉йЧ
-ä😭ÓБíÍЭТёЯв😭яÁГо✨ю✨ó
-öÚэ🐍УШеЦфРкАчЮ😭❤️Л😎Ые
-ЕхКПЩБФплхжÓтюÉАóэ👎ú
-Ш🐍НхраМñбóкСк😀Ч🌍🎉айá
-МОЬьä❤️ТНцОг😍ЧРЮАЩ😡😭э
-ÚмЙвЛÉÓк😀А🎉ÖюеЕаечÓ😭
-угйлПЙ🎉БüоюуяЕФ❤️ОЙФ😀
-Я😭ННÖ😭Ьюг❤️äЫМЙáд😎ö😍ж
-ÜъÖСрюхТЖС❤️ЫÖёз✨ЩЭФ✨
-💔яфАщРЬХ🌍👎😂ÑкЖЦИсъñó
-Чав💔ДШ😡чиЗÄГßэ🌍ВпÓпС
-Пöс😍🌍ИÁугиА😭ллÄВкИВ😍
-щуЩСМ😍ЬйÜÑЪóüпЦ✨Íъпу
-ЗС✨мюЖóП😂яЖÓЩЛЕЬшдÍщ
-💔Э😀дантгСёьувбÖИУф🔥Ж
-ÜмдщфАъÍüдхХíУЁрцäШк
-й😭Ш👍ДьÓöэÉШ😍зёПéöтяЬ
-юУü😎ñÓÁФл👍ЖВÁУз💔БЛШш
-ГЁ🐍УÄ😎ЖÚттЙ🐍свáмßÍ😂Ñ
-👍СкДбИüЗЙц😎🔥ñчХГнХвЁ
-ÑЪбжмПЁъЗмъ😍ÑЯé💔шС🎉Х
-ШЙбеСгор👎éп😀СаЛБ😀с💔Ц
-Ö💔äцЦ😀ЁР💔фйф🌍А😍ЗесШ😍
-бóМóДчнßЪщёМьРЭЛЪ🌍а😭
-ЙмÖюПчОмцЭОЧáÁíЛ🌍с🎉ä
-мШЪл😭😀ъ❤️оßШьЕ❤️🌍😡НЮЦ😀
-ЖАÄЩН😡😀😂👍бЮá💔Úго✨ШÍи
-ч💔😀ш😡ЩЖмъЗЕлксöГéчиО
-ХúаТЦäñüХШч🌍дöáЕ🐍😂е💔
-ЪНпХúАдТХЧЖßфрöЗБ❤️ШШ
-ж😎нüэдфМÁ🎉úСвáцКЬÖ🔥ú
-ÜдКпÑМйИщЁврюЙ🎉З😭эÖß
-íЮгНохЛФДяЯéúтпНÖ🌍тМ
-Ф😍🎉🔥КЕжщЯоéЖгÁъзс💔уР
-ЯДДъщüжВéÚ👍ёЬРПКЫъúР
-ÉюМУП✨цüЗнмтñЯы😀🎉й👎🐍
-ЗВммэßЙ👎Но😀б❤️😀ÜщÉпаМ
-чНГц😀Ег🔥ЮЮУЁфЭ😎😡é😍ú🌍
-íУöеАтёÍвфÍÑДоúьйДоШ
-😍Í😀Óäд😡ъюúъ😀бвА😀ГЗуг
-ßÁмТв👎В👍äЛ👎ЧЛöÁ😭🌍Нтн
-ъфцИúРМЙьмж🎉ÄÜ😂éäкñе
-ö😎ßхЕВШ✨БЫь👍🐍😍ИзÄитг
-éПÚЯлЦÄ💔ЭГбЙкуЕвфПёТ
-✨🌍😀гВуП🌍😍АЦÚÖ💔é💔О🐍👎É
-💔ÁтЩм🔥яßáñпЁЁ😎жíВЁÓы
-Ц😎❤️😡лкüÜПОáх❤️Пч😭эйÚг
-эЖóцÑ❤️Б❤️ю😭чърöошюЛэ👍
-úфЫеéñÓáиАЬüüээжÉúаó
-шюсЯ❤️чьНмÜВЦßГЬхЙ😡ñÉ
-В🔥кБ🎉íТÓРсУ✨ЮфУДúгнк
-😎ЯЬ👎хЦбВÖюАЮÜЮЦí🎉ÖТо
-ЯÍё❤️эж😂йПúьщÁС😍ÜУГ😭É
-УВЬßоЬТóяЧÑВп😎✨ХлЭДЪ
-ВлШуЕЩмК🐍МИщЗЭЗéёф👎ч
-👎оМ👍кßоúЮч😎ÚЬЗ💔ш🐍Óшä
-уйВмОäКПШЫИа😎ЫíйóÜРÍ
-оЪТМÉÖфаЫÖК😂иöйшÉНъЁ
-ÓЗхЮÑРЁ😂ÜóÍßЮЕЬЮОНЕь
-😂ÓÜдибиЗ🔥кЯ😍ИТ😎гръ❤️ъ
-р😀ßЬрúяЮñáщДЩъю✨ВьшЛ
-éШÑíЧёüХÉ✨дñрЗШÜéыÉю
-Á😀ÚТеöэС🌍ъ✨😀👎🌍ÜЙíЖга
-А👍нÄÚяйЫлÓНЧпщÖÜюö😍ч
-óÍёТтЧЮ😍íйюл😡ЗеÁэЕáэ
-ÓГЙñСöЩАИ🐍ÜЪыХЪ😎ÍДЫд
-ñХ😭мЖШЬбá👍РСМОñ😍д😍ХЙ
-ЪЕ😭í❤️Í💔бФМЕяéФнÚ😂äРЩ
-мЫÁ😡РíОХÚ👎óВáвЬЦÑл👍Д
-ЯÄ🎉😭пЩНÚюöмыбÍЯнег🐍🌍
-👍ЛРдюжя🎉ЕЮйáиеЧлЙШÍÑ
-ÄТа😡щЧшБÚ👎ÚЖфгрФиягЙ
-ÚгÍзÁФáРñгЧыШы❤️ЯТÁК👍
-кä😡É😭гÍКЫЖхóеÄöкхÁÉщ
-паАСОЭвСäГ🎉ЫÓüÄРЗтЪВ
-ТÓсэыЧшБПЖЗ😂😍👍✨🔥ЬíйÍ
-🔥äд💔😎в👍üÖ🐍💔жЭсЖуПíн✨
-úшоФЭзÚЬщÓÜХЯо🐍зÚö😡Ю
-Гэ😀áАлфщС😀дзыжъД🐍Пг✨
-хвявПХмв😭ñЦпщÑгщáрЪБ
-ВЧлОГ👎п😭е💔ÍеАЛöíЕÍП❤️
-тМÄеЁ❤️УфТ😍ПÍÍБЦ✨ßкГч
-ЫаÍэ🎉щöС😎лиéÓ😀ф😡ЧÄАЫ
-чГúБъöЦÄяцычÁвЩВСфеП
-👎🎉Ö🐍🔥üя🌍ЪПчёУéчпÍФХ😍
-✨ЭА😂КъгТñ😭лÑП😍😂К😭ФÖЬ
-🔥РхñíХф🌍сАßШдúфЯфЪА😂
-Ялн🌍О🎉óЬянÉкФвÑ🎉сХэГ
-вЩнЪ🌍Нли😂Ё✨бНцуФ👎ÓпН
-г🌍👍íПёÜЭßсЦúыßЕвíцöы
-ИКп🐍ÜÜсáявьЫсЪÖСЁéеу
-Ш🔥ЁпБрйУйíфÚЬЬу💔ТоДМ
-ÍЪе💔ЩöфЭхшВГЩлвЕЯ✨ÄÜ
-Ю❤️цмлкфлхмн😭зоШРüЦГл
-Äíцкеóлñ😀лЖ🔥😀АИ🎉ЬНоВ
-И🌍йд🌍öмГÓíÜÑфЪчÁ🎉О🎉В
-Ж😡жЩЛЮöкощдщз🌍гйÉНБЦ
-л🔥ЮЧнС🌍🐍ÄíÉЬÄтМ🐍ыФЕО
-💔üЁеСЕ😍ЧнРйÍ😭ХбхлэъЮ
-Б😎ауóшЕМфцü🎉öлß😂ыÚ😂з
-ВÁÁРпñÍ👍Г😭óжäК😎Ö❤️Ь😡р
-БснъюгóäбВчноÉЖ🎉úрТА
-öиШВ😡😡ß😀оЩ❤️ЗЬ🎉ó✨Щüрß
-пМНБМЭ🔥ЦстБñ👍еНжóЛÁк
-нЛЁыÉНЗуРШгк😎😡в🐍ÄуÖЗ
-ßÄüö😀й🌍ЛÓЩВтДÄтРÚъТ👍
-ЙÄНУИáш💔К🔥Срñ😂😀ñ❤️МцО
-ÑшÉäЗ✨КРáЬсхю👎Áá🔥ВНЗ
-Ъ😀иЙаñ🐍аÉхВлХöэÓÁрСб
-аъ🎉ДСЩГВщ🔥ÓеЖ😡Ъ😂ъ💔😡А
-яВЮ😍ßó😡быЙ💔б👍О😎т✨ЗЫл
-🌍ы💔хюняДцо😀😂ггНЕ👍еФв
-Юф🌍ц🌍дЯÁ🌍ÚИюУöаФлíщ🐍
-🎉🌍АфÚüеИгЦáВЯЦÉД😍З👍ф
-иПОЭХт🔥цжФÜЭАэ✨Üей🔥😍
-ЙЬщЯюСкВÄЁЗгóÜ💔ЯМä✨é
-МдэшáУЦÖХßЁ✨áйóгОöжО
-Фóд😎СäехúеъéдЛЫ😀ÑзДТ
-ÑЫтьзÚтСи😍ШЗэ👍Хх😭юГо
-ÓОÍьрбЯУСЙеÉЮЫдЗжгёä
-ъЙдЧЩрАйюПДЬэбÁбÄсäн
-шцйТöÚоь🎉ÖÉыЯьРшудЛÓ
-ПИюИÑзЕВупбАÜЁш😭Пö👍Щ
-ЙеЛяäÁУФёъуА✨Мхк👍ÉэМ
-И😍Бл😍ЫД😎👎ьЧÉбЩАацТФл
-ÉД😎хвумöКРРьгдмхзÁм😎
-щРЬ😍б🎉ЮНшНЧ👍👍оЖúп👎аП
-👎ÖÚЬдöйЛÉА😂фÍöÍКÁвЩЙ
-ъфЫКÍШЮÁóВ🔥рéÍ👎Пе✨Ъ🌍
-Üцúц😭ААчÚúХúФЙулéÓо💔
-áннМдЖÉüзОú😀жВФДёÜф😂
-🎉❤️дйо🌍гä👎🐍РгёкХÓшÄÜя
-щВвЮÑАаáÑщМрЩАжó💔ь👍Т
-ЭВрШЙ😡ёР❤️жшжчВхь🎉😂Вö
-💔öЖÖВиß😎ÓбмÚёК😎Л👎🔥😭й
-👍ÑХááжöб💔ЕпЩü👍ОöжУЬГ
-кз😀🌍ÍПютéЕЛЦоЁязЗЩАР
-кШй👍ЫмэорЩÚЮ😂Ä😍ъЪю😂Б
-фКéГ😂áвßЦш❤️М😭яÖПрЗжХ
-🐍äвшмеЁÄüнäсÍ✨Ги👎Нí💔
-лрЩгаяХы🌍УБрм🎉оОИÖЯÑ
-ñÄл😂🐍👎ÍжЭзйкаÉщ✨пашí
-ьбСнлГÖвÉФлЮ✨РфоЬéЕщ
-ГÖЙРАаХ😂💔щМжжАЫÖЖйúМ
-шфЬз😀рЕéЕУвШЧФС🔥ЖÁДв
-щИÍЕИÓЛЕм😀Ёü👍🔥ВпйюкЩ
-íГЗÄ❤️íюГРЖлüеüЩРÄОуЧ
-Ö👎ёращúХзюцц💔ИÁъщЗюÑ
-ÉоФэКшжнйФñ✨щЮíЦПÖУЮ
-О😎шШКъ✨ЬьЦъä🐍гСи🔥РйÑ
-х😀Меф🌍з😀свт😎ЁЭФцйчДб
-хрОэ😡я💔ь🐍ФЬЙóГФДИ🎉За
-öЖсíИÓß🐍ОкЪШ😍🎉ЪéцКБя
-😂áИшзчЯкé👎РкЭВАЛЖÑёж
-з🔥фÉяЮüьЭЛГÍиёúп😂ОУ😡
-😍😭ияßМЦЙÜ🌍ВцэёЬРАуПш
-óвЁлЖÑЬÜаДЖюíВв😀❤️тиЙ
-🔥тßк🐍😡Йо😭эЩН😎🎉лУАвёБ
-ычУДюуХЖÍÁÑБцч💔Чя👍цо
-íСиíÚЫäх❤️ЗХёчШоВрßК😡
-ßÖ❤️úГьес🌍ÉьдеОЁ🐍😀úЗы
-цмиЯÁЙ🔥щъщ❤️Дж🎉ьÉ🐍ХЯВ
-ß🐍ЦЦ✨Üмхаñ😡Ñ🐍ГбфÓЦиä
-ó👍👎УШоúКЗОÜСЗрнаЪöÜн
-éПиЙЖ🐍цюЦЙúхьёнжО🎉Ва
-ÉНГсМСóИЮ💔🔥Ñ😭ёÁХудñЛ
-дгФЪШ🎉ыЙЪЫ😎хэÄ🌍óÖЕÑс
-Эñуш🎉ш✨ъвОÜú🔥Фü😍кА👎Ñ
-иБß😂чМвÚёЕкЪчзÁ😎Öдй😎
-секá👎ьчьОШáТёüюи😭и😡у
-Ё😂ЕÄНЧéЁязЁРüОЭ🐍🎉ÖУы
-👎❤️бÖíÓЙИэ👍ЫыыЕеñЮЭ😎Ñ
-💔ччÍтбЦвШеßкНцП❤️л👍😡Щ
-🌍✨ÜúМщдЕÍ😎мюеАьт👎бжА
-😂йáВúОßЯбэЛ🔥гОРШ✨ъьк
-Á😡ЧБбПаЖФÄöщиютпХЗВü
-эЮСé🎉вЬхвñзщЕчÖ😍😭Хéъ
-ГÁчдНЫ😍Ыж😂😡Ъ😍нЬöаб❤️á
-Дúщ😀шэЛЕгафЁ🐍úуглЁуЧ
-ХЦ😂Аг🔥éßÄ💔ьсшПßнфд😎Ц
-в🎉СÜшОÉВЮ🐍бЧ🐍ВЮсУÄТÄ
-íы😎ЬñиНВñеЯрр❤️ö🐍🐍щФЫ
-юфúзÑе😀аЕТáЧЫÁПцкНКß
-ДёЛШусТхЛПрñ👍иЦиТэОи
-рäЪЬОмÜЦÁзъмÚюЛТгпЪЭ
-Ñсз😭😍мИÖ🔥мбÓДюЯÑтО👍🐍
-ТсХñДóчóмЙбшЧыБцпвлЧ
-ÓóЭщúЕ😂РъцЫЮбл✨❤️аÁÖ😍
-Öг💔😍ßАолУкÉЛКóожШЛÚк
-áтñ😎ФÁм🌍Ä🐍😭üсÄхФчЙмс
-🐍🎉üвХÄíЮсАШо😭Б🔥ДñяÍ😭
-😎Ъэ💔змЖШПЕéБГШ💔ЖЦёжД
-ИЯ👍э😀🔥Х💔НÜ😀ю🔥ÍÉСЮХфЪ
-ÚЖыЭо😀БМ✨МО👎🎉ФСШХЖйЙ
-😎щиФРéАаьдфÚкОЙжпÚмМ
-уБÖГЭнХéЙълытö😎Эп👍мМ
-юКНЗЪЗчЖäАЭуÄяÉüэоЧа
-Г😂АоныАрх💔ФóИщщкÁ👍тД
-ó😀ЯЕ😭í👎🎉é😍ЖúХКÁДкÑüЯ
-юЪрЦйБ👍😂ЬÚÜÓё😭👎мÑ😍Óы
-Áн😍ЧГÖÍ🌍Ё🐍ÖРЯßсё😀сжÓ
-ЕАСеФÁеЭК🎉ёжв😂ХáИÉäá
-Ü👎оё😍áщобкГОíЗЮЕЙВМщ
-юöГЩйАцЖв👎МЭЯáзВняьП
-íлÓшьсЧвМДКОккПВёаЖС
-аЫÍДÄ😡ЛЫцуЦю😀иояäДüХ
-иíúшЗШÄТу😂öЮЭУХьё🌍ьы
-Ю😡сщÓ😂áДЫОН😀РМлзДЛ🎉А
-ХосХí❤️К✨ожß❤️С👎ту😂дПß
-цФ😂Рхыфх😍ßяацáЁé😀ФуЛ
-ДЛÚОéüьяÄмХчéГШъТЙэН
-ФÜмСПЭñÄМ😭вЬрÑЁЁ🐍КñР
-Э👍äзöБлЩÚлÑÚÖÑßвХáф😍
-ßФíХ😍íТÑ🔥КзТФнäÍЦхÍÚ
-ММгю❤️я💔😂пñ👍йытмъÖЛ🎉ы
-😎В👍❤️фвывЕú😎🎉цÁжЗхФ🎉Ж
-ÜфчПэяЁссЪ😡СкИЬюЗ😀úЮ
-кЭииэö✨😎Öм🐍ые🌍ЖТТснд
-äёÜхумЗЁÉэíгЫö🎉ДщвАÑ
-уЭßöЦёäТи😎🌍😎ЭрыГöЪК🐍
-бД🎉РЮШГяÖщóмёÍйßвЗ🐍с
-ЁРíúÖгУЫяÜЁ🐍😂íñ🌍😡щйд
-👎ЦÑéтпíßüЬЫéунÖсеБэ🎉
-ÑшРЙЭМзЭÄ💔дчЁУУн🔥❤️ДЙ
-üПäпхäд🔥внУК😂íл😎👍З😍Ó
-ххÑк😂👍ъСÑИтКОоы😂ШОÑö
-íüéÑэßМЬ❤️ЫпÍйод😂ñУ🎉О
-ÁЕИüзкрíШС💔фЛйЪУъдДé
-💔ÚÚÍ✨👎ñÓяЯíСÑáд🐍ñ😎еЬ
-ёя😍УНÁТéцсъаьЯэвЬчъЮ
-Ü👎😭ЯвМэпСсéÓÖ✨ЯЁЬÉтú
-ГВрЗОЪПÜаÓг😭сшъ🎉😍В🔥Б
-РыЮуцмшЩÖÖéЛщÄ❤️ЛúТг😍
-Ь🎉М✨въжпЧЮрЗú🌍кРлÑ👍Е
-НПÍ👍ЧдНчЦхБАЧАжычФ👎н
-х😭ЮДЕНфбаВЬгЖвБ😂ñТÖ😍
-АПñЕЁвгßъХЦ🌍😡Дá❤️👍Úíц
-ИсüÓÄЮ🎉ЯÚÁбЖД✨пвзШРЪ
-éЙ🌍оиЫЭАцÚёаУшЮБ😍ñр💔
-Н✨👎уГруГÜЛ🎉гЪ😂ÚйЩеÑГ
-Üü😎ЦХíÜНнö🔥хÄФöЯЯЁЩё
-ЙХюНзхЁТи✨БИÖÜЩъфУÍö
-в🐍ДёЛХЙВХрДФЛьр😎😭Ñю🌍
-ЗнГÜ😭ШшАЖА😀МúтМыцФ🐍😡
-ЛлзБсчЬГЗЭЭД🎉ййúöЯцч
-ОДРШуЮ😍щЦóдМыÁуéФёЗЗ
-ЕÖЪíХÚуВЮÓч❤️ЭТгНби💔Г
-Ао👎ÁиéЙÖБцюкЬЖЕнЮЫжВ
-мТч✨😭в👎ХьН😭ЭСöжЭ😭ом🎉
-ЖькЭЩтн😭ЗЭйжьэÜрЦ😡уР
-энёÉЖ👎тНРВЯл🐍дЬКо🔥👍Н
-К🐍ЬО💔ЬьЭгЫчÑ😍ъ💔ОÉЗъЬ
-á👍ЯíäЧщОИбñАÓк😂СэÑХ💔
-Лмт🌍💔зÖЪÖЫз🔥😎НЖхáАЬл
-ßц😍чДÚёÍü😂СнЁЯßКГ😂😍щ
-👍уяÜяУбВвфöНТУзЛцЮх👍
-РКьоáХБÄёаЙÉцЖнвьрé😍
-чизÉаÓЖ💔Я😍тЁЁ😍ЦШÓДÜЪ
-🐍🐍КЫЭхсЧЖВпбЭ🎉аиД👎зз
-юМкй💔😂киÜäУюсЦаññлИÜ
-❤️шЕВöМÑÚ✨Пñ😎ззЮÜхУóЫ
-ъÜЛЁü😡р❤️дÜ🐍íñЧЬмÚиЭÉ
-к❤️АЮÉ✨ЫГЦчéь😍ЩдФ🐍бФ😂
-БёЬпБлóгРёÓ💔й😀НЯфäЯб
-ТчХшШЪсЖтÖ👎ГеСчыВПßс
-ЪШКЖчÑ😍ПЫ🔥Г🔥👍ыЕЫК❤️Т❤️
-íеёпÖ🌍дШЬЫЕ😡п🐍Г👎Мщ💔з
-пмГЦЪИ🎉👎😭ДХУ🔥ÍФñпЖöé
-👎😂💔лапíАöЫРíüéÍ👎ñä👍ä
-ОЖФсфеÄПÜчОйР😎ДпЯш😍😍
-ыпГЙЭО😂üрцÓЧгУпеЁБДс
-ёчáККäъÄÄфР✨мзфыЯññФ
-ЧÖрр🐍НХíВКÄдÉ✨😍Уíéю👍
-СЙÓМЬäщнКЮчьф🐍хвÚХ😍ц
-дд🌍й🌍ГБÄчуБö❤️ЫПсЕШУИ
-лÓКú👎ноЖЯßиäЩД😎ъЖЭяÉ
-ä🎉✨üяЫДí🔥ыАВОÍÁ😍е❤️ñн
-ыБЪüЩОц😂шЁЮÖуУАсэЕею
-úöÉ🎉äщ😂ЗÖЭВШЧаюüЖÍфЕ
-ЕДЫüÉáЩ😡👎ПкÍРА🔥РÉÄЙЫ
-🌍💔🐍ТХ😭ГÓФ🌍ызл😭😍ЯäбÁв
-óпö🔥ьтЪхяÜХйЙБñ😭💔НуЫ
-йёóßúзФу✨óпРщÁ😎ш🐍гüВ
-ЭНЖÜН❤️зЮ🔥áóОюЗйЬл😡Жф
-ÍарЙáкÓчñМКфеóдРÓешó
-РЦИщсвщí🌍ÄÑЁэв😀🔥ÑолЩ
-фñÉРм💔😍гякцÄЬНт❤️éÄаф
-д🐍ыНñгРОёфя💔кé😀ы🎉СöÓ
-а👍öдшсЧЭНхЪПНзеДеЗüЦ
-👍ы💔ХÍсрыфéЩыЩÍ🎉😀äкыЕ
-сйГуДгÜÑДúÖЮуЬьРЩёöÄ
-🎉éоЧÉ🐍чхЫГ😀зÍ😀❤️á👍ЧАй
-áо🎉ÁбРóИы😀ЛФ❤️ыМ😀ЭбкЗ
-ЛхЧÁÉöяШбдДрЬф😀ñфуё👍
-чú🎉иíФфлЩА❤️ноÉчшЪИиЛ
-ШпíРЕЛäздЕсгтиЫоЧжШИ
-Жúя✨ÉЫы👍🔥🐍еиÁувАшЗЪЖ
-Ю🎉СозтьщОüИЯ😍😡Тáä💔у😡
-ÖъЯНеХоáв😡еяЙáБ😎✨ÖС💔
-💔ЯЪ✨👎óНосвéíóÓЦдñЭЙш
-ЭмöЖбфФНЛМо🌍ö❤️яХÁОФо
-ыщЗхсТжЬЩ😍тёГÓ👍цÉНлÍ
-сñФлéхßÜС🐍ГÍпсЧ😂А😭öГ
-ю😡ыЪГхПБы😎😍💔äбёуэ😎йИ
-🐍ЦгРьЬК😂йíЖцÖпßЛуЭÚД
-ЧщьХ😂ФяЫéúЮыÜ🎉ß😀ЖМ😡Ы
-Рú👍öуЧЩÓКЯиЯ😭öéÄРьИц
-псСЧÓтЙ❤️рÁжÍгНЬÁ👍нпШ
-эüЁеЩсЬсБХСв🐍кЯßпНь🔥
-аúюи👎тÍЭюяСпцюÜТ🎉💔гЮ
-мÄДаß✨шхЁщтÖä💔Тфú✨фу
-🔥ЁяцЭЯСёОДóÄ😀ЬЗ💔Я👎ЬВ
-ЗäÍФЬИ😎ЪЩшр🌍А😀Цó😍😎РН
-рóвпÑсафéеОэÁш🐍ШЕЙЬ🐍
-😂щÉуЧ❤️ПжХВÄК❤️дЧÑфзíБ
-íНкüúЯöж😍пóäлÄояé❤️ьú
-🌍ßж😀💔пмггзй🎉ß😂🔥ЖíЮ😂у
-ъ😂ÖТÖрдф👎😍ñё👍😍бъПЗ🌍т
-пч✨щ❤️АгЮ🔥МñАюнэñДНиЖ
-🐍Óь😡яГ😂иЩщÜúЕАёбА💔дй
-эРКш🐍👍эбРÍГÁúЁЛÉäбЗ❤️
-подÉЬ👎РАЦМЯЧзАсдЁк🐍Ч
-😭мäо❤️ЧСöтäÓг😍Юы👎😂ЩЪ💔
-😂👎ÚРХ❤️ЮГЛг👎Ü💔дБКГЕ😎ж
-ü🐍ñбщЙ✨нÚÑСÖЭ😀Ú😍Ó😎са
-йцфÓ🐍глГГмхЛíН😍ОыоЭä
-вНуа😎ъЪ😡цñД😭Ж😍ФÜÓз😂Н
-тÉЧÜу🌍ШФБ😡éúжЁЛ💔Ж🌍жР
-Í🐍😭ÍиЫЦÉчЧ😂äщарфÉБоí
-дЪюßФÍфÚÜÓт🎉ЧÖдЯß🎉щЦ
-😂äúл🌍шУдÄ🔥👍ТüХ😂ППаВш
-Üéс😍😍ИЖúРфÄНАё😡ñÚßЛК
-Ñё🔥ФÁ😭ИñÍÍЭХцНт😎дЙуЬ
-äСсÄÖСнÁЖüяÖЯОЩаÍÚжЭ
-áьте💔ÑЕ🔥Ъ🔥хшÜоЖаЛ😎ьЩ
-ЮусПÓмэъэВрждСÁúыйФр
-шйхБтзкöэи🐍🔥с😭ñМЩЙща
-éУíßш😡🔥Ьюáлжлэих😎тМ👍
-асф🌍ЕгКдиСМЯ😡ЁрыЗысв
-ЁßюäпÉ👎ÚбäЧö😂Е😭рКЫдШ
-СÉВдюÁÑМрРулоАьоЁАПв
-сöÖ👍алÑсжЙÑЫЧü👍тШ🐍ñц
-ПРнсьуЯЗвНбíх🔥áÓШÜЖí
-щёГьГлЗÓьуó🐍😡чÑр😍ют😡
-ÍЯáеЬИ😀ИСú👍эЯКНйШрíа
-бФПдХúхГÓÍл😡цÉВá😍😎ак
-еЙÄФОщфЦú🌍уунеоКÓц🎉З
-ШхДНéНЪнÜЮБб👎шдГю😀Чо
-ЬÍáЁ👍Жжъб👍😡АссГÓ🎉МЭÓ
-ñювоЗфБÁеИсщ😀ю🐍ÑРШик
-яСяТÍМЬ🎉óшъеßÁЭúчдкЦ
-ÜЕъХэБмахкЙшЗРЧЁП🎉😍😎
-СддЭэ🐍Г😂эÚшКúфÁзбчúÉ
-чöйВäвТзз❤️ÖБЗАíцаЗЕ🔥
-✨жбкфйÜЛÉ😭ыаóММÄ😡Ьбд
-дзЦзшÉирÄñнуХдКсЮюч🎉
-ШХЕюЮя🐍Йи😍мЖЯóфÖюфüе
-íцóЮХц😂Ецлрл🔥ñХСöгЪе
-ВщяЗц💔дхЛдÑ👍ЪаЮвлТШР
-ЫсÄЙб😡щу💔СМö👎óЧщ😂ÜЖж
-МажÑ🔥ЁИыфя😍😂óß😭ибВеУ
-М😍ИИ😡изЩ🔥ЁцшÓ😀ÜЭсПюÚ
-ЁьяüÁЩьёЬришЖаЬЗнэЯ😭
-ЪтЖОö😂ХэÄшÚÓзсÖкзфэщ
-ял😂ляюöКФÚфгМßа🐍дгСы
-Ä😡АкИЁЗч🔥еú😎öьШзузЯШ
-саШФ😡гУНÖ😂Чём🔥ФАхéхА
-ßкЭрФ😍ЩРé✨шГфÄМúШ😭💔Ú
-ЛфО😡🌍Пж🔥С👎яФД👍Д👍ХгмЁ
-кÍ😡Т🎉ыПÁЁЭюбРßч😍ФЬ🔥з
-áзÚЦé🌍🔥ыусис🌍щóц👎öРä
-ßжЛЬÄüпТРÉцäХюпж🎉ёШÄ
-🌍👎ЕóСЕтö👎лАыÚ✨👍ХáШвБ
-ЫÚЛиФЙЛЩÁó😀ÖÍЛü❤️ÑнЦл
-Йи🎉цИ🎉ЯЛЁА❤️ü💔❤️🐍😍пЁхН
-КК🌍äоФóЧв✨íЕВ😀ЛЫ🔥БДГ
-ñíНкцвАñ👍✨ÁáъÍЧÑРвзД
-Шщ👎ЪЧв😍вгñф👍Ьл😍мдФРф
-ВЗЗ✨Бшс✨АфсáтжуÓ👎ФЧЙ
-❤️éÜÓХУвЖЪÑÉÁí❤️ПчíЪп👎
-АМиГИе😭йÜю😎ä💔я😀ЩъёñО
-ыжЦлбúМкМ💔еВÁ✨ÖÓ😍тЬК
-ñиЧКЧоНЖфдУфíтйпцъЙÜ
-Гмёä😂Í🎉Фя✨ХРбАяПыТДл
-зэЦзЁБбРз🎉чэг👍поЭыДг
-Щ👎юЙЪ🌍ДкХßхШÍиÁрáßúв
-Úш😂зе👍Д😍💔👎КйухööёбСЮ
-м😡íфО😎😭í🔥МüЬСтЛ🔥Éдуö
-❤️РÉЙ😀ñЬаÑ😭я😭г😀ó😡фО✨А
-éЧБЭъü✨üЫшшшüÖ👎щакзВ
-вÜßш🎉Хьеж❤️Шжг👎úбЯлЫ👎
-ЁуíвщМУЗ😎оррПАШрÄч❤️Ж
-😎😎ФнÍе😡АМÄñ💔😎óдщГх😀к
-ёкЛеыУЖпÁÚлúйöЁо😍ЯÁ🔥
-ШÓ👎Э👍ЕтрöíэыЗШуЧлЛхñ
-пÚäфсЖ😡ВДСыКщÍу😭ИыЪь
-✨ц✨рниЬфгэ😎йÍУк✨гóиÖ
-úЙ🌍Л🎉гв😡ФФЙÍю🔥éÉÍ😡Пз
-нВЮРдÁМГЩЙЧй😂кÚчзщЩО
-ÜЁéÁнÚтъÍЮЙСщÁöэöÄжЗ
-ГШёф❤️❤️Ддßоп👎ÖßöпЁйтÚ
-фВ🌍üтЬ❤️💔хÖп❤️💔ÉЯБчШО😭
-вМНúßÚрФРнеуэЫавéпбю
-🌍ЩЮЫхдХóТдвÑÚíШюéЦ😎Ä
-ÄÉ😎ИЬЁÍ😀ГЫОШьшф✨ÚВыд
-🎉Ужф😂Д🌍😀íЛЖ🐍иПЕлßйЙе
-👍М🎉Ю😀з🐍эНЩА😭СьäЬП🐍Íä
-НэйÍЬЪЬé😍Щ👎бМьПДР💔🔥Ц
-ХсéЩмЕäюцЕÜö🎉ЙщüÓМúÓ
-ЧТр👍❤️óШÁñÁÖрьÓПКЛ👎ÖЗ
-ßНъвьеа😎ШоЮсШ😭я👍ж❤️👍У
-зЭ🐍фЙ😍ппиФЙЪ😭👍бЫЫЫЁй
-н👎ÖЖп👍😎ÖöяóíщПáйщЯхх
-ЦЕГсЭЛдЪТüЮЗт👎ÄИÑЭ💔Т
-о🐍öÉБРОЧоЕöó💔зеЁ😎ьдД
-ÚíБУяДндöРÁá😡Ч✨😡💔ЮВБ
-рÁОßÖГÓЫ😭úЫ💔ШБñЫ😍р🌍Х
-кСГЦñóЮ💔Üй✨Ёх💔ÜфурЫп
-ГЯёРЛЕТЗЗÄС😀Р😀öорвОщ
-РÖ🎉🐍ш😭ПофоÓ👍ÉРАОяЧбХ
-👍😎УГрЫéпУу😍ÄÜЯэ😭É🎉Йй
-кщс😂рджÓÓлäёклЮх💔í😭ü
-Нцдац🎉óСжЗНчÓ❤️ñ🎉БвЭÉ
-рИЙГтийö❤️éЙáÑлßфА👎😭Д
-úцÍ🎉СЦШувЗЧ😂ШзмЬХÖÜЭ
-✨НэЩ😎😭🐍у🌍ьхЙджÍЙЛéЯш
-ЧЖé😂збхньч🐍ÜóЧжч💔öУы
-ёЪпЛЖüдщНуÁдрöÓТвМüУ
-тПиüнБи😂о🔥ÖД🔥СÄнЮм😍❤️
-👍бóЙÚñö👍👎СЩчКüЩ🎉öЩЙТ
-ÄочшшЕюáíяöäöмíÚИПеП
-💔пЗüВсÉÉ😀АН😀ДМбиКЖÓ😍
-ОхыГóрЮЗлЧМäюßрэ✨öкд
-ЮхÉÚН🌍мэъ💔éÍäЧЮНÉпЦÁ
-У😀ЁнЦяКüпчóэЭОС❤️цíÁт
-ЩÉЙеъуВ👎ñрКеЧÚ🔥😎ыфÖ😡
-ÓБяÜеЗОКНШмн👎аЮукоОó
-üéÍвыñУыШúт❤️❤️Жф😀ьнБÓ
-😍😍юцЛКСÍяшТочД😂ШÍ😡ль
-Дйä🎉áжó😂ä👎Э✨аÚéÉéЭйя
-ЯéзьюЦÄябсЮ💔🎉😡ычузúн
-ÖÚЪöщуЙ😭Ж😂С😡н🐍ÍíхдЧ🌍
-✨ХЮБйХúикЙлí🌍😎ОнефИг
-ЦГф🐍🔥ур🔥СжйЁ👎ЙхÍЙ😂АН
-ЫнÚääÜГъПЗАÜмФИИРßЧО
-öвЁÓЦпХÓэвúдзÄ😍äвцыЦ
-🔥ЯЬüßЗяЕÜЩüÄгЛ😍💔тЫуö
-Н😂м😭юъМ😭❤️яоЧжíёНуÑ😡í
-ßщö🎉чуÜóÍРПöО😍ЁлмыЫз
-фбюкФЗúЩ🌍пиÍ👍ЯПз❤️ИЯч
-öÉзАЧЩхЭÜ😍рЙ😭ЛТтé✨МШ
-ÚЗЬ😡🌍аЫ😡ШЛÁЁУ😍лЗЛÁЧр
-АЛÜ❤️зЫЪЬдíТрÍ😭ркнв🎉🐍
-ФЖИъуÉИвÜ🌍чóеРмЛ😀НíЧ
-ÁувüíмГАЕХШжлъыш✨овН
-❤️яВ🐍ТкгÄÖТЫзéó🎉ПшХТП
-БäЪхÜ😎Ш🌍éЙХЙЫа🌍ÁВ🌍ÑЛ
-🎉чÍú🌍РУЯэтвЪüАäёäСзЮ
-ъСáÜЗЖ🌍Р😭ЗьЕКЪЪъг😡мé
-явйЦИзÑъоЪ❤️цР❤️äфАеПУ
-кФИАЦЮÄ😂етШмЦ👎Ó👍двзЁ
-ч❤️ÓÓЯúöЯТиÁЁÁьЖ😂😂👎АП
-ЧÑ😭úн🌍ÄбЁдМ🎉👍üгсм✨ПЖ
-РÑЦÖце😭ñÑРаЖöЖúÜВШуК
-❤️ОíóФТхыЖ😍ётÉЭчдСьЪк
-ЯЙКЗЩИáсЮЖг👍УьÓÓБь👍💔
-Ш😡ЭíРнш😍Ль👎ÄннхЗЯöКь
-ёёвюßЗЗюЙ🔥Б😀еЖ👎úинАЬ
-Вüы👎ÍÑ🎉Ьд👍🌍ЕыÉБОРÍКх
-ÉáÉв👎Ши😎ъэДтíтЧ😂ЗтПъ
-чЁЗМñвÄ👎Оз😡😍ЭЮжíÖÓЪÄ
-Úп💔💔СдТúпППфЕЙÁв✨ухД
-ктяяНéм🎉Есьó🔥ку😂ьач😀
-äфьеюдР😀ÍлЭÄШеха🎉ЭЁЫ
-вóЫи🎉щХнéЮЬХüюуъСлäИ
-ФÓÄЬÉИЙчá🌍хÑе😀зЕВü🎉Ё
-нТЫЩБúЕс❤️тВншР🌍ЬéЛ✨Д
-нюЕ🌍чХÑфÍ😡ЕЮ😂нА🔥Г💔🌍Ю
-жХО🐍😀💔Ам🐍íЬÑп😀яБЧчÖÚ
-МЩé✨ВБдСмбёТÚцМВÁЮуЫ
-ßИыГÄрКФлЯНдЗщоуоСЮм
-оÁüЛрЛщÜО🎉ЕМ🎉ояшУñБИ
-ршИщМÚÜ❤️ДЧюыдÚЮуßТрэ
-мийБмАКáыП💔üгИáиХгчО
-ПьäЁЙ👎áпююРäщЯеПУ✨ÁЩ
-АГмЬЬéПяХЦ👎ЫÄВМКсоаФ
-ЙóрДÑßРÁÖиъксшОÓМщ👍ц
-öБюХ🎉ндгÚЭДоЦяЧЁ😂ыЧр
-💔❤️тЪйЩщхчй😡💔яüжйвю😭с
-цъ😍ЪЖРюЁ😀❤️в😡ГßÉßМ✨😍😀
-усХОэГЮМПзжЭшаСшöóь🎉
-ппéдÉÁСЕÍЯФёК😭Сым👎ПН
-еДéд😍емúгсвÜВМЫчРИüá
-ТКñ✨МЩ😡йД😀лыы👎Вщó😡ö👍
-РцшМКÍЙЭДРкп😭ÜхЛáö😍👍
-ЩХÉа😂😭зÖ🐍ЙйАихЖíЛЛЖЧ
-🔥😍ъдЭ👍🎉ÚАеСеПÍзАДбЭ🌍
-😭пьüé💔íЭ😍éЗéЙЩÁгР😎УР
-ЭХÉöоИ❤️ФР😂оКМуеПßЖхУ
-ЯíöщДьчíüхущъЯОЩуймñ
-ЭчИñй👎шЪЩ❤️ÓíÄß💔У😭у😡з
-гЖнВ✨😂З🌍ÜуъУШüЭМЭÚь😭
-ё👎🐍❤️ю😎жк😀👎ШЭ💔цШчöтЛ🌍
-РöгАÉрцы😎рЁЮ💔НЕБшÁóз
-ж😎😭ÓГЁхАбÍЦ🔥🐍ßéФÚЩÑё
-🌍ÜхцУю🐍ЭдТёхё🌍ЁмöЩ😂с
-зибэííАьá🌍😍👍йёМöÍНöУ
-с👍😎úбéСöТ😎РЬЗв💔💔ÑПщу
-ЁÉП😎ГПÁсВ😂Й😍ЕёфúчЭЮÍ
-❤️íМл😭ТЫ😭С😭áшПЕЖгТóбÑ
-ивé😡рС😡ъ💔чÁáá💔Á💔жНБä
-ыЩньКО💔ЧЮ😭РрЩЯэ🔥🌍ЯÄМ
-ЖШÍГЬúяшгьаДиÚöÑщÁзп
-ÑСÄдйДеЬзА❤️й❤️аГщяЙу🔥
-бüéъж👎🌍йÉß🌍Н😂хзЫЮАцМ
-Í🎉чЫüтХÖéнü🔥ъЖÁ🐍ЫСгт
-✨ЖЫОöпХÓШЫбЪнаПллФÁй
-👍ФХАЦмбиМнÉТ👎óеътöРН
-дЕтуúáйАДИÉншсйь✨мжи
-дíоÁЁГД😍ЧíиГÓь🌍éНкрх
-аЭñÄ😡ХУЮнижАÄфЧÁóв🎉е
-👍яХ😍ЕЯúßЖЮжБЮíтАпДюС
-ЭуАвжснéЙééó😡🔥рЩЭрид
-🐍жАíчЭ🔥😍атЫзхчíэЦГÍ❤️
-ÄШПéзСхЧ😂ьéчлъОд😀тмÜ
-оБКЫÜÓ✨äöÖЧ😍тТ👎úßЯжб
-ъьрÚУпуö😎😡ЬлГÖЗЪäиМü
-ОЯуЖМéЩ🐍ГäяÁéСзвхыко
-срЭтßЯЬиеНБíРвÁÓвÍПФ
-áÜЮЮеёЫГРИуЁЪв🌍ЁБóэí
-äЖИхгтСÜФÜáРü💔ИаУГ👎г
-пзРПÁä👎ЯéВéíГ🔥üрЗЕяи
-ЩБъюпáОéсШЪКивуфнЮЖе
-ъЁСÜÁАёЙГÖкÑУюÄы✨пёс
-энéх🔥ёын😡É🌍йъ👍В✨ЗТхс
-аÓьЧДхÄ👍❤️Ы🎉НЕЪСúясХм
-РОГщÄкИеИЩÄлÄБЁшьд💔😂
-😂С🎉ÉюаяцЪ😍о😍г😀Мñгд👍ш
-ИиёЖУ👎эüАÚ😎ь😡Íá😎п😎Ре
-дч😂зáЛХÓÄ🌍фüВÍчЩйÍрх
-еЭкДÑСэ👎с💔ЯйьЕЧРто💔ь
-зХрцЁКЕ🌍Ф🔥кñФзь😎СбрХ
-вэßн😍ХтÁЛ✨ЖöЪГ😭ÑМß😂г
-🌍ÁщАХТЩ😀ЧЖзП😡и🐍нфвО😭
-🐍рдхÓÄЦэпИиЖп😭ьóюиЩП
-ЦÍ💔эяу💔ÚÓЬ😍ДжЫчыхДьг
-й🔥úК💔уфьóуМеё🐍Ц🌍öЩЛ😀
-бéБтЭучжСМГáЯчПрРЛ🌍ъ
-е🐍Яг💔ъУÄ😡É😭ы🎉ñßíЭÁфВ
-😡ёцьЧüгхЬ🐍ÜЬ😎👎р🌍Уо😂Е
-ÜУвßутЪй😡ШиисРщЬШÚцН
-агЬ🌍хв😡уёЕÍгЗ🔥üЩ😍🐍ТЗ
-ЮЫúРéЦ💔яюМжмüéбЧÖХЯó
-жГэ🔥❤️ХВПГüивэДТкЁЗгЫ
-ЛЛцВЦхыЁшОАñфЙЮüг❤️еп
-ыъíÉÉЦñёöПи🐍✨зУкяúдÉ
-КВъíЙм🐍👎ю💔✨😭ОБ✨íеЦс🌍
-😂óЬшкЯ😍ЫЦыРГЬКñÁ👍ÚШБ
-✨цОä😭✨ñФИÓ🔥аáиз❤️кфщ😍
-👍ТЫьзкзÉьЖчХЬ🎉цЪФУгы
-✨ÜБНОУсЬъъáС💔йМíЕйх😡
-НЛП✨ЭЦгэц✨еюЦ😍ЫкУХá👎
-Ъ👎🐍Р🌍✨Ö😍👍НóäФÑаЙ👎öЧЗ
-ВÖЁоáÖü✨язУДРÖнпóъäЭ
-😂😀уÁ😀жпАЧ😭пУзЖЛЬЦзса
-ÁЬХеЬщó🌍👎чъÍдЯÑЦßЬЭч
-ПБШз💔ЕÓазю😡👎ОóéКъойИ
-рТÓпщñбЛнЭрР👎😀щЩужж😍
-😀ок😍кыäТñУÁЯвЗФ🐍ßöРф
-фиДУóюу😡БúьФÑóÁМÑñБО
-тö🌍ßñэÑИОдСáñеЛ😎КУЯФ
-ñЮ😎ВйíÜьДЭñо💔✨циО🌍фс
-ывУВэñК🎉йвНгÁЙеПчтЕ👎
-ФыГя😂ЦÄЮЫÄчéрБЛйÑЬо😀
-ё👎ХоХйóгзÄоЙзéИЦСлü😂
-ТЛ✨БÁяüаХДщГ👍Ю👎Даэрф
-зúФУСЕПÑф💔щьä💔ÍМшЯñФ
-кчблКдÉÑХÁД👍й💔сыПры😭
-КзОЫäТвоъЪ✨Лш😭ьЬоубí
-НюПéы❤️ññ🐍г❤️бЬУöíЛÑхШ
-БебЧ😀ñÓиФ😂áЧШъÄ✨ЯüПЖ
-х😡йííВÁцÑу👎👎Í😀😀ЪúÑэÓ
-йв😎Í😍É😀МаЫöуáВ🔥💔БпщМ
-СюИг😭ÓждЪéñÁÜÉЪЬкцКБ
-ое✨ßдáÜ😍УäЬó😂ЧэÚú👍ги
-üмüЮЩнЖёщяУ😭елщСрд✨Ñ
-АБУкЩ😍íайзсЦúЮЫЙ🎉Úъö
-чйüеЬюТхрЛизéюфÉеГЦ🔥
-👎икÍ✨ÁичбпПиЁъи👍рЯá👎
-🌍úЙЁß💔✨зПХеиÓээЭэЦёг
-тяОБ😡ар😀лёЙы😀😡é❤️❤️ёрó
-ОвзöуÜПЖьШЯчÖüещХъцЧ
-фкАóäСбоьнТГ😡ьХЯЦóÜú
-ЕН😭дГé🎉ткиёпю😀ЩЦ😀É😡Í
-ГуЬЕöÄПФÜЮАХЦоЭ😂ÖнЫК
-ЦЁ💔йÜÄÍнуГíшМещДЩÓФт
-ЁüÁжагРрж💔мАÑäе👍😀úАЕ
-ЮЧ👎áйюНзКÁЫЖäлéüлъ😀😂
-👎😀ЙэüвшÚДйИътфЦЮЮ✨ьы
-пкАЬЛЮ🎉цОÄ❤️кЫó😡бюиаА
-❤️идáУюП❤️Щ😍Б👎😡Ы😎😎💔хЧю
-ТÁЪмñнДЫОбГЬ😎ьчж🐍ÓÜЮ
-😂ÑМШт😂бßГíäÜплÍОц👎ШЪ
-п👎ÉйЁ💔áЩЖЕ😎ÑЭüÜДРмМк
-ЧРМмш❤️ÓЛЭГёэеШШИóвлЫ
-ШрÖяуифíнЭ😡😂ОÖюЮщОÖО
-юдФЮЦЫмÉÚ🔥МСÚВцЫ😀✨Тщ
-ÄЦЦТЖ😍йРНЫлСИъ👍ßУТщÍ
-ЩекРгэцßЖгЩÚ👎ЫУßЖЫИ✨
-ЕмуÄйЪФÄоеТÚЬ🌍Ь😂рРЯЛ
-ÍаÑъкМ😭Э😡щ😡БХ😡ЗЫí😎жЗ
-ЯйОБД😍ЛейдХнУОÁДы😂мЕ
-ЕШлРóбхГирЗЮЙФлäР✨ж😀
-áхщ💔эгÓÑáЁТиÑьЦгСóУú
-ЗЮ🎉вÄЗ😡ÁьМЖУшпКбТоóж
-иЁУВпжäеÍИТÍЩ🐍😍ТÚрЦÓ
-ЩÚíñРóыö❤️зñЪПÖЬ👍👎🌍ПС
-ä🌍юОä👍вÖÖЕэСсЧжЕН❤️úС
-яñДñОНмÚоесЭÄ😎шФÄЖНЮ
-🐍❤️Аß🐍ЛшОъЭйЕфяЦэаЯвЙ
-👍нÚВóЛ✨üЯА😍КÖшпßъÍП🐍
-Н🎉🐍ЪÍпé🐍В💔рЪкéЪ🔥Зб👍Е
-оКé✨ЪÑжГБ😍ИХÜКíмЗхХ😍
-е🔥РФяд🐍ЛЫЮпÉммнв💔лÉЫ
-БÑäÁЙЗЮ❤️Зсъшы😭юЫй😎Ü😍
-ЗЫОфÓР🐍р👎ЗГёЛ🎉ВЯäÁЫÄ
-éÜФ🐍Ü👍👎рШеÜАТЪЬвЫи😂É
-ÚЯÁóшзьÄЁВШёЖчОЛÜöñп
-фЮúдäííШ😍ÖК👎ре👍иБóъÁ
-ЁАЁТСЫдф😎ßг😭Ы😡ч✨оñК🐍
-ÍÁ✨жн🎉ТмП😭ьЦнúИу😎öЙЭ
-С❤️МЦ😭óäб👍ЗВвлЖЩКá❤️г✨
-😂ÁхВЯЪ🐍é😭óёОХу🐍ЬßÜÍ😀
-ÍчäáОЕзрáÜИсСсЗАан👍ö
-✨рУÁúßАЫХрäКв🐍Вня👍ÓЫ
-ОЙаИАыдЯЩÚЁэтЗСэ❤️öШЁ
-ЯтИнñЪíг😎úúИöРАДУßéí
-ÓывЦютЪуъÑ🔥вци😭😭Éь✨Ц
-🔥ÓЛыц🎉Т😂ДТ😡éВайñяЁшъ
-шч😍🎉дтвлПчжА🌍йЪэМЙпС
-ÓжбкЫЭЮЗÍйцГóХЪВОü❤️í
-🔥öЭх😡ÄйнъзüÖз💔😀п👎ЦдЭ
-ьсЕжхьАí✨ьÖуюöЦßäеёü
-ЕМ🌍эÖяЭзí🎉НуñЩЬЭифБ😂
-уäсХ💔й😭З👍Üж😡🔥😭Íöчпщц
-áЁъÉ❤️д😀мУЬФöшíßщхгСЮ
-😀ъüЮШрÚЯс😀ÑМГ💔üхÑЧóé
-СЗÜЁыÓд😎ВГСдÑß🐍ЩóЬБу
-í😭é😀Üьч👎👎опзмúН🐍💔😂öы
-эÜНЪМБзкр😀ЯрзЦю🎉вЖВШ
-😀ыЭЁüäИñЯ🔥Э😀ЕёоÄвШКЗ
-ёЛбЦыоим😍Л😭пá💔🌍Ú✨СЬч
-🐍ö😂ЖШй🐍❤️еÁúЮСЦгЕз😭в✨
-íÄúзтПеП🎉ЯцУШП😍гнАй👍
-ЕЯРиÖдМшáя😭лíÉНФÚЯОБ
-эгшÁыхССЁВНбíЦб😍ьр💔ъ
-цПКпШ😀ЁТÜ👍щü😭щёзБб👍ь
-ШНыТíÖщÓ🌍🎉óСкХСБУ😭лЬ
-Рёпл🔥гу🔥ÍМъЗПеМÄ👍нéú
-Эи😍íа😎иЪОУфТíД😂Еó😍ÜÑ
-эЖúВ🎉🔥РñÑöАÍúчГжкÉгñ
-лЮÉ👎ЪЭ🔥вЩеЧиШР❤️ЗЬцвШ
-😍Мя💔ём👍óУЕГЗыГтСó🐍ДÁ
-МэéуöлРáЬСЛиÑж🌍😎МяéИ
-ÄвúЫУЪЖэЩ🌍оÄЦйÓ🐍ёсдг
-ЖЦшГЖñЙЁ😭хъъОíи🌍щüь🎉
-ьеÖéФÑÍпмЯüБ🎉üЖЭгöÚñ
-ш❤️💔🔥óйокñüнлó😂äМухЫ🔥
-явöñм✨юдШР🌍😍ÁшК🔥сМьл
-ЭИяГхдпСЪДЕí😡😭мб😎бТ😭
-ЬВÄы😂й🔥ßí👍ьЫРÉсЭбЙ❤️ю
\ No newline at end of file
diff --git a/Tests/Sources/BaseTests/BaseTests+AssertCompareItem.swift b/Tests/Sources/BaseTests/BaseTests+AssertCompareItem.swift
deleted file mode 100644
index 4e935c0..0000000
--- a/Tests/Sources/BaseTests/BaseTests+AssertCompareItem.swift
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// BaseTests+AssertCompareItem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-public extension BaseTests {
- // swiftlint:disable:next function_parameter_count
- func assertItem(
- _ item: CompareItem?,
- _ expectedOld: Int,
- _ expectedChg: Int,
- _ expectedAdd: Int,
- _ expectedMatch: Int,
- _ expectedChildren: Int,
- _ expectedFileName: String?,
- _ expectedType: CompareChangeType,
- _ expectedSubfoldersizeOrFileSize: Int,
- sourceLocation: SourceLocation = #_sourceLocation
- ) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- let safeName = expectedFileName ?? "(nil filename)"
- if let expectedFileName {
- if let fsFileName = item.fileName {
- #expect(fsFileName == expectedFileName, "fileName doesn't match \(fsFileName) <-> \(expectedFileName)", sourceLocation: sourceLocation)
- } else {
- Issue.record("fileName doesn't match path is null <-> \(expectedFileName)")
- }
- } else {
- #expect(item.path == nil, "fileName doesn't match \(safeName) <-> \(item.fileName ?? "")", sourceLocation: sourceLocation)
- }
- #expect(item.olderFiles == expectedOld, "older for '\(safeName)' expected \(expectedOld) found \(item.olderFiles)", sourceLocation: sourceLocation)
- #expect(item.changedFiles == expectedChg, "changed for \(safeName)' expected \(expectedChg) found \(item.changedFiles)", sourceLocation: sourceLocation)
- #expect(item.orphanFiles == expectedAdd, "orphan for '\(safeName)' expected \(expectedAdd) found \(item.orphanFiles)", sourceLocation: sourceLocation)
- #expect(item.matchedFiles == expectedMatch, "matched for '\(safeName)' expected \(expectedMatch) found \(item.matchedFiles)", sourceLocation: sourceLocation)
- #expect(item.children.count == expectedChildren, "children for '\(safeName)' expected \(expectedChildren) found \(item.children.count)", sourceLocation: sourceLocation)
- #expect(item.type == expectedType, "type for '\(safeName)' expected '\(expectedType)' found '\(item.type)'", sourceLocation: sourceLocation)
- if item.isFile {
- #expect(item.fileSize == expectedSubfoldersizeOrFileSize, "fileSize for '\(safeName)' expected \(expectedSubfoldersizeOrFileSize) found \(item.fileSize)", sourceLocation: sourceLocation)
- } else {
- #expect(item.subfoldersSize == expectedSubfoldersizeOrFileSize, "subfoldersSize for '\(safeName)' expected \(expectedSubfoldersizeOrFileSize) found \(item.subfoldersSize)", sourceLocation: sourceLocation)
- }
- }
-
- func assertArrayCount(_ arr: [some Any], _ expectedCount: Int, sourceLocation: SourceLocation = #_sourceLocation) {
- #expect(arr.count == expectedCount, "\(arr) array count expected \(expectedCount) but found \(arr.count)", sourceLocation: sourceLocation)
- }
-
- func assertErrors(_ errors: [Error], _ expected: [FileError], sourceLocation: SourceLocation = #_sourceLocation) {
- #expect(errors.count == expected.count, "Errors must contain \(expected.count) items")
- for (index, error) in errors.enumerated() {
- assertError(error, expected[index], sourceLocation: sourceLocation)
- }
- }
-
- func assertError(_ error: Error, _ expected: FileError, sourceLocation: SourceLocation = #_sourceLocation) {
- guard let fileError = error as? FileError else {
- Issue.record("Error is not a FileError: \(error)", sourceLocation: sourceLocation)
- return
- }
- #expect(
- fileError == expected,
- "Error doesn't match: expected '\(expected) found '\(error)'",
- sourceLocation: sourceLocation
- )
- }
-
- /**
- Create the test setup and then stop execution
- */
- func assertOnlySetup(
- sourceLocation _: SourceLocation = #_sourceLocation
- ) throws {
- #if TEST_ONLY_SETUP
- throw TestError.onlySetup
- #endif
- }
-}
diff --git a/Tests/Sources/BaseTests/BaseTests.swift b/Tests/Sources/BaseTests/BaseTests.swift
deleted file mode 100644
index 5cd5061..0000000
--- a/Tests/Sources/BaseTests/BaseTests.swift
+++ /dev/null
@@ -1,37 +0,0 @@
-//
-// BaseTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/02/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-enum TestError: Error {
- case onlySetup
-}
-
-open class BaseTests {
- public var rootDir: URL
- public var dateBuilder = DateBuilder()
- public var className: String
- // swiftlint:disable:next line_length
- public let defaultPredicate = NSPredicate(format: "fileName == \".DS_Store\" OR fileName LIKE \"CVS\" OR fileName LIKE \".svn\" OR fileName LIKE \".git\" OR fileName LIKE \".hg\" OR fileName LIKE \".bzr\" OR fileName LIKE \"*~\" OR fileName ENDSWITH \".zip\" OR fileName ENDSWITH \".gz\" OR fileName ENDSWITH \".tgz\" OR fileName ENDSWITH \".tar\"")
- public let fm = FileManager.default
-
- public init(rootDir: URL) {
- className = String(describing: Self.self)
- self.rootDir = rootDir.appending(path: className, directoryHint: .isDirectory)
- }
-
- public convenience init() {
- self.init(rootDir: URL
- .desktopDirectory
- .appending(path: "visualdiffer/test_suite_swift/", directoryHint: .isDirectory))
- }
-
- public func buildDate(_ strDate: String) throws -> Date {
- try dateBuilder.isoDate(strDate)
- }
-}
diff --git a/Tests/Sources/BaseTests/DateBuilder.swift b/Tests/Sources/BaseTests/DateBuilder.swift
deleted file mode 100644
index e90af61..0000000
--- a/Tests/Sources/BaseTests/DateBuilder.swift
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// DateBuilder.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/02/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-public struct DateBuilder {
- let isoDateFormatter: DateFormatter
-
- public init() {
- isoDateFormatter = DateFormatter()
- isoDateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss z"
- isoDateFormatter.locale = Locale.current
- isoDateFormatter.timeZone = TimeZone.current
- isoDateFormatter.formatterBehavior = .default
- }
-
- public func isoDate(_ strDate: String) throws -> Date {
- guard let date = isoDateFormatter.date(from: strDate) else {
- throw NSError(domain: "Unable to parse date", code: 0, userInfo: nil)
- }
- return date
- }
-}
diff --git a/Tests/Sources/FileCompare/DiffResult/DiffResultBaseTests.swift b/Tests/Sources/FileCompare/DiffResult/DiffResultBaseTests.swift
deleted file mode 100644
index 01bde25..0000000
--- a/Tests/Sources/FileCompare/DiffResult/DiffResultBaseTests.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// DiffResultBaseTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 10/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-class DiffResultBaseTests: BaseTests {
- func assert(
- sectionSeparators lines: [DiffLine],
- separatorIndexes: [Int],
- sourceLocation: SourceLocation = #_sourceLocation
- ) {
- for (index, line) in lines.enumerated() {
- #expect(line.isSectionSeparator == separatorIndexes.contains(index), sourceLocation: sourceLocation)
- }
- }
-
- func assert(
- sectionSeparators lines: [DiffLine],
- isSeparator: Bool,
- sourceLocation: SourceLocation = #_sourceLocation
- ) {
- for line in lines {
- #expect(line.isSectionSeparator == isSeparator, sourceLocation: sourceLocation)
- }
- }
-
- func assert(
- lines: [DiffLine],
- expectedValue: [DiffChangeType],
- sourceLocation: SourceLocation = #_sourceLocation
- ) {
- #expect(lines.count == expectedValue.count, sourceLocation: sourceLocation)
-
- for (index, line) in lines.enumerated() {
- #expect(line.type == expectedValue[index], sourceLocation: sourceLocation)
- }
- }
-
- func assert(
- linesMode lines: [DiffLine],
- modes: [DiffLine.DisplayMode],
- sourceLocation: SourceLocation = #_sourceLocation
- ) {
- #expect(lines.count == modes.count, sourceLocation: sourceLocation)
-
- for (index, line) in lines.enumerated() {
- #expect(line.mode == modes[index], sourceLocation: sourceLocation)
- }
- }
-}
diff --git a/Tests/Sources/FileCompare/DiffResult/Tests/DiffResultTests.swift b/Tests/Sources/FileCompare/DiffResult/Tests/DiffResultTests.swift
deleted file mode 100644
index d25a507..0000000
--- a/Tests/Sources/FileCompare/DiffResult/Tests/DiffResultTests.swift
+++ /dev/null
@@ -1,564 +0,0 @@
-//
-// DiffResultTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 08/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length
-final class DiffResultTests: DiffResultBaseTests {
- @Test func diffLine() throws {
- let leftText = "line1\n\nline2\nline3"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 1, changed: 1))
-
- assertArrayCount(diffResult.sections, 2)
- #expect(diffResult.sections[0] == DiffSection(start: 1, end: 1))
- #expect(diffResult.sections[1] == DiffSection(start: 3, end: 3))
- }
-
- @Test func findNextSection() throws {
- let leftText = "line1\n\nline2\nline3"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- var didWrap = false
- // first move
- if let section = diffResult.findNextSection(by: -1, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[0])
- #expect(didWrap == false)
- } else {
- Issue.record("No section found")
- }
-
- // second move
- if let section = diffResult.findNextSection(by: 2, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[1])
- #expect(didWrap == false)
- } else {
- Issue.record("No section found")
- }
-
- // third move
- if let section = diffResult.findNextSection(by: 3, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[0])
- #expect(didWrap == true)
- } else {
- Issue.record("No section found")
- }
- }
-
- @Test func findPrevSection() throws {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- var didWrap = false
- // first move
- if let section = diffResult.findPrevSection(by: 5, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[1])
- #expect(didWrap == false)
- } else {
- Issue.record("No section found")
- }
-
- // second move
- if let section = diffResult.findPrevSection(by: 3, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[0])
- #expect(didWrap == false)
- } else {
- Issue.record("No section found")
- }
-
- // third move
- if let section = diffResult.findPrevSection(by: 1, wrapAround: true, didWrap: &didWrap) {
- #expect(section === diffResult.sections[2])
- #expect(didWrap == true)
- } else {
- Issue.record("No section found")
- }
- }
-
- @Test func findSectionRange() throws {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- guard let indexes = diffResult.findSectionIndexSet(with: 6) else {
- Issue.record("No indexes found")
- return
- }
- #expect(indexes == IndexSet(integersIn: 4 ..< 8))
- }
-
- @Test func findAdjacentSections() throws {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- guard let indexes = diffResult.findAdjacentSections(from: 5) else {
- Issue.record("No indexes found")
- return
- }
-
- #expect(indexes == IndexSet(integersIn: 3 ..< 8))
- }
-
- @Test func jumpToLine() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.leftSide.findLineIndex(by: 5) == 4)
- #expect(diffResult.rightSide.findLineIndex(by: 5) == nil)
- }
-
- @Test func justDifferentLines() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- let filtered = DiffResult.justDifferentLines(diffResult)
-
- #expect(filtered.summary == DiffSummary())
-
- assertArrayCount(filtered.leftSide.lines, 6)
- assertArrayCount(filtered.rightSide.lines, 6)
-
- assert(sectionSeparators: filtered.leftSide.lines, separatorIndexes: [0, 1, 5])
- assert(sectionSeparators: filtered.rightSide.lines, separatorIndexes: [0, 1])
-
- assertArrayCount(filtered.sections, 3)
- #expect(filtered.sections[0] == DiffSection(start: 0, end: 0))
- #expect(filtered.sections[1] == DiffSection(start: 1, end: 1))
- #expect(filtered.sections[2] == DiffSection(start: 2, end: 5))
- }
-
- @Test func justMatchingLines() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- let filtered = DiffResult.justMatchingLines(diffResult)
-
- #expect(filtered.summary == DiffSummary())
-
- assertArrayCount(filtered.leftSide.lines, 2)
- assertArrayCount(filtered.rightSide.lines, 2)
-
- assert(sectionSeparators: filtered.leftSide.lines, separatorIndexes: [0, 1])
- assert(sectionSeparators: filtered.rightSide.lines, separatorIndexes: [0, 1])
- }
-
- @Test func copyLines() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- let rowsToCopy = IndexSet([3, 6])
-
- DiffResult.copyLines(
- all: diffResult,
- current: diffResult,
- rows: rowsToCopy,
- source: .left,
- visibility: .all
- )
-
- let leftChangeTypeCopied: [DiffChangeType] = [.matching, .deleted, .matching, .matching, .deleted, .deleted, .matching, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeTypeCopied)
- let rightChangeTypeCopied: [DiffChangeType] = [.matching, .missing, .matching, .matching, .missing, .missing, .matching, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeTypeCopied)
-
- let copiedModes: [DiffLine.DisplayMode] = [.normal, .normal, .normal, .merged, .normal, .normal, .merged, .normal]
- assert(linesMode: diffResult.rightSide.lines, modes: copiedModes)
-
- let linesStatus = diffResult.rightSide.lines
- let lineNumbers = [1, -1, 2, 3, -1, -1, 4, -1]
-
- for (index, line) in linesStatus.enumerated() {
- #expect(line.number == lineNumbers[index])
- }
- }
-
- @Test func copyLinesDifferences() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- let rowsToCopy = IndexSet([1, 4])
-
- let filteredDiffResult = DiffResult.justDifferentLines(diffResult)
-
- DiffResult.copyLines(
- all: diffResult,
- current: filteredDiffResult,
- rows: rowsToCopy,
- source: .right,
- visibility: .differences
- )
-
- let leftChangeTypeCopied: [DiffChangeType] = [.deleted, .deleted, .deleted, .deleted]
- assert(lines: filteredDiffResult.leftSide.lines, expectedValue: leftChangeTypeCopied)
- let rightChangeTypeCopied: [DiffChangeType] = [.missing, .missing, .missing, .missing]
- assert(lines: filteredDiffResult.rightSide.lines, expectedValue: rightChangeTypeCopied)
-
- let copiedMode: [DiffLine.DisplayMode] = Array(repeating: .normal, count: 7)
- assert(linesMode: diffResult.rightSide.lines, modes: copiedMode)
-
- let linesStatus = filteredDiffResult.leftSide.lines
- let lineNumbers = [2, 5, 6, 7]
-
- for (index, line) in linesStatus.enumerated() {
- #expect(line.number == lineNumbers[index])
- }
- }
-
- @Test func deleteLines() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- let rowsToDelete = IndexSet([3, 5, 6, 7])
-
- DiffResult.deleteLines(
- all: diffResult,
- current: diffResult,
- rows: rowsToDelete,
- side: .left,
- visibility: .all
- )
-
- let leftChangeTypeDeleted: [DiffChangeType] = [.matching, .deleted, .matching, .missing, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeTypeDeleted)
- let rightChangeTypeDeleted: [DiffChangeType] = [.matching, .missing, .matching, .added, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeTypeDeleted)
-
- let linesStatus = diffResult.leftSide.lines
- let lineNumbers = [1, 2, 3, -1, 4]
-
- for (index, line) in linesStatus.enumerated() {
- #expect(line.number == lineNumbers[index])
- }
- }
-
- @Test func deleteLinesDifferences() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- let rowsToDelete = IndexSet([2, 3, 5])
-
- let filteredDiffResult = DiffResult.justDifferentLines(diffResult)
-
- DiffResult.deleteLines(
- all: diffResult,
- current: filteredDiffResult,
- rows: rowsToDelete,
- side: .right,
- visibility: .differences
- )
-
- let leftChangeTypeDeleted: [DiffChangeType] = [.deleted, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: filteredDiffResult.leftSide.lines, expectedValue: leftChangeTypeDeleted)
- let rightChangeTypeDeleted: [DiffChangeType] = [.missing, .changed, .missing, .missing, .missing, .missing]
- assert(lines: filteredDiffResult.rightSide.lines, expectedValue: rightChangeTypeDeleted)
-
- let linesStatus = filteredDiffResult.rightSide.lines
- let lineNumbers = [-1, 3, -1, -1, -1, -1]
-
- for (index, line) in linesStatus.enumerated() {
- #expect(line.number == lineNumbers[index])
- }
- }
-
- @Test func deleteLinesMatches() {
- let leftText = "line1\n\nline2\nline3\nline5\nline7\nline8\nline9"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .changed, .deleted, .deleted, .deleted, .deleted]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .changed, .missing, .missing, .missing, .missing]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 5, changed: 1))
-
- let rowsToDelete = IndexSet([0])
-
- let filteredDiffResult = DiffResult.justMatchingLines(diffResult)
-
- DiffResult.deleteLines(
- all: diffResult,
- current: filteredDiffResult,
- rows: rowsToDelete,
- side: .right,
- visibility: .matches
- )
-
- let leftChangeTypeDeleted: [DiffChangeType] = [.matching]
- assert(lines: filteredDiffResult.leftSide.lines, expectedValue: leftChangeTypeDeleted)
- let rightChangeTypeDeleted: [DiffChangeType] = [.matching]
- assert(lines: filteredDiffResult.rightSide.lines, expectedValue: rightChangeTypeDeleted)
-
- let linesStatus = filteredDiffResult.rightSide.lines
- let lineNumbers = [1]
-
- for (index, line) in linesStatus.enumerated() {
- #expect(line.number == lineNumbers[index])
- }
- }
-
- @Test func insertLinesLeftDestination() throws {
- let leftText = "line1\n\nline2\nline3"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let newLines = "line2.1\nline2.2\n"
- diffResult.insert(text: newLines, at: 3, side: .left)
-
- let leftChangeType: [DiffChangeType] = [.matching, .deleted, .matching, .deleted, .deleted, .changed]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .missing, .matching, .missing, .missing, .changed]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 1, changed: 1))
-
- assertArrayCount(diffResult.sections, 2)
- #expect(diffResult.sections[0] == DiffSection(start: 1, end: 1))
- #expect(diffResult.sections[1] == DiffSection(start: 3, end: 3))
-
- let expectedLeftLines = [
- (1, "line1"),
- (2, ""),
- (3, "line2"),
- (4, "line2.1"),
- (5, "line2.2"),
- (6, "line3"),
- ]
-
- let expectedRightLines = [
- (1, "line1"),
- (-1, ""),
- (2, "line2"),
- (-1, ""),
- (-1, ""),
- (3, "line4"),
- ]
-
- for (index, (leftNumber, leftLine)) in expectedLeftLines.enumerated() {
- let (rightNumber, rightLine) = expectedRightLines[index]
- let diffLeftLine = diffResult.leftSide.lines[index]
- let diffRightLine = diffResult.rightSide.lines[index]
-
- #expect(leftNumber == diffLeftLine.number)
- #expect(leftLine == diffLeftLine.text)
-
- #expect(rightNumber == diffRightLine.number)
- #expect(rightLine == diffRightLine.text)
- }
- }
-
- @Test func insertLinesRightDestination() throws {
- let leftText = "line1\n\nline2\nline3"
- let rightText = "line1\nline2\nline4"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText)
-
- let newLines = "line1.1\nline1.2\n"
- diffResult.insert(text: newLines, at: 1, side: .right)
-
- let leftChangeType: [DiffChangeType] = [.matching, .changed, .missing, .matching, .changed]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .changed, .added, .matching, .changed]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 1, changed: 1))
-
- assertArrayCount(diffResult.sections, 2)
- #expect(diffResult.sections[0] == DiffSection(start: 1, end: 1))
- #expect(diffResult.sections[1] == DiffSection(start: 3, end: 3))
-
- let expectedLeftLines = [
- (1, "line1"),
- (2, ""),
- (-1, ""),
- (3, "line2"),
- (4, "line3"),
- ]
-
- let expectedRightLines = [
- (1, "line1"),
- (2, "line1.1"),
- (3, "line1.2"),
- (4, "line2"),
- (5, "line4"),
- ]
-
- for (index, (leftNumber, leftLine)) in expectedLeftLines.enumerated() {
- let (rightNumber, rightLine) = expectedRightLines[index]
- let diffLeftLine = diffResult.leftSide.lines[index]
- let diffRightLine = diffResult.rightSide.lines[index]
-
- #expect(leftNumber == diffLeftLine.number)
- #expect(leftLine == diffLeftLine.text)
-
- #expect(rightNumber == diffRightLine.number)
- #expect(rightLine == diffRightLine.text)
- }
- }
-}
-
-// swiftlint:enable file_length
diff --git a/Tests/Sources/FileCompare/DiffResult/Tests/EndOfLineTests.swift b/Tests/Sources/FileCompare/DiffResult/Tests/EndOfLineTests.swift
deleted file mode 100644
index 23bfecb..0000000
--- a/Tests/Sources/FileCompare/DiffResult/Tests/EndOfLineTests.swift
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// EndOfLineTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/10/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-final class EndOfLineTests: DiffResultBaseTests {
- @Test func endOfLine() {
- let eolCarriageMixed = DiffLineComponent.splitLines("line1\rline2\nline3").detectEOL()
- let eolUnix = DiffLineComponent.splitLines("line1\nline2\nline3").detectEOL()
- let eolCRLFMixed = DiffLineComponent.splitLines("line1\r\nline2\nline3").detectEOL()
- let eolCR = DiffLineComponent.splitLines("line1\rline2\rline3").detectEOL()
- let eolCRLF = DiffLineComponent.splitLines("line1\r\nline2\r\nline3").detectEOL()
- let eolLineWithoutEOL = DiffLineComponent.splitLines("long line").detectEOL()
-
- #expect(eolCarriageMixed == .mixed)
- #expect(eolUnix == .unix)
- #expect(eolCRLFMixed == .mixed)
- #expect(eolCRLF == .pcCRLF)
- #expect(eolCR == .pcCR)
- #expect(eolLineWithoutEOL == .missing)
- }
-}
diff --git a/Tests/Sources/FileCompare/DiffResult/Tests/WhitespacesTests.swift b/Tests/Sources/FileCompare/DiffResult/Tests/WhitespacesTests.swift
deleted file mode 100644
index f0b3d44..0000000
--- a/Tests/Sources/FileCompare/DiffResult/Tests/WhitespacesTests.swift
+++ /dev/null
@@ -1,136 +0,0 @@
-//
-// WhitespacesTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/12/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-final class WhitespacesTests: DiffResultBaseTests {
- @Test func ignoreLeadingWhitespaces() {
- let leftText =
- " leading spaces\n" +
- " another line"
- let rightText =
- " leading spaces\n" +
- "another line"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText, options: .ignoreLeadingWhitespaces)
-
- let leftChangeType: [DiffChangeType] = [.matching, .matching]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .matching]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 0, changed: 0))
-
- assertArrayCount(diffResult.sections, 0)
- }
-
- @Test func ignoreInternalWhitespaces() {
- let leftText =
- " line1\n" +
- "another text\t\ttabs and spaces"
- let rightText =
- "line1\n" +
- "another text tabs and spaces"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText, options: .ignoreInternalWhitespaces)
-
- let leftChangeType: [DiffChangeType] = [.changed, .matching]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.changed, .matching]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 1, added: 0, deleted: 0, changed: 1))
-
- assertArrayCount(diffResult.sections, 1)
- }
-
- @Test func ignoreAllWhitespaces() {
- let leftText =
- " line1\n" +
- "another text\t\ttabs and spaces\r\n" +
- "last line "
- let rightText =
- "line1\n" +
- "another text tabs and spaces\n" +
- " last line"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText, options: [.allIgnoreWhitespaces, .ignoreLineEndings])
-
- let leftChangeType: [DiffChangeType] = [.matching, .matching, .matching]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .matching, .matching]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 3, added: 0, deleted: 0, changed: 0))
-
- assertArrayCount(diffResult.sections, 0)
- }
-
- @Test("Ignore all whitespaces differences but compare EOLs") func ignoreAllWhitespacesThenEol() {
- let leftText =
- " line1\n" +
- "another text\t\ttabs and spaces\r\n" +
- "last line "
- let rightText =
- "line1\n" +
- "another text tabs and spaces\n" +
- " last line"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText, options: [.allIgnoreWhitespaces])
-
- let leftChangeType: [DiffChangeType] = [.matching, .changed, .matching]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .changed, .matching]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 0, changed: 1))
-
- assertArrayCount(diffResult.sections, 1)
- }
-
- @Test func ignoreCharacterCase() {
- let leftText =
- "LINE ONE\n" +
- "Another Line"
- let rightText =
- "line One\n" +
- "another line"
-
- let diffResult = DiffResult()
- diffResult.diff(leftText: leftText, rightText: rightText, options: .ignoreCharacterCase)
-
- let leftChangeType: [DiffChangeType] = [.matching, .matching]
- assert(lines: diffResult.leftSide.lines, expectedValue: leftChangeType)
- let rightChangeType: [DiffChangeType] = [.matching, .matching]
- assert(lines: diffResult.rightSide.lines, expectedValue: rightChangeType)
-
- assert(sectionSeparators: diffResult.leftSide.lines, isSeparator: false)
- assert(sectionSeparators: diffResult.rightSide.lines, isSeparator: false)
-
- #expect(diffResult.summary == DiffSummary(matching: 2, added: 0, deleted: 0, changed: 0))
-
- assertArrayCount(diffResult.sections, 0)
- }
-}
diff --git a/Tests/Sources/FileSystem/BaseTests+AssertFileSystem.swift b/Tests/Sources/FileSystem/BaseTests+AssertFileSystem.swift
deleted file mode 100644
index c5ebf21..0000000
--- a/Tests/Sources/FileSystem/BaseTests+AssertFileSystem.swift
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// BaseTests+AssertFileSystem.swift
-// VisualDiffer
-//
-// Created by davide ficano on 28/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping
-public extension BaseTests {
- func assertSymlink(
- _ item: CompareItem,
- _ destPath: String,
- _ isFolder: Bool,
- functionName: String = #function,
- sourceLocation: SourceLocation = #_sourceLocation
- ) throws {
- guard let url = item.toUrl() else {
- try #require(item.path != nil, "Unable to find path for \(item)", sourceLocation: sourceLocation)
- return
- }
- do {
- let resolved = try FileManager.default.destinationOfSymbolicLink(atPath: url.osPath)
- let real = URL(filePath: resolved, directoryHint: item.isFolder ? .isDirectory : .notDirectory)
- let destUrl = appendFolder(destPath, functionName: functionName)
- #expect(destUrl == real, "symlink dest doesn't match: expected \(destUrl) found \(real)", sourceLocation: sourceLocation)
- #expect(item.isSymbolicLink, "\(url) must be a symlink", sourceLocation: sourceLocation)
- if isFolder {
- #expect(item.isFolder, "\(url) must be a folder", sourceLocation: sourceLocation)
- } else {
- #expect(item.isFile, "\(url) must be a file", sourceLocation: sourceLocation)
- }
- } catch {
- Issue.record(error, sourceLocation: sourceLocation)
- }
- }
-
- func assertTimestamps(
- _ item: CompareItem?,
- _ strCreateDate: String?,
- _ strModDate: String?,
- sourceLocation: SourceLocation = #_sourceLocation
- ) throws {
- guard let item else {
- try #require(item != nil, "fs is nil", sourceLocation: sourceLocation)
- return
- }
- guard let fsPath = item.path else {
- try #require(item.path != nil, "Unable to find path for \(item)", sourceLocation: sourceLocation)
- return
- }
- do {
- let attrs = try FileManager.default.attributesOfItem(atPath: fsPath)
-
- if let strCreateDate {
- if let creationDate = attrs[.creationDate] as? Date {
- let isDateEqual = try buildDate(strCreateDate) == creationDate
- #expect(isDateEqual, "Expected creation date for \(item.fileName!) is \(strCreateDate) but found \(creationDate)", sourceLocation: sourceLocation)
- } else {
- Issue.record("Unable to get file creation date for \(fsPath)", sourceLocation: sourceLocation)
- }
- }
-
- if let strModDate {
- if let modificationDate = attrs[.modificationDate] as? Date {
- let isDateEqual = try buildDate(strModDate) == modificationDate
- #expect(isDateEqual, "Expected modification date for \(item.fileName!) is \(strModDate) but found \(modificationDate)", sourceLocation: sourceLocation)
- } else {
- Issue.record("Unable to get file modification date for \(fsPath)", sourceLocation: sourceLocation)
- }
- }
- } catch {
- Issue.record(error)
- }
- }
-
- func assertMismatchingTags(_ item: CompareItem?, _ oldValue: Int, _ fileName: String, sourceLocation: SourceLocation = #_sourceLocation) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- #expect(item.mismatchingTags == oldValue, "Tags for '\(fileName)' expected \(oldValue) found \(item.mismatchingTags)", sourceLocation: sourceLocation)
- }
-
- func assertFolderTags(_ item: CompareItem?, _ value: Bool, _ fileName: String, sourceLocation: SourceLocation = #_sourceLocation) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- #expect(item.summary.hasMetadataTags == value, "Folder '\(fileName)' tags must be \(value)", sourceLocation: sourceLocation)
- }
-
- func assertMismatchingLabels(_ item: CompareItem?, _ oldValue: Int, _ fileName: String? = "", sourceLocation: SourceLocation = #_sourceLocation) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- #expect(item.mismatchingLabels == oldValue, "Labels for '\(fileName!)' expected \(oldValue) found \(item.mismatchingLabels)", sourceLocation: sourceLocation)
- }
-
- func assertFolderLabels(_ item: CompareItem?, _ value: Bool, _ fileName: String? = "", sourceLocation: SourceLocation = #_sourceLocation) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- #expect(item.summary.hasMetadataLabels == value, "Folder '\(fileName!)' labels must be \(value)", sourceLocation: sourceLocation)
- }
-
- func assertResourceFileLabels(_ item: CompareItem?, _ expectedValue: Int, _ path: URL, sourceLocation: SourceLocation = #_sourceLocation) {
- guard let item else {
- Issue.record("CompareItem is nil", sourceLocation: sourceLocation)
- return
- }
- do {
- let foundValue = try getLabelNumber(item.toUrl()!)
- #expect(foundValue == expectedValue, "Label for '\(path)' expected \(expectedValue) found \(foundValue)", sourceLocation: sourceLocation)
- } catch {
- Issue.record("Found error \(error)", sourceLocation: sourceLocation)
- }
- }
-}
-
-// swiftlint:enable force_unwrapping
diff --git a/Tests/Sources/FileSystem/BaseTests+FileSystemOperations.swift b/Tests/Sources/FileSystem/BaseTests+FileSystemOperations.swift
deleted file mode 100644
index d342626..0000000
--- a/Tests/Sources/FileSystem/BaseTests+FileSystemOperations.swift
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// BaseTests+FileSystemOperations.swift
-// VisualDiffer
-//
-// Created by davide ficano on 25/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-public extension BaseTests {
- func appendFolder(_ path: String, _ isFolder: Bool = true, functionName: String = #function) -> URL {
- rootDir
- .appending(path: functionName.trimmingCharacters(in: CharacterSet(charactersIn: "()")), directoryHint: .isDirectory)
- .appending(path: path, directoryHint: isFolder ? .isDirectory : .notDirectory)
- }
-
- internal func createFolder(_ path: String, functionName: String = #function) throws {
- try fm.createDirectory(
- at: appendFolder(path, functionName: functionName),
- withIntermediateDirectories: true,
- attributes: nil
- )
- }
-
- internal func createFile(_ path: String, _ content: String, functionName: String = #function) throws {
- try content.write(
- to: appendFolder(path, functionName: functionName),
- atomically: true,
- encoding: .utf8
- )
- }
-
- internal func removeItem(_ path: String, ignoreError: Bool = true, functionName: String = #function) throws {
- if ignoreError {
- try? fm.removeItem(at: appendFolder(path, functionName: functionName))
- } else {
- try fm.removeItem(at: appendFolder(path, functionName: functionName))
- }
- }
-
- func setFileTimestamp(_ path: String, _ dateString: String, isFolder: Bool = true, functionName: String = #function) throws {
- try fm.setAttributes(
- [.modificationDate: dateBuilder.isoDate(dateString)],
- ofItemAtPath: appendFolder(path, isFolder, functionName: functionName).osPath
- )
- }
-
- func createDataFile(_ path: String, _ bytes: [UInt8], functionName: String = #function) throws {
- try Data(bytes: bytes, count: bytes.count).write(to: appendFolder(path, functionName: functionName))
- }
-
- func setFileCreationTime(_ path: String, _ dateString: String, isFolder: Bool = true, functionName: String = #function) throws {
- try fm.setAttributes(
- [.creationDate: dateBuilder.isoDate(dateString)],
- ofItemAtPath: appendFolder(path, isFolder, functionName: functionName).osPath
- )
- }
-
- func createSymlink(_ path: String, _ destPath: String, functionName: String = #function) throws {
- if destPath.starts(with: "..") {
- // URL create absolute paths so we use the string version for relative paths
- try fm.createSymbolicLink(
- atPath: appendFolder(path, functionName: functionName).osPath,
- withDestinationPath: destPath
- )
- } else {
- try fm.createSymbolicLink(
- at: appendFolder(path, functionName: functionName),
- withDestinationURL: appendFolder(destPath, functionName: functionName)
- )
- }
- }
-
- func add(
- tags: [String],
- fullPath url: URL
- ) throws {
- // Apple removed from Swift the ability to change tags/labels
- // The workaround consists to continue to use the legacy NSURL
- // https://developer.apple.com/forums/thread/703028
- try (url as NSURL).setResourceValue(tags, forKey: .tagNamesKey)
- }
-
- func add(
- labelNumber: Int,
- fullPath url: URL
- ) throws {
- // Apple removed from Swift the ability to change tags/labels
- // The workaround consists to continue to use the legacy NSURL
- // https://developer.apple.com/forums/thread/703028
- try (url as NSURL).setResourceValue(NSNumber(value: labelNumber), forKey: .labelNumberKey)
- }
-
- func getLabelNumber(_ url: URL) throws -> Int {
- let resources = try url.resourceValues(forKeys: [.labelNumberKey])
- if let labelNumber = resources.labelNumber {
- return labelNumber
- }
- return 0
- }
-}
diff --git a/Tests/Sources/FileSystem/CaseSensitiveBaseTest.swift b/Tests/Sources/FileSystem/CaseSensitiveBaseTest.swift
deleted file mode 100644
index d184b07..0000000
--- a/Tests/Sources/FileSystem/CaseSensitiveBaseTest.swift
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// CaseSensitiveBaseTest.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-import Testing
-
-open class CaseSensitiveBaseTest: BaseTests {
- static let serialQueue = DispatchQueue(label: "com.visualdiffer.volume.testQueue")
-
- let volumeName = "VDTestsMatchCase_Swift"
- let volumePath: URL
-
- override public init(rootDir _: URL) {
- volumePath = URL(filePath: "/Volumes/\(volumeName)/")
- super.init(rootDir: volumePath)
-
- mountVolume()
- }
-
- public func mountVolume() {
- Self.serialQueue.sync {
- // create the case sensitive ram disk if necessary
- if !FileManager.default.fileExists(atPath: volumePath.osPath) {
- let process = Process()
- process.executableURL = URL(filePath: "/bin/sh")
- process.arguments = ["-c", "diskutil erasevolume 'Case-sensitive HFS+' '\(volumeName)' `hdiutil attach -nomount ram://1048576`"]
- do {
- try process.run()
- } catch {
- Issue.record("Failed to create volume \(volumeName) \(error)")
- }
- process.waitUntilExit()
- }
- }
- }
-}
-
-extension CaseSensitiveBaseTest {
- func assertVolumeMounted(sourceLocation: SourceLocation = #_sourceLocation) throws {
- try #require(
- fm.fileExists(atPath: rootDir.deletingLastPathComponent().osPath),
- "Unable to find the case sensitive disk, test can't be executed",
- sourceLocation: sourceLocation
- )
- }
-}
diff --git a/Tests/Sources/FileSystem/Mock/MockFileOperationManagerDelegate.swift b/Tests/Sources/FileSystem/Mock/MockFileOperationManagerDelegate.swift
deleted file mode 100644
index f2a28d2..0000000
--- a/Tests/Sources/FileSystem/Mock/MockFileOperationManagerDelegate.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// MockFileOperationManagerDelegate.swift
-// VisualDiffer
-//
-// Created by davide ficano on 27/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@testable import VisualDiffer
-
-class MockFileOperationManagerDelegate: FileOperationManagerDelegate {
- let confirmReplace: ConfirmReplace
- var isRunning: Bool
- var errors = [any Error]()
-
- init(
- replaceAll: Bool = true,
- isRunning: Bool = true
- ) {
- confirmReplace = ConfirmReplace(
- yesToAll: replaceAll,
- noToAll: false
- ) { _, _ in false }
- self.isRunning = isRunning
- }
-
- func waitPause(for _: FileOperationManager) {}
-
- func isRunning(_: FileOperationManager) -> Bool {
- isRunning
- }
-
- func fileManager(
- _: FileOperationManager,
- canReplaceFromPath fromPath: String,
- fromAttrs: [FileAttributeKey: Any]?,
- toPath: String,
- toAttrs: [FileAttributeKey: Any]?
- ) -> Bool {
- confirmReplace.canReplace(
- fromPath: fromPath,
- fromAttrs: fromAttrs,
- toPath: toPath,
- toAttrs: toAttrs
- )
- }
-
- func fileManager(_: FileOperationManager, initForItem _: CompareItem) {}
-
- func fileManager(_: FileOperationManager, updateForItem _: CompareItem) {}
-
- func fileManager(_: FileOperationManager, addError error: any Error, forItem _: CompareItem) {
- errors.append(error)
- }
-
- func fileManager(_: FileOperationManager, startBigFileOperationForItem _: CompareItem) {}
-
- func isBigFileOperationCancelled(_: FileOperationManager) -> Bool {
- false
- }
-
- func isBigFileOperationCompleted(_: FileOperationManager) -> Bool {
- false
- }
-
- func fileManager(_: FileOperationManager, setCancelled _: Bool) {}
-
- func fileManager(_: FileOperationManager, setCompleted _: Bool) {}
-
- func fileManager(_: FileOperationManager, updateBytesCompleted _: Double, totalBytes _: Double, throughput _: Double) {}
-}
diff --git a/Tests/Sources/FileSystem/Mock/MockFolderReaderDelegate.swift b/Tests/Sources/FileSystem/Mock/MockFolderReaderDelegate.swift
deleted file mode 100644
index 41b3d13..0000000
--- a/Tests/Sources/FileSystem/Mock/MockFolderReaderDelegate.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// MockFolderReaderDelegate.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@testable import VisualDiffer
-
-class MockFolderReaderDelegate: FolderReaderDelegate {
- var isRunning = false
- var errors = [Error]()
-
- init(isRunning: Bool) {
- self.isRunning = isRunning
- }
-
- func isRunning(_: VisualDiffer.FolderReader) -> Bool {
- isRunning
- }
-
- func progress(_: VisualDiffer.FolderReader, status _: VisualDiffer.FolderReaderStatus) {}
-
- func folderReader(_: VisualDiffer.FolderReader, handleError error: any Error, forPath _: URL) -> Bool {
- errors.append(error)
- return true
- }
-}
diff --git a/Tests/Sources/FileSystem/Mock/MockItemComparatorDelegate.swift b/Tests/Sources/FileSystem/Mock/MockItemComparatorDelegate.swift
deleted file mode 100644
index 508f973..0000000
--- a/Tests/Sources/FileSystem/Mock/MockItemComparatorDelegate.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-//
-// MockItemComparatorDelegate.swift
-// VisualDiffer
-//
-// Created by davide ficano on 26/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-@testable import VisualDiffer
-
-class MockItemComparatorDelegate: ItemComparatorDelegate {
- var isRunning: Bool
-
- init(isRunning: Bool = true) {
- self.isRunning = isRunning
- }
-
- func isRunning(_: ItemComparator) -> Bool {
- isRunning
- }
-}
diff --git a/Tests/Sources/FileSystem/Tests/AlignmentTests.swift b/Tests/Sources/FileSystem/Tests/AlignmentTests.swift
deleted file mode 100644
index 450e6c8..0000000
--- a/Tests/Sources/FileSystem/Tests/AlignmentTests.swift
+++ /dev/null
@@ -1,1605 +0,0 @@
-//
-// AlignmentTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/07/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class AlignmentTests: CaseSensitiveBaseTest {
- @Test func leftMatchCaseRightIgnoreCase() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .timestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/1.txt", "")
- try createFile("l/d.TXT", "")
- try createFile("r/m.txt", "")
- try createFile("l/m.tXt", "")
- try createFile("r/m.tXt", "")
- try createFile("r/m.Txt", "")
- try createFile("l/m.TXT", "")
- try createFile("r/m.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 2, 2, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 2, 6, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
-
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 6)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 2, 2, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 2, 6, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
- }
-
- @Test func leftMatchCaseRightIgnoreCase2() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: true,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/0.txt", "")
- try createFile("r/1.txt", "")
- try createFile("r/d.TXT", "")
- try createFile("l/m.txt", "")
- try createFile("l/m.tXt", "")
- try createFile("r/m.tXt", "")
- try createFile("l/m.Txt", "")
- try createFile("r/m.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 2, 2, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 2, 6, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 6)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 2, 2, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 2, 6, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
- }
-
- @Test func leftMatchCaseRightIgnoreCase3() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: true,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("r/1.txt", "")
- try createFile("r/d.TXT", "")
- try createFile("l/m.txt", "")
- try createFile("l/m.tXt", "")
- try createFile("l/m.Txt", "")
- try createFile("l/m.TXT", "")
- try createFile("r/m.TXT", "")
- try createFile("r/n.tXt", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 3, 1, 7, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 3, 1, 7, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.tXt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
-
- let child8 = child1.children[6] // l <-> r
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "n.tXt", .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 7)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 3, 1, 7, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 3, 1, 7, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.tXt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
-
- let childVI8 = childVI1.children[6] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "n.tXt", .orphan, 0)
- }
- }
-
- @Test func bothIgnoreCase() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/10.jpg", "")
- try createFile("r/10.Jpg", "")
- try createFile("l/20.jpg", "")
- try createFile("r/20.JPG", "")
- try createFile("l/debug.jpg", "")
- try createFile("l/Help.jpg", "")
- try createFile("r/help.jpg", "")
- try createFile("l/sea.txt", "")
- try createFile("r/sea.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 1, 4, 5, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 4, 5, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "10.jpg", .same, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "10.Jpg", .same, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "20.jpg", .same, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "20.JPG", .same, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "debug.jpg", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "Help.jpg", .same, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "help.jpg", .same, 0)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "sea.txt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "sea.TXT", .same, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 5)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 1, 4, 5, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 4, 5, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "10.jpg", .same, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "10.Jpg", .same, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "20.jpg", .same, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "20.JPG", .same, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "debug.jpg", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "Help.jpg", .same, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "help.jpg", .same, 0)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "sea.txt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "sea.TXT", .same, 0)
- }
- }
-
- @Test func onlyOneOnLeft() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: true
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("r/m.txt", "")
- try createFile("l/m.txT", "")
- try createFile("r/m.tXt", "")
- try createFile("r/m.Txt", "")
- try createFile("r/m.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 1, 4, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 3, 1, 4, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "m.txT", .same, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "m.TXT", .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 4)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 1, 4, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 3, 1, 4, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "m.txT", .same, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "m.Txt", .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "m.TXT", .orphan, 0)
- }
- }
-
- @Test func createLeftOrphans() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: true
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/1.txt", "")
- try createFile("l/d.TXT", "")
- try createFile("l/m.txt", "")
- try createFile("l/m.tXt", "")
- try createFile("l/m.Txt", "")
- try createFile("r/m.Txt", "")
- try createFile("l/m.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 5, 1, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 6, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.tXt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 1, 0, 0, "m.TXT", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 6)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 5, 1, 6, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 6, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 1, 0, 0, "m.tXt", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 1, 0, 0, "m.TXT", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func folders() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: true
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/m.TxT")
- try createFolder("r/m.TxT")
- try createFolder("l/M.TxT")
- try createFolder("r/M.TxT")
-
- // create files
- try createFile("l/m.TxT/hello.txt", "")
- try setFileTimestamp("l/m.TxT/hello.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/m.TxT/hello.txt", "1")
- try createFile("r/m.TxT/Hello.txt", "12")
- try createFile("l/M.TxT/hello.txt", "")
- try createFile("l/M.TxT/Hello.txt", "123")
- try setFileTimestamp("l/M.TxT/Hello.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/M.TxT/Hello.txt", "1234")
- try createFile("l/0.txt", "")
- try createFile("r/1.txt", "")
- try createFile("r/d.TXT", "")
- try createFile("l/m.txt", "")
- try createFile("l/m.tXt", "")
- try createFile("r/m.tXt", "")
- try createFile("l/m.Txt", "")
- try createFile("r/m.TXT", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 2, 0, 3, 2, 8, "l", .orphan, 3)
- assertItem(child1.linkedItem, 0, 2, 3, 2, 8, "r", .orphan, 7)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 1, 0, 0, 0, 2, "m.TxT", .orphan, 0)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 2, "m.TxT", .orphan, 3)
-
- let child3 = child2.children[0] // m.TxT <-> m.TxT
- assertItem(child3, 1, 0, 0, 0, 0, "hello.txt", .old, 0)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "hello.txt", .changed, 1)
-
- let child4 = child2.children[1] // m.TxT <-> m.TxT
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "Hello.txt", .orphan, 2)
-
- let child5 = child1.children[1] // l <-> r
- assertItem(child5, 1, 0, 1, 0, 2, "M.TxT", .orphan, 3)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 2, "M.TxT", .orphan, 4)
-
- let child6 = child5.children[0] // M.TxT <-> M.TxT
- assertItem(child6, 0, 0, 1, 0, 0, "hello.txt", .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child5.children[1] // M.TxT <-> M.TxT
- assertItem(child7, 1, 0, 0, 0, 0, "Hello.txt", .old, 3)
- assertItem(child7.linkedItem, 0, 1, 0, 0, 0, "Hello.txt", .changed, 4)
-
- let child8 = child1.children[2] // l <-> r
- assertItem(child8, 0, 0, 1, 0, 0, "0.txt", .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child9 = child1.children[3] // l <-> r
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child10 = child1.children[4] // l <-> r
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let child11 = child1.children[5] // l <-> r
- assertItem(child11, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child12 = child1.children[6] // l <-> r
- assertItem(child12, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child12.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let child13 = child1.children[7] // l <-> r
- assertItem(child13, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child13.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 8)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 2, 0, 3, 2, 8, "l", .orphan, 3)
- assertItem(child1.linkedItem, 0, 2, 3, 2, 8, "r", .orphan, 7)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 1, 0, 0, 0, 2, "m.TxT", .orphan, 0)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 2, "m.TxT", .orphan, 3)
-
- let childVI3 = childVI2.children[0] // m.TxT <--> m.TxT
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // m.TxT <-> m.TxT
- assertItem(child3, 1, 0, 0, 0, 0, "hello.txt", .old, 0)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "hello.txt", .changed, 1)
-
- let childVI4 = childVI2.children[1] // m.TxT <--> m.TxT
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // m.TxT <-> m.TxT
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "Hello.txt", .orphan, 2)
-
- let childVI5 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI5.children, 2)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 1, 0, 1, 0, 2, "M.TxT", .orphan, 3)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 2, "M.TxT", .orphan, 4)
-
- let childVI6 = childVI5.children[0] // M.TxT <--> M.TxT
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // M.TxT <-> M.TxT
- assertItem(child6, 0, 0, 1, 0, 0, "hello.txt", .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI5.children[1] // M.TxT <--> M.TxT
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // M.TxT <-> M.TxT
- assertItem(child7, 1, 0, 0, 0, 0, "Hello.txt", .old, 3)
- assertItem(child7.linkedItem, 0, 1, 0, 0, 0, "Hello.txt", .changed, 4)
-
- let childVI8 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 1, 0, 0, "0.txt", .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI9 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // l <-> r
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI10 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // l <-> r
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let childVI11 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // l <-> r
- assertItem(child11, 0, 0, 1, 0, 0, "m.txt", .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI12 = childVI1.children[6] // l <--> r
- assertArrayCount(childVI12.children, 0)
- let child12 = childVI12.item // l <-> r
- assertItem(child12, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
- assertItem(child12.linkedItem, 0, 0, 0, 1, 0, "m.tXt", .same, 0)
-
- let childVI13 = childVI1.children[7] // l <--> r
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // l <-> r
- assertItem(child13, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child13.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 0)
- }
- }
-
- @Test func closestMatch() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: true
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("r/1.txt", "")
- try createFile("r/d.TXT", "")
- try createFile("l/m.Txt", "")
- try createFile("r/m.txt", "")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 1, 3, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 3, "r", .orphan, 0)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "m.txt", .same, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 3)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 1, 3, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 3, "r", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "d.TXT", .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 0, 1, 0, "m.Txt", .same, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "m.txt", .same, 0)
- }
- }
-
- @Test func copyFolder() throws {
- try assertVolumeMounted()
-
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: true
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/0.txt", "12")
- try createFile("r/1.txt", "")
- try createFile("l/m.txt", "123")
- try createFile("l/m.tXt", "")
- try setFileTimestamp("l/m.tXt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/m.tXt", "1234")
- try createFile("l/m.Txt", "12345678901234")
- try setFileTimestamp("l/m.Txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/m.TXT", "12345")
- try createFile("r/next.txt", "")
-
- let copyRoot: CompareItem
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 2, 0, 2, 0, 6, "l", .orphan, 19)
- assertItem(child1.linkedItem, 0, 2, 2, 0, 6, "r", .orphan, 9)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 3)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 1, 0, 0, 0, 0, "m.tXt", .old, 0)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "m.tXt", .changed, 4)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 1, 0, 0, 0, 0, "m.Txt", .old, 14)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "m.TXT", .changed, 5)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "next.txt", .orphan, 0)
-
- copyRoot = child6
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 6)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 2, 0, 2, 0, 6, "l", .orphan, 19)
- assertItem(child1.linkedItem, 0, 2, 2, 0, 6, "r", .orphan, 9)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 3)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 1, 0, 0, 0, 0, "m.tXt", .old, 0)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "m.tXt", .changed, 4)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 1, 0, 0, 0, 0, "m.Txt", .old, 14)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "m.TXT", .changed, 5)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "next.txt", .orphan, 0)
- }
-
- let fileOperaionDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperaionDelegate
- )
- let copyCompareItem = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- copyCompareItem.copy(
- srcRoot: copyRoot,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 1, 0, 2, 1, 6, "l", .orphan, 19)
- assertItem(child1.linkedItem, 0, 1, 2, 1, 6, "r", .orphan, 18)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 3)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 1, 0, 0, 0, 0, "m.tXt", .old, 0)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "m.tXt", .changed, 4)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.Txt", .same, 14)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 14)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "next.txt", .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 6)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 1, 0, 2, 1, 6, "l", .orphan, 19)
- assertItem(child1.linkedItem, 0, 1, 2, 1, 6, "r", .orphan, 18)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 0, 0, "0.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "1.txt", .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 0, 1, 0, 0, "m.txt", .orphan, 3)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 1, 0, 0, 0, 0, "m.tXt", .old, 0)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "m.tXt", .changed, 4)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 0, 0, 1, 0, "m.Txt", .same, 14)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "m.TXT", .same, 14)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "next.txt", .orphan, 0)
- }
- }
-
- @Test func regExpr() throws {
- try assertVolumeMounted()
-
- // align both .raw and .png to .jpg
- let fileNameAlignments: [AlignRule] = [
- AlignRule(
- regExp: AlignRegExp(pattern: "(.*)\\.", options: []),
- template: AlignTemplate(pattern: "$1", options: [])
- ),
- ]
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: true,
- isRightCaseSensitive: true,
- fileNameAlignments: fileNameAlignments
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/001.jpg", "1")
- try setFileTimestamp("l/001.jpg", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/001.raw", "12")
- try createFile("l/002.jpg", "123")
- try createFile("l/003.jpg", "12345")
- try createFile("r/003.raw", "1234")
- try createFile("l/004.jpg", "1234567")
- try createFile("r/004.raw", "1234567")
- try createFile("l/005.jpg", "123456789")
- try createFile("r/005.raw", "12345678")
- try setFileTimestamp("r/005.raw", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/006.jpg", "12345678901")
- try createFile("l/007.jpg", "1234567890123")
- try createFile("r/007.png", "1234")
- try setFileTimestamp("r/007.png", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/008.jpg", "123456789012345")
- try createFile("r/008.raw", "1234567890")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 1, 4, 2, 1, 8, "l", .orphan, 64)
- assertItem(child1.linkedItem, 2, 3, 0, 1, 8, "r", .orphan, 35)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 1, 0, 0, 0, 0, "001.jpg", .old, 1)
- assertItem(child2.linkedItem, 0, 1, 0, 0, 0, "001.raw", .changed, 2)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "002.jpg", .orphan, 3)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child1.children[2] // l <-> r
- assertItem(child4, 0, 1, 0, 0, 0, "003.jpg", .changed, 5)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "003.raw", .changed, 4)
-
- let child5 = child1.children[3] // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "004.jpg", .same, 7)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "004.raw", .same, 7)
-
- let child6 = child1.children[4] // l <-> r
- assertItem(child6, 0, 1, 0, 0, 0, "005.jpg", .changed, 9)
- assertItem(child6.linkedItem, 1, 0, 0, 0, 0, "005.raw", .old, 8)
-
- let child7 = child1.children[5] // l <-> r
- assertItem(child7, 0, 0, 1, 0, 0, "006.jpg", .orphan, 11)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child8 = child1.children[6] // l <-> r
- assertItem(child8, 0, 1, 0, 0, 0, "007.jpg", .changed, 13)
- assertItem(child8.linkedItem, 1, 0, 0, 0, 0, "007.png", .old, 4)
-
- let child9 = child1.children[7] // l <-> r
- assertItem(child9, 0, 1, 0, 0, 0, "008.jpg", .changed, 15)
- assertItem(child9.linkedItem, 0, 1, 0, 0, 0, "008.raw", .changed, 10)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 8)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 1, 4, 2, 1, 8, "l", .orphan, 64)
- assertItem(child1.linkedItem, 2, 3, 0, 1, 8, "r", .orphan, 35)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 1, 0, 0, 0, 0, "001.jpg", .old, 1)
- assertItem(child2.linkedItem, 0, 1, 0, 0, 0, "001.raw", .changed, 2)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 1, 0, 0, "002.jpg", .orphan, 3)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // l <-> r
- assertItem(child4, 0, 1, 0, 0, 0, "003.jpg", .changed, 5)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "003.raw", .changed, 4)
-
- let childVI5 = childVI1.children[3] // l <--> r
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // l <-> r
- assertItem(child5, 0, 0, 0, 1, 0, "004.jpg", .same, 7)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "004.raw", .same, 7)
-
- let childVI6 = childVI1.children[4] // l <--> r
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // l <-> r
- assertItem(child6, 0, 1, 0, 0, 0, "005.jpg", .changed, 9)
- assertItem(child6.linkedItem, 1, 0, 0, 0, 0, "005.raw", .old, 8)
-
- let childVI7 = childVI1.children[5] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 1, 0, 0, "006.jpg", .orphan, 11)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI8 = childVI1.children[6] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 1, 0, 0, 0, "007.jpg", .changed, 13)
- assertItem(child8.linkedItem, 1, 0, 0, 0, 0, "007.png", .old, 4)
-
- let childVI9 = childVI1.children[7] // l <--> r
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // l <-> r
- assertItem(child9, 0, 1, 0, 0, 0, "008.jpg", .changed, 15)
- assertItem(child9.linkedItem, 0, 1, 0, 0, 0, "008.raw", .changed, 10)
- }
- }
-
- @Test func regNoMatchButIgnoreCaseMatch() throws {
- try assertVolumeMounted()
-
- // No file matches this rule but they must be aligned by case
- let fileNameAlignments: [AlignRule] = [
- AlignRule(
- regExp: AlignRegExp(pattern: "(.*)\\.jpg", options: []),
- template: AlignTemplate(pattern: "$1.raw", options: [])
- ),
- ]
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.alignIgnoreCase, .contentTimestamp, .size],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false,
- fileNameAlignments: fileNameAlignments
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/New York.jpg", "123")
- try createFile("r/New York.jpg", "123")
- try createFile("l/SanDiego.jpg", "1")
- try createFile("r/sandiego.jpg", "1")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 4)
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 4)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "New York.jpg", .same, 3)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "New York.jpg", .same, 3)
-
- let child3 = child1.children[1] // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "SanDiego.jpg", .same, 1)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "sandiego.jpg", .same, 1)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 4)
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 4)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "New York.jpg", .same, 3)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "New York.jpg", .same, 3)
-
- let childVI3 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // l <-> r
- assertItem(child3, 0, 0, 0, 1, 0, "SanDiego.jpg", .same, 1)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "sandiego.jpg", .same, 1)
- }
- }
-
- @Test func bigFolderLeftIgnoreRightMatch() throws {
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- srandom(1000)
- for _ in 0 ..< 10 {
- let len = Int.random(in: 0 ..< 34) + 6
- var str = String(repeating: " ", count: Int(len))
- for l in 0 ..< len {
- let index = str.index(str.startIndex, offsetBy: l)
- str.replaceSubrange(index ... index, with: String(generateAsciiChar()))
- }
- for _ in 0 ..< 10 {
- let index = Int.random(in: 0 ..< len)
- invertCase(&str, index: index)
- let direction = Bool.random() ? "l" : "r"
- let path = "\(direction)/\(str).txt"
-
- try createFile(path, "12")
- }
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/BufferedInputStreamTests.swift b/Tests/Sources/FileSystem/Tests/BufferedInputStreamTests.swift
deleted file mode 100644
index ab35365..0000000
--- a/Tests/Sources/FileSystem/Tests/BufferedInputStreamTests.swift
+++ /dev/null
@@ -1,204 +0,0 @@
-//
-// BufferedInputStreamTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/09/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping
-final class BufferedInputStreamTests {
- @Test func minBufferSize() throws {
- let lines = [
- "Ciao 👋",
- "🍕+🍺=❤️",
- "🚀 Go!",
- ]
- try testLines(
- lines: lines,
- bufferSize: 1
- )
- try testBisLines(
- lines: lines,
- bufferSize: 1
- )
- }
-
- @Test func bigBufferSize() throws {
- let lines = [
- "Ciao 👋",
- "🍕+🍺=❤️",
- "🚀 Go!",
- ]
- try testLines(
- lines: lines,
- bufferSize: 100_000
- )
- try testBisLines(
- lines: lines,
- bufferSize: 100_000
- )
- }
-
- func testLines(
- lines: [String],
- bufferSize: Int,
- encoding: String.Encoding = .utf8,
- sourceLocation: SourceLocation = #_sourceLocation
- ) throws {
- let inputStrem = InputStream(data: lines.joined(separator: "\n").data(using: encoding)!)
- defer {
- inputStrem.close()
- }
- let bis = BufferedInputStream(
- stream: inputStrem,
- encoding: encoding,
- bufferSize: bufferSize
- )
- defer {
- bis.close()
- }
-
- bis.open()
-
- var i = 0
- while let line = bis.readLine() {
- #expect(line == lines[i], sourceLocation: sourceLocation)
- i += 1
- }
- }
-
- func testBisLines(
- lines: [String],
- bufferSize: Int,
- encoding: String.Encoding = .utf8,
- sourceLocation: SourceLocation = #_sourceLocation
- ) throws {
- let inputStrem = InputStream(data: lines.joined(separator: "\n").data(using: encoding)!)
- defer {
- inputStrem.close()
- }
- let bis = BufferedInputStream(
- stream: inputStrem,
- encoding: encoding,
- bufferSize: bufferSize
- )
- defer {
- bis.close()
- }
-
- bis.open()
-
- var i = 0
- while let line = bis.readLine() {
- #expect(line == lines[i], sourceLocation: sourceLocation)
- i += 1
- }
- }
-
- @Test func bigFile() throws {
- let testBundle = Bundle(for: type(of: self))
-
- guard let filePath = testBundle.url(forResource: "big_file_5000_lines", withExtension: "txt") else {
- Issue.record("Unable to find resource big_file_5000_lines.txt")
- return
- }
-
- let bis = try BufferedInputStream(
- url: filePath,
- encoding: .utf8,
- bufferSize: 500
- )
- defer {
- bis.close()
- }
-
- bis.open()
-
- var lineCount = 0
- while bis.readLine() != nil {
- lineCount += 1
- }
-
- #expect(lineCount == 5000)
- }
-
- #if OLD_OBJC_BUFFERED_INPUT_STREAM
- @Test("Test any regression with the original Objc code") func bigFile2() throws {
- let testBundle = Bundle(for: type(of: self))
-
- guard let filePath = testBundle.url(forResource: "big_file_5000_lines", withExtension: "txt") else {
- Issue.record("Unable to find resource big_file_5000_lines.txt")
- return
- }
-
- let bisNew = try BufferedInputStream(
- url: filePath,
- encoding: .utf8,
- bufferSize: 500
- )
- let bisOld = TOPBufferedInputStream(
- fileAtPath: filePath.osPath,
- encoding: String.Encoding.utf8.rawValue,
- bufferSize: 500
- )
- defer {
- bisNew.close()
- bisOld.close()
- }
-
- bisNew.open()
- bisOld.open()
-
- var lineCount = 0
-
- while true {
- guard let bisNewLine = bisNew.readLine(),
- let bisOldLine = bisOld.readLine() else {
- break
- }
- lineCount += 1
- #expect(bisNewLine == bisOldLine)
- }
-
- #expect(lineCount == 5000)
- }
- #endif
-
- @Test("Native Swift Data Encoding differs from Objc") func nativeSwiftAsciiEncoding() {
- let data = Data(
- [
- 0x62,
- 0x70,
- 0x6C,
- 0x69,
- 0x73,
- 0x74,
- 0x30,
- 0x30,
- 0xD4,
- 0x00,
- 0x01,
- 0x00,
- 0x02,
- 0x00,
- 0x03,
- 0x00,
- 0x04,
- 0x00,
- 0x05,
- ]
- )
- // we can't use the native Swift String(data:encoding) because the results are different
- let swiftString = String(data: data, encoding: .ascii)
- let nsString = NSString(data: data, encoding: String.Encoding.ascii.rawValue)
-
- #expect(swiftString == nil)
- #expect(nsString != nil)
- }
-}
-
-// swiftlint:enable force_unwrapping
diff --git a/Tests/Sources/FileSystem/Tests/ComparatorTests.swift b/Tests/Sources/FileSystem/Tests/ComparatorTests.swift
deleted file mode 100644
index 07f4979..0000000
--- a/Tests/Sources/FileSystem/Tests/ComparatorTests.swift
+++ /dev/null
@@ -1,336 +0,0 @@
-//
-// ComparatorTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/03/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping
-final class ComparatorTests: BaseTests {
- @Test() func timestampTolerance() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .timestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192,
- timestampToleranceSeconds: 5
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/sample01.txt", "content")
- try createFile("l/sample02.txt", "content")
- try createFile("l/sample03.txt", "content")
- try createFile("l/sample04.txt", "content")
- try createFile("l/sample05.txt", "content")
-
- try createFile("r/sample01.txt", "content")
- try createFile("r/sample02.txt", "content")
- try createFile("r/sample03.txt", "content")
- try createFile("r/sample04.txt", "content")
- try createFile("r/sample05.txt", "content")
-
- try setFileTimestamp("l/sample01.txt", "2001-03-24 10: 45: 00 +0600")
- try setFileTimestamp("l/sample02.txt", "2001-03-24 10: 45: 14 +0600")
- try setFileTimestamp("l/sample03.txt", "2001-03-24 10: 45: 30 +0600")
- try setFileTimestamp("l/sample04.txt", "2001-03-24 10: 45: 40 +0600")
- try setFileTimestamp("l/sample05.txt", "2001-03-24 10: 45: 20 +0600")
-
- try setFileTimestamp("r/sample01.txt", "2001-03-24 10: 45: 05 +0600")
- try setFileTimestamp("r/sample02.txt", "2001-03-24 10: 45: 10 +0600")
- try setFileTimestamp("r/sample03.txt", "2001-03-24 10: 45: 36 +0600")
- try setFileTimestamp("r/sample04.txt", "2001-03-24 10: 45: 20 +0600")
- try setFileTimestamp("r/sample05.txt", "2001-03-24 10: 45: 15 +0600")
-
- let rootL = folderReader.readFolder(
- atPath: appendFolder("l"),
- parent: nil,
- recursive: false
- )!
-
- let rootR = folderReader.readFolder(
- atPath: appendFolder("r"),
- parent: nil,
- recursive: false
- )!
-
- let expectedResults: [ComparisonResult] = [
- .orderedSame,
- .orderedSame,
- .orderedAscending,
- .orderedDescending,
- .orderedSame,
- ]
- let count = expectedResults.count
-
- #expect(count == rootL.children.count, "Expected count \(count) found \(rootL.children.count)")
-
- for i in 0 ..< rootL.children.count {
- let l = rootL.children[i]
- let r = rootR.children[i]
- let result = comparator.compare(l, r)
- #expect(result == expectedResults[i], "Result \(result) : Dates tolerance (\(comparator.timestampToleranceSeconds) secs) error \(String(describing: l.fileModificationDate)), \(String(describing: r.fileModificationDate))")
- }
- }
-
- @Test func compareAsText() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .asText,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/sample01.txt", "a\nb")
- try createFile("r/sample01.txt", "a\r\nb")
-
- try createFile("l/sample02.txt", "a\nb")
- try createFile("r/sample02.txt", "a\n\rb")
-
- try createFile("l/sample03.txt", "a\n\n\nb")
- try createFile("r/sample03.txt", "a\r\n\r\n\r\nb")
-
- let rootL = folderReader.readFolder(
- atPath: appendFolder("l"),
- parent: nil,
- recursive: false
- )!
-
- let rootR = folderReader.readFolder(
- atPath: appendFolder("r"),
- parent: nil,
- recursive: false
- )!
-
- let expectedResults: [ComparisonResult] = [
- .orderedSame,
- .orderedDescending,
- .orderedSame,
- ]
- let count = expectedResults.count
-
- #expect(count == rootL.children.count, "Expected count \(count) found \(rootL.children.count)")
-
- for i in 0 ..< count {
- let l = rootL.children[i]
- let r = rootR.children[i]
- let result = comparator.compareContent(l, r, ignoreLineEndingDiff: true)
- #expect(result == expectedResults[i], "Result (index \(i)) expected \(expectedResults[i]) found \(result)")
- }
- }
-
- @Test func binaryContent() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .content,
- delegate: comparatorDelegate,
- bufferSize: 13
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- // a and b are identical
- let leftBytes: [UInt8] = [
- 0x96, 0xBD, 0x8D, 0xC7, 0xE9, 0xE8, 0x75, 0x18, 0x99, 0xF1,
- 0x15, 0x2F, 0x58, 0xCC, 0x8B, 0xB1, 0x50, 0x3F, 0xD1, 0xEF,
- 0xC9, 0xF8, 0xCD, 0xE1, 0x90, 0x18, 0x1D, 0x0B, 0x02, 0x8A,
- 0x71, 0x0E, 0x49, 0xB9, 0x1B, 0xE3, 0x78, 0x68, 0x9D, 0x97,
- ]
- var rightBytes: [UInt8] = [
- 0x96, 0xBD, 0x8D, 0xC7, 0xE9, 0xE8, 0x75, 0x18, 0x99, 0xF1,
- 0x15, 0x2F, 0x58, 0xCC, 0x8B, 0xB1, 0x50, 0x3F, 0xD1, 0xEF,
- 0xC9, 0xF8, 0xCD, 0xE1, 0x90, 0x18, 0x1D, 0x0B, 0x02, 0x8A,
- 0x71, 0x0E, 0x49, 0xB9, 0x1B, 0xE3, 0x78, 0x68, 0x9D, 0x97,
- ]
-
- // create files
- try createDataFile("l/sample01.txt", leftBytes)
- try createDataFile("l/sample02.txt", leftBytes)
- try createDataFile("l/sample03.txt", leftBytes)
-
- // increment last byte
- rightBytes[rightBytes.count - 1] = leftBytes[leftBytes.count - 1]
- rightBytes[rightBytes.count - 1] += 0x11
- try createDataFile("r/sample01.txt", rightBytes)
-
- try createDataFile("r/sample02.txt", leftBytes)
-
- // decrement last byte
- rightBytes[rightBytes.count - 1] = leftBytes[leftBytes.count - 1]
- rightBytes[rightBytes.count - 1] -= 0x11
- try createDataFile("r/sample03.txt", rightBytes)
-
- let rootL = folderReader.readFolder(
- atPath: appendFolder("l"),
- parent: nil,
- recursive: false
- )!
-
- let rootR = folderReader.readFolder(
- atPath: appendFolder("r"),
- parent: nil,
- recursive: false
- )!
-
- let expectedResults: [ComparisonResult] = [
- .orderedAscending,
- .orderedSame,
- .orderedDescending,
- ]
- let count = expectedResults.count
-
- #expect(count == rootL.children.count, "Expected count \(count) found \(rootL.children.count)")
-
- for i in 0 ..< rootL.children.count {
- let l = rootL.children[i]
- let r = rootR.children[i]
- let result = comparator.compare(l, r)
- #expect(result == expectedResults[i], "Result \(result) found \(expectedResults[i]): Content \(l.path!) \(r.path!)")
- }
- }
-
- @Test func size() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .size,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/sample01.txt", "1")
- try createFile("l/sample02.txt", "123456")
- try createFile("l/sample03.txt", "123456")
- try createFile("l/sample04.txt", "21")
-
- try createFile("r/sample01.txt", "1234")
- try createFile("r/sample02.txt", "1")
- try createFile("r/sample03.txt", "123")
- try createFile("r/sample04.txt", "21")
-
- let rootL = folderReader.readFolder(
- atPath: appendFolder("l"),
- parent: nil,
- recursive: false
- )!
-
- let rootR = folderReader.readFolder(
- atPath: appendFolder("r"),
- parent: nil,
- recursive: false
- )!
-
- let expectedResults: [ComparisonResult] = [
- .orderedAscending,
- .orderedDescending,
- .orderedDescending,
- .orderedSame,
- ]
- let count = expectedResults.count
-
- #expect(count == rootL.children.count, "Expected count \(count) found \(rootL.children.count)")
-
- for i in 0 ..< rootL.children.count {
- let l = rootL.children[i]
- let r = rootR.children[i]
- let result = comparator.compare(l, r)
- #expect(result == expectedResults[i], "Result \(result) : Size error \(l.fileSize), \(r.fileSize)")
- }
- }
-}
-
-// swiftlint:enable force_unwrapping
diff --git a/Tests/Sources/FileSystem/Tests/CopyFilesTests.swift b/Tests/Sources/FileSystem/Tests/CopyFilesTests.swift
deleted file mode 100644
index 52a10e3..0000000
--- a/Tests/Sources/FileSystem/Tests/CopyFilesTests.swift
+++ /dev/null
@@ -1,1633 +0,0 @@
-//
-// CopyFilesTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class CopyFilesTests: BaseTests {
- @Test func copyFilesOnlyMatches() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/a/bb/ccc")
- try createFolder("r/a/bb/ccc")
-
- try createFile("l/a/bb/ccc/second.txt", "123456789012")
-
- try createFile("r/a/bb/ccc/file.txt", "123456789012")
- try createFile("r/a/bb/ccc/second.txt", "123456789")
-
- try setFileTimestamp("l/a/bb/ccc/second.txt", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 1, 0, 0, 0, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 1, "a", .orphan, 21)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 0, 0, 0, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 1, "bb", .orphan, 21)
-
- var child3 = child2.children[0]
- assertItem(child3, 1, 0, 0, 0, 2, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 1, 1, 0, 2, "ccc", .orphan, 21)
-
- var child4 = child3.children[0]
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 12)
-
- var child5 = child3.children[1]
- assertItem(child5, 1, 0, 0, 0, 0, "second.txt", .old, 12)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "second.txt", .changed, 9)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 0, 0, 0, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 1, "a", .orphan, 21)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 1, 0, 0, 0, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 1, "bb", .orphan, 21)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 1, 0, 0, 0, 2, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 1, 1, 0, 2, "ccc", .orphan, 21)
-
- let childVI4 = childVI3.children[0] // ccc <--> ccc
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // ccc <-> ccc
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 12)
-
- let childVI5 = childVI3.children[1] // ccc <--> ccc
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // ccc <-> ccc
- assertItem(child5, 1, 0, 0, 0, 0, "second.txt", .old, 12)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "second.txt", .changed, 9)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child2,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 1, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 0, 1, 1, 1, "a", .orphan, 24)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 1, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 0, 1, 1, 1, "bb", .orphan, 24)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 1, 2, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 0, 1, 1, 2, "ccc", .orphan, 24)
-
- child4 = child3.children[0]
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 12)
-
- child5 = child3.children[1]
- assertItem(child5, 0, 0, 0, 1, 0, "second.txt", .same, 12)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "second.txt", .same, 12)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 0, 1, 1, 1, "a", .orphan, 24)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 0, 0, 0, 1, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 0, 1, 1, 1, "bb", .orphan, 24)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 0, 0, 0, 1, 2, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 0, 1, 1, 2, "ccc", .orphan, 24)
-
- let childVI4 = childVI3.children[0] // ccc <--> ccc
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // ccc <-> ccc
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 12)
-
- let childVI5 = childVI3.children[1] // ccc <--> ccc
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // ccc <-> ccc
- assertItem(child5, 0, 0, 0, 1, 0, "second.txt", .same, 12)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "second.txt", .same, 12)
- }
- }
-
- @Test func copyFilesReplaceNoToAll() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_0/folder_1")
- try createFolder("r/folder_0/folder_1")
-
- // create files
- try createFile("l/folder_0/folder_1/file_1.txt", "1234567890")
- try setFileTimestamp("l/folder_0/folder_1/file_1.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/folder_0/folder_1/file_1.txt", "1234")
-
- try createFile("l/folder_0/file_2.txt", "1234567890")
- try createFile("r/folder_0/file_2.txt", "1234567")
- try setFileTimestamp("r/folder_0/file_2.txt", "2001-03-24 10: 45: 32 +0600")
-
- try createFile("r/folder_0/file_3.h", "123")
- try createFile("r/folder_0/file_3.m", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 1, 1, 0, 0, 4, "folder_0", .orphan, 20)
- assertItem(child1.linkedItem, 1, 1, 2, 0, 4, "folder_0", .orphan, 16)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 0, 0, 0, 1, "folder_1", .orphan, 10)
- assertItem(child2.linkedItem, 0, 1, 0, 0, 1, "folder_1", .orphan, 4)
-
- var child3 = child2.children[0]
- assertItem(child3, 1, 0, 0, 0, 0, "file_1.txt", .old, 10)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "file_1.txt", .changed, 4)
-
- var child4 = child1.children[1]
- assertItem(child4, 0, 1, 0, 0, 0, "file_2.txt", .changed, 10)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_2.txt", .old, 7)
-
- var child5 = child1.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_3.h", .orphan, 3)
-
- var child6 = child1.children[3]
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file_3.m", .orphan, 2)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 4)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 1, 0, 0, 4, "folder_0", .orphan, 20)
- assertItem(child1.linkedItem, 1, 1, 2, 0, 4, "folder_0", .orphan, 16)
-
- let childVI2 = childVI1.children[0] // folder_0 <--> folder_0
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_0 <-> folder_0
- assertItem(child2, 1, 0, 0, 0, 1, "folder_1", .orphan, 10)
- assertItem(child2.linkedItem, 0, 1, 0, 0, 1, "folder_1", .orphan, 4)
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 1, 0, 0, 0, 0, "file_1.txt", .old, 10)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "file_1.txt", .changed, 4)
-
- let childVI4 = childVI1.children[1] // folder_0 <--> folder_0
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_0 <-> folder_0
- assertItem(child4, 0, 1, 0, 0, 0, "file_2.txt", .changed, 10)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_2.txt", .old, 7)
-
- let childVI5 = childVI1.children[2] // folder_0 <--> folder_0
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_0 <-> folder_0
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_3.h", .orphan, 3)
-
- let childVI6 = childVI1.children[3] // folder_0 <--> folder_0
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_0 <-> folder_0
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file_3.m", .orphan, 2)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- // src is on right so folders are inverted
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child1.linkedItem!,
- srcBaseDir: appendFolder("r"),
- destBaseDir: appendFolder("l")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 1, 0, 3, 4, "folder_0", .orphan, 19)
- assertItem(child1.linkedItem, 1, 0, 0, 3, 4, "folder_0", .orphan, 16)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 1, 1, "folder_1", .orphan, 4)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "folder_1", .orphan, 4)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 1, 0, "file_1.txt", .same, 4)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "file_1.txt", .same, 4)
-
- child4 = child1.children[1]
- assertItem(child4, 0, 1, 0, 0, 0, "file_2.txt", .changed, 10)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_2.txt", .old, 7)
-
- child5 = child1.children[2]
- assertItem(child5, 0, 0, 0, 1, 0, "file_3.h", .same, 3)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file_3.h", .same, 3)
-
- child6 = child1.children[3]
- assertItem(child6, 0, 0, 0, 1, 0, "file_3.m", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file_3.m", .same, 2)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 4)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 1, 0, 3, 4, "folder_0", .orphan, 19)
- assertItem(child1.linkedItem, 1, 0, 0, 3, 4, "folder_0", .orphan, 16)
-
- let childVI2 = childVI1.children[0] // folder_0 <--> folder_0
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_0 <-> folder_0
- assertItem(child2, 0, 0, 0, 1, 1, "folder_1", .orphan, 4)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "folder_1", .orphan, 4)
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 1, 0, "file_1.txt", .same, 4)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "file_1.txt", .same, 4)
-
- let childVI4 = childVI1.children[1] // folder_0 <--> folder_0
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_0 <-> folder_0
- assertItem(child4, 0, 1, 0, 0, 0, "file_2.txt", .changed, 10)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_2.txt", .old, 7)
-
- let childVI5 = childVI1.children[2] // folder_0 <--> folder_0
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_0 <-> folder_0
- assertItem(child5, 0, 0, 0, 1, 0, "file_3.h", .same, 3)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file_3.h", .same, 3)
-
- let childVI6 = childVI1.children[3] // folder_0 <--> folder_0
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_0 <-> folder_0
- assertItem(child6, 0, 0, 0, 1, 0, "file_3.m", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file_3.m", .same, 2)
- }
- }
-
- @Test func copyOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/only_on_left")
- try createFolder("l/only_on_left/second_folder")
- try createFolder("l/only_on_left/second_folder/cartella senza titolo")
- try createFolder("l/only_on_left/second_folder/cartella senza titolo 2")
-
- try createFolder("r")
-
- // create files
- try createFile("l/only_on_left/second_folder/symlinks copia.zip", "12345")
- try createFile("l/only_on_left/symlinks.zip", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- var child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, "symlinks copia.zip", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child6 = child1.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, "symlinks.zip", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child2,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, "only_on_left", .orphan, 0)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "second_folder", .orphan, 0)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
-
- child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
-
- child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, "symlinks copia.zip", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child6 = child1.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, "symlinks.zip", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, "only_on_left", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> only_on_left
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // only_on_left <-> only_on_left
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "second_folder", .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> second_folder
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> second_folder
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> second_folder
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> second_folder
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- }
- }
-
- @Test func copyFilesPresentOnBothSidesWithFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
- try createFolder("l/folder_1/folder_1_2")
-
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
- try createFolder("r/folder_1/folder_1_2")
-
- // create files
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_changed.m", "12345")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.txt", "1234")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "12345")
- try createFile("l/folder_1/folder_1_2/match_2_1.m", "12")
- try createFile("l/folder_1/file.txt", "1")
-
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.txt", "1234")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.txt", "1")
- try createFile("r/folder_1/folder_1_2/match_2_1.m", "12")
- try createFile("r/folder_1/file.txt", "1")
- try createFile("r/folder_1/right_orphan.txt", "1234567")
-
- try setFileTimestamp("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "2001-03-24 10: 45: 32 +0600")
- try setFileTimestamp("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let l = rootL.children[0]
- assertItem(l, 1, 1, 0, 3, 4, "folder_1", .orphan, 17)
- assertItem(l.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 16)
-
- var child1 = l.children[0]
- assertItem(child1, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 14)
- assertItem(child1.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 6)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 14)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 6)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 1, 0, 0, 0, "file_changed.m", .changed, 5)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 1)
-
- var child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.txt", .same, 4)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 4)
-
- var child5 = child2.children[2]
- assertItem(child5, 1, 0, 0, 0, 0, "file_older.txt", .old, 5)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
-
- var child6 = l.children[1]
- assertItem(child6, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- var child7 = child6.children[0]
- assertItem(child7, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- var child8 = l.children[2]
- assertItem(child8, 0, 0, 0, 1, 0, "file.txt", .same, 1)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 1)
-
- var child9 = l.children[3]
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
-
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 1, 1, 0, 3, 1, "l", .orphan, 17)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 1, 1, 3, 1, "r", .orphan, 16)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 1, 1, 0, 3, 4, "folder_1", .orphan, 17)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 16)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 14)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 6)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // folder_1_1 <-> folder_1_1
- assertItem(child4, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 14)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 6)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 1, 0, 0, 0, "file_changed.m", .changed, 5)
- assertItem(child5.linkedItem!, 1, 0, 0, 0, 0, "file_changed.m", .old, 1)
-
- let childVI6 = childVI4.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_2_1 <-> folder_2_1
- assertItem(child6, 1, 0, 0, 0, 0, "file_older.txt", .old, 5)
- assertItem(child6.linkedItem!, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
-
- let childVI7 = childVI2.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child1,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 5, 4, "folder_1", .orphan, 17)
- assertItem(child1.linkedItem, 0, 0, 1, 5, 4, "folder_1", .orphan, 24)
-
- child2 = child1.children[0] // folder_1
- assertItem(child2, 0, 0, 0, 3, 1, "folder_1_1", .orphan, 14)
- assertItem(child2.linkedItem, 0, 0, 0, 3, 1, "folder_1_1", .orphan, 14)
-
- child3 = child2.children[0] // folder_1_1
- assertItem(child3, 0, 0, 0, 3, 3, "folder_2_1", .orphan, 14)
- assertItem(child3.linkedItem, 0, 0, 0, 3, 3, "folder_2_1", .orphan, 14)
-
- child4 = child3.children[0] // folder_2_1
- assertItem(child4, 0, 0, 0, 1, 0, "file_changed.m", .same, 5)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_changed.m", .same, 5)
-
- child5 = child3.children[1] // folder_2_1
- assertItem(child5, 0, 0, 0, 1, 0, "file_matched.txt", .same, 4)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 4)
-
- child6 = child3.children[2] // folder_2_1
- assertItem(child6, 0, 0, 0, 1, 0, "file_older.txt", .same, 5)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file_older.txt", .same, 5)
-
- child7 = child1.children[1] // folder_1
- assertItem(child7, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- child8 = child7.children[0] // folder_1_2
- assertItem(child8, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- child9 = child1.children[2] // folder_1
- assertItem(child9, 0, 0, 0, 1, 0, "file.txt", .same, 1)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 1)
-
- let child10 = child1.children[3] // folder_1
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 5, 1, "l", .orphan, 17)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 1, 5, 1, "r", .orphan, 24)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 5, 4, "folder_1", .orphan, 17)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 1, 5, 4, "folder_1", .orphan, 24)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
- }
-
- @Test func copyDontFollowSymLink() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder1")
- try createFolder("l/folder1/folder2")
- try createFolder("l/folder1/folder2/folder3")
- try createSymlink("l/folder1/folder2/symlink1", "symlink_test1")
-
- try createFolder("r/folder1")
- try createFolder("r/folder1/folder2")
-
- // folders out of comparison but used to create symlinks to them
- try createFolder("symlink_test1")
- try createFolder("symlink_test2")
-
- // create files
- try createSymlink("r/folder1/folder2/folder3", "symlink_test1")
- try createSymlink("r/folder1/folder2/symlink1", "symlink_test2")
- try createSymlink("r/folder1/folder2/orphan_symlink", "symlink_test2")
-
- try createFile("symlink_test1/file1.txt", "12345")
- try createFile("symlink_test2/file2.txt", "123")
- try createFile("r/folder1/folder2/sample.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
-
- var child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
-
- var child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child4 = child2.children[1] // folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
-
- var child5 = child2.children[2] // folder2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
-
- var child6 = child2.children[3] // folder2
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
-
- var child7 = child2.children[4] // folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 4)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // folder2 <--> folder2
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder2 <-> folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
-
- let childVI5 = childVI2.children[2] // folder2 <--> folder2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder2 <-> folder2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
-
- let childVI6 = childVI2.children[3] // folder2 <--> folder2
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder2 <-> folder2
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: true
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child2.linkedItem!,
- srcBaseDir: appendFolder("r"),
- destBaseDir: appendFolder("l")
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
-
- child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 1, 5, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 5, "folder2", .orphan, 2)
-
- child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child4 = child2.children[1] // folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- try assertSymlink(child4.linkedItem!, "symlink_test1", true)
-
- child5 = child2.children[2] // folder2
- assertItem(child5, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
- try assertSymlink(child5, "symlink_test2", true)
- try assertSymlink(child5.linkedItem!, "symlink_test2", true)
-
- child6 = child2.children[3] // folder2
- assertItem(child6, 0, 0, 0, 1, 0, "sample.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "sample.txt", .same, 2)
-
- child7 = child2.children[4] // folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- try assertSymlink(child7, "symlink_test2", true)
- try assertSymlink(child7.linkedItem!, "symlink_test2", true)
-
- assertErrors(fileOperationDelegate.errors, [
- FileError.createSymLink(path: child3.path!),
- ])
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 1, 5, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 5, "folder2", .orphan, 2)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // folder2 <--> folder2
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder2 <-> folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- }
- }
-
- @Test func copyFollowSymLink() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder1")
- try createFolder("l/folder1/folder2")
- try createFolder("l/folder1/folder2/folder3")
- try createSymlink("l/folder1/folder2/symlink1", "symlink_test1")
-
- try createFolder("r/folder1")
- try createFolder("r/folder1/folder2")
-
- // folders out of comparison but used to create symlinks to them
- try createFolder("symlink_test1")
- try createFolder("symlink_test2")
-
- // create files
- try createSymlink("r/folder1/folder2/folder3", "symlink_test1")
- try createSymlink("r/folder1/folder2/symlink1", "symlink_test2")
- try createSymlink("r/folder1/folder2/orphan_symlink", "symlink_test2")
-
- try createFile("symlink_test1/file1.txt", "12345")
- try createFile("symlink_test1/file2.txt", "123")
- try createFile("symlink_test2/file2.txt", "123")
- try createFile("r/folder1/folder2/sample.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 1, 1, "folder1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 4, 1, 1, "folder1", .orphan, 16)
-
- var child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 1, 1, 4, "folder2", .orphan, 8)
- assertItem(child2.linkedItem, 0, 0, 4, 1, 4, "folder2", .orphan, 16)
-
- var child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 2, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 2, "folder3", .orphan, 8)
-
- var child4 = child3.children[0] // folder3
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
-
- var child5 = child3.children[1] // folder3
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 3)
-
- var child6 = child2.children[1] // folder2
- assertItem(child6, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 1, "orphan_symlink", .orphan, 3)
-
- var child7 = child6.children[0] // (null)
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 3)
-
- var child8 = child2.children[2] // folder2
- assertItem(child8, 0, 0, 1, 1, 2, "symlink1", .orphan, 8)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 2, "symlink1", .orphan, 3)
-
- var child9 = child8.children[0] // symlink1
- assertItem(child9, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child10 = child8.children[1] // symlink1
- assertItem(child10, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
-
- var child11 = child2.children[3] // folder2
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 1, 1, "folder1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 4, 1, 1, "folder1", .orphan, 16)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 4)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 1, 1, 4, "folder2", .orphan, 8)
- assertItem(child2.linkedItem, 0, 0, 4, 1, 4, "folder2", .orphan, 16)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 0, 2, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 2, "folder3", .orphan, 8)
-
- let childVI4 = childVI3.children[0] // folder3 <--> folder3
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder3 <-> folder3
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
-
- let childVI5 = childVI3.children[1] // folder3 <--> folder3
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder3 <-> folder3
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 3)
-
- let childVI6 = childVI2.children[1] // folder2 <--> folder2
- assertArrayCount(childVI6.children, 1)
- let child6 = childVI6.item // folder2 <-> folder2
- assertItem(child6, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 1, "orphan_symlink", .orphan, 3)
-
- let childVI7 = childVI6.children[0] // (null) <--> orphan_symlink
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // (null) <-> orphan_symlink
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 3)
-
- let childVI8 = childVI2.children[2] // folder2 <--> folder2
- assertArrayCount(childVI8.children, 1)
- let child8 = childVI8.item // folder2 <-> folder2
- assertItem(child8, 0, 0, 1, 1, 2, "symlink1", .orphan, 8)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 2, "symlink1", .orphan, 3)
-
- let childVI9 = childVI8.children[0] // symlink1 <--> symlink1
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // symlink1 <-> symlink1
- assertItem(child9, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI10 = childVI2.children[3] // folder2 <--> folder2
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // folder2 <-> folder2
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child2.linkedItem!,
- srcBaseDir: appendFolder("r"),
- destBaseDir: appendFolder("l")
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 5, 1, "folder1", .orphan, 21)
- assertItem(child1.linkedItem, 0, 0, 0, 5, 1, "folder1", .orphan, 16)
-
- child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 1, 5, 4, "folder2", .orphan, 21)
- assertItem(child2.linkedItem, 0, 0, 0, 5, 4, "folder2", .orphan, 16)
-
- child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 2, 2, "folder3", .orphan, 8)
- assertItem(child3.linkedItem, 0, 0, 0, 2, 2, "folder3", .orphan, 8)
-
- child4 = child3.children[0] // folder3
- assertItem(child4, 0, 0, 0, 1, 0, "file1.txt", .same, 5)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 5)
-
- child5 = child3.children[1] // folder3
- assertItem(child5, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
-
- child6 = child2.children[1] // folder2
- assertItem(child6, 0, 0, 0, 1, 1, "orphan_symlink", .orphan, 3)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 1, "orphan_symlink", .orphan, 3)
-
- child7 = child6.children[0] // orphan_symlink
- assertItem(child7, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
-
- child8 = child2.children[2] // folder2
- assertItem(child8, 0, 0, 1, 1, 2, "symlink1", .orphan, 8)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 2, "symlink1", .orphan, 3)
-
- child9 = child8.children[0] // symlink1
- assertItem(child9, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child10 = child8.children[1] // symlink1
- assertItem(child10, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 3)
-
- child11 = child2.children[3] // folder2
- assertItem(child11, 0, 0, 0, 1, 0, "sample.txt", .same, 2)
- assertItem(child11.linkedItem, 0, 0, 0, 1, 0, "sample.txt", .same, 2)
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 1, 5, 1, "l", .orphan, 21)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 5, 1, "r", .orphan, 16)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 1, 5, 1, "folder1", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 5, 1, "folder1", .orphan, 16)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder1 <--> folder1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder1 <-> folder1
- assertItem(child3, 0, 0, 1, 5, 4, "folder2", .orphan, 21)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 5, 4, "folder2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // folder2 <--> folder2
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // folder2 <-> folder2
- assertItem(child4, 0, 0, 1, 1, 2, "symlink1", .orphan, 8)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 0, 1, 2, "symlink1", .orphan, 3)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // symlink1 <--> symlink1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // symlink1 <-> symlink1
- assertItem(child5, 0, 0, 1, 0, 0, "file1.txt", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func copyFailure() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("l/dir1/dir2/dir3")
-
- // create files
- try createFile("l/dir1/dir2/dir3/file1.txt", "1234567")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- // simulate a copy error deleting the file to copy
- do {
- try fm.removeItem(atPath: child4.path!)
- } catch {
- Issue.record("Found error \(error)")
- }
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // dir2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // dir2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // dir3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child4,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0] // l
- do {
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // dir2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // dir2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // dir3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func copyPreserveFolderTimestamp() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/folder1/folder2/folder3")
- try createFolder("r/folder1")
-
- try createFile("l/folder1/folder2/folder3/file1.txt", "12")
-
- try setFileCreationTime("l/folder1", "2010-01-01 00: 00: 00 +0000")
- try setFileTimestamp("l/folder1", "2010-02-02 02: 02: 00 +0000")
-
- try setFileCreationTime("l/folder1/folder2", "2010-04-04 04: 04: 00 +0000")
- try setFileTimestamp("l/folder1/folder2", "2010-05-05 05: 05: 00 +0000")
-
- try setFileCreationTime("l/folder1/folder2/folder3", "2011-05-05 05: 00: 30 +0000")
- try setFileTimestamp("l/folder1/folder2/folder3", "2011-06-06 06: 00: 30 +0000")
-
- try setFileCreationTime("l/folder1/folder2/folder3/file1.txt", "2012-07-07 09: 09: 00 +0000")
- try setFileTimestamp("l/folder1/folder2/folder3/file1.txt", "2012-08-08 10: 10: 10 +0000")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 1, 0, 1, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 1, 0, 1, "folder3", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // folder3
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 1, 0, 1, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // folder2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "folder3", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // folder3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: child1,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
- try assertTimestamps(child1.linkedItem, "2010-01-01 00: 00: 00 +0000", "2010-02-02 02: 02: 00 +0000")
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 1, 1, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "folder2", .orphan, 2)
- try assertTimestamps(child2.linkedItem, "2010-04-04 04: 04: 00 +0000", "2010-05-05 05: 05: 00 +0000")
-
- let child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 1, 1, "folder3", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "folder3", .orphan, 2)
- try assertTimestamps(child3.linkedItem, "2011-05-05 05: 00: 30 +0000", "2011-06-06 06: 00: 30 +0000")
-
- let child4 = child3.children[0] // folder3
- assertItem(child4, 0, 0, 0, 1, 0, "file1.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 2)
- try assertTimestamps(child4.linkedItem, "2012-07-07 09: 09: 00 +0000", "2012-08-08 10: 10: 10 +0000")
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "folder1", .orphan, 2)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 1, 1, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "folder2", .orphan, 2)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 1, 1, "folder3", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "folder3", .orphan, 2)
-
- let childVI4 = childVI3.children[0] // folder3 <--> folder3
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder3 <-> folder3
- assertItem(child4, 0, 0, 0, 1, 0, "file1.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 2)
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/DeleteFileTests.swift b/Tests/Sources/FileSystem/Tests/DeleteFileTests.swift
deleted file mode 100644
index c432e3f..0000000
--- a/Tests/Sources/FileSystem/Tests/DeleteFileTests.swift
+++ /dev/null
@@ -1,1069 +0,0 @@
-//
-// DeleteFileTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class DeleteFileTests: BaseTests {
- /**
- * Delete folder with files on right: there is an orphan file and a newer file
- */
- @Test func deleteCreatingOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/a/bb/ccc")
- try createFolder("r/a/bb/ccc")
-
- try createFile("l/a/bb/ccc/second.txt", "123456789012")
-
- try createFile("r/a/bb/ccc/file.txt", "123")
- try createFile("r/a/bb/ccc/second.txt", "12345678")
-
- try setFileTimestamp("l/a/bb/ccc/second.txt", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- let vi = rootL.visibleItem!
-
- var l = rootL.children[0]
- assertItem(l, 1, 0, 0, 0, 1, "a", .orphan, 12)
- assertItem(l.linkedItem, 0, 1, 1, 0, 1, "a", .orphan, 11)
-
- var child1 = l.children[0]
- assertItem(child1, 1, 0, 0, 0, 1, "bb", .orphan, 12)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 1, "bb", .orphan, 11)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 0, 0, 0, 2, "ccc", .orphan, 12)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 2, "ccc", .orphan, 11)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 3)
-
- let child4 = child2.children[1]
- assertItem(child4, 1, 0, 0, 0, 0, "second.txt", .old, 12)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "second.txt", .changed, 8)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 0, 0, 0, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 1, "a", .orphan, 11)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 1, 0, 0, 0, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 1, "bb", .orphan, 11)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 1, 0, 0, 0, 2, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 1, 1, 0, 2, "ccc", .orphan, 11)
-
- let childVI4 = childVI3.children[0] // ccc <--> ccc
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // ccc <-> ccc
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file.txt", .orphan, 3)
-
- let childVI5 = childVI3.children[1] // ccc <--> ccc
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // ccc <-> ccc
- assertItem(child5, 1, 0, 0, 0, 0, "second.txt", .old, 12)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "second.txt", .changed, 8)
- }
-
- try assertOnlySetup()
-
- let fileOperaionDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperaionDelegate
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child2.linkedItem!,
- baseDir: appendFolder("r")
- )
-
- l = rootL.children[0]
- assertItem(l, 0, 0, 1, 0, 1, "a", .orphan, 12)
- assertItem(l.linkedItem, 0, 0, 0, 0, 1, "a", .orphan, 0)
-
- child1 = l.children[0]
- assertItem(child1, 0, 0, 1, 0, 1, "bb", .orphan, 12)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "bb", .orphan, 0)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 1, 0, 1, "ccc", .orphan, 12)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 1, 0, 0, "second.txt", .orphan, 12)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "a", .orphan, 12)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "a", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 0, 0, 1, 0, 1, "bb", .orphan, 12)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "bb", .orphan, 0)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 0, 0, 1, 0, 1, "ccc", .orphan, 12)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // ccc <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // ccc <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "second.txt", .orphan, 12)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- /**
- * Delete the folder on left including filtered files
- * Folder is orphan
- */
- @Test func deleteOrphanWithFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- try createFolder("l/only_on_left/second_folder/subfolder1")
- try createFolder("l/only_on_left/second_folder/subfolder2")
-
- try createFile("l/only_on_left/second_folder/test1.zip", "123456789")
- try createFile("l/only_on_left/test2.zip", "123456789")
- try createFile("l/.DS_Store", "1234567890123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var l = rootL.children[0]
- assertItem(l, 0, 0, 0, 0, 2, "only_on_left", .orphan, 18)
- assertItem(l.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let child1 = l.children[0]
- assertItem(child1, 0, 0, 0, 0, 3, "second_folder", .orphan, 9)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 0, "subfolder1", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1]
- assertItem(child3, 0, 0, 0, 0, 0, "subfolder2", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child1.children[2]
- assertItem(child4, 0, 0, 0, 0, 0, "test1.zip", .orphan, 9)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child5 = l.children[1]
- assertItem(child5, 0, 0, 0, 0, 0, "test2.zip", .orphan, 9)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child6 = rootL.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, ".DS_Store", .orphan, 13)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 18)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 3)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 9)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "subfolder1", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "subfolder2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI2.children[2] // second_folder <--> (null)
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // second_folder <-> (null)
- assertItem(child5, 0, 0, 0, 0, 0, "test1.zip", .orphan, 9)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[1] // only_on_left <--> (null)
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // only_on_left <-> (null)
- assertItem(child6, 0, 0, 0, 0, 0, "test2.zip", .orphan, 9)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child1,
- baseDir: appendFolder("l/only_on_left/second_folder")
- )
-
- l = rootL.children[0]
- assertItem(l, 0, 0, 0, 0, 1, "only_on_left", .orphan, 9)
- assertItem(l.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- child5 = l.children[0]
- assertItem(child5, 0, 0, 0, 0, 0, "test2.zip", .orphan, 9)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child6 = rootL.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, ".DS_Store", .orphan, 13)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "only_on_left", .orphan, 9)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 0, "test2.zip", .orphan, 9)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- /**
- * Delete the folder on left, filtered files remain
- * Folder is orphan
- */
- @Test func deleteOrphanLeaveFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l")
- try createFolder("r")
-
- try createFolder("l/only_on_left/second_folder/subfolder1")
- try createFolder("l/only_on_left/second_folder/subfolder2")
- try createFile("l/only_on_left/second_folder/test1.zip", "12345")
- try createFile("l/only_on_left/test2.zip", "12")
- try createFile("l/.DS_Store", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var l = rootL.children[0]
- assertItem(l, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(l.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- var child1 = l.children[0]
- assertItem(child1, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- var child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 0, "subfolder1", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child3 = child1.children[1]
- assertItem(child3, 0, 0, 0, 0, 0, "subfolder2", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child1.children[2]
- assertItem(child4, 0, 0, 0, 0, 0, "test1.zip", .orphan, 5)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child5 = l.children[1]
- assertItem(child5, 0, 0, 0, 0, 0, "test2.zip", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child6 = rootL.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, ".DS_Store", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 3)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "subfolder1", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "subfolder2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI2.children[2] // second_folder <--> (null)
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // second_folder <-> (null)
- assertItem(child5, 0, 0, 0, 0, 0, "test1.zip", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[1] // only_on_left <--> (null)
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // only_on_left <-> (null)
- assertItem(child6, 0, 0, 0, 0, 0, "test2.zip", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child1,
- baseDir: appendFolder("l/only_on_left/second_folder")
- )
-
- l = rootL.children[0]
- assertItem(l, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(l.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- child1 = l.children[0]
- assertItem(child1, 0, 0, 0, 0, 1, "second_folder", .orphan, 5)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 0, "test1.zip", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child5 = l.children[1]
- assertItem(child5, 0, 0, 0, 0, 0, "test2.zip", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child6 = rootL.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, ".DS_Store", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 1, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "test1.zip", .orphan, 5)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI1.children[1] // only_on_left <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // only_on_left <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "test2.zip", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func deleteFilesPresentOnBothSides() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
- try createFolder("l/folder_1/folder_1_2")
-
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
- try createFolder("r/folder_1/folder_1_2")
-
- // create files
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_changed.m", "123456")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "123")
- try createFile("l/folder_1/folder_1_2/match_2_1.m", "1234")
- try createFile("l/folder_1/file.txt", "1")
-
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1234")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.txt", "1")
- try createFile("r/folder_1/folder_1_2/match_2_1.m", "1234")
- try createFile("r/folder_1/file.txt", "1")
- try createFile("r/folder_1/right_orphan.txt", "1234567")
-
- try setFileTimestamp("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "2001-03-24 10: 45: 32 +0600")
- try setFileTimestamp("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let l = rootL.children[0]
- assertItem(l, 1, 1, 0, 3, 4, "folder_1", .orphan, 16)
- assertItem(l.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 19)
-
- let child1 = l.children[0]
- assertItem(child1, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 11)
- assertItem(child1.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 7)
-
- let child2 = child1.children[0]
- assertItem(child2, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 11)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 7)
-
- let child3 = child2.children[0]
- assertItem(child3, 0, 1, 0, 0, 0, "file_changed.m", .changed, 6)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 4)
-
- let child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
-
- let child5 = child2.children[2]
- assertItem(child5, 1, 0, 0, 0, 0, "file_older.txt", .old, 3)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
-
- let child6 = l.children[1]
- assertItem(child6, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
-
- let child7 = child6.children[0]
- assertItem(child7, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
-
- let child8 = l.children[2]
- assertItem(child8, 0, 0, 0, 1, 0, "file.txt", .same, 1)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 1)
-
- let child9 = l.children[3]
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
-
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 1, 1, 0, 3, 1, "l", .orphan, 16)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 1, 1, 3, 1, "r", .orphan, 19)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 1, 1, 0, 3, 4, "folder_1", .orphan, 16)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 19)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 11)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 7)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // folder_1_1 <-> folder_1_1
- assertItem(child4, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 11)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 7)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 1, 0, 0, 0, "file_changed.m", .changed, 6)
- assertItem(child5.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 4)
-
- let childVI6 = childVI4.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_2_1 <-> folder_2_1
- assertItem(child6, 1, 0, 0, 0, 0, "file_older.txt", .old, 3)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
-
- let childVI7 = childVI2.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child1,
- baseDir: appendFolder("l")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 7)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 3, 1, "r", .orphan, 19)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 3, 4, "folder_1", .orphan, 7)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 3, 4, "folder_1", .orphan, 19)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 7)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // folder_1_1 <-> folder_1_1
- assertItem(child4, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 7)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let child5 = child4.children[0] // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 4)
-
- let child6 = child4.children[1] // folder_2_1 <-> folder_2_1
- assertItem(child6, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
-
- let child7 = child4.children[2] // folder_2_1 <-> folder_2_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 1)
-
- let child8 = child2.children[1] // folder_1 <-> folder_1
- assertItem(child8, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
- #expect(child8.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let child9 = child8.children[0] // folder_1_2 <-> folder_1_2
- assertItem(child9, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
-
- let child10 = child2.children[2] // folder_1 <-> folder_1
- assertItem(child10, 0, 0, 0, 1, 0, "file.txt", .same, 1)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 1)
-
- let child11 = child2.children[3] // folder_1 <-> folder_1
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 7)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 3, 1, "r", .orphan, 19)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 3, 4, "folder_1", .orphan, 7)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 3, 4, "folder_1", .orphan, 19)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 7)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // folder_1_1 <-> folder_1_1
- assertItem(child4, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 7)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 4)
-
- let childVI6 = childVI4.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_2_1 <-> folder_2_1
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 1)
-
- let childVI7 = childVI2.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
- }
-
- @Test func deleteDontFollowSymLink() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder1")
- try createFolder("l/folder1/folder2")
-
- try createFolder("r/folder1")
-
- // folders out of comparison but used to create symlinks to them
- try createFolder("symlink_test1")
- try createFolder("symlink_test2")
-
- // create files
- try createSymlink("l/folder1/folder2/folder3", "symlink_test2")
- try createSymlink("l/folder1/folder2/symlink1", "symlink_test1")
-
- try createFile("symlink_test1/file1.txt", "12345")
- try createFile("symlink_test1/file1_1.txt", "12")
- try createFile("symlink_test2/file2.txt", "123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 0, 2, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- try assertSymlink(child3, "symlink_test2", true)
-
- let child4 = child2.children[1] // folder2
- assertItem(child4, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- try assertSymlink(child4, "symlink_test1", true)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 0, 2, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // folder2 <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // folder2 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder2 <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child2,
- baseDir: appendFolder("l")
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 0, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 0, "folder1", .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 0)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 0, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 0, "folder1", .orphan, 0)
- }
- }
-
- @Test func deleteFolderCreatingOnlyOrphans() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
- try createFolder("l/dir1/dir2/dir3")
- try createFolder("r/dir1/dir2/dir3")
-
- // create files
- try createFile("l/dir1/dir2/dir3/file_2.txt", "1234567890")
- try createFile("r/dir1/dir2/dir3/file_2.txt", "1234567890")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 1, 1, "dir1", .orphan, 10)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "dir1", .orphan, 10)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 0, 1, 1, "dir2", .orphan, 10)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "dir2", .orphan, 10)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 1, 1, "dir3", .orphan, 10)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "dir3", .orphan, 10)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 0, 1, 0, "file_2.txt", .same, 10)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_2.txt", .same, 10)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- child2.linkedItem!,
- baseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 10)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 10)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 10)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 1, 0, 0, "file_2.txt", .orphan, 10)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 10)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 10)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // dir2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // dir2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 10)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // dir3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file_2.txt", .orphan, 10)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/DisplayTests.swift b/Tests/Sources/FileSystem/Tests/DisplayTests.swift
deleted file mode 100644
index bcc1752..0000000
--- a/Tests/Sources/FileSystem/Tests/DisplayTests.swift
+++ /dev/null
@@ -1,322 +0,0 @@
-//
-// DisplayTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping function_body_length
-final class DisplayTests: BaseTests {
- @Test("Bug 0000170: Display filter set to 'No Orphan' hides not matching files") func displayFilterNoOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .noOrphan
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- // create folders
- try createFolder("l/dir050")
- try createFolder("r/dir050")
- try createFolder("l/dir050/dir100")
- try createFolder("r/dir050/dir100")
- try createFolder("r/dir050/dir100/dir110")
- try createFolder("l/dir050/dir100/dir120")
- try createFolder("r/dir050/dir100/dir120")
-
- // create files
- try createFile("r/dir050/dir100/dir110/file101.txt", "12")
- try createFile("l/dir050/dir100/dir120/file101.txt", "12")
- try createFile("r/dir050/dir100/dir120/file101.txt", "12")
- try createFile("l/dir050/dir100/dir120/file102.txt", "123456")
- try setFileTimestamp("l/dir050/dir100/dir120/file102.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/dir050/dir100/dir120/file102.txt", "123")
- try createFile("l/dir050/dir100/dir120/file103.txt", "12")
- try createFile("r/dir050/dir100/dir120/file103.txt", "12")
- try createFile("l/dir050/dir100/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 1, 0, 1, 2, 1, "dir050", .orphan, 16)
- assertItem(child1.linkedItem, 0, 1, 1, 2, 1, "dir050", .orphan, 9)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 1, 0, 1, 2, 3, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 1, 2, 3, "dir100", .orphan, 9)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 1, "dir110", .orphan, 2)
-
- let child4 = child3.children[0] // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child5 = child2.children[1] // dir100 <-> dir100
- assertItem(child5, 1, 0, 0, 2, 3, "dir120", .orphan, 10)
- assertItem(child5.linkedItem, 0, 1, 0, 2, 3, "dir120", .orphan, 7)
-
- let child6 = child5.children[0] // dir120 <-> dir120
- assertItem(child6, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
-
- let child7 = child5.children[1] // dir120 <-> dir120
- assertItem(child7, 1, 0, 0, 0, 0, "file102.txt", .old, 6)
- assertItem(child7.linkedItem, 0, 1, 0, 0, 0, "file102.txt", .changed, 3)
-
- let child8 = child5.children[2] // dir120 <-> dir120
- assertItem(child8, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
-
- let child9 = child2.children[2] // dir100 <-> dir100
- assertItem(child9, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 0, 1, 2, 1, "dir050", .orphan, 16)
- assertItem(child1.linkedItem, 0, 1, 1, 2, 1, "dir050", .orphan, 9)
-
- let childVI2 = childVI1.children[0] // dir050 <--> dir050
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir050 <-> dir050
- assertItem(child2, 1, 0, 1, 2, 3, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 1, 2, 3, "dir100", .orphan, 9)
-
- let childVI3 = childVI2.children[0] // dir100 <--> dir100
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // dir100 <-> dir100
- assertItem(child3, 1, 0, 0, 2, 3, "dir120", .orphan, 10)
- assertItem(child3.linkedItem, 0, 1, 0, 2, 3, "dir120", .orphan, 7)
-
- let childVI4 = childVI3.children[0] // dir120 <--> dir120
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir120 <-> dir120
- assertItem(child4, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
-
- let childVI5 = childVI3.children[1] // dir120 <--> dir120
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // dir120 <-> dir120
- assertItem(child5, 1, 0, 0, 0, 0, "file102.txt", .old, 6)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file102.txt", .changed, 3)
-
- let childVI6 = childVI3.children[2] // dir120 <--> dir120
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // dir120 <-> dir120
- assertItem(child6, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
- }
- }
-
- @Test func displayNoOrphanShowEmptyFolders() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyOrphans
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/folder_1")
- try createFolder("r/folder_1")
- try createFolder("l/folder_1/folder_1_1")
- try createFolder("r/folder_1/folder_1_1")
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
- try createFolder("l/folder_1/folder_1_2")
- try createFolder("r/folder_1/folder_1_2")
-
- // create files
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1234")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.txt", "1")
- try createFile("l/folder_1/folder_1_2/match_2_1.m", "1234")
- try createFile("r/folder_1/folder_1_2/match_2_1.m", "1234")
- try createFile("l/folder_1/file.txt", "1")
- try createFile("r/folder_1/file.txt", "1")
- try createFile("r/folder_1/right_orphan.txt", "1234567")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 7)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 3, 1, "r", .orphan, 19)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 3, 4, "folder_1", .orphan, 7)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 3, 4, "folder_1", .orphan, 19)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 7)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // folder_1_1 <-> folder_1_1
- assertItem(child4, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 7)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let child5 = child4.children[0] // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 4)
-
- let child6 = child4.children[1] // folder_2_1 <-> folder_2_1
- assertItem(child6, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
-
- let child7 = child4.children[2] // folder_2_1 <-> folder_2_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 1)
-
- let child8 = child2.children[1] // folder_1 <-> folder_1
- assertItem(child8, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
- #expect(child8.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 4)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let child9 = child8.children[0] // folder_1_2 <-> folder_1_2
- assertItem(child9, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 4)
-
- let child10 = child2.children[2] // folder_1 <-> folder_1
- assertItem(child10, 0, 0, 0, 1, 0, "file.txt", .same, 1)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 1)
-
- let child11 = child2.children[3] // folder_1 <-> folder_1
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
-
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 7)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 3, 1, "r", .orphan, 19)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 3, 4, "folder_1", .orphan, 7)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 3, 4, "folder_1", .orphan, 19)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder_1 <-> folder_1
- assertItem(child3, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 7)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // folder_1_1 <-> folder_1_1
- assertItem(child4, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 7)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 4)
-
- let childVI6 = childVI4.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_2_1 <-> folder_2_1
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 1)
-
- let childVI7 = childVI2.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 7)
- }
- }
-}
-
-// swiftlint:enable force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/EmptyFolderColorTests.swift b/Tests/Sources/FileSystem/Tests/EmptyFolderColorTests.swift
deleted file mode 100644
index 3e98d89..0000000
--- a/Tests/Sources/FileSystem/Tests/EmptyFolderColorTests.swift
+++ /dev/null
@@ -1,1075 +0,0 @@
-//
-// EmptyFolderColorTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 02/11/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class EmptyFolderColorTests: BaseTests {
- @Test func initialColors() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/empty")
- try createFolder("r/empty")
- try createFolder("r/empty/empty1")
- try createFolder("r/empty/empty1/empty2")
- try createFolder("r/empty/empty1/empty2/empty3")
- try createFolder("r/empty/empty2")
- try createFolder("r/empty/empty3")
- try createFolder("l/utils")
- try createFolder("r/utils")
- try createFolder("l/utils/cell")
- try createFolder("r/utils/cell")
- try createFolder("l/utils/cell/popup")
- try createFolder("r/utils/cell/popup")
- try createFolder("l/utils/view")
- try createFolder("l/utils/view/splitview")
-
- // create files
- try createFile("l/utils/cell/popup/file", "12345")
- try createFile("r/utils/cell/popup/file", "123456")
- try setFileTimestamp("r/utils/cell/popup/file", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/file", "1234")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let child5 = child4.children[0] // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let child6 = child2.children[1] // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let child7 = child2.children[2] // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let child9 = child8.children[0] // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let child10 = child9.children[0] // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let child11 = child10.children[0] // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let child12 = child8.children[1] // utils <-> utils
- assertItem(child12, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.orphanFolders)")
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child13 = child12.children[0] // view <-> (null)
- assertItem(child13, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.orphanFolders)")
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[2] // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 3)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 3)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // empty <--> empty
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // (null) <--> empty1
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // (null) <--> empty2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let childVI6 = childVI2.children[1] // empty <--> empty
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let childVI7 = childVI2.children[2] // empty <--> empty
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 2)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let childVI9 = childVI8.children[0] // utils <--> utils
- assertArrayCount(childVI9.children, 1)
- let child9 = childVI9.item // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let childVI10 = childVI9.children[0] // cell <--> cell
- assertArrayCount(childVI10.children, 1)
- let child10 = childVI10.item // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let childVI11 = childVI10.children[0] // popup <--> popup
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let childVI12 = childVI8.children[1] // utils <--> utils
- assertArrayCount(childVI12.children, 1)
- let child12 = childVI12.item // utils <-> utils
- assertItem(child12, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.orphanFolders)")
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI13 = childVI12.children[0] // view <--> (null)
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // view <-> (null)
- assertItem(child13, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.orphanFolders)")
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI14 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI14.children, 0)
- let child14 = childVI14.item // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
- }
-
- @Test func moveFolderWithChild() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/empty")
- try createFolder("r/empty")
- try createFolder("r/empty/empty1")
- try createFolder("r/empty/empty1/empty2")
- try createFolder("r/empty/empty1/empty2/empty3")
- try createFolder("r/empty/empty2")
- try createFolder("r/empty/empty3")
- try createFolder("l/utils")
- try createFolder("r/utils")
- try createFolder("l/utils/cell")
- try createFolder("r/utils/cell")
- try createFolder("l/utils/cell/popup")
- try createFolder("r/utils/cell/popup")
- try createFolder("l/utils/view")
- try createFolder("l/utils/view/splitview")
-
- // create files
- try createFile("l/utils/cell/popup/file", "12345")
- try createFile("r/utils/cell/popup/file", "123456")
- try setFileTimestamp("r/utils/cell/popup/file", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/file", "1234")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let child5 = child4.children[0] // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let child6 = child2.children[1] // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let child7 = child2.children[2] // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let child9 = child8.children[0] // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let child10 = child9.children[0] // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let child11 = child10.children[0] // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let child12 = child8.children[1] // utils <-> utils
- operationElement = child12
- assertItem(child12, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.orphanFolders)")
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child13 = child12.children[0] // view <-> (null)
- assertItem(child13, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.orphanFolders)")
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[2] // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 3)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 3)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // empty <--> empty
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // (null) <--> empty1
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // (null) <--> empty2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let childVI6 = childVI2.children[1] // empty <--> empty
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let childVI7 = childVI2.children[2] // empty <--> empty
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 2)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.linkedItem!.orphanFolders)")
-
- let childVI9 = childVI8.children[0] // utils <--> utils
- assertArrayCount(childVI9.children, 1)
- let child9 = childVI9.item // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let childVI10 = childVI9.children[0] // cell <--> cell
- assertArrayCount(childVI10.children, 1)
- let child10 = childVI10.item // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let childVI11 = childVI10.children[0] // popup <--> popup
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let childVI12 = childVI8.children[1] // utils <--> utils
- assertArrayCount(childVI12.children, 1)
- let child12 = childVI12.item // utils <-> utils
- assertItem(child12, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.orphanFolders)")
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI13 = childVI12.children[0] // view <--> (null)
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // view <-> (null)
- assertItem(child13, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.orphanFolders)")
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI14 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI14.children, 0)
- let child14 = childVI14.item // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
- fileOperation.move(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 7, "OrphanFolder: Expected count \(7) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let child5 = child4.children[0] // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let child6 = child2.children[1] // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let child7 = child2.children[2] // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.linkedItem!.orphanFolders)")
-
- let child9 = child8.children[0] // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let child10 = child9.children[0] // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let child11 = child10.children[0] // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let child12 = child8.children[1] // utils <-> utils
- assertItem(child12, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.linkedItem!.orphanFolders)")
-
- let child13 = child12.children[0] // (null) <-> view
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.linkedItem!.orphanFolders)")
-
- let child14 = child1.children[2] // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 3)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 0, 3, "l", .orphan, 5)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 1, 0, 3, "r", .orphan, 10)
- #expect(child1.linkedItem!.orphanFolders == 7, "OrphanFolder: Expected count \(7) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 3)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "empty", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 5, "OrphanFolder: Expected count \(5) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // empty <--> empty
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // empty <-> empty
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "empty1", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // (null) <--> empty1
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // (null) <-> empty1
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 1, "empty2", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child4.linkedItem!.orphanFolders)")
-
- let childVI5 = childVI4.children[0] // (null) <--> empty2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> empty2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child5.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child5.linkedItem!.orphanFolders)")
-
- let childVI6 = childVI2.children[1] // empty <--> empty
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // empty <-> empty
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "empty2", .orphan, 0)
- #expect(child6.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child6.linkedItem!.orphanFolders)")
-
- let childVI7 = childVI2.children[2] // empty <--> empty
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // empty <-> empty
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "empty3", .orphan, 0)
- #expect(child7.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child7.linkedItem!.orphanFolders)")
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 2)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 1, 0, 0, 2, "utils", .orphan, 5)
- #expect(child8.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child8.orphanFolders)")
- assertItem(child8.linkedItem, 1, 0, 0, 0, 2, "utils", .orphan, 6)
- #expect(child8.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child8.linkedItem!.orphanFolders)")
-
- let childVI9 = childVI8.children[0] // utils <--> utils
- assertArrayCount(childVI9.children, 1)
- let child9 = childVI9.item // utils <-> utils
- assertItem(child9, 0, 1, 0, 0, 1, "cell", .orphan, 5)
- #expect(child9.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.orphanFolders)")
- assertItem(child9.linkedItem, 1, 0, 0, 0, 1, "cell", .orphan, 6)
- #expect(child9.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child9.linkedItem!.orphanFolders)")
-
- let childVI10 = childVI9.children[0] // cell <--> cell
- assertArrayCount(childVI10.children, 1)
- let child10 = childVI10.item // cell <-> cell
- assertItem(child10, 0, 1, 0, 0, 1, "popup", .orphan, 5)
- #expect(child10.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.orphanFolders)")
- assertItem(child10.linkedItem, 1, 0, 0, 0, 1, "popup", .orphan, 6)
- #expect(child10.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child10.linkedItem!.orphanFolders)")
-
- let childVI11 = childVI10.children[0] // popup <--> popup
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // popup <-> popup
- assertItem(child11, 0, 1, 0, 0, 0, "file", .changed, 5)
- assertItem(child11.linkedItem, 1, 0, 0, 0, 0, "file", .old, 6)
-
- let childVI12 = childVI8.children[1] // utils <--> utils
- assertArrayCount(childVI12.children, 1)
- let child12 = childVI12.item // utils <-> utils
- assertItem(child12, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child12.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child12.linkedItem!.orphanFolders)")
-
- let childVI13 = childVI12.children[0] // (null) <--> view
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // (null) <-> view
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child13.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child13.linkedItem!.orphanFolders)")
-
- let childVI14 = childVI1.children[2] // l <--> r
- assertArrayCount(childVI14.children, 0)
- let child14 = childVI14.item // l <-> r
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file", .orphan, 4)
- }
- }
-
- @Test func copy() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/utils")
- try createFolder("r/utils")
- try createFolder("l/utils/view")
- try createFolder("l/utils/view/splitview")
-
- // create files
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // view <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // utils <--> utils
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // view <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // view <-> (null)
- operationElement = child4
- assertItem(child4, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
- fileOperation.copy(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // view <-> view
- assertItem(child4, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // utils <--> utils
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
-
- let childVI4 = childVI3.children[0] // view <--> view
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // view <-> view
- assertItem(child4, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "splitview", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- }
- }
-
- @Test func deleteFolder() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/utils")
- try createFolder("r/utils")
- try createFolder("l/utils/view")
- try createFolder("r/utils/view")
- try createFolder("r/utils/view/splitView")
-
- // create files
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.linkedItem!.orphanFolders)")
-
- let child4 = child3.children[0] // view <-> view
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "splitView", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // utils <--> utils
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, "view", .orphan, 0)
- #expect(child3.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.linkedItem!.orphanFolders)")
- operationElement = child3.linkedItem!
-
- let childVI4 = childVI3.children[0] // view <--> view
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // view <-> view
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "splitView", .orphan, 0)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
-
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
- fileOperation.delete(
- operationElement,
- baseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let child3 = child2.children[0] // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 0, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- #expect(child1.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "r", .orphan, 0)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "utils", .orphan, 0)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
-
- let childVI3 = childVI2.children[0] // utils <--> utils
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // utils <-> utils
- assertItem(child3, 0, 0, 0, 0, 0, "view", .orphan, 0)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/FiltersTests.swift b/Tests/Sources/FileSystem/Tests/FiltersTests.swift
deleted file mode 100644
index 5e9eddb..0000000
--- a/Tests/Sources/FileSystem/Tests/FiltersTests.swift
+++ /dev/null
@@ -1,127 +0,0 @@
-//
-// FiltersTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/09/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-final class FiltersTests: BaseTests {
- @Test func filterFileNameIgnoreCase() {
- let root = CompareItem(
- path: "/fakePath",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: nil
- )
- let item = CompareItem(
- path: "/fakePath/all_lower_case.txt",
- attrs: [.type: FileAttributeType.typeRegular],
- fileExtraOptions: [],
- parent: root
- )
-
- let filter = #"fileName ==[c] "ALL_LOWER_CASE.txt""#
- #expect(item.evaluate(filter: NSPredicate(format: filter)))
- }
-
- @Test() func filterFileNameCaseSensitive() {
- let root = CompareItem(
- path: "/fakePath",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: nil
- )
- let item = CompareItem(
- path: "/fakePath/all_lower_case.txt",
- attrs: [.type: FileAttributeType.typeRegular],
- fileExtraOptions: [],
- parent: root
- )
-
- let filter = #"fileName CONTAINS "ALL_LOWER_CASE.txt""#
- #expect(item.evaluate(filter: NSPredicate(format: filter)) == false)
- }
-
- @Test() func filterPathIgnoreCase() {
- let root = CompareItem(
- path: "/fakePath",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: nil
- )
- let dirName1 = CompareItem(
- path: "/fakePath/dirName1",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: root
- )
- let item = CompareItem(
- path: "/fakePath/dirName1/all_lower_case.txt",
- attrs: [.type: FileAttributeType.typeRegular],
- fileExtraOptions: [],
- parent: dirName1
- )
-
- let filter = #"pathRelativeToRoot CONTAINS[c] "DIRNAME1""#
- #expect(item.evaluate(filter: NSPredicate(format: filter)))
- }
-
- @Test() func filterPathCaseSensitive() {
- let root = CompareItem(
- path: "/fakePath",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: nil
- )
- let dirName1 = CompareItem(
- path: "/fakePath/dirName1",
- attrs: [.type: FileAttributeType.typeDirectory],
- fileExtraOptions: [],
- parent: root
- )
- let item = CompareItem(
- path: "/fakePath/dirName1/all_lower_case.txt",
- attrs: [.type: FileAttributeType.typeRegular],
- fileExtraOptions: [],
- parent: dirName1
- )
-
- let filter = #"pathRelativeToRoot CONTAINS "DIRNAME1""#
- #expect(item.evaluate(filter: NSPredicate(format: filter)) == false)
- }
-
- @Test func filterFileSize() {
- let attributes: [FileAttributeKey: Any] = [
- .size: NSNumber(value: 5),
- ]
- let item = CompareItem(
- path: nil,
- attrs: attributes,
- fileExtraOptions: [],
- parent: nil
- )
-
- let filter = "fileSize == 5"
- #expect(item.evaluate(filter: NSPredicate(format: filter)))
- }
-
- @Test func filterModificationDate() throws {
- let attributes: [FileAttributeKey: Any] = try [
- .modificationDate: buildDate("2012-05-05 11: 00: 11 +0000"),
- ]
- let item = CompareItem(
- path: nil,
- attrs: attributes,
- fileExtraOptions: [],
- parent: nil
- )
-
- // after 2012-06-01 06:00
- let filter = #"fileObjectModificationDate > CAST(347518800.000000, "NSDate")"#
- #expect(item.evaluate(filter: NSPredicate(format: filter)))
- }
-}
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/LabelsCopyTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/LabelsCopyTests.swift
deleted file mode 100644
index afec523..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/LabelsCopyTests.swift
+++ /dev/null
@@ -1,501 +0,0 @@
-//
-// LabelsCopyTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class LabelsCopyTests: BaseTests {
- @Test func copyFolderWithLabels() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase, .finderLabel],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/Level2")
- try createFolder("r/Parent/Level2")
- try createFolder("l/Parent/Level2/FolderWithLabels")
- try createFolder("r/Parent/Level2/FolderWithLabels")
-
- // create files
- try add(labelNumber: 2, fullPath: appendFolder("r/Parent/Level2"))
- try add(labelNumber: 3, fullPath: appendFolder("r/Parent/Level2/FolderWithLabels"))
- try createFile("l/Parent/Level2/FolderWithLabels/file1.txt", "123456")
- try createFile("r/Parent/Level2/FolderWithLabels/file1.txt", "123456")
- try add(labelNumber: 7, fullPath: appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
- try createFile("l/Parent/Level2/FolderWithLabels/file2.txt", "1234567890")
- try add(labelNumber: 3, fullPath: appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- try createFile("r/Parent/Level2/FolderWithLabels/file2.txt", "1234567890")
- try add(labelNumber: 3, fullPath: appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
- try createFile("l/Parent/line2.txt", "12345")
- try createFile("r/Parent/line2.txt", "12345")
- try add(labelNumber: 2, fullPath: appendFolder("r/Parent/line2.txt"))
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 4, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 4, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 4, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 4, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let child3 = child2.children[0] // Parent <-> Parent
- operationElement = child3
- assertItem(child3, 0, 0, 0, 1, 1, "Level2", .mismatchingLabels, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, true, "Level2")
- assertMismatchingLabels(child3, 2, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "Level2", .mismatchingLabels, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, true, "Level2")
- assertMismatchingLabels(child3.linkedItem, 2, "Level2")
- assertResourceFileLabels(child3.linkedItem, 2, appendFolder("r/Parent/Level2"))
-
- let child4 = child3.children[0] // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, true, "FolderWithLabels")
- assertMismatchingLabels(child4, 1, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 1, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let child5 = child4.children[0] // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 7, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let child6 = child4.children[1] // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 3, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 4, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 4, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 4, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 4, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 1, "Level2", .mismatchingLabels, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, true, "Level2")
- assertMismatchingLabels(child3, 2, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "Level2", .mismatchingLabels, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, true, "Level2")
- assertMismatchingLabels(child3.linkedItem, 2, "Level2")
- assertResourceFileLabels(child3.linkedItem, 2, appendFolder("r/Parent/Level2"))
-
- let childVI4 = childVI3.children[0] // Level2 <--> Level2
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, true, "FolderWithLabels")
- assertMismatchingLabels(child4, 1, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 1, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let childVI5 = childVI4.children[0] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 7, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let childVI6 = childVI4.children[1] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 3, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 3, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 1, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 3, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 1, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 1, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 1, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 1, "Level2", .orphan, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, false, "Level2")
- assertMismatchingLabels(child3, 0, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 2, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 0, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let child4 = child3.children[0] // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 2, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, false, "FolderWithLabels")
- assertMismatchingLabels(child4, 0, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 2, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, false, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 0, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let child5 = child4.children[0] // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 0, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 0, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let child6 = child4.children[1] // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 3, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 3, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 1, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 3, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 1, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 1, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 1, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 1, "Level2", .orphan, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, false, "Level2")
- assertMismatchingLabels(child3, 0, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 2, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 0, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let childVI4 = childVI3.children[0] // Level2 <--> Level2
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 2, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, false, "FolderWithLabels")
- assertMismatchingLabels(child4, 0, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 2, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, false, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 0, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let childVI5 = childVI4.children[0] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 0, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 0, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let childVI6 = childVI4.children[1] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 3, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/LabelsCreateTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/LabelsCreateTests.swift
deleted file mode 100644
index 4726102..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/LabelsCreateTests.swift
+++ /dev/null
@@ -1,219 +0,0 @@
-//
-// LabelsCreateTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping function_body_length
-final class LabelsCreateTests: BaseTests {
- @Test func createLabels() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase, .finderLabel],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithLabels")
- try createFolder("r/Parent/FolderWithLabels")
-
- // create files
- try add(labelNumber: 3, fullPath: appendFolder("r/Parent/FolderWithLabels"))
- try createFile("l/Parent/FolderWithLabels/attachment_one.txt", "123456")
- try createFile("r/Parent/FolderWithLabels/attachment_one.txt", "123456")
- try createFile("l/Parent/FolderWithLabels/file1.txt", "123456")
- try createFile("r/Parent/FolderWithLabels/file1.txt", "123456")
- try add(labelNumber: 7, fullPath: appendFolder("r/Parent/FolderWithLabels/file1.txt"))
- try createFile("l/Parent/FolderWithLabels/file2.txt", "1234567890")
- try createFile("r/Parent/FolderWithLabels/file2.txt", "1234567890")
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 3, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 3, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1, false, "r")
- assertMismatchingLabels(child1, 2, "r")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 2, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 2, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 2, "Parent")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 2, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithLabels", .mismatchingLabels, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithLabels", .mismatchingLabels, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3, true, "FolderWithLabels")
- assertMismatchingLabels(child3, 1, "FolderWithLabels")
- assertFolderLabels(child3.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child3.linkedItem, 1, "FolderWithLabels")
-
- let child4 = child3.children[0] // FolderWithLabels <-> FolderWithLabels
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderLabels(child4, false, "attachment_one.txt")
- assertMismatchingLabels(child4, 0, "attachment_one.txt")
- assertFolderLabels(child4.linkedItem, false, "attachment_one.txt")
- assertMismatchingLabels(child4.linkedItem, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child7, false, "line1.txt")
- assertMismatchingLabels(child7, 0, "line1.txt")
- assertFolderLabels(child7.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child7.linkedItem, 0, "line1.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 3, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 3, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1, false, "r")
- assertMismatchingLabels(child1, 2, "r")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 2, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 2, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 2, "Parent")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 2, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithLabels", .mismatchingLabels, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithLabels", .mismatchingLabels, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3, true, "FolderWithLabels")
- assertMismatchingLabels(child3, 1, "FolderWithLabels")
- assertFolderLabels(child3.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child3.linkedItem, 1, "FolderWithLabels")
-
- let childVI4 = childVI3.children[0] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderLabels(child4, false, "attachment_one.txt")
- assertMismatchingLabels(child4, 0, "attachment_one.txt")
- assertFolderLabels(child4.linkedItem, false, "attachment_one.txt")
- assertMismatchingLabels(child4.linkedItem, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
-
- let childVI7 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child7, false, "line1.txt")
- assertMismatchingLabels(child7, 0, "line1.txt")
- assertFolderLabels(child7.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child7.linkedItem, 0, "line1.txt")
- }
- }
-}
-
-// swiftlint:enable force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/LabelsMoveTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/LabelsMoveTests.swift
deleted file mode 100644
index 7b0baff..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/LabelsMoveTests.swift
+++ /dev/null
@@ -1,482 +0,0 @@
-//
-// LabelsMoveTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 17/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class LabelsMoveTests: BaseTests {
- @Test func moveFolderWithLabels() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase, .finderLabel],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/Level2")
- try createFolder("r/Parent/Level2")
- try createFolder("l/Parent/Level2/FolderWithLabels")
- try createFolder("r/Parent/Level2/FolderWithLabels")
-
- // create files
- try add(labelNumber: 3, fullPath: appendFolder("r/Parent/Level2/FolderWithLabels"))
- try createFile("l/Parent/Level2/FolderWithLabels/file1.txt", "123456")
- try createFile("r/Parent/Level2/FolderWithLabels/file1.txt", "123456")
- try add(labelNumber: 7, fullPath: appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
- try createFile("l/Parent/Level2/FolderWithLabels/file2.txt", "1234567890")
- try createFile("r/Parent/Level2/FolderWithLabels/file2.txt", "1234567890")
- try createFile("l/Parent/line2.txt", "12345")
- try createFile("r/Parent/line2.txt", "12345")
- try add(labelNumber: 2, fullPath: appendFolder("r/Parent/line2.txt"))
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 3, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 3, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 3, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 3, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 1, "Level2", .orphan, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, false, "Level2")
- assertMismatchingLabels(child3, 2, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 2, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let child4 = child3.children[0] // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, true, "FolderWithLabels")
- assertMismatchingLabels(child4, 1, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 1, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let child5 = child4.children[0] // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 7, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let child6 = child4.children[1] // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 26)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 3, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 3, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 3, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 0, 1, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 3, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // Parent <-> Parent
- operationElement = child3
- assertItem(child3, 0, 0, 0, 1, 1, "Level2", .orphan, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertFolderLabels(child3, false, "Level2")
- assertMismatchingLabels(child3, 2, "Level2")
- assertResourceFileLabels(child3, 0, appendFolder("l/Parent/Level2"))
- assertItem(child3.linkedItem, 0, 0, 0, 1, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 2, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let childVI4 = childVI3.children[0] // Level2 <--> Level2
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // Level2 <-> Level2
- assertItem(child4, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.orphanFolders)")
- assertFolderLabels(child4, true, "FolderWithLabels")
- assertMismatchingLabels(child4, 1, "FolderWithLabels")
- assertResourceFileLabels(child4, 0, appendFolder("l/Parent/Level2/FolderWithLabels"))
- assertItem(child4.linkedItem, 0, 0, 0, 1, 2, "FolderWithLabels", .mismatchingLabels, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, true, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 1, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 3, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let childVI5 = childVI4.children[0] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5, false, "file1.txt")
- assertMismatchingLabels(child5, 1, "file1.txt")
- assertResourceFileLabels(child5, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file1.txt"))
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 1, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 7, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let childVI6 = childVI4.children[1] // FolderWithLabels <--> FolderWithLabels
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithLabels <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6, false, "file2.txt")
- assertMismatchingLabels(child6, 0, "file2.txt")
- assertResourceFileLabels(child6, 0, appendFolder("l/Parent/Level2/FolderWithLabels/file2.txt"))
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
- fileOperation.move(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 1, 2, "l", .orphan, 10)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 1, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 2, 1, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 1, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 5)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 1, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 2, 0, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 1, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertFolderLabels(child3, false, nil)
- assertMismatchingLabels(child3, 0, nil)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 0, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let child4 = child3.children[0] // (null) <-> Level2
- assertItem(child4, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertFolderLabels(child4, false, nil)
- assertMismatchingLabels(child4, 0, nil)
- assertItem(child4.linkedItem, 0, 0, 2, 0, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, false, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 0, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let child5 = child4.children[0] // (null) <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertFolderLabels(child5, false, nil)
- assertMismatchingLabels(child5, 0, nil)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 0, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let child6 = child4.children[1] // (null) <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertFolderLabels(child6, false, nil)
- assertMismatchingLabels(child6, 0, nil)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let child8 = child1.children[1] // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 1, 2, "l", .orphan, 10)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertFolderLabels(child1, false, "l")
- assertMismatchingLabels(child1, 1, "l")
- assertResourceFileLabels(child1, 0, appendFolder("l"))
- assertItem(child1.linkedItem, 0, 0, 2, 1, 2, "r", .orphan, 26)
- #expect(child1.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child1.linkedItem!.orphanFolders)")
- assertFolderLabels(child1.linkedItem, false, "r")
- assertMismatchingLabels(child1.linkedItem, 1, "r")
- assertResourceFileLabels(child1.linkedItem, 0, appendFolder("r"))
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 5)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertFolderLabels(child2, false, "Parent")
- assertMismatchingLabels(child2, 1, "Parent")
- assertResourceFileLabels(child2, 0, appendFolder("l/Parent"))
- assertItem(child2.linkedItem, 0, 0, 2, 0, 2, "Parent", .orphan, 21)
- #expect(child2.linkedItem!.orphanFolders == 2, "OrphanFolder: Expected count \(2) found \(child2.linkedItem!.orphanFolders)")
- assertFolderLabels(child2.linkedItem, false, "Parent")
- assertMismatchingLabels(child2.linkedItem, 1, "Parent")
- assertResourceFileLabels(child2.linkedItem, 0, appendFolder("r/Parent"))
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertFolderLabels(child3, false, nil)
- assertMismatchingLabels(child3, 0, nil)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 1, "Level2", .orphan, 16)
- #expect(child3.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child3.linkedItem!.orphanFolders)")
- assertFolderLabels(child3.linkedItem, false, "Level2")
- assertMismatchingLabels(child3.linkedItem, 0, "Level2")
- assertResourceFileLabels(child3.linkedItem, 0, appendFolder("r/Parent/Level2"))
-
- let childVI4 = childVI3.children[0] // (null) <--> Level2
- assertArrayCount(childVI4.children, 2)
- let child4 = childVI4.item // (null) <-> Level2
- assertItem(child4, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertFolderLabels(child4, false, nil)
- assertMismatchingLabels(child4, 0, nil)
- assertItem(child4.linkedItem, 0, 0, 2, 0, 2, "FolderWithLabels", .orphan, 16)
- #expect(child4.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child4.linkedItem!.orphanFolders)")
- assertFolderLabels(child4.linkedItem, false, "FolderWithLabels")
- assertMismatchingLabels(child4.linkedItem, 0, "FolderWithLabels")
- assertResourceFileLabels(child4.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels"))
-
- let childVI5 = childVI4.children[0] // (null) <--> FolderWithLabels
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> FolderWithLabels
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertFolderLabels(child5, false, nil)
- assertMismatchingLabels(child5, 0, nil)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderLabels(child5.linkedItem, false, "file1.txt")
- assertMismatchingLabels(child5.linkedItem, 0, "file1.txt")
- assertResourceFileLabels(child5.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file1.txt"))
-
- let childVI6 = childVI4.children[1] // (null) <--> FolderWithLabels
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> FolderWithLabels
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertFolderLabels(child6, false, nil)
- assertMismatchingLabels(child6, 0, nil)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderLabels(child6.linkedItem, false, "file2.txt")
- assertMismatchingLabels(child6.linkedItem, 0, "file2.txt")
- assertResourceFileLabels(child6.linkedItem, 0, appendFolder("r/Parent/Level2/FolderWithLabels/file2.txt"))
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7, false, "line2.txt")
- assertMismatchingLabels(child7, 1, "line2.txt")
- assertResourceFileLabels(child7, 0, appendFolder("l/Parent/line2.txt"))
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "line2.txt", .same, 5)
- assertFolderLabels(child7.linkedItem, false, "line2.txt")
- assertMismatchingLabels(child7.linkedItem, 1, "line2.txt")
- assertResourceFileLabels(child7.linkedItem, 2, appendFolder("r/Parent/line2.txt"))
-
- let childVI8 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // l <-> r
- assertItem(child8, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8, false, "line1.txt")
- assertMismatchingLabels(child8, 0, "line1.txt")
- assertResourceFileLabels(child8, 0, appendFolder("l/line1.txt"))
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertFolderLabels(child8.linkedItem, false, "line1.txt")
- assertMismatchingLabels(child8.linkedItem, 0, "line1.txt")
- assertResourceFileLabels(child8.linkedItem, 0, appendFolder("r/line1.txt"))
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/TagsCopyTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/TagsCopyTests.swift
deleted file mode 100644
index 43392a8..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/TagsCopyTests.swift
+++ /dev/null
@@ -1,589 +0,0 @@
-//
-// TagsCopyTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class TagsCopyTests: BaseTests {
- @Test func copyFileWithTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "1234567")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try setFileTimestamp("r/Parent/FolderWithTags/attachment_one.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file1.txt"))
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 1, 2, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 1, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 1, 0, 0, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 0, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 1, 0, 0, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 0, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- operationElement = child5
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 1, 2, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 1, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 1, 0, 0, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 0, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 1, 0, 0, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 0, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let childVI7 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.copy(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 2, 2, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 2, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 1, 0, 1, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 2, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 1, 0, 1, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 0, "file1.txt")
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 2, 2, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 2, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 1, 0, 1, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 2, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 1, 0, 1, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let childVI7 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- }
-
- @Test func copyFolderWithTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "1234567")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try setFileTimestamp("r/Parent/FolderWithTags/attachment_one.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file1.txt"))
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 1, 0, 0, 1, "l", .orphan, 23)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 0, 1, "r", .orphan, 22)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 1, 0, 0, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 0, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- operationElement = child3.linkedItem!
- assertItem(child3, 0, 1, 0, 0, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 0, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 1, "file2.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 1, 0, 0, 1, "l", .orphan, 23)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 1, 0, 0, 0, 1, "r", .orphan, 22)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 1, 0, 0, 1, "Parent", .orphan, 23)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 1, 0, 0, 0, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 1, 0, 0, 3, "FolderWithTags", .mismatchingTags, 23)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 1, 0, 0, 0, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 1, 0, 0, 0, "attachment_one.txt", .changed, 7)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "attachment_one.txt", .old, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 1, "file2.txt")
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = CopyCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
- fileOperation.copy(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("r"),
- destBaseDir: appendFolder("l")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 22)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 3, 1, "r", .orphan, 22)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 0, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 3, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 3, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 0, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 3, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 3, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 3, 1, "l", .orphan, 22)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 3, 1, "r", .orphan, 22)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 0, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 3, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 3, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 0, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 3, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 3, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/TagsCreateTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/TagsCreateTests.swift
deleted file mode 100644
index f0d922d..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/TagsCreateTests.swift
+++ /dev/null
@@ -1,178 +0,0 @@
-//
-// TagsCreateTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping function_body_length
-final class TagsCreateTests: BaseTests {
- @Test func createTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file1.txt"))
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let childVI7 = childVI1.children[1] // l <--> r
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- }
-}
-
-// swiftlint:enable force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/TagsDeleteTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/TagsDeleteTests.swift
deleted file mode 100644
index 9a573da..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/TagsDeleteTests.swift
+++ /dev/null
@@ -1,582 +0,0 @@
-//
-// TagsDeleteTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class TagsDeleteTests: BaseTests {
- @Test func deleteFileWithTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file1.txt"))
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
- try createFile("l/line1.txt", "12345")
- try createFile("r/line1.txt", "12345")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- operationElement = child5
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 27)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 2, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertMismatchingTags(child4, 1, "file1.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child5, 1, "file2.txt")
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- operationElement,
- baseDir: appendFolder("l")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 21)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 1, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 2, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 16)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 1, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 2, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 1, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- operationElement = child5
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child6, 1, "file2.txt")
-
- let child7 = child1.children[1] // l <-> r
- assertItem(child7, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "line1.txt", .same, 5)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 2, "l", .orphan, 21)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 1, 2, 2, "r", .orphan, 27)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertMismatchingTags(child1, 2, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 1, "Parent", .orphan, 16)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 1, 1, 1, "Parent", .orphan, 22)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertMismatchingTags(child2, 2, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 1, 3, "FolderWithTags", .mismatchingTags, 16)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 1, 1, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file2.txt", .same, 10)
- assertMismatchingTags(child5, 1, "file2.txt")
- }
- }
-
- @Test func deleteFolderWithTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
- try createFile("l/Parent/anotherFile.txt", "123456")
- try add(tags: ["Blue", "Purple"], fullPath: appendFolder("l/Parent/anotherFile.txt"))
- try createFile("r/Parent/anotherFile.txt", "123456")
- try add(tags: ["Blue"], fullPath: appendFolder("r/Parent/anotherFile.txt"))
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 1, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 1, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- operationElement = child3
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = DeleteCompareItem(operationManager: fileOperationManager)
-
- fileOperation.delete(
- operationElement,
- baseDir: appendFolder("l")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 6)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 0, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 1, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 6)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 0, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 1, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
-
- let child4 = child3.children[0] // (null) <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "attachment_one.txt", .orphan, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // (null) <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
-
- let child6 = child3.children[2] // (null) <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 6)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 0, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 1, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 6)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 0, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 1, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // (null) <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "attachment_one.txt", .orphan, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // (null) <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
-
- let childVI6 = childVI3.children[2] // (null) <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MetaData/TagsMoveTests.swift b/Tests/Sources/FileSystem/Tests/MetaData/TagsMoveTests.swift
deleted file mode 100644
index 8834896..0000000
--- a/Tests/Sources/FileSystem/Tests/MetaData/TagsMoveTests.swift
+++ /dev/null
@@ -1,359 +0,0 @@
-//
-// TagsMoveTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 06/12/21.
-// Copyright (c) 2021 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping function_body_length
-final class TagsMoveTests: BaseTests {
- @Test func moveFolderWithTags() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .finderTags, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 9100,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
- try createFolder("l/Parent")
- try createFolder("r/Parent")
- try createFolder("l/Parent/FolderWithTags")
- try createFolder("r/Parent/FolderWithTags")
-
- // create files
- try add(tags: ["Red"], fullPath: appendFolder("l/Parent/FolderWithTags"))
- try createFile("l/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("r/Parent/FolderWithTags/attachment_one.txt", "123456")
- try createFile("l/Parent/FolderWithTags/file1.txt", "123456")
- try createFile("r/Parent/FolderWithTags/file1.txt", "123456")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file1.txt"))
- try createFile("l/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("l/Parent/FolderWithTags/file2.txt"))
- try createFile("r/Parent/FolderWithTags/file2.txt", "1234567890")
- try add(tags: ["Yellow", "Red"], fullPath: appendFolder("r/Parent/FolderWithTags/file2.txt"))
- try createFile("l/Parent/anotherFile.txt", "123456")
- try add(tags: ["Blue", "Purple"], fullPath: appendFolder("l/Parent/anotherFile.txt"))
- try createFile("r/Parent/anotherFile.txt", "123456")
- try add(tags: ["Blue"], fullPath: appendFolder("r/Parent/anotherFile.txt"))
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var operationElement: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 2, 1, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let child4 = child3.children[0] // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let child6 = child3.children[2] // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 2, 1, "l", .orphan, 28)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 3, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 0, 2, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 3, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- operationElement = child3
- assertItem(child3, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.orphanFolders)")
- assertItem(child3.linkedItem, 0, 0, 0, 2, 3, "FolderWithTags", .mismatchingTags, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, true, "FolderWithTags")
- assertMismatchingTags(child3, 1, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // FolderWithTags <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "attachment_one.txt", .same, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // FolderWithTags <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "file1.txt", .same, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 1, "file1.txt")
-
- let childVI6 = childVI3.children[2] // FolderWithTags <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // FolderWithTags <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file2.txt", .same, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: operationElement,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 6)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 0, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 1, "r")
- assertFolderTags(child1.linkedItem, false, "r")
- assertMismatchingTags(child1.linkedItem, 1, "r")
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 6)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 0, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 1, "Parent")
- assertFolderTags(child2.linkedItem, false, "Parent")
- assertMismatchingTags(child2.linkedItem, 1, "Parent")
-
- let child3 = child2.children[0] // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
- assertFolderTags(child3.linkedItem, false, "FolderWithTags")
- assertMismatchingTags(child3.linkedItem, 0, "FolderWithTags")
-
- let child4 = child3.children[0] // (null) <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "attachment_one.txt", .orphan, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
- assertFolderTags(child4.linkedItem, false, "attachment_one.txt")
- assertMismatchingTags(child4.linkedItem, 0, "attachment_one.txt")
-
- let child5 = child3.children[1] // (null) <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
- assertFolderTags(child5.linkedItem, false, "file1.txt")
- assertMismatchingTags(child5.linkedItem, 0, "file1.txt")
-
- let child6 = child3.children[2] // (null) <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
- assertFolderTags(child6.linkedItem, false, "file2.txt")
- assertMismatchingTags(child6.linkedItem, 0, "file2.txt")
-
- let child7 = child2.children[1] // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- assertFolderTags(child7.linkedItem, false, "anotherFile.txt")
- assertMismatchingTags(child7.linkedItem, 1, "anotherFile.txt")
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 6)
- #expect(child1.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child1.orphanFolders)")
- assertItem(child1.linkedItem, 0, 0, 3, 0, 1, "r", .orphan, 28)
- #expect(child1.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child1.linkedItem!.orphanFolders)")
- assertFolderTags(child1, false, "r")
- assertMismatchingTags(child1, 1, "r")
- assertFolderTags(child1.linkedItem, false, "r")
- assertMismatchingTags(child1.linkedItem, 1, "r")
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 2, "Parent", .orphan, 6)
- #expect(child2.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child2.orphanFolders)")
- assertItem(child2.linkedItem, 0, 0, 3, 0, 2, "Parent", .orphan, 28)
- #expect(child2.linkedItem!.orphanFolders == 1, "OrphanFolder: Expected count \(1) found \(child2.linkedItem!.orphanFolders)")
- assertFolderTags(child2, false, "Parent")
- assertMismatchingTags(child2, 1, "Parent")
- assertFolderTags(child2.linkedItem, false, "Parent")
- assertMismatchingTags(child2.linkedItem, 1, "Parent")
-
- let childVI3 = childVI2.children[0] // Parent <--> Parent
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // Parent <-> Parent
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "FolderWithTags", .orphan, 22)
- #expect(child3.linkedItem!.orphanFolders == 0, "OrphanFolder: Expected count \(0) found \(child3.linkedItem!.orphanFolders)")
- assertFolderTags(child3, false, "FolderWithTags")
- assertMismatchingTags(child3, 0, "FolderWithTags")
- assertFolderTags(child3.linkedItem, false, "FolderWithTags")
- assertMismatchingTags(child3.linkedItem, 0, "FolderWithTags")
-
- let childVI4 = childVI3.children[0] // (null) <--> FolderWithTags
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> FolderWithTags
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "attachment_one.txt", .orphan, 6)
- assertFolderTags(child4, false, "attachment_one.txt")
- assertMismatchingTags(child4, 0, "attachment_one.txt")
- assertFolderTags(child4.linkedItem, false, "attachment_one.txt")
- assertMismatchingTags(child4.linkedItem, 0, "attachment_one.txt")
-
- let childVI5 = childVI3.children[1] // (null) <--> FolderWithTags
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> FolderWithTags
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file1.txt", .orphan, 6)
- assertFolderTags(child5, false, "file1.txt")
- assertMismatchingTags(child5, 0, "file1.txt")
- assertFolderTags(child5.linkedItem, false, "file1.txt")
- assertMismatchingTags(child5.linkedItem, 0, "file1.txt")
-
- let childVI6 = childVI3.children[2] // (null) <--> FolderWithTags
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> FolderWithTags
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file2.txt", .orphan, 10)
- assertFolderTags(child6, false, "file2.txt")
- assertMismatchingTags(child6, 0, "file2.txt")
- assertFolderTags(child6.linkedItem, false, "file2.txt")
- assertMismatchingTags(child6.linkedItem, 0, "file2.txt")
-
- let childVI7 = childVI2.children[1] // Parent <--> Parent
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // Parent <-> Parent
- assertItem(child7, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "anotherFile.txt", .same, 6)
- assertFolderTags(child7, false, "anotherFile.txt")
- assertMismatchingTags(child7, 1, "anotherFile.txt")
- assertFolderTags(child7.linkedItem, false, "anotherFile.txt")
- assertMismatchingTags(child7.linkedItem, 1, "anotherFile.txt")
- }
- }
-}
-
-// swiftlint:enable force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/MoveFilesTests.swift b/Tests/Sources/FileSystem/Tests/MoveFilesTests.swift
deleted file mode 100644
index cdd4b32..0000000
--- a/Tests/Sources/FileSystem/Tests/MoveFilesTests.swift
+++ /dev/null
@@ -1,1988 +0,0 @@
-//
-// MoveFilesTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class MoveFilesTests: BaseTests {
- @Test func moveFilesPresentOnBothSidesWithFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
- try createFolder("l/folder_1/folder_1_2")
-
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
- try createFolder("r/folder_1/folder_1_2")
-
- // create files
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_changed.m", "1234567890")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.txt", "1")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "1234567")
- try createFile("l/folder_1/folder_1_2/match_2_1.m", "12")
- try createFile("l/folder_1/file.txt", "123")
-
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.txt", "1")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.txt", "1234")
- try createFile("r/folder_1/folder_1_2/match_2_1.m", "12")
- try createFile("r/folder_1/file.txt", "123")
- try createFile("r/folder_1/right_orphan.txt", "1234567890")
-
- try setFileTimestamp("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "2001-03-24 10: 45: 32 +0600")
- try setFileTimestamp("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var l = rootL.children[0]
- assertItem(l, 1, 1, 0, 3, 4, "folder_1", .orphan, 23)
- assertItem(l.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 21)
-
- var child1 = l.children[0]
- assertItem(child1, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 18)
- assertItem(child1.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 6)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 18)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 6)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 1, 0, 0, 0, "file_changed.m", .changed, 10)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 1)
-
- var child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.txt", .same, 1)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 1)
-
- var child5 = child2.children[2]
- assertItem(child5, 1, 0, 0, 0, 0, "file_older.txt", .old, 7)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 4)
-
- var child6 = l.children[1]
- assertItem(child6, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- var child7 = child6.children[0]
- assertItem(child7, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- var child8 = l.children[2]
- assertItem(child8, 0, 0, 0, 1, 0, "file.txt", .same, 3)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 3)
-
- var child9 = l.children[3]
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 10)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 4)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 1, 0, 3, 4, "folder_1", .orphan, 23)
- assertItem(child1.linkedItem, 1, 1, 1, 3, 4, "folder_1", .orphan, 21)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 18)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 6)
-
- let childVI3 = childVI2.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // folder_1_1 <-> folder_1_1
- assertItem(child3, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 18)
- assertItem(child3.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 6)
-
- let childVI4 = childVI3.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_2_1 <-> folder_2_1
- assertItem(child4, 0, 1, 0, 0, 0, "file_changed.m", .changed, 10)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 1)
-
- let childVI5 = childVI3.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 1, 0, "file_matched.txt", .same, 1)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 1)
-
- let childVI6 = childVI3.children[2] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder_2_1 <-> folder_2_1
- assertItem(child6, 1, 0, 0, 0, 0, "file_older.txt", .old, 7)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 4)
-
- let childVI7 = childVI1.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 1)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- let childVI8 = childVI7.children[0] // folder_1_2 <--> folder_1_2
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // folder_1_2 <-> folder_1_2
- assertItem(child8, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- let childVI9 = childVI1.children[2] // folder_1 <--> folder_1
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // folder_1 <-> folder_1
- assertItem(child9, 0, 0, 0, 1, 0, "file.txt", .same, 3)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 3)
-
- let childVI10 = childVI1.children[3] // folder_1 <--> folder_1
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // folder_1 <-> folder_1
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 10)
- }
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child1,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- l = rootL.children[0]
- assertItem(l, 0, 0, 0, 2, 4, "folder_1", .orphan, 5)
- assertItem(l.linkedItem, 0, 0, 4, 2, 4, "folder_1", .orphan, 33)
-
- child1 = l.children[0]
- assertItem(child1, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 3, 0, 1, "folder_1_1", .orphan, 18)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 3, 0, 3, "folder_2_1", .orphan, 18)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 10)
-
- child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file_matched.txt", .orphan, 1)
-
- child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 7)
-
- child6 = l.children[1]
- assertItem(child6, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- child7 = child6.children[0]
- assertItem(child7, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- child8 = l.children[2]
- assertItem(child8, 0, 0, 0, 1, 0, "file.txt", .same, 3)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 3)
-
- child9 = l.children[3]
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 10)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 4)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 2, 4, "folder_1", .orphan, 5)
- assertItem(child1.linkedItem, 0, 0, 4, 2, 4, "folder_1", .orphan, 33)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 3, 0, 1, "folder_1_1", .orphan, 18)
-
- let childVI3 = childVI2.children[0] // (null) <--> folder_1_1
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // (null) <-> folder_1_1
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "folder_2_1", .orphan, 18)
-
- let childVI4 = childVI3.children[0] // (null) <--> folder_2_1
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> folder_2_1
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 10)
-
- let childVI5 = childVI3.children[1] // (null) <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_matched.txt", .orphan, 1)
-
- let childVI6 = childVI3.children[2] // (null) <--> folder_2_1
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> folder_2_1
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 7)
-
- let childVI7 = childVI1.children[1] // folder_1 <--> folder_1
- assertArrayCount(childVI7.children, 1)
- let child7 = childVI7.item // folder_1 <-> folder_1
- assertItem(child7, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 1, "folder_1_2", .orphan, 2)
-
- let childVI8 = childVI7.children[0] // folder_1_2 <--> folder_1_2
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // folder_1_2 <-> folder_1_2
- assertItem(child8, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "match_2_1.m", .same, 2)
-
- let childVI9 = childVI1.children[2] // folder_1 <--> folder_1
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // folder_1 <-> folder_1
- assertItem(child9, 0, 0, 0, 1, 0, "file.txt", .same, 3)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "file.txt", .same, 3)
-
- let childVI10 = childVI1.children[3] // folder_1 <--> folder_1
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // folder_1 <-> folder_1
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "right_orphan.txt", .orphan, 10)
- }
- }
-
- @Test func moveFilesPresentOnBothSides() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
-
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
-
- // create files
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "12345")
-
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.txt", "12")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.txt", "1")
-
- try setFileTimestamp("l/folder_1/folder_1_1/folder_2_1/file_older.txt", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var l = rootL.children[0]
- assertItem(l, 1, 0, 0, 1, 1, "folder_1", .orphan, 7)
- assertItem(l.linkedItem, 0, 1, 1, 1, 1, "folder_1", .orphan, 4)
-
- var child1 = l.children[0]
- assertItem(child1, 1, 0, 0, 1, 1, "folder_1_1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 1, 1, 1, 1, "folder_1_1", .orphan, 4)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 0, 0, 1, 3, "folder_2_1", .orphan, 7)
- assertItem(child2.linkedItem, 0, 1, 1, 1, 3, "folder_2_1", .orphan, 4)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 1)
-
- var child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
-
- var child5 = child2.children[2]
- assertItem(child5, 1, 0, 0, 0, 0, "file_older.txt", .old, 5)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 0, 0, 1, 1, "folder_1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 1, 1, 1, 1, "folder_1", .orphan, 4)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 1, 0, 0, 1, 1, "folder_1_1", .orphan, 7)
- assertItem(child2.linkedItem, 0, 1, 1, 1, 1, "folder_1_1", .orphan, 4)
-
- let childVI3 = childVI2.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // folder_1_1 <-> folder_1_1
- assertItem(child3, 1, 0, 0, 1, 3, "folder_2_1", .orphan, 7)
- assertItem(child3.linkedItem, 0, 1, 1, 1, 3, "folder_2_1", .orphan, 4)
-
- let childVI4 = childVI3.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_2_1 <-> folder_2_1
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 1)
-
- let childVI5 = childVI3.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 1, 0, 0, 0, 0, "file_older.txt", .old, 5)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file_older.txt", .changed, 1)
- }
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child1,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- l = rootL.children[0]
- assertItem(l, 0, 0, 0, 1, 1, "folder_1", .orphan, 2)
- assertItem(l.linkedItem, 0, 0, 2, 1, 1, "folder_1", .orphan, 8)
-
- child1 = l.children[0]
- assertItem(child1, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 8)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 8)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 1)
-
- child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.txt", .same, 2)
-
- child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 5)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "folder_1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 1, "folder_1", .orphan, 8)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 0, 0, 0, 1, 1, "folder_1_1", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 1, 1, "folder_1_1", .orphan, 8)
-
- let childVI3 = childVI2.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // folder_1_1 <-> folder_1_1
- assertItem(child3, 0, 0, 0, 1, 3, "folder_2_1", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 2, 1, 3, "folder_2_1", .orphan, 8)
-
- let childVI4 = childVI3.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_2_1 <-> folder_2_1
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file_changed.m", .orphan, 1)
-
- let childVI5 = childVI3.children[1] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder_2_1 <-> folder_2_1
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_older.txt", .orphan, 5)
- }
- }
-
- @Test func moveFilesOrphansNoFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/bootstrap")
- try createFolder("r/bootstrap")
-
- try createFolder("l/bootstrap/data")
- try createFolder("r/bootstrap/data")
-
- try createFolder("l/bootstrap/data/hypersonic")
- try createFolder("r/bootstrap/data/hypersonic")
-
- // create files
- try createFile("l/bootstrap/data/hypersonic/dvd.log", "1")
-
- try createFile("l/bootstrap/data/hypersonic/dvd.properties", "12")
-
- try createFile("l/bootstrap/data/hypersonic/localDB.lck", "123")
- try createFile("l/bootstrap/data/hypersonic/localDB.log", "1234")
-
- try createFile("r/bootstrap/data/hypersonic/localDB.log", "1234")
-
- try createFile("l/bootstrap/data/hypersonic/localDB.properties", "123456")
-
- try createFile("l/bootstrap/data/hypersonic/localDB.script", "1234567")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let l = rootL.children[0]
- assertItem(l, 0, 0, 5, 1, 1, "bootstrap", .orphan, 23)
- assertItem(l.linkedItem, 0, 0, 0, 1, 1, "bootstrap", .orphan, 4)
-
- let child = l.children[0]
- assertItem(child, 0, 0, 5, 1, 1, "data", .orphan, 23)
- assertItem(child.linkedItem, 0, 0, 0, 1, 1, "data", .orphan, 4)
-
- var child1 = child.children[0]
- assertItem(child1, 0, 0, 5, 1, 6, "hypersonic", .orphan, 23)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 6, "hypersonic", .orphan, 4)
-
- var child2 = child1.children[0]
- assertItem(child2, 0, 0, 1, 0, 0, "dvd.log", .orphan, 1)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child3 = child1.children[1]
- assertItem(child3, 0, 0, 1, 0, 0, "dvd.properties", .orphan, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child4 = child1.children[2]
- assertItem(child4, 0, 0, 1, 0, 0, "localDB.lck", .orphan, 3)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child5 = child1.children[3]
- assertItem(child5, 0, 0, 0, 1, 0, "localDB.log", .same, 4)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "localDB.log", .same, 4)
-
- var child6 = child1.children[4]
- assertItem(child6, 0, 0, 1, 0, 0, "localDB.properties", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child7 = child1.children[5]
- assertItem(child7, 0, 0, 1, 0, 0, "localDB.script", .orphan, 7)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 5, 1, 1, "bootstrap", .orphan, 23)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "bootstrap", .orphan, 4)
-
- let childVI2 = childVI1.children[0] // bootstrap <--> bootstrap
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // bootstrap <-> bootstrap
- assertItem(child2, 0, 0, 5, 1, 1, "data", .orphan, 23)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 1, "data", .orphan, 4)
-
- let childVI3 = childVI2.children[0] // data <--> data
- assertArrayCount(childVI3.children, 5)
- let child3 = childVI3.item // data <-> data
- assertItem(child3, 0, 0, 5, 1, 6, "hypersonic", .orphan, 23)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 6, "hypersonic", .orphan, 4)
-
- let childVI4 = childVI3.children[0] // hypersonic <--> hypersonic
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // hypersonic <-> hypersonic
- assertItem(child4, 0, 0, 1, 0, 0, "dvd.log", .orphan, 1)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI3.children[1] // hypersonic <--> hypersonic
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // hypersonic <-> hypersonic
- assertItem(child5, 0, 0, 1, 0, 0, "dvd.properties", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI3.children[2] // hypersonic <--> hypersonic
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // hypersonic <-> hypersonic
- assertItem(child6, 0, 0, 1, 0, 0, "localDB.lck", .orphan, 3)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI3.children[3] // hypersonic <--> hypersonic
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // hypersonic <-> hypersonic
- assertItem(child7, 0, 0, 1, 0, 0, "localDB.properties", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI8 = childVI3.children[4] // hypersonic <--> hypersonic
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // hypersonic <-> hypersonic
- assertItem(child8, 0, 0, 1, 0, 0, "localDB.script", .orphan, 7)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child1,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 1, 1, "bootstrap", .orphan, 4)
- assertItem(child1.linkedItem, 0, 0, 5, 1, 1, "bootstrap", .orphan, 23)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 1, 1, "data", .orphan, 4)
- assertItem(child2.linkedItem, 0, 0, 5, 1, 1, "data", .orphan, 23)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 1, 6, "hypersonic", .orphan, 4)
- assertItem(child3.linkedItem, 0, 0, 5, 1, 6, "hypersonic", .orphan, 23)
-
- child4 = child3.children[0]
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "dvd.log", .orphan, 1)
-
- child5 = child3.children[1]
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "dvd.properties", .orphan, 2)
-
- child6 = child3.children[2]
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "localDB.lck", .orphan, 3)
-
- child7 = child3.children[3]
- assertItem(child7, 0, 0, 0, 1, 0, "localDB.log", .same, 4)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "localDB.log", .same, 4)
-
- let child8 = child3.children[4]
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "localDB.properties", .orphan, 6)
-
- let child9 = child3.children[5]
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "localDB.script", .orphan, 7)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "bootstrap", .orphan, 4)
- assertItem(child1.linkedItem, 0, 0, 5, 1, 1, "bootstrap", .orphan, 23)
-
- let childVI2 = childVI1.children[0] // bootstrap <--> bootstrap
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // bootstrap <-> bootstrap
- assertItem(child2, 0, 0, 0, 1, 1, "data", .orphan, 4)
- assertItem(child2.linkedItem, 0, 0, 5, 1, 1, "data", .orphan, 23)
-
- let childVI3 = childVI2.children[0] // data <--> data
- assertArrayCount(childVI3.children, 5)
- let child3 = childVI3.item // data <-> data
- assertItem(child3, 0, 0, 0, 1, 6, "hypersonic", .orphan, 4)
- assertItem(child3.linkedItem, 0, 0, 5, 1, 6, "hypersonic", .orphan, 23)
-
- let childVI4 = childVI3.children[0] // hypersonic <--> hypersonic
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // hypersonic <-> hypersonic
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "dvd.log", .orphan, 1)
-
- let childVI5 = childVI3.children[1] // hypersonic <--> hypersonic
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // hypersonic <-> hypersonic
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "dvd.properties", .orphan, 2)
-
- let childVI6 = childVI3.children[2] // hypersonic <--> hypersonic
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // hypersonic <-> hypersonic
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "localDB.lck", .orphan, 3)
-
- let childVI7 = childVI3.children[3] // hypersonic <--> hypersonic
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // hypersonic <-> hypersonic
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "localDB.properties", .orphan, 6)
-
- let childVI8 = childVI3.children[4] // hypersonic <--> hypersonic
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // hypersonic <-> hypersonic
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "localDB.script", .orphan, 7)
- }
- }
-
- @Test func moveFilesAllFilesFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/src/it/unipa/cuc/codicefiscale")
- try createFolder("r/src/it/unipa/cuc/codicefiscale")
-
- // create files
- try createFile("l/src/it/unipa/cuc/codicefiscale/CodiceFiscale.java", "12345")
- try createFile("r/src/it/unipa/cuc/codicefiscale/CodiceFiscale.java", "12345")
- try createFile("l/src/it/unipa/cuc/codicefiscale/CodiceFiscaleChecker.java", "123")
- try createFile("r/src/it/unipa/cuc/codicefiscale/CodiceFiscaleChecker.java", "123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 2, 1, "src", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "src", .orphan, 8)
-
- var child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 2, 1, "it", .orphan, 8)
- assertItem(child2.linkedItem, 0, 0, 0, 2, 1, "it", .orphan, 8)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 2, 1, "unipa", .orphan, 8)
- assertItem(child3.linkedItem, 0, 0, 0, 2, 1, "unipa", .orphan, 8)
-
- var child4 = child3.children[0]
- assertItem(child4, 0, 0, 0, 2, 1, "cuc", .orphan, 8)
- assertItem(child4.linkedItem, 0, 0, 0, 2, 1, "cuc", .orphan, 8)
-
- var child5 = child4.children[0]
- assertItem(child5, 0, 0, 0, 2, 2, "codicefiscale", .orphan, 8)
- assertItem(child5.linkedItem, 0, 0, 0, 2, 2, "codicefiscale", .orphan, 8)
-
- var child6 = child5.children[0]
- assertItem(child6, 0, 0, 0, 1, 0, "CodiceFiscale.java", .same, 5)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "CodiceFiscale.java", .same, 5)
-
- var child7 = child5.children[1]
- assertItem(child7, 0, 0, 0, 1, 0, "CodiceFiscaleChecker.java", .same, 3)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "CodiceFiscaleChecker.java", .same, 3)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 2, 1, "src", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 0, 2, 1, "src", .orphan, 8)
-
- let childVI2 = childVI1.children[0] // src <--> src
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // src <-> src
- assertItem(child2, 0, 0, 0, 2, 1, "it", .orphan, 8)
- assertItem(child2.linkedItem, 0, 0, 0, 2, 1, "it", .orphan, 8)
-
- let childVI3 = childVI2.children[0] // it <--> it
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // it <-> it
- assertItem(child3, 0, 0, 0, 2, 1, "unipa", .orphan, 8)
- assertItem(child3.linkedItem, 0, 0, 0, 2, 1, "unipa", .orphan, 8)
-
- let childVI4 = childVI3.children[0] // unipa <--> unipa
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // unipa <-> unipa
- assertItem(child4, 0, 0, 0, 2, 1, "cuc", .orphan, 8)
- assertItem(child4.linkedItem, 0, 0, 0, 2, 1, "cuc", .orphan, 8)
-
- let childVI5 = childVI4.children[0] // cuc <--> cuc
- assertArrayCount(childVI5.children, 2)
- let child5 = childVI5.item // cuc <-> cuc
- assertItem(child5, 0, 0, 0, 2, 2, "codicefiscale", .orphan, 8)
- assertItem(child5.linkedItem, 0, 0, 0, 2, 2, "codicefiscale", .orphan, 8)
-
- let childVI6 = childVI5.children[0] // codicefiscale <--> codicefiscale
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // codicefiscale <-> codicefiscale
- assertItem(child6, 0, 0, 0, 1, 0, "CodiceFiscale.java", .same, 5)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "CodiceFiscale.java", .same, 5)
-
- let childVI7 = childVI5.children[1] // codicefiscale <--> codicefiscale
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // codicefiscale <-> codicefiscale
- assertItem(child7, 0, 0, 0, 1, 0, "CodiceFiscaleChecker.java", .same, 3)
- assertItem(child7.linkedItem, 0, 0, 0, 1, 0, "CodiceFiscaleChecker.java", .same, 3)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child2,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 0, 1, "src", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 1, "src", .orphan, 8)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 1, "it", .orphan, 8)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 1, "unipa", .orphan, 8)
-
- child4 = child3.children[0]
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 2, 0, 1, "cuc", .orphan, 8)
-
- child5 = child4.children[0]
- assertItem(child5, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 2, 0, 2, "codicefiscale", .orphan, 8)
-
- child6 = child5.children[0]
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "CodiceFiscale.java", .orphan, 5)
-
- child7 = child5.children[1]
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "CodiceFiscaleChecker.java", .orphan, 3)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "src", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 1, "src", .orphan, 8)
-
- let childVI2 = childVI1.children[0] // src <--> src
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // src <-> src
- assertItem(child2, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 1, "it", .orphan, 8)
-
- let childVI3 = childVI2.children[0] // (null) <--> it
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // (null) <-> it
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 1, "unipa", .orphan, 8)
-
- let childVI4 = childVI3.children[0] // (null) <--> unipa
- assertArrayCount(childVI4.children, 1)
- let child4 = childVI4.item // (null) <-> unipa
- assertItem(child4, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 2, 0, 1, "cuc", .orphan, 8)
-
- let childVI5 = childVI4.children[0] // (null) <--> cuc
- assertArrayCount(childVI5.children, 2)
- let child5 = childVI5.item // (null) <-> cuc
- assertItem(child5, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 2, 0, 2, "codicefiscale", .orphan, 8)
-
- let childVI6 = childVI5.children[0] // (null) <--> codicefiscale
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> codicefiscale
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "CodiceFiscale.java", .orphan, 5)
-
- let childVI7 = childVI5.children[1] // (null) <--> codicefiscale
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // (null) <-> codicefiscale
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "CodiceFiscaleChecker.java", .orphan, 3)
- }
- }
-
- @Test func moveFilesOnlyMatches() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder_1")
- try createFolder("r/folder_1")
- try createFolder("l/folder_1/folder_1_1")
- try createFolder("r/folder_1/folder_1_1")
- try createFolder("l/folder_1/folder_1_1/folder_2_1")
- try createFolder("r/folder_1/folder_1_1/folder_2_1")
-
- // create files
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_changed.m", "123")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "1234567890")
- try setFileTimestamp("r/folder_1/folder_1_1/folder_2_1/file_changed.m", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_matched.m", "12345")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_matched.m", "12345")
- try createFile("l/folder_1/folder_1_1/folder_2_1/file_older.m", "1234")
- try setFileTimestamp("l/folder_1/folder_1_1/folder_2_1/file_older.m", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/folder_1/folder_1_1/folder_2_1/file_older.m", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 1, 1, 0, 1, 1, "folder_1", .orphan, 12)
- assertItem(child1.linkedItem, 1, 1, 0, 1, 1, "folder_1", .orphan, 21)
-
- var child2 = child1.children[0]
- assertItem(child2, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 12)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 21)
-
- var child3 = child2.children[0]
- assertItem(child3, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 12)
- assertItem(child3.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 21)
-
- var child4 = child3.children[0]
- assertItem(child4, 0, 1, 0, 0, 0, "file_changed.m", .changed, 3)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 10)
-
- var child5 = child3.children[1]
- assertItem(child5, 0, 0, 0, 1, 0, "file_matched.m", .same, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "file_matched.m", .same, 5)
-
- var child6 = child3.children[2]
- assertItem(child6, 1, 0, 0, 0, 0, "file_older.m", .old, 4)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "file_older.m", .changed, 6)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 1, 0, 1, 1, "folder_1", .orphan, 12)
- assertItem(child1.linkedItem, 1, 1, 0, 1, 1, "folder_1", .orphan, 21)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 12)
- assertItem(child2.linkedItem, 1, 1, 0, 1, 1, "folder_1_1", .orphan, 21)
-
- let childVI3 = childVI2.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // folder_1_1 <-> folder_1_1
- assertItem(child3, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 12)
- assertItem(child3.linkedItem, 1, 1, 0, 1, 3, "folder_2_1", .orphan, 21)
-
- let childVI4 = childVI3.children[0] // folder_2_1 <--> folder_2_1
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder_2_1 <-> folder_2_1
- assertItem(child4, 0, 0, 0, 1, 0, "file_matched.m", .same, 5)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file_matched.m", .same, 5)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child5,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 1, 1, 0, 0, 1, "folder_1", .orphan, 7)
- assertItem(child1.linkedItem, 1, 1, 1, 0, 1, "folder_1", .orphan, 21)
-
- child2 = child1.children[0]
- assertItem(child2, 1, 1, 0, 0, 1, "folder_1_1", .orphan, 7)
- assertItem(child2.linkedItem, 1, 1, 1, 0, 1, "folder_1_1", .orphan, 21)
-
- child3 = child2.children[0]
- assertItem(child3, 1, 1, 0, 0, 3, "folder_2_1", .orphan, 7)
- assertItem(child3.linkedItem, 1, 1, 1, 0, 3, "folder_2_1", .orphan, 21)
-
- child4 = child3.children[0]
- assertItem(child4, 0, 1, 0, 0, 0, "file_changed.m", .changed, 3)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "file_changed.m", .old, 10)
-
- child5 = child3.children[1]
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file_matched.m", .orphan, 5)
-
- child6 = child3.children[2]
- assertItem(child6, 1, 0, 0, 0, 0, "file_older.m", .old, 4)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "file_older.m", .changed, 6)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 1, 0, 0, 1, "folder_1", .orphan, 7)
- assertItem(child1.linkedItem, 1, 1, 1, 0, 1, "folder_1", .orphan, 21)
-
- let childVI2 = childVI1.children[0] // folder_1 <--> folder_1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder_1 <-> folder_1
- assertItem(child2, 1, 1, 0, 0, 1, "folder_1_1", .orphan, 7)
- assertItem(child2.linkedItem, 1, 1, 1, 0, 1, "folder_1_1", .orphan, 21)
-
- let childVI3 = childVI2.children[0] // folder_1_1 <--> folder_1_1
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder_1_1 <-> folder_1_1
- assertItem(child3, 1, 1, 0, 0, 3, "folder_2_1", .orphan, 7)
- assertItem(child3.linkedItem, 1, 1, 1, 0, 3, "folder_2_1", .orphan, 21)
- }
- }
-
- @Test func moveOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/only_on_left")
- try createFolder("l/only_on_left/second_folder")
- try createFolder("l/only_on_left/second_folder/cartella senza titolo")
- try createFolder("l/only_on_left/second_folder/cartella senza titolo 2")
-
- try createFolder("r")
-
- // create files
- try createFile("l/only_on_left/second_folder/symlinks copia.zip", "12345")
- try createFile("l/only_on_left/symlinks.zip", "12345678")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 13)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- var child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- var child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, "symlinks copia.zip", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child6 = child1.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, "symlinks.zip", .orphan, 8)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 13)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, nil, .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> (null)
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // only_on_left <-> (null)
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> (null)
- assertItem(child4, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child2,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0]
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 13)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, "only_on_left", .orphan, 0)
-
- child2 = child1.children[0]
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "second_folder", .orphan, 0)
-
- child3 = child2.children[0]
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
-
- child4 = child2.children[1]
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
-
- child5 = child2.children[2]
- assertItem(child5, 0, 0, 0, 0, 0, "symlinks copia.zip", .orphan, 5)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child6 = child1.children[1]
- assertItem(child6, 0, 0, 0, 0, 0, "symlinks.zip", .orphan, 8)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 2, "only_on_left", .orphan, 13)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 2, "only_on_left", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // only_on_left <--> only_on_left
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // only_on_left <-> only_on_left
- assertItem(child2, 0, 0, 0, 0, 3, "second_folder", .orphan, 5)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 3, "second_folder", .orphan, 0)
-
- let childVI3 = childVI2.children[0] // second_folder <--> second_folder
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // second_folder <-> second_folder
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo", .orphan, 0)
-
- let childVI4 = childVI2.children[1] // second_folder <--> second_folder
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // second_folder <-> second_folder
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "cartella senza titolo 2", .orphan, 0)
- }
- }
-
- @Test func moveDontFollowSymLink() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder1")
- try createFolder("l/folder1/folder2")
- try createFolder("l/folder1/folder2/folder3")
- try createSymlink("l/folder1/folder2/symlink1", "symlink_test1")
-
- try createFolder("r/folder1")
- try createFolder("r/folder1/folder2")
-
- // folders out of comparison but used to create symlinks to them
- try createFolder("symlink_test1")
- try createFolder("symlink_test2")
-
- // create files
- try createSymlink("r/folder1/folder2/folder3", "symlink_test1")
- try createSymlink("r/folder1/folder2/symlink1", "symlink_test2")
- try createSymlink("r/folder1/folder2/orphan_symlink", "symlink_test2")
-
- try createFile("symlink_test1/file1.txt", "12345")
- try createFile("symlink_test2/file2.txt", "123")
- try createFile("r/folder1/folder2/sample.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
-
- var child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
-
- var child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- var child4 = child2.children[1] // folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
-
- var child5 = child2.children[2] // folder2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
-
- var child6 = child2.children[3] // folder2
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
-
- var child7 = child2.children[4] // folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 5)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // folder2 <--> folder2
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder2 <-> folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
-
- let childVI5 = childVI2.children[2] // folder2 <--> folder2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder2 <-> folder2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
-
- let childVI6 = childVI2.children[3] // folder2 <--> folder2
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder2 <-> folder2
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
-
- let childVI7 = childVI2.children[4] // folder2 <--> folder2
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder2 <-> folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- }
-
- try assertOnlySetup()
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child2.linkedItem!,
- srcBaseDir: appendFolder("r"),
- destBaseDir: appendFolder("l")
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
-
- child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child4 = child2.children[1] // folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- try assertSymlink(child4.linkedItem!, "symlink_test1", true)
-
- child5 = child2.children[2] // folder2
- assertItem(child5, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- try assertSymlink(child5, "symlink_test2", true)
-
- child6 = child2.children[3] // folder2
- assertItem(child6, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- child7 = child2.children[4] // folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- try assertSymlink(child7, "symlink_test2", true)
-
- assertErrors(fileOperationDelegate.errors, [
- FileError.createSymLink(path: child3.path!),
- ])
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "folder1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 5)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 1, 0, 5, "folder2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 5, "folder2", .orphan, 0)
-
- let childVI3 = childVI2.children[0] // folder2 <--> folder2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[1] // folder2 <--> folder2
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // folder2 <-> folder2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
-
- let childVI5 = childVI2.children[2] // folder2 <--> folder2
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // folder2 <-> folder2
- assertItem(child5, 0, 0, 0, 0, 0, "orphan_symlink", .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI2.children[3] // folder2 <--> folder2
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // folder2 <-> folder2
- assertItem(child6, 0, 0, 1, 0, 0, "sample.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI2.children[4] // folder2 <--> folder2
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // folder2 <-> folder2
- assertItem(child7, 0, 0, 0, 0, 0, "symlink1", .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func moveFailure() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("l/dir1/dir2/dir3")
-
- // create files
- try createFile("l/dir1/dir2/dir3/file1.txt", "1234567")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- // simulate a copy error deleting the file to copy
- do {
- try fm.removeItem(atPath: child4.path!)
- } catch {
- Issue.record("Found error \(error)")
- }
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // dir2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // dir2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // dir3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child4,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- child1 = rootL.children[0] // l
- do {
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir3
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 1, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // dir2 <--> (null)
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // dir2 <-> (null)
- assertItem(child3, 0, 0, 1, 0, 1, "dir3", .orphan, 7)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI4 = childVI3.children[0] // dir3 <--> (null)
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir3 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file1.txt", .orphan, 7)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func movePreserveFolderTimestamp() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/folder1/folder2/folder3")
- try createFolder("r/folder1")
-
- try setFileCreationTime("l/folder1", "2010-01-01 00: 00: 00 +0000")
- try setFileTimestamp("l/folder1", "2010-02-02 02: 02: 00 +0000")
-
- try setFileCreationTime("l/folder1/folder2", "2010-04-04 04: 04: 00 +0000")
- try setFileTimestamp("l/folder1/folder2", "2010-05-05 05: 05: 00 +0000")
-
- try setFileCreationTime("l/folder1/folder2/folder3", "2011-05-05 05: 00: 30 +0000")
- try setFileTimestamp("l/folder1/folder2/folder3", "2011-06-06 06: 00: 30 +0000")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 0, 1, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let child3 = child2.children[0] // folder2
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 0, 1, "folder2", .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, nil, .orphan, 0)
-
- let childVI3 = childVI2.children[0] // folder2 <--> (null)
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // folder2 <-> (null)
- assertItem(child3, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: child2,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "folder2", .orphan, 0)
- try assertTimestamps(child2.linkedItem, "2010-04-04 04: 04: 00 +0000", "2010-05-05 05: 05: 00 +0000")
-
- let child3 = child2.children[0] // (null)
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- try assertTimestamps(child3.linkedItem, "2011-05-05 05: 00: 30 +0000", "2011-06-06 06: 00: 30 +0000")
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "folder1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // folder1 <--> folder1
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // folder1 <-> folder1
- assertItem(child2, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 1, "folder2", .orphan, 0)
-
- let childVI3 = childVI2.children[0] // (null) <--> folder2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // (null) <-> folder2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 0, "folder3", .orphan, 0)
- }
- }
-
- @Test(.disabled("BUG 0000230: Orphan file not colored correctly after move: Not yet fixed, this test fails")) func moveMatchFileBecomeFiltered() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp, .size, .alignMatchCase],
- delegate: comparatorDelegate,
- bufferSize: 8192,
- isLeftCaseSensitive: false,
- isRightCaseSensitive: false
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: true,
- hideEmptyFolders: true,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .noOrphan
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l")
- try createFolder("r")
-
- // create files
- try createFile("l/file1.html", "12345678901")
- try createFile("r/file1.html", "12345678901")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let moveItem: CompareItem
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 1, 1, "l", .orphan, 11)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "r", .orphan, 11)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "file1.html", .same, 11)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "file1.html", .same, 11)
-
- moveItem = child2
- }
-
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 1, 1, "l", .orphan, 11)
- assertItem(child1.linkedItem, 0, 0, 0, 1, 1, "r", .orphan, 11)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 1, 0, "file1.html", .same, 11)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "file1.html", .same, 11)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: false)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = MoveCompareItem(
- operationManager: fileOperationManager,
- bigFileSizeThreshold: 100_000
- )
-
- fileOperation.move(
- srcRoot: moveItem,
- srcBaseDir: appendFolder("l"),
- destBaseDir: appendFolder("r")
- )
-
- do {
- let child1 = rootL // l <-> r
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "r", .orphan, 11)
-
- let child2 = child1.children[0] // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "file1.html", .orphan, 11)
- }
- do {
- // VisibleItems
- let childVI1 = vi // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // (null) <-> (null)
- assertItem(child1, 0, 0, 0, 0, 1, "l", .orphan, 0)
- assertItem(child1.linkedItem, 0, 0, 1, 0, 1, "r", .orphan, 11)
-
- let childVI2 = childVI1.children[0] // l <--> r
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // l <-> r
- assertItem(child2, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 1, 0, 0, "file1.html", .orphan, 11)
- #expect(child2.isFiltered == true, "\(child2.fileName!) must be filtered")
- #expect(child2.linkedItem!.isFiltered == true, "\(child2.linkedItem!.fileName!) must be filtered")
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/RenameFilesTests.swift b/Tests/Sources/FileSystem/Tests/RenameFilesTests.swift
deleted file mode 100644
index 4c99593..0000000
--- a/Tests/Sources/FileSystem/Tests/RenameFilesTests.swift
+++ /dev/null
@@ -1,2296 +0,0 @@
-//
-// RenameFilesTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 27/04/13.
-// Copyright (c) 2013 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable file_length force_unwrapping function_body_length
-final class RenameFilesTests: BaseTests {
- @Test func renameFileOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/dir1")
- try createFolder("r/dir1")
-
- try createFile("l/dir1/100.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- var child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 0, "100.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child2,
- toName: "110.txt"
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFileOrphanToOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
-
- // create files
- try createFile("r/dir1/dir2/010.txt", "123")
- try createFile("l/dir1/dir2/100.txt", "12")
- try createFile("r/dir1/dir2/109.txt", "1234")
- try createFile("l/dir1/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 3, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2
- assertItem(child4, 0, 0, 1, 0, 0, "100.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child2.children[2] // dir2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "109.txt", .orphan, 4)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
- fileOperation.rename(
- srcRoot: child4,
- toName: "110.txt"
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 3, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "109.txt", .orphan, 4)
-
- let child5 = child2.children[2] // dir2
- assertItem(child5, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- // must be recreated
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 2, "dir1", .orphan, 7)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 3, "dir2", .orphan, 7)
-
- let childVI3 = childVI2.children[0] // dir2 <--> dir2
- let child3 = childVI3.item // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let childVI4 = childVI2.children[1] // dir2 <--> dir2
- let child4 = childVI4.item // dir2 <-> dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "109.txt", .orphan, 4)
-
- let childVI5 = childVI2.children[2] // dir2 <--> dir2
- let child5 = childVI5.item // dir2 <-> dir2
- assertItem(child5, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI6 = childVI1.children[1] // dir1 <--> dir1
- let child6 = childVI6.item // dir1 <-> dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFileOrphanToMatching() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
-
- // create files
- try createFile("r/dir1/dir2/010.txt", "123")
- try createFile("l/dir1/dir2/100.txt", "12")
- try createFile("r/dir1/dir2/109.txt", "1234")
- try createFile("l/dir1/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 3, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2
- assertItem(child4, 0, 0, 1, 0, 0, "100.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child2.children[2] // dir2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "109.txt", .orphan, 4)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child4,
- toName: "109.txt"
- )
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 1, 1, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1 <-> dir1
- assertItem(child2, 0, 1, 0, 0, 2, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 2, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2 <-> dir2
- assertItem(child4, 0, 1, 0, 0, 0, "109.txt", .changed, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "109.txt", .changed, 4)
-
- let child5 = child1.children[1] // dir1 <-> dir1
- assertItem(child5, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 1, 1, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 1, 1, 0, 2, "dir1", .orphan, 7)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 1, 0, 0, 2, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 1, 1, 0, 2, "dir2", .orphan, 7)
-
- let childVI3 = childVI2.children[0] // dir2 <--> dir2
- let child3 = childVI3.item // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let childVI4 = childVI2.children[1] // dir2 <--> dir2
- let child4 = childVI4.item // dir2 <-> dir2
- assertItem(child4, 0, 1, 0, 0, 0, "109.txt", .changed, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "109.txt", .changed, 4)
-
- let childVI5 = childVI1.children[1] // dir1 <--> dir1
- let child5 = childVI5.item // dir1 <-> dir1
- assertItem(child5, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFileMismatch() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
-
- // create files
- try createFile("r/dir1/dir2/010.txt", "123")
- try createFile("r/dir1/dir2/50.txt", "1234")
- try createFile("l/dir1/dir2/100.txt", "12")
- try createFile("r/dir1/dir2/100.txt", "1234")
- try createFile("l/dir1/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 1, 1, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 1, 2, 0, 2, "dir1", .orphan, 11)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 1, 0, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 1, 2, 0, 3, "dir2", .orphan, 11)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child5 = child2.children[1] // dir2
- assertItem(child5, 0, 1, 0, 0, 0, "100.txt", .changed, 2)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "100.txt", .changed, 4)
-
- let child4 = child2.children[2] // dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "50.txt", .orphan, 4)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child5,
- toName: "110.txt"
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 3, 0, 2, "dir1", .orphan, 11)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 4, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 3, 0, 4, "dir2", .orphan, 11)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child5 = child2.children[1] // dir2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "100.txt", .orphan, 4)
-
- let child6 = child2.children[2] // dir2
- assertItem(child6, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child4 = child2.children[3] // dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "50.txt", .orphan, 4)
-
- let child7 = child1.children[1] // dir1
- assertItem(child7, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 2, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 3, 0, 2, "dir1", .orphan, 11)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 4, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 3, 0, 4, "dir2", .orphan, 11)
-
- let childVI3 = childVI2.children[0] // dir2 <--> dir2
- let child3 = childVI3.item // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let childVI5 = childVI2.children[1] // dir2 <--> dir2
- let child5 = childVI5.item // dir2 <-> dir2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "100.txt", .orphan, 4)
-
- let childVI6 = childVI2.children[2] // dir2 <--> dir2
- let child6 = childVI6.item // dir2 <-> dir2
- assertItem(child6, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI4 = childVI2.children[3] // dir2 <--> dir2
- let child4 = childVI4.item // dir2 <-> dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "50.txt", .orphan, 4)
-
- let childVI7 = childVI1.children[1] // dir1 <--> dir1
- let child7 = childVI7.item // dir1 <-> dir1
- assertItem(child7, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFileMatchingToMatching() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
-
- // create files
- try createFile("r/dir1/dir2/010.txt", "123")
- try createFile("l/dir1/dir2/100.txt", "12")
- try createFile("r/dir1/dir2/100.txt", "1234")
- try createFile("r/dir1/dir2/110.txt", "12")
- try createFile("l/dir1/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 1, 1, 0, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 1, 2, 0, 2, "dir1", .orphan, 9)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 1, 0, 0, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 1, 2, 0, 3, "dir2", .orphan, 9)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2
- assertItem(child4, 0, 1, 0, 0, 0, "100.txt", .changed, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "100.txt", .changed, 4)
-
- let child5 = child2.children[2] // dir2
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child4,
- toName: "110.txt"
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 1, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 2, "dir1", .orphan, 9)
-
- let child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 0, 1, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 1, 3, "dir2", .orphan, 9)
-
- let child3 = child2.children[0] // dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "100.txt", .orphan, 4)
-
- let child5 = child2.children[2] // dir2
- assertItem(child5, 0, 0, 0, 1, 0, "110.txt", .same, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 1, 0, "110.txt", .same, 2)
-
- let child6 = child1.children[1] // dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 2)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 1, 2, "dir1", .orphan, 8)
- assertItem(child1.linkedItem, 0, 0, 2, 1, 2, "dir1", .orphan, 9)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 0, 1, 3, "dir2", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 2, 1, 3, "dir2", .orphan, 9)
-
- let childVI3 = childVI2.children[0] // dir2 <--> dir2
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let childVI4 = childVI2.children[1] // dir2 <--> dir2
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir2 <-> dir2
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "100.txt", .orphan, 4)
-
- let childVI5 = childVI1.children[1] // dir1 <--> dir1
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // dir1 <-> dir1
- assertItem(child5, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFileOrphanToOrphan_OnlyOrphan_Right() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyOrphans
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir1")
- try createFolder("r/dir1")
- try createFolder("l/dir1/dir2")
- try createFolder("r/dir1/dir2")
-
- // create files
- try createFile("r/dir1/dir2/010.txt", "123")
- try createFile("l/dir1/dir2/100.txt", "12345")
- try createFile("r/dir1/dir2/100.txt", "1234")
- try setFileTimestamp("r/dir1/dir2/100.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("l/dir1/dir2/110.txt", "12")
- try createFile("l/dir1/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 1, 2, 0, 2, "dir1", .orphan, 13)
- assertItem(child1.linkedItem, 1, 0, 1, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1 <-> dir1
- assertItem(child2, 0, 1, 1, 0, 3, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 1, 0, 1, 0, 3, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2 <-> dir2
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "010.txt", .orphan, 3)
-
- let child4 = child2.children[1] // dir2 <-> dir2
- assertItem(child4, 0, 1, 0, 0, 0, "100.txt", .changed, 5)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "100.txt", .old, 4)
-
- let child5 = child2.children[2] // dir2 <-> dir2
- assertItem(child5, 0, 0, 1, 0, 0, "110.txt", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[1] // dir1 <-> dir1
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child3.linkedItem!,
- toName: "110.txt"
- )
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 2, 1, 0, 2, "dir1", .orphan, 13)
- assertItem(child1.linkedItem, 1, 1, 0, 0, 2, "dir1", .orphan, 7)
-
- let child2 = child1.children[0] // dir1 <-> dir1
- assertItem(child2, 0, 2, 0, 0, 2, "dir2", .orphan, 7)
- assertItem(child2.linkedItem, 1, 1, 0, 0, 2, "dir2", .orphan, 7)
-
- let child3 = child2.children[0] // dir2 <-> dir2
- assertItem(child3, 0, 1, 0, 0, 0, "100.txt", .changed, 5)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 0, "100.txt", .old, 4)
-
- let child4 = child2.children[1] // dir2 <-> dir2
- assertItem(child4, 0, 1, 0, 0, 0, "110.txt", .changed, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "110.txt", .changed, 3)
-
- let child5 = child1.children[1] // dir1 <-> dir1
- assertItem(child5, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 2, 1, 0, 2, "dir1", .orphan, 13)
- assertItem(child1.linkedItem, 1, 1, 0, 0, 2, "dir1", .orphan, 7)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- // MARK: -
-
- // MARK: Folders rename tests
-
- @Test func renameFolderFromBothSidesToOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir100")
- try createFolder("r/dir100")
- try createFolder("l/dir100/dir110")
- try createFolder("r/dir100/dir110")
-
- // create files
- try createFile("l/dir100/dir110/file001.txt", "12")
- try createFile("r/dir100/dir110/file001.txt", "123")
- try createFile("l/dir100/dir110/file002.txt", "123456")
- try createFile("r/dir100/dir110/file002.txt", "123456")
- try createFile("l/dir100/dir110/file003.txt", "12")
- try createFile("l/dir100/011.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 1, 2, 1, 2, "dir100", .orphan, 16)
- assertItem(child1.linkedItem, 0, 1, 0, 1, 2, "dir100", .orphan, 9)
-
- let child2 = child1.children[0] // dir100
- assertItem(child2, 0, 1, 1, 1, 3, "dir110", .orphan, 10)
- assertItem(child2.linkedItem, 0, 1, 0, 1, 3, "dir110", .orphan, 9)
-
- let child3 = child2.children[0] // dir110
- assertItem(child3, 0, 1, 0, 0, 0, "file001.txt", .changed, 2)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "file001.txt", .changed, 3)
-
- let child4 = child2.children[1] // dir110
- assertItem(child4, 0, 0, 0, 1, 0, "file002.txt", .same, 6)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file002.txt", .same, 6)
-
- let child5 = child2.children[2] // dir110
- assertItem(child5, 0, 0, 1, 0, 0, "file003.txt", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child1.children[1] // dir100
- assertItem(child6, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child2,
- toName: "dir120"
- )
-
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 4, 0, 3, "dir100", .orphan, 16)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 3, "dir100", .orphan, 9)
-
- let child2 = child1.children[0] // dir100
- assertItem(child2, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 9)
-
- let child3 = child2.children[0] // (null)
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file001.txt", .orphan, 3)
-
- let child4 = child2.children[1] // (null)
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file002.txt", .orphan, 6)
-
- let child5 = child1.children[1] // dir100
- assertItem(child5, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child6 = child5.children[0] // dir120
- assertItem(child6, 0, 0, 1, 0, 0, "file001.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child5.children[1] // dir120
- assertItem(child7, 0, 0, 1, 0, 0, "file002.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child8 = child5.children[2] // dir120
- assertItem(child8, 0, 0, 1, 0, 0, "file003.txt", .orphan, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child9 = child1.children[2] // dir100
- assertItem(child9, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 3)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 4, 0, 3, "dir100", .orphan, 16)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 3, "dir100", .orphan, 9)
-
- let childVI2 = childVI1.children[0] // dir100 <--> dir100
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // dir100 <-> dir100
- assertItem(child2, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 9)
-
- let childVI3 = childVI2.children[0] // (null) <--> dir110
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // (null) <-> dir110
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file001.txt", .orphan, 3)
-
- let childVI4 = childVI2.children[1] // (null) <--> dir110
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file002.txt", .orphan, 6)
-
- let childVI5 = childVI1.children[1] // dir100 <--> dir100
- assertArrayCount(childVI5.children, 3)
- let child5 = childVI5.item // dir100 <-> dir100
- assertItem(child5, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI6 = childVI5.children[0] // dir120 <--> (null)
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // dir120 <-> (null)
- assertItem(child6, 0, 0, 1, 0, 0, "file001.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI5.children[1] // dir120 <--> (null)
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // dir120 <-> (null)
- assertItem(child7, 0, 0, 1, 0, 0, "file002.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI8 = childVI5.children[2] // dir120 <--> (null)
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // dir120 <-> (null)
- assertItem(child8, 0, 0, 1, 0, 0, "file003.txt", .orphan, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI9 = childVI1.children[2] // dir100 <--> dir100
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // dir100 <-> dir100
- assertItem(child9, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-
- @Test func renameFolderOrphanToOrphan() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir050")
- try createFolder("r/dir050")
- try createFolder("l/dir050/dir100")
- try createFolder("r/dir050/dir100")
- try createFolder("l/dir050/dir100/dir105")
- try createFolder("r/dir050/dir100/dir110")
-
- // create files
- try createFile("l/dir050/dir100/dir105/file101.txt", "12")
- try createFile("l/dir050/dir100/dir105/file102.txt", "123456")
- try createFile("l/dir050/dir100/dir105/file103.txt", "12")
- try createFile("r/dir050/dir100/dir110/file401.txt", "12")
- try createFile("r/dir050/dir100/dir110/file403.txt", "123")
- try createFile("l/dir050/dir100/011.txt", "123456")
- try createFile("r/dir050/dir100/file301.txt", "123")
- try createFile("r/dir050/dir100/file302.txt", "123456")
- try createFile("l/dir050/020.txt", "123456")
- try createFile("l/dir050/040.txt", "123456")
- try createFile("r/dir050/file201.txt", "123")
- try createFile("r/dir050/file202.txt", "123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 6, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 6, 0, 5, "dir050", .orphan, 20)
-
- let child2 = child1.children[0] // dir050
- assertItem(child2, 0, 0, 4, 0, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 4, 0, 5, "dir100", .orphan, 14)
-
- let child3 = child2.children[0] // dir100
- assertItem(child3, 0, 0, 3, 0, 3, "dir105", .orphan, 10)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir105
- assertItem(child4, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child3.children[1] // dir105
- assertItem(child5, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child3.children[2] // dir105
- assertItem(child6, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child2.children[1] // dir100
- assertItem(child7, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 5)
-
- let child8 = child7.children[0] // (null)
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let child9 = child7.children[1] // (null)
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file403.txt", .orphan, 3)
-
- let child10 = child2.children[2] // dir100
- assertItem(child10, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child11 = child2.children[3] // dir100
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child12 = child2.children[4] // dir100
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child13 = child1.children[1] // dir050
- assertItem(child13, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[2] // dir050
- assertItem(child14, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child15 = child1.children[3] // dir050
- assertItem(child15, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child15.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child16 = child1.children[4] // dir050
- assertItem(child16, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child16.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child3,
- toName: "dir120"
- )
- do {
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 6, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 6, 0, 5, "dir050", .orphan, 20)
-
- let child2 = child1.children[0] // dir050
- assertItem(child2, 0, 0, 4, 0, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 4, 0, 5, "dir100", .orphan, 14)
-
- let child3 = child2.children[0] // dir100
- assertItem(child3, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 5)
-
- let child4 = child3.children[0] // (null)
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let child5 = child3.children[1] // (null)
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file403.txt", .orphan, 3)
-
- let child6 = child2.children[1] // dir100
- assertItem(child6, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child7 = child6.children[0] // dir120
- assertItem(child7, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child8 = child6.children[1] // dir120
- assertItem(child8, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child9 = child6.children[2] // dir120
- assertItem(child9, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child10 = child2.children[2] // dir100
- assertItem(child10, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child11 = child2.children[3] // dir100
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child12 = child2.children[4] // dir100
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child13 = child1.children[1] // dir050
- assertItem(child13, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[2] // dir050
- assertItem(child14, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child15 = child1.children[3] // dir050
- assertItem(child15, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child15.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child16 = child1.children[4] // dir050
- assertItem(child16, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child16.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 5)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 6, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 6, 0, 5, "dir050", .orphan, 20)
-
- let childVI2 = childVI1.children[0] // dir050 <--> dir050
- assertArrayCount(childVI2.children, 5)
- let child2 = childVI2.item // dir050 <-> dir050
- assertItem(child2, 0, 0, 4, 0, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 4, 0, 5, "dir100", .orphan, 14)
-
- let childVI3 = childVI2.children[0] // dir100 <--> dir100
- assertArrayCount(childVI3.children, 2)
- let child3 = childVI3.item // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 5)
-
- let childVI4 = childVI3.children[0] // (null) <--> dir110
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let childVI5 = childVI3.children[1] // (null) <--> dir110
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> dir110
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file403.txt", .orphan, 3)
-
- let childVI6 = childVI2.children[1] // dir100 <--> dir100
- assertArrayCount(childVI6.children, 3)
- let child6 = childVI6.item // dir100 <-> dir100
- assertItem(child6, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let childVI7 = childVI6.children[0] // dir120 <--> (null)
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // dir120 <-> (null)
- assertItem(child7, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI8 = childVI6.children[1] // dir120 <--> (null)
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // dir120 <-> (null)
- assertItem(child8, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI9 = childVI6.children[2] // dir120 <--> (null)
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // dir120 <-> (null)
- assertItem(child9, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI10 = childVI2.children[2] // dir100 <--> dir100
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // dir100 <-> dir100
- assertItem(child10, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI11 = childVI2.children[3] // dir100 <--> dir100
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // dir100 <-> dir100
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let childVI12 = childVI2.children[4] // dir100 <--> dir100
- assertArrayCount(childVI12.children, 0)
- let child12 = childVI12.item // dir100 <-> dir100
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let childVI13 = childVI1.children[1] // dir050 <--> dir050
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // dir050 <-> dir050
- assertItem(child13, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI14 = childVI1.children[2] // dir050 <--> dir050
- assertArrayCount(childVI14.children, 0)
- let child14 = childVI14.item // dir050 <-> dir050
- assertItem(child14, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI15 = childVI1.children[3] // dir050 <--> dir050
- assertArrayCount(childVI15.children, 0)
- let child15 = childVI15.item // dir050 <-> dir050
- assertItem(child15, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child15.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let childVI16 = childVI1.children[4] // dir050 <--> dir050
- assertArrayCount(childVI16.children, 0)
- let child16 = childVI16.item // dir050 <-> dir050
- assertItem(child16, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child16.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- }
-
- @Test func renameFolderMatchingToMatching() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/dir050")
- try createFolder("r/dir050")
- try createFolder("l/dir050/dir100")
- try createFolder("r/dir050/dir100")
- try createFolder("l/dir050/dir100/dir110")
- try createFolder("r/dir050/dir100/dir110")
- try createFolder("r/dir050/dir100/dir120")
-
- // create files
- try createFile("l/dir050/dir100/dir110/file101.txt", "12")
- try createFile("r/dir050/dir100/dir110/file101.txt", "12")
- try createFile("l/dir050/dir100/dir110/file102.txt", "123456")
- try createFile("l/dir050/dir100/dir110/file103.txt", "12")
- try setFileTimestamp("l/dir050/dir100/dir110/file103.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/dir050/dir100/dir110/file103.txt", "123")
- try createFile("r/dir050/dir100/dir110/file104.txt", "1234567")
- try createFile("r/dir050/dir100/dir120/file101.txt", "12")
- try createFile("r/dir050/dir100/dir120/file102.txt", "123456")
- try createFile("r/dir050/dir100/dir120/file103.txt", "12")
- try createFile("l/dir050/dir100/011.txt", "123456")
- try createFile("r/dir050/dir100/file301.txt", "123")
- try createFile("r/dir050/dir100/file302.txt", "123456")
- try createFile("l/dir050/020.txt", "123456")
- try createFile("l/dir050/040.txt", "123456")
- try createFile("r/dir050/file201.txt", "123")
- try createFile("r/dir050/file202.txt", "123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 1, 0, 4, 1, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 1, 8, 1, 5, "dir050", .orphan, 37)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 1, 0, 2, 1, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 6, 1, 5, "dir100", .orphan, 31)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 1, 0, 1, 1, 4, "dir110", .orphan, 10)
- assertItem(child3.linkedItem, 0, 1, 1, 1, 4, "dir110", .orphan, 12)
-
- let child4 = child3.children[0] // dir110 <-> dir110
- assertItem(child4, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
-
- let child5 = child3.children[1] // dir110 <-> dir110
- assertItem(child5, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child3.children[2] // dir110 <-> dir110
- assertItem(child6, 1, 0, 0, 0, 0, "file103.txt", .old, 2)
- assertItem(child6.linkedItem, 0, 1, 0, 0, 0, "file103.txt", .changed, 3)
-
- let child7 = child3.children[3] // dir110 <-> dir110
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file104.txt", .orphan, 7)
-
- let child8 = child2.children[1] // dir100 <-> dir100
- assertItem(child8, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
-
- let child9 = child8.children[0] // (null) <-> dir120
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child10 = child8.children[1] // (null) <-> dir120
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
-
- let child11 = child8.children[2] // (null) <-> dir120
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
-
- let child12 = child2.children[2] // dir100 <-> dir100
- assertItem(child12, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child13 = child2.children[3] // dir100 <-> dir100
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child14 = child2.children[4] // dir100 <-> dir100
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child15 = child1.children[1] // dir050 <-> dir050
- assertItem(child15, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child15.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child16 = child1.children[2] // dir050 <-> dir050
- assertItem(child16, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child16.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child17 = child1.children[3] // dir050 <-> dir050
- assertItem(child17, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child17.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child18 = child1.children[4] // dir050 <-> dir050
- assertItem(child18, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child18.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child3,
- toName: "dir120"
- )
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 0, 3, 3, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 7, 3, 5, "dir050", .orphan, 37)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 0, 0, 1, 3, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 5, 3, 5, "dir100", .orphan, 31)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "dir110", .orphan, 12)
-
- let child4 = child3.children[0] // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child5 = child3.children[1] // (null) <-> dir110
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file103.txt", .orphan, 3)
-
- let child6 = child3.children[2] // (null) <-> dir110
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file104.txt", .orphan, 7)
-
- let child7 = child2.children[1] // dir100 <-> dir100
- assertItem(child7, 0, 0, 0, 3, 3, "dir120", .orphan, 10)
- assertItem(child7.linkedItem, 0, 0, 0, 3, 3, "dir120", .orphan, 10)
-
- let child8 = child7.children[0] // dir120 <-> dir120
- assertItem(child8, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
-
- let child9 = child7.children[1] // dir120 <-> dir120
- assertItem(child9, 0, 0, 0, 1, 0, "file102.txt", .same, 6)
- assertItem(child9.linkedItem, 0, 0, 0, 1, 0, "file102.txt", .same, 6)
-
- let child10 = child7.children[2] // dir120 <-> dir120
- assertItem(child10, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
-
- let child11 = child2.children[2] // dir100 <-> dir100
- assertItem(child11, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child12 = child2.children[3] // dir100 <-> dir100
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child13 = child2.children[4] // dir100 <-> dir100
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child14 = child1.children[1] // dir050 <-> dir050
- assertItem(child14, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child15 = child1.children[2] // dir050 <-> dir050
- assertItem(child15, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child15.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child16 = child1.children[3] // dir050 <-> dir050
- assertItem(child16, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child16.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child17 = child1.children[4] // dir050 <-> dir050
- assertItem(child17, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child17.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 5)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 3, 3, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 7, 3, 5, "dir050", .orphan, 37)
-
- let childVI2 = childVI1.children[0] // dir050 <--> dir050
- assertArrayCount(childVI2.children, 4)
- let child2 = childVI2.item // dir050 <-> dir050
- assertItem(child2, 0, 0, 1, 3, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 5, 3, 5, "dir100", .orphan, 31)
-
- let childVI3 = childVI2.children[0] // dir100 <--> dir100
- assertArrayCount(childVI3.children, 3)
- let child3 = childVI3.item // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 3, 0, 3, "dir110", .orphan, 12)
-
- let childVI4 = childVI3.children[0] // (null) <--> dir110
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let childVI5 = childVI3.children[1] // (null) <--> dir110
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // (null) <-> dir110
- assertItem(child5, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 1, 0, 0, "file103.txt", .orphan, 3)
-
- let childVI6 = childVI3.children[2] // (null) <--> dir110
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // (null) <-> dir110
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file104.txt", .orphan, 7)
-
- let childVI7 = childVI2.children[1] // dir100 <--> dir100
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // dir100 <-> dir100
- assertItem(child7, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI8 = childVI2.children[2] // dir100 <--> dir100
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // dir100 <-> dir100
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let childVI9 = childVI2.children[3] // dir100 <--> dir100
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // dir100 <-> dir100
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let childVI10 = childVI1.children[1] // dir050 <--> dir050
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // dir050 <-> dir050
- assertItem(child10, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI11 = childVI1.children[2] // dir050 <--> dir050
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // dir050 <-> dir050
- assertItem(child11, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI12 = childVI1.children[3] // dir050 <--> dir050
- assertArrayCount(childVI12.children, 0)
- let child12 = childVI12.item // dir050 <-> dir050
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let childVI13 = childVI1.children[4] // dir050 <--> dir050
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // dir050 <-> dir050
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- }
-
- @Test func renameFolder_NoOrphan_Left() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .noOrphan
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir050")
- try createFolder("r/dir050")
- try createFolder("l/dir050/dir100")
- try createFolder("r/dir050/dir100")
- try createFolder("r/dir050/dir100/dir110")
- try createFolder("l/dir050/dir100/dir120")
- try createFolder("r/dir050/dir100/dir120")
-
- // create files
- try createFile("r/dir050/dir100/dir110/file101.txt", "12")
- try createFile("l/dir050/dir100/dir120/file101.txt", "12")
- try createFile("r/dir050/dir100/dir120/file101.txt", "12")
- try createFile("l/dir050/dir100/dir120/file102.txt", "123456")
- try setFileTimestamp("l/dir050/dir100/dir120/file102.txt", "2001-03-24 10: 45: 32 +0600")
- try createFile("r/dir050/dir100/dir120/file102.txt", "123")
- try createFile("l/dir050/dir100/dir120/file103.txt", "12")
- try createFile("r/dir050/dir100/dir120/file103.txt", "12")
- try createFile("l/dir050/dir100/011.txt", "123456")
- try createFile("l/dir050/050.txt", "123456")
- try createFile("r/dir050/050.txt", "123456")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 1, 0, 1, 3, 2, "dir050", .orphan, 22)
- assertItem(child1.linkedItem, 0, 1, 1, 3, 2, "dir050", .orphan, 15)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 1, 0, 1, 2, 3, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 1, 2, 3, "dir100", .orphan, 9)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 1, "dir110", .orphan, 2)
-
- let child4 = child3.children[0] // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child5 = child2.children[1] // dir100 <-> dir100
- assertItem(child5, 1, 0, 0, 2, 3, "dir120", .orphan, 10)
- assertItem(child5.linkedItem, 0, 1, 0, 2, 3, "dir120", .orphan, 7)
-
- let child6 = child5.children[0] // dir120 <-> dir120
- assertItem(child6, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 1, 0, "file101.txt", .same, 2)
-
- let child7 = child5.children[1] // dir120 <-> dir120
- assertItem(child7, 1, 0, 0, 0, 0, "file102.txt", .old, 6)
- assertItem(child7.linkedItem, 0, 1, 0, 0, 0, "file102.txt", .changed, 3)
-
- let child8 = child5.children[2] // dir120 <-> dir120
- assertItem(child8, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 1, 0, "file103.txt", .same, 2)
-
- let child9 = child2.children[2] // dir100 <-> dir100
- assertItem(child9, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child10 = child1.children[1] // dir050 <-> dir050
- assertItem(child10, 0, 0, 0, 1, 0, "050.txt", .same, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 1, 0, "050.txt", .same, 6)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child5,
- toName: "dir150"
- )
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 0, 4, 1, 2, "dir050", .orphan, 22)
- assertItem(child1.linkedItem, 0, 0, 4, 1, 2, "dir050", .orphan, 15)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 0, 0, 4, 0, 4, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 4, 0, 4, "dir100", .orphan, 9)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 0, 0, 0, 1, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 1, "dir110", .orphan, 2)
-
- let child4 = child3.children[0] // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child5 = child2.children[1] // dir100 <-> dir100
- assertItem(child5, 0, 0, 0, 0, 3, nil, .orphan, 0)
- assertItem(child5.linkedItem, 0, 0, 3, 0, 3, "dir120", .orphan, 7)
-
- let child6 = child5.children[0] // (null) <-> dir120
- assertItem(child6, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child6.linkedItem, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
-
- let child7 = child5.children[1] // (null) <-> dir120
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file102.txt", .orphan, 3)
-
- let child8 = child5.children[2] // (null) <-> dir120
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
-
- let child9 = child2.children[2] // dir100 <-> dir100
- assertItem(child9, 0, 0, 3, 0, 3, "dir150", .orphan, 10)
- assertItem(child9.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child10 = child9.children[0] // dir150 <-> (null)
- assertItem(child10, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child11 = child9.children[1] // dir150 <-> (null)
- assertItem(child11, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child12 = child9.children[2] // dir150 <-> (null)
- assertItem(child12, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child13 = child2.children[3] // dir100 <-> dir100
- assertItem(child13, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[1] // dir050 <-> dir050
- assertItem(child14, 0, 0, 0, 1, 0, "050.txt", .same, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 1, 0, "050.txt", .same, 6)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 4, 1, 2, "dir050", .orphan, 22)
- assertItem(child1.linkedItem, 0, 0, 4, 1, 2, "dir050", .orphan, 15)
-
- let childVI2 = childVI1.children[0] // dir050 <--> dir050
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // dir050 <-> dir050
- assertItem(child2, 0, 0, 0, 1, 0, "050.txt", .same, 6)
- assertItem(child2.linkedItem, 0, 0, 0, 1, 0, "050.txt", .same, 6)
- }
- }
-
- @Test func renameFolderOrphanToOrphan_OnlyMismatches_Right() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: true,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir050")
- try createFolder("r/dir050")
- try createFolder("l/dir050/dir100")
- try createFolder("r/dir050/dir100")
- try createFolder("l/dir050/dir100/dir105")
- try createFolder("r/dir050/dir100/dir110")
-
- // create files
- try createFile("l/dir050/dir100/dir105/file101.txt", "12")
- try createFile("l/dir050/dir100/dir105/file102.txt", "123456")
- try createFile("l/dir050/dir100/dir105/file103.txt", "12")
- try createFile("r/dir050/dir100/dir110/file102.txt", "123")
- try createFile("r/dir050/dir100/dir110/file401.txt", "12")
- try createFile("l/dir050/dir100/011.txt", "123456")
- try createFile("r/dir050/dir100/file301.txt", "123")
- try createFile("r/dir050/dir100/file302.txt", "123456")
- try createFile("l/dir050/020.txt", "123456")
- try createFile("l/dir050/040.txt", "123456")
- try createFile("r/dir050/file201.txt", "123")
- try createFile("r/dir050/file202.txt", "123")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 0, 6, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 0, 6, 0, 5, "dir050", .orphan, 20)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 0, 0, 4, 0, 5, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 0, 4, 0, 5, "dir100", .orphan, 14)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 0, 3, 0, 3, "dir105", .orphan, 10)
- assertItem(child3.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child4 = child3.children[0] // dir105 <-> (null)
- assertItem(child4, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child3.children[1] // dir105 <-> (null)
- assertItem(child5, 0, 0, 1, 0, 0, "file102.txt", .orphan, 6)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child6 = child3.children[2] // dir105 <-> (null)
- assertItem(child6, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child2.children[1] // dir100 <-> dir100
- assertItem(child7, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 5)
-
- let child8 = child7.children[0] // (null) <-> dir110
- assertItem(child8, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child8.linkedItem, 0, 0, 1, 0, 0, "file102.txt", .orphan, 3)
-
- let child9 = child7.children[1] // (null) <-> dir110
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let child10 = child2.children[2] // dir100 <-> dir100
- assertItem(child10, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child10.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child11 = child2.children[3] // dir100 <-> dir100
- assertItem(child11, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child11.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child12 = child2.children[4] // dir100 <-> dir100
- assertItem(child12, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child12.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child13 = child1.children[1] // dir050 <-> dir050
- assertItem(child13, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child13.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child14 = child1.children[2] // dir050 <-> dir050
- assertItem(child14, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child14.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child15 = child1.children[3] // dir050 <-> dir050
- assertItem(child15, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child15.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child16 = child1.children[4] // dir050 <-> dir050
- assertItem(child16, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child16.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child7.linkedItem!,
- toName: "dir105"
- )
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 1, 5, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 1, 5, 0, 5, "dir050", .orphan, 20)
-
- let child2 = child1.children[0] // dir050 <-> dir050
- assertItem(child2, 0, 1, 3, 0, 4, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 3, 0, 4, "dir100", .orphan, 14)
-
- let child3 = child2.children[0] // dir100 <-> dir100
- assertItem(child3, 0, 1, 2, 0, 4, "dir105", .orphan, 10)
- assertItem(child3.linkedItem, 0, 1, 1, 0, 4, "dir105", .orphan, 5)
-
- let child4 = child3.children[0] // dir105 <-> dir105
- assertItem(child4, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child5 = child3.children[1] // dir105 <-> dir105
- assertItem(child5, 0, 1, 0, 0, 0, "file102.txt", .changed, 6)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file102.txt", .changed, 3)
-
- let child6 = child3.children[2] // dir105 <-> dir105
- assertItem(child6, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child3.children[3] // dir105 <-> dir105
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let child8 = child2.children[1] // dir100 <-> dir100
- assertItem(child8, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child9 = child2.children[2] // dir100 <-> dir100
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let child10 = child2.children[3] // dir100 <-> dir100
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let child11 = child1.children[1] // dir050 <-> dir050
- assertItem(child11, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child12 = child1.children[2] // dir050 <-> dir050
- assertItem(child12, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child13 = child1.children[3] // dir050 <-> dir050
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let child14 = child1.children[4] // dir050 <-> dir050
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 5)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 1, 5, 0, 5, "dir050", .orphan, 28)
- assertItem(child1.linkedItem, 0, 1, 5, 0, 5, "dir050", .orphan, 20)
-
- let childVI2 = childVI1.children[0] // dir050 <--> dir050
- assertArrayCount(childVI2.children, 4)
- let child2 = childVI2.item // dir050 <-> dir050
- assertItem(child2, 0, 1, 3, 0, 4, "dir100", .orphan, 16)
- assertItem(child2.linkedItem, 0, 1, 3, 0, 4, "dir100", .orphan, 14)
-
- let childVI3 = childVI2.children[0] // dir100 <--> dir100
- assertArrayCount(childVI3.children, 4)
- let child3 = childVI3.item // dir100 <-> dir100
- assertItem(child3, 0, 1, 2, 0, 4, "dir105", .orphan, 10)
- assertItem(child3.linkedItem, 0, 1, 1, 0, 4, "dir105", .orphan, 5)
-
- let childVI4 = childVI3.children[0] // dir105 <--> dir105
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // dir105 <-> dir105
- assertItem(child4, 0, 0, 1, 0, 0, "file101.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI5 = childVI3.children[1] // dir105 <--> dir105
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // dir105 <-> dir105
- assertItem(child5, 0, 1, 0, 0, 0, "file102.txt", .changed, 6)
- assertItem(child5.linkedItem, 0, 1, 0, 0, 0, "file102.txt", .changed, 3)
-
- let childVI6 = childVI3.children[2] // dir105 <--> dir105
- assertArrayCount(childVI6.children, 0)
- let child6 = childVI6.item // dir105 <-> dir105
- assertItem(child6, 0, 0, 1, 0, 0, "file103.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI7 = childVI3.children[3] // dir105 <--> dir105
- assertArrayCount(childVI7.children, 0)
- let child7 = childVI7.item // dir105 <-> dir105
- assertItem(child7, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child7.linkedItem, 0, 0, 1, 0, 0, "file401.txt", .orphan, 2)
-
- let childVI8 = childVI2.children[1] // dir100 <--> dir100
- assertArrayCount(childVI8.children, 0)
- let child8 = childVI8.item // dir100 <-> dir100
- assertItem(child8, 0, 0, 1, 0, 0, "011.txt", .orphan, 6)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI9 = childVI2.children[2] // dir100 <--> dir100
- assertArrayCount(childVI9.children, 0)
- let child9 = childVI9.item // dir100 <-> dir100
- assertItem(child9, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child9.linkedItem, 0, 0, 1, 0, 0, "file301.txt", .orphan, 3)
-
- let childVI10 = childVI2.children[3] // dir100 <--> dir100
- assertArrayCount(childVI10.children, 0)
- let child10 = childVI10.item // dir100 <-> dir100
- assertItem(child10, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child10.linkedItem, 0, 0, 1, 0, 0, "file302.txt", .orphan, 6)
-
- let childVI11 = childVI1.children[1] // dir050 <--> dir050
- assertArrayCount(childVI11.children, 0)
- let child11 = childVI11.item // dir050 <-> dir050
- assertItem(child11, 0, 0, 1, 0, 0, "020.txt", .orphan, 6)
- assertItem(child11.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI12 = childVI1.children[2] // dir050 <--> dir050
- assertArrayCount(childVI12.children, 0)
- let child12 = childVI12.item // dir050 <-> dir050
- assertItem(child12, 0, 0, 1, 0, 0, "040.txt", .orphan, 6)
- assertItem(child12.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let childVI13 = childVI1.children[3] // dir050 <--> dir050
- assertArrayCount(childVI13.children, 0)
- let child13 = childVI13.item // dir050 <-> dir050
- assertItem(child13, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child13.linkedItem, 0, 0, 1, 0, 0, "file201.txt", .orphan, 3)
-
- let childVI14 = childVI1.children[4] // dir050 <--> dir050
- assertArrayCount(childVI14.children, 0)
- let child14 = childVI14.item // dir050 <-> dir050
- assertItem(child14, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child14.linkedItem, 0, 0, 1, 0, 0, "file202.txt", .orphan, 3)
- }
- }
-
- @Test func renameFolderOrphanToMatching_OnlyMatches_Right_ShowEmptyFolder() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.size, .contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/dir100")
- try createFolder("r/dir100")
- try createFolder("r/dir100/dir110")
- try createFolder("l/dir100/dir120")
-
- // create files
- try createFile("r/dir100/dir110/file001.txt", "12")
- try createFile("r/dir100/dir110/file002.txt", "12345")
- try createFile("l/dir100/dir120/file001.txt", "12")
- try createFile("l/dir100/dir120/file002.txt", "123456")
- try createFile("l/dir100/dir120/file003.txt", "12")
-
- try setFileTimestamp("l/dir100/dir120/file002.txt", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 0, 0, 3, 0, 2, "dir100", .orphan, 10)
- assertItem(child1.linkedItem, 0, 0, 2, 0, 2, "dir100", .orphan, 7)
-
- let child2 = child1.children[0] // dir100 <-> dir100
- assertItem(child2, 0, 0, 0, 0, 2, nil, .orphan, 0)
- assertItem(child2.linkedItem, 0, 0, 2, 0, 2, "dir110", .orphan, 7)
-
- let child3 = child2.children[0] // (null) <-> dir110
- assertItem(child3, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child3.linkedItem, 0, 0, 1, 0, 0, "file001.txt", .orphan, 2)
-
- let child4 = child2.children[1] // (null) <-> dir110
- assertItem(child4, 0, 0, 0, 0, 0, nil, .orphan, 0)
- assertItem(child4.linkedItem, 0, 0, 1, 0, 0, "file002.txt", .orphan, 5)
-
- let child5 = child1.children[1] // dir100 <-> dir100
- assertItem(child5, 0, 0, 3, 0, 3, "dir120", .orphan, 10)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 3, nil, .orphan, 0)
-
- let child6 = child5.children[0] // dir120 <-> (null)
- assertItem(child6, 0, 0, 1, 0, 0, "file001.txt", .orphan, 2)
- assertItem(child6.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child7 = child5.children[1] // dir120 <-> (null)
- assertItem(child7, 0, 0, 1, 0, 0, "file002.txt", .orphan, 6)
- assertItem(child7.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- let child8 = child5.children[2] // dir120 <-> (null)
- assertItem(child8, 0, 0, 1, 0, 0, "file003.txt", .orphan, 2)
- assertItem(child8.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
-
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = RenameCompareItem(operationManager: fileOperationManager)
-
- fileOperation.rename(
- srcRoot: child2.linkedItem!,
- toName: "dir120"
- )
-
- do {
- let child1 = rootL.children[0] // l <-> r
- assertItem(child1, 1, 0, 1, 1, 1, "dir100", .orphan, 10)
- assertItem(child1.linkedItem, 0, 1, 0, 1, 1, "dir100", .orphan, 7)
-
- let child2 = child1.children[0] // dir100 <-> dir100
- assertItem(child2, 1, 0, 1, 1, 3, "dir120", .orphan, 10)
- assertItem(child2.linkedItem, 0, 1, 0, 1, 3, "dir120", .orphan, 7)
-
- let child3 = child2.children[0] // dir120 <-> dir120
- assertItem(child3, 0, 0, 0, 1, 0, "file001.txt", .same, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "file001.txt", .same, 2)
-
- let child4 = child2.children[1] // dir120 <-> dir120
- assertItem(child4, 1, 0, 0, 0, 0, "file002.txt", .old, 6)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "file002.txt", .changed, 5)
-
- let child5 = child2.children[2] // dir120 <-> dir120
- assertItem(child5, 0, 0, 1, 0, 0, "file003.txt", .orphan, 2)
- assertItem(child5.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 0, 1, 1, 1, "dir100", .orphan, 10)
- assertItem(child1.linkedItem, 0, 1, 0, 1, 1, "dir100", .orphan, 7)
-
- let childVI2 = childVI1.children[0] // dir100 <--> dir100
- assertArrayCount(childVI2.children, 1)
- let child2 = childVI2.item // dir100 <-> dir100
- assertItem(child2, 1, 0, 1, 1, 3, "dir120", .orphan, 10)
- assertItem(child2.linkedItem, 0, 1, 0, 1, 3, "dir120", .orphan, 7)
-
- let childVI3 = childVI2.children[0] // dir120 <--> dir120
- assertArrayCount(childVI3.children, 0)
- let child3 = childVI3.item // dir120 <-> dir120
- assertItem(child3, 0, 0, 0, 1, 0, "file001.txt", .same, 2)
- assertItem(child3.linkedItem, 0, 0, 0, 1, 0, "file001.txt", .same, 2)
- }
- }
-}
-
-// swiftlint:enable file_length force_unwrapping function_body_length
diff --git a/Tests/Sources/FileSystem/Tests/SymbolicLinkTests.swift b/Tests/Sources/FileSystem/Tests/SymbolicLinkTests.swift
deleted file mode 100644
index 7e31fcc..0000000
--- a/Tests/Sources/FileSystem/Tests/SymbolicLinkTests.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// SymbolicLinkTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 15/12/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-final class SymbolicLinkTests: BaseTests {
- @Test func symbolicLinkLoop() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .onlyMismatches
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/parent")
- try createSymlink("l/parent/sym_parent", "../parent")
-
- try createFolder("r")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- assertErrors(
- folderReaderDelegate.errors, [
- FileError.symlinkLoop(path: appendFolder("l/parent/sym_parent").osPath),
- ]
- )
- }
-}
diff --git a/Tests/Sources/FileSystem/Tests/TouchFilesTests.swift b/Tests/Sources/FileSystem/Tests/TouchFilesTests.swift
deleted file mode 100644
index 9d167c9..0000000
--- a/Tests/Sources/FileSystem/Tests/TouchFilesTests.swift
+++ /dev/null
@@ -1,312 +0,0 @@
-//
-// TouchFilesTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 11/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping function_body_length
-final class TouchFilesTests: BaseTests {
- @Test func touchOlderFiles() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/a/bb/cc")
- try createFolder("r/a/bb/cc")
-
- try createFile("l/a/bb/cc/cc_file.txt", "12")
- try createFile("l/a/bb/bb_file.txt", "12")
-
- try createFile("r/a/bb/cc/cc_file.txt", "123")
- try createFile("r/a/bb/bb_file.txt", "123")
-
- try setFileTimestamp("l/a/bb/cc/cc_file.txt", "2001-03-24 10: 45: 32 +0600")
- try setFileTimestamp("r/a/bb/cc/cc_file.txt", "2002-03-24 10: 45: 32 +0600")
-
- try setFileTimestamp("l/a/bb/bb_file.txt", "2002-03-24 10: 45: 32 +0600")
- try setFileTimestamp("r/a/bb/bb_file.txt", "2001-03-24 10: 45: 32 +0600")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0]
- assertItem(child1, 1, 1, 0, 0, 1, "a", .orphan, 4)
- assertItem(child1.linkedItem, 1, 1, 0, 0, 1, "a", .orphan, 6)
-
- var child2 = child1.children[0] // a
- assertItem(child2, 1, 1, 0, 0, 2, "bb", .orphan, 4)
- assertItem(child2.linkedItem, 1, 1, 0, 0, 2, "bb", .orphan, 6)
-
- var child3 = child2.children[0] // bb
- assertItem(child3, 1, 0, 0, 0, 1, "cc", .orphan, 2)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 1, "cc", .orphan, 3)
-
- var child4 = child3.children[0] // cc
- assertItem(child4, 1, 0, 0, 0, 0, "cc_file.txt", .old, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "cc_file.txt", .changed, 3)
-
- var child5 = child2.children[1] // bb
- assertItem(child5, 0, 1, 0, 0, 0, "bb_file.txt", .changed, 2)
- assertItem(child5.linkedItem, 1, 0, 0, 0, 0, "bb_file.txt", .old, 3)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 1, 1, 0, 0, 1, "a", .orphan, 4)
- assertItem(child1.linkedItem, 1, 1, 0, 0, 1, "a", .orphan, 6)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 1, 1, 0, 0, 2, "bb", .orphan, 4)
- assertItem(child2.linkedItem, 1, 1, 0, 0, 2, "bb", .orphan, 6)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 1, 0, 0, 0, 1, "cc", .orphan, 2)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 1, "cc", .orphan, 3)
-
- let childVI4 = childVI3.children[0] // cc <--> cc
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // cc <-> cc
- assertItem(child4, 1, 0, 0, 0, 0, "cc_file.txt", .old, 2)
- assertItem(child4.linkedItem, 0, 1, 0, 0, 0, "cc_file.txt", .changed, 3)
-
- let childVI5 = childVI2.children[1] // bb <--> bb
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // bb <-> bb
- assertItem(child5, 0, 1, 0, 0, 0, "bb_file.txt", .changed, 2)
- assertItem(child5.linkedItem, 1, 0, 0, 0, 0, "bb_file.txt", .old, 3)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let touchDate = try buildDate("2012-05-05 11: 00: 11 +0000")
-
- let fileOperationDelegate = MockFileOperationManagerDelegate()
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = TouchCompareItem(operationManager: fileOperationManager)
-
- fileOperation.touch(
- srcRoot: child1,
- includeSubfolders: true,
- touchDate: touchDate
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 2, 0, 0, 1, "a", .orphan, 4)
- assertItem(child1.linkedItem, 2, 0, 0, 0, 1, "a", .orphan, 6)
- try assertTimestamps(child1, nil, "2012-05-05 11: 00: 11 +0000")
-
- child2 = child1.children[0] // a
- assertItem(child2, 0, 2, 0, 0, 2, "bb", .orphan, 4)
- assertItem(child2.linkedItem, 2, 0, 0, 0, 2, "bb", .orphan, 6)
- try assertTimestamps(child2, nil, "2012-05-05 11: 00: 11 +0000")
-
- child3 = child2.children[0] // bb
- assertItem(child3, 0, 1, 0, 0, 1, "cc", .orphan, 2)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 1, "cc", .orphan, 3)
- try assertTimestamps(child3, nil, "2012-05-05 11: 00: 11 +0000")
-
- child4 = child3.children[0] // cc
- assertItem(child4, 0, 1, 0, 0, 0, "cc_file.txt", .changed, 2)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "cc_file.txt", .old, 3)
- try assertTimestamps(child4, nil, "2012-05-05 11: 00: 11 +0000")
-
- child5 = child2.children[1] // bb
- assertItem(child5, 0, 1, 0, 0, 0, "bb_file.txt", .changed, 2)
- assertItem(child5.linkedItem, 1, 0, 0, 0, 0, "bb_file.txt", .old, 3)
- try assertTimestamps(child5, nil, "2012-05-05 11: 00: 11 +0000")
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 2, 0, 0, 1, "a", .orphan, 4)
- assertItem(child1.linkedItem, 2, 0, 0, 0, 1, "a", .orphan, 6)
-
- let childVI2 = childVI1.children[0] // a <--> a
- assertArrayCount(childVI2.children, 2)
- let child2 = childVI2.item // a <-> a
- assertItem(child2, 0, 2, 0, 0, 2, "bb", .orphan, 4)
- assertItem(child2.linkedItem, 2, 0, 0, 0, 2, "bb", .orphan, 6)
-
- let childVI3 = childVI2.children[0] // bb <--> bb
- assertArrayCount(childVI3.children, 1)
- let child3 = childVI3.item // bb <-> bb
- assertItem(child3, 0, 1, 0, 0, 1, "cc", .orphan, 2)
- assertItem(child3.linkedItem, 1, 0, 0, 0, 1, "cc", .orphan, 3)
-
- let childVI4 = childVI3.children[0] // cc <--> cc
- assertArrayCount(childVI4.children, 0)
- let child4 = childVI4.item // cc <-> cc
- assertItem(child4, 0, 1, 0, 0, 0, "cc_file.txt", .changed, 2)
- assertItem(child4.linkedItem, 1, 0, 0, 0, 0, "cc_file.txt", .old, 3)
-
- let childVI5 = childVI2.children[1] // bb <--> bb
- assertArrayCount(childVI5.children, 0)
- let child5 = childVI5.item // bb <-> bb
- assertItem(child5, 0, 1, 0, 0, 0, "bb_file.txt", .changed, 2)
- assertItem(child5.linkedItem, 1, 0, 0, 0, 0, "bb_file.txt", .old, 3)
- }
- }
-
- @Test func touchOrphanFile() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: .contentTimestamp,
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: true,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- try createFolder("l/dir1")
- try createFolder("r/dir1")
-
- try createFile("l/dir1/file1.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
- let vi = rootL.visibleItem!
-
- var child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- var child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
-
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-
- try assertOnlySetup()
-
- // VDLocalFileManager doesn't hold the delegate so allocate it as local variable
- // otherwise is released to early it the test crashes
- let touchDate = try buildDate("2012-05-05 11: 00: 11 +0000")
-
- let fileOperationDelegate = MockFileOperationManagerDelegate(replaceAll: true)
- let fileOperationManager = FileOperationManager(
- filterConfig: filterConfig,
- comparator: comparator,
- delegate: fileOperationDelegate,
- includesFiltered: false
- )
- let fileOperation = TouchCompareItem(operationManager: fileOperationManager)
- fileOperation.touch(
- srcRoot: child2,
- includeSubfolders: false,
- touchDate: touchDate
- )
-
- child1 = rootL.children[0] // l
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- child2 = child1.children[0] // dir1
- assertItem(child2, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- try assertTimestamps(child2, nil, "2012-05-05 11: 00: 11 +0000")
- do {
- // VisibleItems
- let childVI1 = vi.children[0] // l <--> r
- assertArrayCount(childVI1.children, 1)
- let child1 = childVI1.item // l <-> r
- assertItem(child1, 0, 0, 1, 0, 1, "dir1", .orphan, 2)
- assertItem(child1.linkedItem, 0, 0, 0, 0, 1, "dir1", .orphan, 0)
-
- let childVI2 = childVI1.children[0] // dir1 <--> dir1
- assertArrayCount(childVI2.children, 0)
- let child2 = childVI2.item // dir1 <-> dir1
- assertItem(child2, 0, 0, 1, 0, 0, "file1.txt", .orphan, 2)
- assertItem(child2.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
- }
-}
-
-// swiftlint:enable force_unwrapping function_body_length
diff --git a/Tests/Sources/Path/LeafPathTests.swift b/Tests/Sources/Path/LeafPathTests.swift
deleted file mode 100644
index 99fef49..0000000
--- a/Tests/Sources/Path/LeafPathTests.swift
+++ /dev/null
@@ -1,221 +0,0 @@
-//
-// LeafPathTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 30/01/14.
-// Copyright (c) 2014 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable function_body_length
-final class LeafPathTests: BaseTests {
- func findLeafPaths(_ paths: [String]) -> [CompareItem] {
- let arr = paths.map { CompareItem(
- path: $0,
- attrs: nil,
- fileExtraOptions: [],
- parent: nil
- )
- }
-
- return CompareItem.findLeafPaths(arr)
- }
-
- @Test func findLeafPaths1() {
- let paths = [
- "/Users/dave/trash/test_suite/createDir/l/dir1/dir2/dir3/test_date",
- "/Users/dave/trash/test_suite/createDir/l/dir1/dir2/dir3/test_date copia",
- ]
- let result = findLeafPaths(paths)
- assertArrayCount(result, 2)
- #expect(result[0].path == paths[0], "\(String(describing: result[0].path))")
- #expect(result[1].path == paths[1], "\(String(describing: result[1].path))")
- }
-
- @Test func findLeafPaths2() {
- let paths = [
- "/Users/dave/trash/test_suite/createDir/l/dir1/dir2",
- "/Users/dave/trash/test_suite/createDir/l/dir1/dir2/dir3",
- "/Users/dave/trash/test_suite/createDir/l/dir1/dir2/dir3/test_date",
- ]
- let result = findLeafPaths(paths)
- assertArrayCount(result, 1)
- #expect(result[0].path == paths[2], "\(String(describing: result[0].path))")
- }
-
- @Test func findLeafPaths3() {
- let paths = [
- "/Users/dave/trash/test_suite/createDir/test/10/20/30/40",
- "/Users/dave/trash/test_suite/createDir/test/10/40",
- ]
- let result = findLeafPaths(paths)
- assertArrayCount(result, 2)
- #expect(result[0].path == paths[0], "\(String(describing: result[0].path))")
- #expect(result[1].path == paths[1], "\(String(describing: result[1].path))")
- }
-
- @Test func findLeafPaths4() {
- let paths = [
- "/Users/dave/trash/app/VisualDiffer.xcodeproj",
- "/Users/dave/trash/app/VisualDiffer.xcodeproj/project.xcworkspace",
- "/Users/dave/trash/app/VisualDiffer.xcodeproj/project.xcworkspace/xcuserdata",
- "/Users/dave/trash/app/VisualDiffer.xcodeproj/project.xcworkspace/xcuserdata/dave.xcuserdatad",
- "/Users/dave/trash/app/VisualDiffer.xcodeproj/project.xcworkspace/xcuserdata/dave.xcuserdatad/UserInterfaceState.xcuserstate",
- "/Users/dave/trash/app/VisualDiffer.xcodeproj/xcuserdata",
- ]
- let result = findLeafPaths(paths)
- assertArrayCount(result, 2)
- #expect(result[0].path == paths[4], "\(String(describing: result[0].path))")
- #expect(result[1].path == paths[5], "\(String(describing: result[1].path))")
- }
-
- @Test func closestPath() {
- var arr = [
- "/Users/dave/trash/test_suite/bug244/r.txt",
- "/Users/dave/trash/0latest_stable/app",
- "/opt/devel/0dafiprj/git.github/android/ListViewOverlay",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrep",
- "/opt/devel/0dafiprj/git.github/android/BatteryChargerNotifier/BatteryChargerNotifier",
- "/Users/dave/trash/photoshelf_all/photoshelf_cached/app",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrep/en.lproj/MainMenu.xib",
- "/opt/devel/0dafiprj/git.github/android/TestApp",
- "/Users/dave/trash/Crawler/src",
- "/Users/dave/Dropbox/applicazioni/photoshelf/tags (1).csv",
- "/opt/devel/0dafiprj/git.github/dafizilla/slamtracker",
- "/opt/devel/0dafiprj/sourceforge/dafizilla/trunk/webapp/viewsourcewith/update.rdf",
- "/opt/devel/0dafiprj/osx/visualdiffer/website",
- "/Users/dave/trash/photoshelf_all/photoshelf_before_module/app/src/main/res",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrep/utils/document",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/src",
- "/Volumes/Seneca/devel/tests/visualdiffer/immaweb/svn/immaweb",
- "/Users/dave/trash/vd_localized/Localizable.strings",
- "/Users/dave/trash/test_suite/refactor_visibileItem/r",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrepTests/support/ita-001-input.txt",
- "/Users/dave/trash/photoshelf_all/photoshelf_before_module/app/src/main/java",
- "/opt/devel/0dafiprj/osx/visualdiffer/website/css",
- "/Volumes/Seneca/mm/movies/xxx/app",
- "/Volumes/Seneca/devel/mycocoapod/TOPKit/TOPKit",
- "/Users/dave/trash/test_suite/bug239/r.csv",
- "/Users/dave/trash/test-encoding-word-file.doc",
- "/Users/dave/trash/Crawler",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/src/main/java/com",
- "/opt/devel/0dafiprj/osx/visualdiffer/app/common",
- "/Users/dave/trash",
- "/opt/devel/0dafiprj/osx/visualdiffer/visualdiffer.github.com/css",
- "/opt/devel/0dafiprj/sourceforge/dafizilla_old/trunk",
- "/Users/dave/trash/progressbar",
- "/Users/dave/trash/photoshelf_all/photoshelf_gridview2",
- "/opt/devel/0dafiprj/sourceforge/dafizilla",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/src/main/java/com/ternaryop",
- "/Users/dave/trash/test_suite/bug255",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/profile/ff/extensions/{eecba28f-b68b-4b3a-b501-6ce12e6b8696}/chrome/plainfiles",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrep/utils",
- "/Users/dave/trash/test_suite/bug244/l.txt",
- "/opt/devel/0dafiprj/osx/visualdiffer/visualdiffer.github.com/_plugins/tocGenerator.rb",
- "/Users/dave/trash/test_suite/FileSystemUtilsTests/testMoveMatchFileBecomeFiltered/r",
- "/Volumes/Seneca/devel/tests/visualdiffer/immaweb/svn/immaweb/trunk",
- "/opt/devel/0dafiprj/sourceforge/dafizilla_old",
- "/Users/dave/trash/test_suite/bug255/l",
- "/Volumes/Seneca/mm/movies/xxx/Archivio/commonutils-master",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/src/main/res",
- "/Users/dave/trash/update.rdf",
- "/Users/dave/trash/photoshelf_all/tags.csv",
- "/Users/dave/trash/test_suite/bug255/r",
- "/Users/dave/trash/hidefiles/sql1.txt",
- "/opt/devel/0dafiprj/osx/visualgrepswift",
- "/Volumes/Seneca/mm/movies/xxx/Archivio/photoshelf",
- "/Users/dave/trash/photoshelf_all/photoshelf_cached",
- "/Users/dave/trash/VisualDiffer/common/VDPathViewController.m",
- "/Volumes/Seneca/devel/examples/android/apk/PhotoShelf-release/AndroidManifest.xml",
- "/Users/dave/trash/test_suite/bug239/l.csv",
- "/Users/dave/trash/visualdi_mant1-141116.sql",
- "/Volumes/Seneca/mm/movies/person.of.interest",
- "/Users/dave/trash/test_suite/FileSystemUtilsTests/testMoveMatchFileBecomeFiltered/l",
- "/Volumes/Seneca/mm/movies/temp/visualdi_mant1.sql",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/dist/bin/viewsourcewith-0.9.4.3",
- "/opt/devel/0dafiprj/osx/visualdiffer/website/new/css",
- "/Users/dave/trash/test_suite/refactor_visibileItem/l",
- "/Users/dave/Dropbox/applicazioni/photoshelf/tags.csv",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/dist/bin/amo",
- "/Users/dave/trash/hidefiles/list-only-files.txt",
- "/opt/devel/0dafiprj/osx/visualdiffer/app/common/VDPathViewController.m",
- "/Users/dave/trash/tocgen_html_site",
- "/opt/devel/0dafiprj/git.github/android/photoshelf",
- "/Users/dave/trash/tocgen_xhtml_site",
- "/Users/dave/trash/ShareActionProvider-main.xml",
- "/Users/dave/trash/0latest_stable/app 2",
- "/Volumes/Seneca/mm/movies/xxx/Archivio/photoshelf-master",
- "/Volumes/Seneca/devel/tests/visualdiffer/immaweb/svn/immaweb/trunk/src",
- "/Users/dave/trash/test_suite/a.txt",
- "/opt/devel/0dafiprj/git.github/android/commonutils/app/src/main/java/com",
- "/opt/devel/0dafiprj/osx/visualdiffer/app/utils/document",
- "/opt/devel/0dafiprj/git.github/jekyll-toc-generator/_plugins/tocGenerator.rb",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/dist/bin/debug",
- "/opt/devel/0dafiprj/osx/visualdiffer/app",
- "/opt/devel/0dafiprj/osx/visualdiffer/visualdiffer.github.com",
- "/Users/dave/Dropbox/Applicazioni/PhotoShelf/birthdays.csv",
- "/opt/devel/0dafiprj/sourceforge/dafizilla/trunk/bespin",
- "/Users/dave/trash/photoshelf_all/photoshelf_toolbar",
- "/Volumes/Seneca/mm/movies/temp",
- "/Volumes/Seneca/devel/examples/android/dropbox-android-sync-sdk-3.0.2/libs",
- "/private/var",
- "/Users/dave/trash/visualgrepswift/VisualGrepSwift",
- "/Users/dave/trash/test_suite/FileSystemUtilsTests/testCopyFollowSymLink/l",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrep/utils/io",
- "/Users/dave/trash/photoshelf_all/CommonUtilsModule",
- "/opt/devel/0dafiprj/osx/visualdiffer/app/utils",
- "/opt/devel/0dafiprj/git.github/android/commonutils",
- "/Users/dave/trash/VisualDiffer",
- "/Users/dave/.Trash/update.rdf",
- "/Users/dave/trash/test_suite/bug218/l",
- "/opt/devel/0dafiprj/osx/visualgrep/app/VisualGrepTests/support/ita-001-pattern.txt",
- "/Volumes/Seneca/devel/tests/visualdiffer/immaweb/prj/immaweb",
- "/Users/dave/trash/birthdays-150129.csv",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/dist/bin/amo/viewsourcewith-0.9.4.3",
- "/Users/dave/trash/Project_Default.xml",
- "/Users/dave/trash/VisualDiffer/common",
- "/Users/dave/trash/test_suite/FileSystemUtilsTests/testCopyFollowSymLink/r",
- "/Users/dave/trash/test_suite/bug218/r",
- "/Volumes/Seneca/devel/tests/visualdiffer/immaweb/prj/immaweb/src",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/src/main/java",
- "/opt/devel/0dafiprj/osx/visualdiffer/app/English.lproj/Localizable.strings",
- "/Users/dave/trash/test_suite/bug251/l",
- "/opt/devel/0dafiprj/osx/visualgrep/site",
- "/Users/dave/trash/photoshelf_all/photoshelf_added_icons",
- "/opt/devel/0dafiprj/git.github/dafizilla/viewsourcewith/src/main",
- "/opt/devel/0dafiprj/git.github/android/commonutils/app/src/main/java",
- "/opt/devel/0dafiprj/git.github/android/photoshelf/app/libs",
- "/Users/dave/trash/test_suite/bug251/r",
- ]
-
- var found: String?
- var expectedResult: String?
-
- expectedResult = "/opt/devel/0dafiprj/git.github/android/BatteryChargerNotifier/BatteryChargerNotifier"
- found = SecureBookmark.shared.findClosestPath(to: URL(filePath: "/opt/devel/0dafiprj/git.github/android/BatteryChargerNotifier/BatteryChargerNotifier/gradle"), searchPaths: arr)
- #expect(found == expectedResult, "found \(String(describing: found)) expected \(String(describing: expectedResult))")
-
- expectedResult = "/Users/dave/trash/0latest_stable/app 2"
- found = SecureBookmark.shared.findClosestPath(to: URL(filePath: "/Users/dave/trash/0latest_stable/app 2"), searchPaths: arr)
- #expect(found == expectedResult, "found \(String(describing: found)) expected \(String(describing: expectedResult))")
-
- expectedResult = "/opt/devel/0dafiprj/osx/visualdiffer/app"
- found = SecureBookmark.shared.findClosestPath(to: URL(filePath: "/opt/devel/0dafiprj/osx/visualdiffer/app"), searchPaths: arr)
- #expect(found == expectedResult, "found \(String(describing: found)) expected \(String(describing: expectedResult))")
-
- arr = ["/Users/app 2 3"]
- expectedResult = nil
- found = SecureBookmark.shared.findClosestPath(to: URL(filePath: "/Users/app 2"), searchPaths: arr)
- #expect(found == expectedResult, "found \(String(describing: found)) expected \(String(describing: expectedResult))")
-
- arr = ["/Users/app", "/All/aa", "/Zoom/hello"]
- expectedResult = "/Users/app"
- found = SecureBookmark.shared.findClosestPath(to: URL(filePath: "/Users/app/file"), searchPaths: arr)
- #expect(found == expectedResult, "found \(String(describing: found)) expected \(String(describing: expectedResult))")
- }
-}
-
-// swiftlint:enable function_body_length
diff --git a/Tests/Sources/UI/Tests/FoldersWindowControllerTests.swift b/Tests/Sources/UI/Tests/FoldersWindowControllerTests.swift
deleted file mode 100644
index ec495b6..0000000
--- a/Tests/Sources/UI/Tests/FoldersWindowControllerTests.swift
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// FoldersWindowControllerTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 22/11/12.
-// Copyright (c) 2012 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-// swiftlint:disable force_unwrapping
-final class FoldersWindowControllerTests: BaseTests {
- // This create a test case to generate the error trapped on
- // [FoldersWindowController (id)outlineView: outlineView child: (NSInteger)index ofItem: (id)item]
- @Test func savedFromArrayOutOfBound() throws {
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/empty_folder1")
- try createFolder("r/empty_folder1")
- try createFolder("l/empty_folder2")
- try createFolder("r/folder_one_file_inside")
-
- // create files
- try createFile("r/folder_one_file_inside/AppDelegate.m", "12345")
- }
-
- @Test("This isn't a test but a way to prepare the folders for the test") func excludingByName() throws {
- let comparatorDelegate = MockItemComparatorDelegate()
- let comparator = ItemComparator(
- options: [.contentTimestamp],
- delegate: comparatorDelegate,
- bufferSize: 8192
- )
- let filterConfig = FilterConfig(
- showFilteredFiles: false,
- hideEmptyFolders: false,
- followSymLinks: false,
- skipPackages: false,
- traverseFilteredFolders: false,
- predicate: defaultPredicate,
- fileExtraOptions: [],
- displayOptions: .showAll
- )
- let folderReaderDelegate = MockFolderReaderDelegate(isRunning: true)
- let folderReader = FolderReader(
- with: folderReaderDelegate,
- comparator: comparator,
- filterConfig: filterConfig,
- refreshInfo: RefreshInfo(initState: true)
- )
-
- try removeItem("l")
- try removeItem("r")
-
- // create folders
- try createFolder("l/folder1")
- try createFolder("r/folder1")
- try createFolder("l/folder1/folder2")
- try createFolder("r/folder1/folder2")
-
- // create files
- try createFile("l/folder1/folder2/file3.txt", "12345")
- try createFile("r/folder1/folder2/file3.txt", "12")
- try createFile("l/folder1/file2.txt", "12")
-
- folderReader.start(
- withLeftRoot: nil,
- rightRoot: nil,
- leftPath: appendFolder("l"),
- rightPath: appendFolder("r")
- )
-
- let rootL = folderReader.leftRoot!
- // let rootR = folderReader.rightRoot!
-
- let child1 = rootL.children[0] // l
- assertItem(child1, 0, 1, 1, 0, 2, "folder1", .orphan, 7)
- assertItem(child1.linkedItem, 0, 1, 0, 0, 2, "folder1", .orphan, 2)
-
- let child2 = child1.children[0] // folder1
- assertItem(child2, 0, 1, 0, 0, 1, "folder2", .orphan, 5)
- assertItem(child2.linkedItem, 0, 1, 0, 0, 1, "folder2", .orphan, 2)
-
- let child3 = child2.children[0] // folder2
- assertItem(child3, 0, 1, 0, 0, 0, "file3.txt", .changed, 5)
- assertItem(child3.linkedItem, 0, 1, 0, 0, 0, "file3.txt", .changed, 2)
-
- let child4 = child1.children[1] // folder1
- assertItem(child4, 0, 0, 1, 0, 0, "file2.txt", .orphan, 2)
- assertItem(child4.linkedItem, 0, 0, 0, 0, 0, nil, .orphan, 0)
- }
-}
-
-// swiftlint:enable force_unwrapping
diff --git a/Tests/Sources/UI/Tests/RefreshInfoTests.swift b/Tests/Sources/UI/Tests/RefreshInfoTests.swift
deleted file mode 100644
index bdd6f95..0000000
--- a/Tests/Sources/UI/Tests/RefreshInfoTests.swift
+++ /dev/null
@@ -1,130 +0,0 @@
-//
-// RefreshInfoTests.swift
-// VisualDiffer
-//
-// Created by davide ficano on 24/08/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Testing
-@testable import VisualDiffer
-
-final class RefreshInfoTests: BaseTests {
- @Test func refreshInfoStartComparisonNoExpand() {
- let expected = RefreshInfo(
- initState: true,
- expandAllFolders: false
- )
-
- #expect(expected.refreshFolders == true)
- #expect(expected.realign == true)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == false)
- }
-
- @Test func refreshInfoExcludeByNameNoExpand() {
- let expected = RefreshInfo(
- initState: false
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == false)
- #expect(expected.expandAllFolders == false)
- }
-
- @Test func refreshInfoSelectComparisonNoExpand() {
- let expected = RefreshInfo(
- initState: false,
- refreshComparison: true
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == false)
- }
-
- @Test func refreshInfoSelectDisplayFlagsNoExpand() {
- let expected = RefreshInfo(
- initState: false
- )
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == false)
- #expect(expected.expandAllFolders == false)
- }
-
- @Test func refreshInfoSetBaseFoldersSrcNoExpand() {
- let expected = RefreshInfo(
- initState: false,
- realign: true
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == true)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == false)
- }
-
- // MARK: - expand
-
- @Test func refreshInfoStartComparisonExpand() {
- let expected = RefreshInfo(
- initState: true
- )
- #expect(expected.refreshFolders == true)
- #expect(expected.realign == true)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == true)
- }
-
- @Test func refreshInfoExcludeByNameExpand() {
- let expected = RefreshInfo(
- initState: false,
- expandAllFolders: true
- )
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == false)
- #expect(expected.expandAllFolders == true)
- }
-
- @Test func refreshInfoSelectComparisonExpand() {
- let expected = RefreshInfo(
- initState: false,
- refreshComparison: true,
- expandAllFolders: true
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == true)
- }
-
- @Test func refreshInfoSelectDisplayFlagsExpand() {
- let expected = RefreshInfo(
- initState: false,
- expandAllFolders: true
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == false)
- #expect(expected.refreshComparison == false)
- #expect(expected.expandAllFolders == true)
- }
-
- @Test func refreshInfoSetBaseFoldersSrcExpand() {
- let expected = RefreshInfo(
- initState: false,
- realign: true,
- expandAllFolders: true
- )
-
- #expect(expected.refreshFolders == false)
- #expect(expected.realign == true)
- #expect(expected.refreshComparison == true)
- #expect(expected.expandAllFolders == true)
- }
-}
diff --git a/Tests/Sources/Utils/StringUtils.swift b/Tests/Sources/Utils/StringUtils.swift
deleted file mode 100644
index f5eae2e..0000000
--- a/Tests/Sources/Utils/StringUtils.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// StringUtils.swift
-// VisualDiffer
-//
-// Created by davide ficano on 01/03/25.
-// Copyright (c) 2025 visualdiffer.com
-//
-
-import Foundation
-
-public func generateAsciiChar() -> Character {
- // swiftlint:disable:next force_unwrapping
- Character(Unicode.Scalar(Int.random(in: 0 ..< 26) + 97)!)
-}
-
-public func invertCase(_ str: inout String, index: Int) {
- let len = str.count
- guard len > 0 else {
- return
- }
- let index = str.index(str.startIndex, offsetBy: index)
- let ch: Character = str[index]
- let inverted = ch.isUppercase ? str[index].lowercased() : str[index].uppercased()
- str.replaceSubrange(index ... index, with: inverted)
-}
diff --git a/Versions-Template.xcconfig b/Versions-Template.xcconfig
deleted file mode 100644
index daf4d96..0000000
--- a/Versions-Template.xcconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Versions.xcconfig
-// VisualDiffer
-//
-// Created by davide on 01/02/22.
-// Copyright (c) 2022 visualdiffer.com
-//
-
-// Copy this file to Versions.xcconfig and edit the values
-
-APP_VERSION = 1.0.0
-APP_BUNDLE_VERSION = $(APP_VERSION)
-
-// Remove comment to generate tests setup without running tests
-//SWIFT_ACTIVE_COMPILATION_CONDITIONS = TEST_ONLY_SETUP
diff --git a/VisualDiffer-Bridging-Header.h b/VisualDiffer-Bridging-Header.h
deleted file mode 100644
index 2e1fe33..0000000
--- a/VisualDiffer-Bridging-Header.h
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// Use this file to import your target's public headers that you would like to expose to Swift.
-//
-
-#import "BigFileFileOperationManager.h"
-#import "MGScopeBar.h"
-#import "MGScopeBarDelegateProtocol.h"
-#import "NSPredicate+Objc.h"
-#import "TitlePredicateEditorRowTemplate.h"
-#import "TOPFileSizePredicateEditorRowTemplate.h"
-#import "TOPTimestampPredicateEditorRowTemplate.h"
-#import "UnifiedDiff.h"
-#import "UDiffScriptBuilder.h"
diff --git a/VisualDiffer-Info.plist b/VisualDiffer-Info.plist
deleted file mode 100644
index 114350f..0000000
--- a/VisualDiffer-Info.plist
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleDisplayName
- VisualDiffer
- CFBundleDocumentTypes
-
-
- CFBundleTypeExtensions
-
- vdiff
-
- CFBundleTypeIconFile
- vd
- CFBundleTypeMIMETypes
-
- application/octet-stream
-
- CFBundleTypeName
- VisualDiffer
- CFBundleTypeRole
- Editor
- LSTypeIsPackage
-
- LSHandlerRank
- Owner
- NSDocumentClass
- VDDocument
- NSPersistentStoreTypeKey
- Binary
-
-
- CFBundleExecutable
- ${EXECUTABLE_NAME}
- CFBundleHelpBookFolder
- VisualDifferHelp
- CFBundleHelpBookName
- com.visualdiffer.help
- CFBundleIconFile
- vd.icns
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- ${PRODUCT_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(APP_VERSION)
- CFBundleSignature
- ????
- CFBundleVersion
- $(APP_BUNDLE_VERSION)
- LSApplicationCategoryType
- public.app-category.utilities
- LSMinimumSystemVersion
- ${MACOSX_DEPLOYMENT_TARGET}
- NSHumanReadableCopyright
- 2010, visualdiffer.com
- NSMainNibFile
- MainMenu
- NSPrincipalClass
- NSApplication
- ITSAppUsesNonExemptEncryption
-
- NSAppleScriptEnabled
-
- OSAScriptingDefinition
- ${PRODUCT_NAME}.sdef
-
-
diff --git a/VisualDiffer-Sparkle-Info.plist b/VisualDiffer-Sparkle-Info.plist
deleted file mode 100644
index 7f6ba8c..0000000
--- a/VisualDiffer-Sparkle-Info.plist
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- English
- CFBundleDisplayName
- VisualDiffer
- CFBundleDocumentTypes
-
-
- CFBundleTypeExtensions
-
- vdiff
-
- CFBundleTypeIconFile
- vd
- CFBundleTypeMIMETypes
-
- application/octet-stream
-
- CFBundleTypeName
- VisualDiffer
- CFBundleTypeRole
- Editor
- LSTypeIsPackage
-
- LSHandlerRank
- Owner
- NSDocumentClass
- VDDocument
- NSPersistentStoreTypeKey
- Binary
-
-
- CFBundleExecutable
- ${EXECUTABLE_NAME}
- CFBundleHelpBookFolder
- VisualDifferHelp
- CFBundleHelpBookName
- com.visualdiffer.help
- CFBundleIconFile
- vd.icns
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- ${PRODUCT_NAME}
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(APP_VERSION)
- CFBundleSignature
- ????
- CFBundleVersion
- $(APP_BUNDLE_VERSION)
- LSApplicationCategoryType
- public.app-category.utilities
- LSMinimumSystemVersion
- ${MACOSX_DEPLOYMENT_TARGET}
- NSHumanReadableCopyright
- 2010, visualdiffer.com
- NSMainNibFile
- MainMenu
- NSPrincipalClass
- NSApplication
- ITSAppUsesNonExemptEncryption
-
- NSAppleScriptEnabled
-
- OSAScriptingDefinition
- ${PRODUCT_NAME}.sdef
-
- SUFeedURL
- https://app.visualdiffer.com/appcast.xml
-
- SUPublicEDKey
- kuAijnKlIhNOPvlWkldxU/ZRNY2d35Ltwcd1JnO3DzA=
-
- SUEnableInstallerLauncherService
-
-
-
-
diff --git a/VisualDiffer-Sparkle.entitlements b/VisualDiffer-Sparkle.entitlements
deleted file mode 100644
index a32a63f..0000000
--- a/VisualDiffer-Sparkle.entitlements
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
- com.apple.security.application-groups
-
- $(TeamIdentifierPrefix)com.appgroup.visualdiffer
-
- com.apple.security.files.bookmarks.app-scope
-
-
- com.apple.security.temporary-exception.mach-lookup.global-name
-
- $(PRODUCT_BUNDLE_IDENTIFIER)-spks
- $(PRODUCT_BUNDLE_IDENTIFIER)-spki
-
-
-
-
diff --git a/VisualDiffer.entitlements b/VisualDiffer.entitlements
deleted file mode 100644
index 3b2397e..0000000
--- a/VisualDiffer.entitlements
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- com.apple.security.application-groups
-
- $(TeamIdentifierPrefix)com.appgroup.visualdiffer
-
- com.apple.security.files.bookmarks.app-scope
-
-
-
diff --git a/VisualDiffer.xcodeproj/project.pbxproj b/VisualDiffer.xcodeproj/project.pbxproj
deleted file mode 100644
index fd309e2..0000000
--- a/VisualDiffer.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,4481 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 54;
- objects = {
-
-/* Begin PBXBuildFile section */
- 2F7446AB0DB6BCF400F9684A /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2F7446A70DB6BCF400F9684A /* MainMenu.xib */; };
- 55157D7512898F8800826FF8 /* folder-000-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6012898F8800826FF8 /* folder-000-open.png */; };
- 55157D7612898F8800826FF8 /* folder-000.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6112898F8800826FF8 /* folder-000.png */; };
- 55157D7712898F8800826FF8 /* folder-001-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6212898F8800826FF8 /* folder-001-open.png */; };
- 55157D7812898F8800826FF8 /* folder-001.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6312898F8800826FF8 /* folder-001.png */; };
- 55157D7912898F8800826FF8 /* folder-010-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6412898F8800826FF8 /* folder-010-open.png */; };
- 55157D7A12898F8800826FF8 /* folder-010.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6512898F8800826FF8 /* folder-010.png */; };
- 55157D7B12898F8800826FF8 /* folder-011-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6612898F8800826FF8 /* folder-011-open.png */; };
- 55157D7C12898F8800826FF8 /* folder-011.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6712898F8800826FF8 /* folder-011.png */; };
- 55157D7D12898F8800826FF8 /* folder-100-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6812898F8800826FF8 /* folder-100-open.png */; };
- 55157D7E12898F8800826FF8 /* folder-100.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6912898F8800826FF8 /* folder-100.png */; };
- 55157D7F12898F8800826FF8 /* folder-101-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6A12898F8800826FF8 /* folder-101-open.png */; };
- 55157D8012898F8800826FF8 /* folder-101.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6B12898F8800826FF8 /* folder-101.png */; };
- 55157D8112898F8800826FF8 /* folder-110-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6C12898F8800826FF8 /* folder-110-open.png */; };
- 55157D8212898F8800826FF8 /* folder-110.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6D12898F8800826FF8 /* folder-110.png */; };
- 55157D8312898F8800826FF8 /* folder-111-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6E12898F8800826FF8 /* folder-111-open.png */; };
- 55157D8412898F8800826FF8 /* folder-111.png in Resources */ = {isa = PBXBuildFile; fileRef = 55157D6F12898F8800826FF8 /* folder-111.png */; };
- 551BF0DA1643B91B009CC9D1 /* folder-000-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0C81643B91B009CC9D1 /* folder-000-open@2x.png */; };
- 551BF0DB1643B91B009CC9D1 /* folder-000@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0C91643B91B009CC9D1 /* folder-000@2x.png */; };
- 551BF0DC1643B91B009CC9D1 /* folder-001-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CA1643B91B009CC9D1 /* folder-001-open@2x.png */; };
- 551BF0DD1643B91B009CC9D1 /* folder-001@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CB1643B91B009CC9D1 /* folder-001@2x.png */; };
- 551BF0DE1643B91B009CC9D1 /* folder-010-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CC1643B91B009CC9D1 /* folder-010-open@2x.png */; };
- 551BF0DF1643B91B009CC9D1 /* folder-010@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CD1643B91B009CC9D1 /* folder-010@2x.png */; };
- 551BF0E01643B91B009CC9D1 /* folder-011-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CE1643B91B009CC9D1 /* folder-011-open@2x.png */; };
- 551BF0E11643B91B009CC9D1 /* folder-011@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0CF1643B91B009CC9D1 /* folder-011@2x.png */; };
- 551BF0E21643B91B009CC9D1 /* folder-100-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D01643B91B009CC9D1 /* folder-100-open@2x.png */; };
- 551BF0E31643B91B009CC9D1 /* folder-100@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D11643B91B009CC9D1 /* folder-100@2x.png */; };
- 551BF0E41643B91B009CC9D1 /* folder-101-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D21643B91B009CC9D1 /* folder-101-open@2x.png */; };
- 551BF0E51643B91B009CC9D1 /* folder-101@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D31643B91B009CC9D1 /* folder-101@2x.png */; };
- 551BF0E61643B91B009CC9D1 /* folder-110-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D41643B91B009CC9D1 /* folder-110-open@2x.png */; };
- 551BF0E71643B91B009CC9D1 /* folder-110@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D51643B91B009CC9D1 /* folder-110@2x.png */; };
- 551BF0E81643B91B009CC9D1 /* folder-111-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D61643B91B009CC9D1 /* folder-111-open@2x.png */; };
- 551BF0E91643B91B009CC9D1 /* folder-111@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D71643B91B009CC9D1 /* folder-111@2x.png */; };
- 551BF0EA1643B91B009CC9D1 /* folder-999-open@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D81643B91B009CC9D1 /* folder-999-open@2x.png */; };
- 551BF0EB1643B91B009CC9D1 /* folder-999@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 551BF0D91643B91B009CC9D1 /* folder-999@2x.png */; };
- 551DE39F2ED422820067AB18 /* FilesWindowController+SessionPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE39E2ED422820067AB18 /* FilesWindowController+SessionPreferences.swift */; };
- 551DE3A62ED4237B0067AB18 /* FileSessionPreferencesWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE3A42ED4237B0067AB18 /* FileSessionPreferencesWindow.swift */; };
- 551DE3AA2ED428B40067AB18 /* FilePreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE3A92ED428A50067AB18 /* FilePreferences.swift */; };
- 551DE3B42ED42AD90067AB18 /* FilePreferencesComparisonPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE3B32ED42AD00067AB18 /* FilePreferencesComparisonPanel.swift */; };
- 551DE3B62ED42B4E0067AB18 /* FileComparisonBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE3B52ED42B4E0067AB18 /* FileComparisonBox.swift */; };
- 551DE3B82ED439AF0067AB18 /* PreferencesBoxDataSource+Default.swift in Sources */ = {isa = PBXBuildFile; fileRef = 551DE3B72ED4399B0067AB18 /* PreferencesBoxDataSource+Default.swift */; };
- 551DEDE1160477CA0014DF88 /* prefs_folder.png in Resources */ = {isa = PBXBuildFile; fileRef = 551DEDE0160477CA0014DF88 /* prefs_folder.png */; };
- 5532516C2765F06B0092D65F /* mask-back.png in Resources */ = {isa = PBXBuildFile; fileRef = 553251672765F06B0092D65F /* mask-back.png */; };
- 5532516D2765F06B0092D65F /* mask-full.png in Resources */ = {isa = PBXBuildFile; fileRef = 553251682765F06B0092D65F /* mask-full.png */; };
- 5532516E2765F06B0092D65F /* mask-middle.png in Resources */ = {isa = PBXBuildFile; fileRef = 553251692765F06B0092D65F /* mask-middle.png */; };
- 5532516F2765F06B0092D65F /* mask-back-white.png in Resources */ = {isa = PBXBuildFile; fileRef = 5532516A2765F06B0092D65F /* mask-back-white.png */; };
- 553251702765F06B0092D65F /* mask-front.png in Resources */ = {isa = PBXBuildFile; fileRef = 5532516B2765F06B0092D65F /* mask-front.png */; };
- 5536ADBA2EF169820019EFBF /* SessionDiff+ExtraData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5536ADB92EF169820019EFBF /* SessionDiff+ExtraData.swift */; };
- 553741792E9372DF00AB56D0 /* NSAppearance+DarkMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740E52E9372DF00AB56D0 /* NSAppearance+DarkMode.swift */; };
- 5537417A2E9372DF00AB56D0 /* QLPreviewPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740FD2E9372DF00AB56D0 /* QLPreviewPanel.swift */; };
- 5537417B2E9372DF00AB56D0 /* TrustedPathsPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740A12E9372DF00AB56D0 /* TrustedPathsPreferencesPanel.swift */; };
- 5537417C2E9372DF00AB56D0 /* TouchPickersStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740142E9372DF00AB56D0 /* TouchPickersStackView.swift */; };
- 5537417D2E9372DF00AB56D0 /* BasePreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740862E9372DF00AB56D0 /* BasePreferences.swift */; };
- 5537417E2E9372DF00AB56D0 /* DualPaneSplitViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741532E9372DF00AB56D0 /* DualPaneSplitViewDelegate.swift */; };
- 5537417F2E9372DF00AB56D0 /* FoldersOutlineView+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FED2E9372DF00AB56D0 /* FoldersOutlineView+Menu.swift */; };
- 553741802E9372DF00AB56D0 /* AlignRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F8F2E9372DF00AB56D0 /* AlignRule.swift */; };
- 553741812E9372DF00AB56D0 /* VisualizationBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537409F2E9372DF00AB56D0 /* VisualizationBox.swift */; };
- 553741822E9372DF00AB56D0 /* CommonPrefs+FileCompare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F992E9372DF00AB56D0 /* CommonPrefs+FileCompare.swift */; };
- 553741832E9372DF00AB56D0 /* TablePanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741732E9372DF00AB56D0 /* TablePanelView.swift */; };
- 553741852E9372DF00AB56D0 /* NSOpenPanel+Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740FC2E9372DF00AB56D0 /* NSOpenPanel+Application.swift */; };
- 553741862E9372DF00AB56D0 /* ConfirmReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740012E9372DF00AB56D0 /* ConfirmReplace.swift */; };
- 553741872E9372DF00AB56D0 /* SessionDiff.ItemType+Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA62E9372DF00AB56D0 /* SessionDiff.ItemType+Paths.swift */; };
- 553741882E9372DF00AB56D0 /* FileSizeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537412C2E9372DF00AB56D0 /* FileSizeFormatter.swift */; };
- 553741892E9372DF00AB56D0 /* TOPTimestampPredicateEditorRowTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740DB2E9372DF00AB56D0 /* TOPTimestampPredicateEditorRowTemplate.m */; };
- 5537418A2E9372DF00AB56D0 /* DocumentWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F9F2E9372DF00AB56D0 /* DocumentWindow.swift */; };
- 5537418B2E9372DF00AB56D0 /* CommonPrefs+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F9D2E9372DF00AB56D0 /* CommonPrefs+Name.swift */; };
- 5537418C2E9372DF00AB56D0 /* ImageNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F922E9372DF00AB56D0 /* ImageNames.swift */; };
- 5537418D2E9372DF00AB56D0 /* FilePathTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537416D2E9372DF00AB56D0 /* FilePathTextField.swift */; };
- 5537418E2E9372DF00AB56D0 /* CopyCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740392E9372DF00AB56D0 /* CopyCompareItem.swift */; };
- 5537418F2E9372DF00AB56D0 /* ColoredFoldersManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE62E9372DF00AB56D0 /* ColoredFoldersManager.swift */; };
- 553741902E9372DF00AB56D0 /* FilesTableView+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB72E9372DF00AB56D0 /* FilesTableView+Menu.swift */; };
- 553741912E9372DF00AB56D0 /* NSBox+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741172E9372DF00AB56D0 /* NSBox+Helper.swift */; };
- 553741922E9372DF00AB56D0 /* FontPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740942E9372DF00AB56D0 /* FontPreferencesPanel.swift */; };
- 553741932E9372DF00AB56D0 /* DisplayOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537404B2E9372DF00AB56D0 /* DisplayOptions.swift */; };
- 553741942E9372DF00AB56D0 /* FilesWindowController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCE2E9372DF00AB56D0 /* FilesWindowController+Menu.swift */; };
- 553741952E9372DF00AB56D0 /* OptionSet+Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740F92E9372DF00AB56D0 /* OptionSet+Toggle.swift */; };
- 553741962E9372DF00AB56D0 /* URL+Finder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741102E9372DF00AB56D0 /* URL+Finder.swift */; };
- 553741982E9372DF00AB56D0 /* CommonPrefs+FolderCompare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F9A2E9372DF00AB56D0 /* CommonPrefs+FolderCompare.swift */; };
- 553741992E9372DF00AB56D0 /* FoldersWindowController+PathControlDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402E2E9372DF00AB56D0 /* FoldersWindowController+PathControlDelegate.swift */; };
- 5537419A2E9372DF00AB56D0 /* FontBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740932E9372DF00AB56D0 /* FontBox.swift */; };
- 5537419B2E9372DF00AB56D0 /* FilesTableViewFindTextDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB82E9372DF00AB56D0 /* FilesTableViewFindTextDelegate.swift */; };
- 5537419C2E9372DF00AB56D0 /* DeleteFileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FFD2E9372DF00AB56D0 /* DeleteFileOperationExecutor.swift */; };
- 5537419D2E9372DF00AB56D0 /* DualPaneSplitView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741522E9372DF00AB56D0 /* DualPaneSplitView.swift */; };
- 5537419E2E9372DF00AB56D0 /* StandardButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537414D2E9372DF00AB56D0 /* StandardButtons.swift */; };
- 5537419F2E9372DF00AB56D0 /* ConfirmationsFoldersBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537408B2E9372DF00AB56D0 /* ConfirmationsFoldersBox.swift */; };
- 553741A02E9372DF00AB56D0 /* DifferenceNavigatorBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537408E2E9372DF00AB56D0 /* DifferenceNavigatorBox.swift */; };
- 553741A12E9372DF00AB56D0 /* FolderReaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740602E9372DF00AB56D0 /* FolderReaderDelegate.swift */; };
- 553741A22E9372DF00AB56D0 /* UDiffScriptBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740BD2E9372DF00AB56D0 /* UDiffScriptBuilder.m */; };
- 553741A32E9372DF00AB56D0 /* String+RegularExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741072E9372DF00AB56D0 /* String+RegularExpression.swift */; };
- 553741A42E9372DF00AB56D0 /* FileSystemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740182E9372DF00AB56D0 /* FileSystemController.swift */; };
- 553741A52E9372DF00AB56D0 /* ComparatorOptions+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740482E9372DF00AB56D0 /* ComparatorOptions+Helper.swift */; };
- 553741A62E9372DF00AB56D0 /* AppearanceBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740962E9372DF00AB56D0 /* AppearanceBox.swift */; };
- 553741A72E9372DF00AB56D0 /* FolderComparisonBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740972E9372DF00AB56D0 /* FolderComparisonBox.swift */; };
- 553741A82E9372DF00AB56D0 /* FoldersWindowController+Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740242E9372DF00AB56D0 /* FoldersWindowController+Document.swift */; };
- 553741A92E9372DF00AB56D0 /* FilterConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537405D2E9372DF00AB56D0 /* FilterConfig.swift */; };
- 553741AA2E9372DF00AB56D0 /* IconUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537412F2E9372DF00AB56D0 /* IconUtils.swift */; };
- 553741AB2E9372DF00AB56D0 /* ScopeBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740D22E9372DF00AB56D0 /* ScopeBarItem.swift */; };
- 553741AC2E9372DF00AB56D0 /* NSTextView+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741202E9372DF00AB56D0 /* NSTextView+Style.swift */; };
- 553741AD2E9372DF00AB56D0 /* FoldersOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE72E9372DF00AB56D0 /* FoldersOutlineView.swift */; };
- 553741AE2E9372DF00AB56D0 /* PreferredEditorBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740992E9372DF00AB56D0 /* PreferredEditorBox.swift */; };
- 553741AF2E9372DF00AB56D0 /* MoveCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740412E9372DF00AB56D0 /* MoveCompareItem.swift */; };
- 553741B12E9372DF00AB56D0 /* TextFieldSelectionHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537415C2E9372DF00AB56D0 /* TextFieldSelectionHolder.swift */; };
- 553741B22E9372DF00AB56D0 /* TouchFileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740132E9372DF00AB56D0 /* TouchFileOperationExecutor.swift */; };
- 553741B32E9372DF00AB56D0 /* NSTextFieldCell+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741452E9372DF00AB56D0 /* NSTextFieldCell+Helper.swift */; };
- 553741B42E9372DF00AB56D0 /* NSApplication.ModalResponse+ReplaceFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740032E9372DF00AB56D0 /* NSApplication.ModalResponse+ReplaceFile.swift */; };
- 553741B52E9372DF00AB56D0 /* DiffOpenerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA42E9372DF00AB56D0 /* DiffOpenerDelegate.swift */; };
- 553741B62E9372DF00AB56D0 /* MGScopeBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740D02E9372DF00AB56D0 /* MGScopeBar.m */; };
- 553741B72E9372DF00AB56D0 /* PreferencesCheckbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740832E9372DF00AB56D0 /* PreferencesCheckbox.swift */; };
- 553741B82E9372DF00AB56D0 /* FileManager+Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740F12E9372DF00AB56D0 /* FileManager+Attributes.swift */; };
- 553741B92E9372DF00AB56D0 /* MainThreadFolderReaderDelegateBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537401C2E9372DF00AB56D0 /* MainThreadFolderReaderDelegateBridge.swift */; };
- 553741BA2E9372DF00AB56D0 /* VisibleWhitespaces.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537413F2E9372DF00AB56D0 /* VisibleWhitespaces.swift */; };
- 553741BB2E9372DF00AB56D0 /* DisplayPositionable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F912E9372DF00AB56D0 /* DisplayPositionable.swift */; };
- 553741BC2E9372DF00AB56D0 /* AlignRuleWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AA2E9372DF00AB56D0 /* AlignRuleWindow.swift */; };
- 553741BD2E9372DF00AB56D0 /* DeleteCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403A2E9372DF00AB56D0 /* DeleteCompareItem.swift */; };
- 553741BE2E9372DF00AB56D0 /* DiffChangeType+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FDD2E9372DF00AB56D0 /* DiffChangeType+Color.swift */; };
- 553741BF2E9372DF00AB56D0 /* DescriptionOutlineNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741412E9372DF00AB56D0 /* DescriptionOutlineNode.swift */; };
- 553741C02E9372DF00AB56D0 /* FilesTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB62E9372DF00AB56D0 /* FilesTableView.swift */; };
- 553741C12E9372DF00AB56D0 /* String+Occcurrences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741052E9372DF00AB56D0 /* String+Occcurrences.swift */; };
- 553741C22E9372DF00AB56D0 /* FoldersWindowController+QLPreviewPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402F2E9372DF00AB56D0 /* FoldersWindowController+QLPreviewPanel.swift */; };
- 553741C32E9372DF00AB56D0 /* FoldersOutlineView+DifferenceNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537405A2E9372DF00AB56D0 /* FoldersOutlineView+DifferenceNavigator.swift */; };
- 553741C42E9372DF00AB56D0 /* JumpToLineWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE32E9372DF00AB56D0 /* JumpToLineWindow.swift */; };
- 553741C52E9372DF00AB56D0 /* EncodingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741282E9372DF00AB56D0 /* EncodingError.swift */; };
- 553741C62E9372DF00AB56D0 /* FileExtraOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537404E2E9372DF00AB56D0 /* FileExtraOptions.swift */; };
- 553741C72E9372DF00AB56D0 /* Array+MoveIndexes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740E72E9372DF00AB56D0 /* Array+MoveIndexes.swift */; };
- 553741C82E9372DF00AB56D0 /* BigFileFileOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740C82E9372DF00AB56D0 /* BigFileFileOperationManager.m */; };
- 553741C92E9372DF00AB56D0 /* FoldersWindowController+BaseFolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740202E9372DF00AB56D0 /* FoldersWindowController+BaseFolder.swift */; };
- 553741CB2E9372DF00AB56D0 /* FoldersWindowController+UICreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740322E9372DF00AB56D0 /* FoldersWindowController+UICreation.swift */; };
- 553741CC2E9372DF00AB56D0 /* FilesWindowController+UICreation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD82E9372DF00AB56D0 /* FilesWindowController+UICreation.swift */; };
- 553741CD2E9372DF00AB56D0 /* NSTableView+Row.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537410A2E9372DF00AB56D0 /* NSTableView+Row.swift */; };
- 553741CE2E9372DF00AB56D0 /* FindText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537416E2E9372DF00AB56D0 /* FindText.swift */; };
- 553741CF2E9372DF00AB56D0 /* FoldersTraversalBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740902E9372DF00AB56D0 /* FoldersTraversalBox.swift */; };
- 553741D02E9372DF00AB56D0 /* FileError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741342E9372DF00AB56D0 /* FileError.swift */; };
- 553741D12E9372DF00AB56D0 /* OpenEditorError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537413B2E9372DF00AB56D0 /* OpenEditorError.swift */; };
- 553741D22E9372DF00AB56D0 /* GeneralPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740982E9372DF00AB56D0 /* GeneralPreferencesPanel.swift */; };
- 553741D32E9372DF00AB56D0 /* CompareItem+DifferenceNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537405B2E9372DF00AB56D0 /* CompareItem+DifferenceNavigator.swift */; };
- 553741D42E9372DF00AB56D0 /* PreferencesBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740812E9372DF00AB56D0 /* PreferencesBox.swift */; };
- 553741D52E9372DF00AB56D0 /* NSAlert+ReplaceFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740022E9372DF00AB56D0 /* NSAlert+ReplaceFile.swift */; };
- 553741D72E9372DF00AB56D0 /* URL+SymLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741152E9372DF00AB56D0 /* URL+SymLink.swift */; };
- 553741D82E9372DF00AB56D0 /* RecentDocumentPopupMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA22E9372DF00AB56D0 /* RecentDocumentPopupMenu.swift */; };
- 553741D92E9372DF00AB56D0 /* FoldersWindowController+FoldersOutlineViewContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740282E9372DF00AB56D0 /* FoldersWindowController+FoldersOutlineViewContextMenu.swift */; };
- 553741DA2E9372DF00AB56D0 /* FileAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403B2E9372DF00AB56D0 /* FileAttributes.swift */; };
- 553741DB2E9372DF00AB56D0 /* SyncFileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537400C2E9372DF00AB56D0 /* SyncFileController.swift */; };
- 553741DC2E9372DF00AB56D0 /* ConfirmationsFilesBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537408A2E9372DF00AB56D0 /* ConfirmationsFilesBox.swift */; };
- 553741DD2E9372DF00AB56D0 /* CompareItem+Accessors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740502E9372DF00AB56D0 /* CompareItem+Accessors.swift */; };
- 553741DE2E9372DF00AB56D0 /* FilesWindowController+JumpLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCC2E9372DF00AB56D0 /* FilesWindowController+JumpLine.swift */; };
- 553741DF2E9372DF00AB56D0 /* CommonPrefs+ConsoleLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740362E9372DF00AB56D0 /* CommonPrefs+ConsoleLog.swift */; };
- 553741E02E9372DF00AB56D0 /* NSToolbar+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537410C2E9372DF00AB56D0 /* NSToolbar+Create.swift */; };
- 553741E12E9372DF00AB56D0 /* String+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741032E9372DF00AB56D0 /* String+Helper.swift */; };
- 553741E32E9372DF00AB56D0 /* LineNumberTableRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC02E9372DF00AB56D0 /* LineNumberTableRowView.swift */; };
- 553741E42E9372DF00AB56D0 /* FolderReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537405E2E9372DF00AB56D0 /* FolderReader.swift */; };
- 553741E52E9372DF00AB56D0 /* DateFormatter+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740F32E9372DF00AB56D0 /* DateFormatter+Helper.swift */; };
- 553741E62E9372DF00AB56D0 /* FoldersWindowController+Navigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402B2E9372DF00AB56D0 /* FoldersWindowController+Navigation.swift */; };
- 553741E72E9372DF00AB56D0 /* HistoryEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FAB2E9372DF00AB56D0 /* HistoryEntity.swift */; };
- 553741E82E9372DF00AB56D0 /* CompareItem+Clone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740512E9372DF00AB56D0 /* CompareItem+Clone.swift */; };
- 553741E92E9372DF00AB56D0 /* URL+Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741122E9372DF00AB56D0 /* URL+Path.swift */; };
- 553741EA2E9372DF00AB56D0 /* PathChooser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA12E9372DF00AB56D0 /* PathChooser.swift */; };
- 553741EB2E9372DF00AB56D0 /* VDDocumentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA92E9372DF00AB56D0 /* VDDocumentController.swift */; };
- 553741EC2E9372DF00AB56D0 /* CopyFileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FFB2E9372DF00AB56D0 /* CopyFileOperationExecutor.swift */; };
- 553741ED2E9372DF00AB56D0 /* FoldersOutlineView+Columns.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE92E9372DF00AB56D0 /* FoldersOutlineView+Columns.swift */; };
- 553741EE2E9372DF00AB56D0 /* NSTextField+CenterVertically.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537416F2E9372DF00AB56D0 /* NSTextField+CenterVertically.swift */; };
- 553741EF2E9372DF00AB56D0 /* BufferedInputStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741322E9372DF00AB56D0 /* BufferedInputStream.swift */; };
- 553741F02E9372DF00AB56D0 /* ComparisonStandardUserDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740802E9372DF00AB56D0 /* ComparisonStandardUserDataSource.swift */; };
- 553741F12E9372DF00AB56D0 /* TextPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537409E2E9372DF00AB56D0 /* TextPreferencesPanel.swift */; };
- 553741F22E9372DF00AB56D0 /* AlignPopupButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741642E9372DF00AB56D0 /* AlignPopupButtonCell.swift */; };
- 553741F32E9372DF00AB56D0 /* FolderSelectionInfo+ViewerActionValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537406D2E9372DF00AB56D0 /* FolderSelectionInfo+ViewerActionValidator.swift */; };
- 553741F42E9372DF00AB56D0 /* PopUpButtonUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741722E9372DF00AB56D0 /* PopUpButtonUrl.swift */; };
- 553741F52E9372DF00AB56D0 /* OpenEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741392E9372DF00AB56D0 /* OpenEditor.swift */; };
- 553741F62E9372DF00AB56D0 /* NSMenu+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740F72E9372DF00AB56D0 /* NSMenu+File.swift */; };
- 553741F72E9372DF00AB56D0 /* FilesWindowController+FileInfoBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC92E9372DF00AB56D0 /* FilesWindowController+FileInfoBarDelegate.swift */; };
- 553741F82E9372DF00AB56D0 /* KeyboardPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537409C2E9372DF00AB56D0 /* KeyboardPreferencesPanel.swift */; };
- 553741F92E9372DF00AB56D0 /* CompareItem+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740402E9372DF00AB56D0 /* CompareItem+Metadata.swift */; };
- 553741FA2E9372DF00AB56D0 /* TextFieldVerticalCentered.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC32E9372DF00AB56D0 /* TextFieldVerticalCentered.swift */; };
- 553741FB2E9372DF00AB56D0 /* KeyEquivalent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F932E9372DF00AB56D0 /* KeyEquivalent.swift */; };
- 553741FC2E9372DF00AB56D0 /* CompareItem+VisibleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740572E9372DF00AB56D0 /* CompareItem+VisibleItem.swift */; };
- 553741FD2E9372DF00AB56D0 /* FoldersWindowController+SessionPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740312E9372DF00AB56D0 /* FoldersWindowController+SessionPreferences.swift */; };
- 553741FE2E9372DF00AB56D0 /* CompareItemTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF62E9372DF00AB56D0 /* CompareItemTableCellView.swift */; };
- 553741FF2E9372DF00AB56D0 /* ProgressBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741582E9372DF00AB56D0 /* ProgressBarView.swift */; };
- 553742002E9372DF00AB56D0 /* FolderManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403F2E9372DF00AB56D0 /* FolderManagerError.swift */; };
- 553742012E9372DF00AB56D0 /* FolderSelectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537401E2E9372DF00AB56D0 /* FolderSelectionInfo.swift */; };
- 553742022E9372DF00AB56D0 /* SynchroScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537415A2E9372DF00AB56D0 /* SynchroScrollView.swift */; };
- 553742032E9372DF00AB56D0 /* FilesWindowController+Save.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD52E9372DF00AB56D0 /* FilesWindowController+Save.swift */; };
- 553742042E9372DF00AB56D0 /* FoldersWindowController+ConsoleViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740222E9372DF00AB56D0 /* FoldersWindowController+ConsoleViewDelegate.swift */; };
- 553742052E9372DF00AB56D0 /* PreferencesBoxDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740822E9372DF00AB56D0 /* PreferencesBoxDataSource.swift */; };
- 553742062E9372DF00AB56D0 /* TOPFileSizePredicateEditorRowTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740D92E9372DF00AB56D0 /* TOPFileSizePredicateEditorRowTemplate.m */; };
- 553742072E9372DF00AB56D0 /* FolderReader+Detached.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537401B2E9372DF00AB56D0 /* FolderReader+Detached.swift */; };
- 553742082E9372DF00AB56D0 /* ViewLinkable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F962E9372DF00AB56D0 /* ViewLinkable.swift */; };
- 553742092E9372DF00AB56D0 /* SessionPreferencesFiltersBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740B42E9372DF00AB56D0 /* SessionPreferencesFiltersBox.swift */; };
- 5537420A2E9372DF00AB56D0 /* FilesWindowController+Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC72E9372DF00AB56D0 /* FilesWindowController+Common.swift */; };
- 5537420B2E9372DF00AB56D0 /* FilesWindowController+NSToolbarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD12E9372DF00AB56D0 /* FilesWindowController+NSToolbarDelegate.swift */; };
- 5537420C2E9372DF00AB56D0 /* FilesWindowController+TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD72E9372DF00AB56D0 /* FilesWindowController+TableView.swift */; };
- 5537420D2E9372DF00AB56D0 /* NSProgressIndicator+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537411C2E9372DF00AB56D0 /* NSProgressIndicator+Helper.swift */; };
- 5537420E2E9372DF00AB56D0 /* ComparatorOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740462E9372DF00AB56D0 /* ComparatorOptions.swift */; };
- 5537420F2E9372DF00AB56D0 /* PathTimestamps.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740422E9372DF00AB56D0 /* PathTimestamps.swift */; };
- 553742102E9372DF00AB56D0 /* FilesWindowController+Clipboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC62E9372DF00AB56D0 /* FilesWindowController+Clipboard.swift */; };
- 553742112E9372DF00AB56D0 /* RSVerticallyCenteredTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741462E9372DF00AB56D0 /* RSVerticallyCenteredTextFieldCell.swift */; };
- 553742122E9372DF00AB56D0 /* CompareItem+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740532E9372DF00AB56D0 /* CompareItem+Description.swift */; };
- 553742132E9372DF00AB56D0 /* SessionPreferencesWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740A62E9372DF00AB56D0 /* SessionPreferencesWindow.swift */; };
- 553742142E9372DF00AB56D0 /* UserDefinedRulesBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AF2E9372DF00AB56D0 /* UserDefinedRulesBox.swift */; };
- 553742162E9372DF00AB56D0 /* ProgressIndicatorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740092E9372DF00AB56D0 /* ProgressIndicatorController.swift */; };
- 553742172E9372DF00AB56D0 /* FolderPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF52E9372DF00AB56D0 /* FolderPanelView.swift */; };
- 553742182E9372DF00AB56D0 /* ComparatorOptions+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740472E9372DF00AB56D0 /* ComparatorOptions+Description.swift */; };
- 553742192E9372DF00AB56D0 /* FoldersOutlineView+Clipboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE82E9372DF00AB56D0 /* FoldersOutlineView+Clipboard.swift */; };
- 5537421A2E9372DF00AB56D0 /* DatePickersStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740112E9372DF00AB56D0 /* DatePickersStackView.swift */; };
- 5537421B2E9372DF00AB56D0 /* UnifiedDiff.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740BF2E9372DF00AB56D0 /* UnifiedDiff.m */; };
- 5537421C2E9372DF00AB56D0 /* SyncOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537400F2E9372DF00AB56D0 /* SyncOutlineView.swift */; };
- 5537421D2E9372DF00AB56D0 /* CompareItem+Comparison.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740522E9372DF00AB56D0 /* CompareItem+Comparison.swift */; };
- 5537421E2E9372DF00AB56D0 /* NSError+Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740EF2E9372DF00AB56D0 /* NSError+Format.swift */; };
- 5537421F2E9372DF00AB56D0 /* RefreshInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740612E9372DF00AB56D0 /* RefreshInfo.swift */; };
- 553742202E9372DF00AB56D0 /* FileDropView+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741562E9372DF00AB56D0 /* FileDropView+Helper.swift */; };
- 553742212E9372DF00AB56D0 /* SyncFileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537400D2E9372DF00AB56D0 /* SyncFileOperationExecutor.swift */; };
- 553742222E9372DF00AB56D0 /* CompareItem+FilterConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740542E9372DF00AB56D0 /* CompareItem+FilterConfig.swift */; };
- 553742232E9372DF00AB56D0 /* NSStackView+PreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740A32E9372DF00AB56D0 /* NSStackView+PreferencesPanel.swift */; };
- 553742242E9372DF00AB56D0 /* CustomValidationToolbarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741482E9372DF00AB56D0 /* CustomValidationToolbarItem.swift */; };
- 553742252E9372DF00AB56D0 /* VisibleItem+Sort.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740732E9372DF00AB56D0 /* VisibleItem+Sort.swift */; };
- 553742262E9372DF00AB56D0 /* LineNumberTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBF2E9372DF00AB56D0 /* LineNumberTableCellView.swift */; };
- 553742272E9372DF00AB56D0 /* FilesWindowController+Slider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD62E9372DF00AB56D0 /* FilesWindowController+Slider.swift */; };
- 553742282E9372DF00AB56D0 /* VDDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA82E9372DF00AB56D0 /* VDDocument.swift */; };
- 553742292E9372DF00AB56D0 /* FilesWindowController+Read.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD42E9372DF00AB56D0 /* FilesWindowController+Read.swift */; };
- 5537422A2E9372DF00AB56D0 /* PowerAssertion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741352E9372DF00AB56D0 /* PowerAssertion.swift */; };
- 5537422C2E9372DF00AB56D0 /* FilesWindowController+UISetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD92E9372DF00AB56D0 /* FilesWindowController+UISetup.swift */; };
- 5537422D2E9372DF00AB56D0 /* CompareUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741332E9372DF00AB56D0 /* CompareUtil.swift */; };
- 5537422E2E9372DF00AB56D0 /* DisplayFiltersScopeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF42E9372DF00AB56D0 /* DisplayFiltersScopeBar.swift */; };
- 5537422F2E9372DF00AB56D0 /* HistorySessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FAC2E9372DF00AB56D0 /* HistorySessionManager.swift */; };
- 553742302E9372DF00AB56D0 /* FilePanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBB2E9372DF00AB56D0 /* FilePanelView.swift */; };
- 553742312E9372DF00AB56D0 /* FilesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC52E9372DF00AB56D0 /* FilesWindowController.swift */; };
- 553742322E9372DF00AB56D0 /* FilesWindowController+MenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCF2E9372DF00AB56D0 /* FilesWindowController+MenuDelegate.swift */; };
- 553742332E9372DF00AB56D0 /* DifferenceCounters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537416B2E9372DF00AB56D0 /* DifferenceCounters.swift */; };
- 553742342E9372DF00AB56D0 /* ReplaceFileAttributeKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740042E9372DF00AB56D0 /* ReplaceFileAttributeKey.swift */; };
- 553742352E9372DF00AB56D0 /* FoldersWindowController+Select.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740302E9372DF00AB56D0 /* FoldersWindowController+Select.swift */; };
- 553742362E9372DF00AB56D0 /* FoldersWindowController+Comparison.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740212E9372DF00AB56D0 /* FoldersWindowController+Comparison.swift */; };
- 553742372E9372DF00AB56D0 /* PathView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741712E9372DF00AB56D0 /* PathView.swift */; };
- 553742382E9372DF00AB56D0 /* DiffLine+Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FDB2E9372DF00AB56D0 /* DiffLine+Color.swift */; };
- 553742392E9372DF00AB56D0 /* FileDropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741552E9372DF00AB56D0 /* FileDropView.swift */; };
- 5537423A2E9372DF00AB56D0 /* PreferredEditorPopupCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537413D2E9372DF00AB56D0 /* PreferredEditorPopupCell.swift */; };
- 5537423B2E9372DF00AB56D0 /* FilePanelView+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBC2E9372DF00AB56D0 /* FilePanelView+File.swift */; };
- 5537423C2E9372DF00AB56D0 /* KeyboardDocumentBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537409B2E9372DF00AB56D0 /* KeyboardDocumentBox.swift */; };
- 5537423D2E9372DF00AB56D0 /* FoldersOutlineView+VisibleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FEE2E9372DF00AB56D0 /* FoldersOutlineView+VisibleItem.swift */; };
- 5537423E2E9372DF00AB56D0 /* FileNameCaseBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AE2E9372DF00AB56D0 /* FileNameCaseBox.swift */; };
- 5537423F2E9372DF00AB56D0 /* URL+Metadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741112E9372DF00AB56D0 /* URL+Metadata.swift */; };
- 553742402E9372DF00AB56D0 /* FoldersWindowController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740292E9372DF00AB56D0 /* FoldersWindowController+Menu.swift */; };
- 553742412E9372DF00AB56D0 /* OperationSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740192E9372DF00AB56D0 /* OperationSummaryView.swift */; };
- 553742422E9372DF00AB56D0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F8D2E9372DF00AB56D0 /* AppDelegate.swift */; };
- 553742432E9372DF00AB56D0 /* ExpressionBox+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AD2E9372DF00AB56D0 /* ExpressionBox+Menu.swift */; };
- 553742442E9372DF00AB56D0 /* FilesWindowController+PathControlDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD32E9372DF00AB56D0 /* FilesWindowController+PathControlDelegate.swift */; };
- 553742452E9372DF00AB56D0 /* VisibleItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537406F2E9372DF00AB56D0 /* VisibleItem.swift */; };
- 553742462E9372DF00AB56D0 /* DiffChangeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FDE2E9372DF00AB56D0 /* DiffChangeType.swift */; };
- 553742472E9372DF00AB56D0 /* NotificationCenter+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F942E9372DF00AB56D0 /* NotificationCenter+Helper.swift */; };
- 553742482E9372DF00AB56D0 /* NSImage+Tint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740F52E9372DF00AB56D0 /* NSImage+Tint.swift */; };
- 553742492E9372DF00AB56D0 /* NSButton+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741192E9372DF00AB56D0 /* NSButton+Helper.swift */; };
- 5537424A2E9372DF00AB56D0 /* FoldersWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537401F2E9372DF00AB56D0 /* FoldersWindowController.swift */; };
- 5537424B2E9372DF00AB56D0 /* VisibleItem+Find.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740702E9372DF00AB56D0 /* VisibleItem+Find.swift */; };
- 5537424C2E9372DF00AB56D0 /* String+Highlights.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741042E9372DF00AB56D0 /* String+Highlights.swift */; };
- 5537424D2E9372DF00AB56D0 /* SyncItemsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537400E2E9372DF00AB56D0 /* SyncItemsInfo.swift */; };
- 5537424E2E9372DF00AB56D0 /* FileOperationManager+FileOperationManagerAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403D2E9372DF00AB56D0 /* FileOperationManager+FileOperationManagerAction.swift */; };
- 5537424F2E9372DF00AB56D0 /* NoodleCustomImageRep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741302E9372DF00AB56D0 /* NoodleCustomImageRep.swift */; };
- 553742502E9372DF00AB56D0 /* FoldersWindowController+FileSystemControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740262E9372DF00AB56D0 /* FoldersWindowController+FileSystemControllerDelegate.swift */; };
- 553742512E9372DF00AB56D0 /* FilesWindowController+NSWindowDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD22E9372DF00AB56D0 /* FilesWindowController+NSWindowDelegate.swift */; };
- 553742522E9372DF00AB56D0 /* FilesWindowController+Navigate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FD02E9372DF00AB56D0 /* FilesWindowController+Navigate.swift */; };
- 553742532E9372DF00AB56D0 /* DiffCountersItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741692E9372DF00AB56D0 /* DiffCountersItem.swift */; };
- 553742542E9372DF00AB56D0 /* SaveFileAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC22E9372DF00AB56D0 /* SaveFileAccessoryView.swift */; };
- 553742552E9372DF00AB56D0 /* FileThumbnailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBE2E9372DF00AB56D0 /* FileThumbnailView.swift */; };
- 553742562E9372DF00AB56D0 /* FilesTableView+EditorData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE12E9372DF00AB56D0 /* FilesTableView+EditorData.swift */; };
- 553742572E9372DF00AB56D0 /* ComparatorPopUpButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741652E9372DF00AB56D0 /* ComparatorPopUpButtonCell.swift */; };
- 553742582E9372DF00AB56D0 /* IntegerFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537412D2E9372DF00AB56D0 /* IntegerFormatter.swift */; };
- 553742592E9372DF00AB56D0 /* SessionDiff+ResolvePath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB22E9372DF00AB56D0 /* SessionDiff+ResolvePath.swift */; };
- 5537425A2E9372DF00AB56D0 /* CompareItem+NSTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF12E9372DF00AB56D0 /* CompareItem+NSTableCellView.swift */; };
- 5537425B2E9372DF00AB56D0 /* DocumentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA52E9372DF00AB56D0 /* DocumentError.swift */; };
- 5537425C2E9372DF00AB56D0 /* FolderSelectionInfo+FileSystemActionValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537406A2E9372DF00AB56D0 /* FolderSelectionInfo+FileSystemActionValidator.swift */; };
- 5537425D2E9372DF00AB56D0 /* FoldersWindowController+Exclude.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740252E9372DF00AB56D0 /* FoldersWindowController+Exclude.swift */; };
- 5537425E2E9372DF00AB56D0 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740872E9372DF00AB56D0 /* Preferences.swift */; };
- 5537425F2E9372DF00AB56D0 /* OutlineViewItemDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740342E9372DF00AB56D0 /* OutlineViewItemDelegate.swift */; };
- 553742612E9372DF00AB56D0 /* NSImage+SymbolCompat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F952E9372DF00AB56D0 /* NSImage+SymbolCompat.swift */; };
- 553742622E9372DF00AB56D0 /* TableViewContextMenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741432E9372DF00AB56D0 /* TableViewContextMenuDelegate.swift */; };
- 553742632E9372DF00AB56D0 /* NSPredicate+Objc.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740D52E9372DF00AB56D0 /* NSPredicate+Objc.m */; };
- 553742642E9372DF00AB56D0 /* FileSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740172E9372DF00AB56D0 /* FileSummaryView.swift */; };
- 553742652E9372DF00AB56D0 /* CompareItemTableRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF72E9372DF00AB56D0 /* CompareItemTableRowView.swift */; };
- 553742662E9372DF00AB56D0 /* FolderSelectionInfo+FolderActionValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537406C2E9372DF00AB56D0 /* FolderSelectionInfo+FolderActionValidator.swift */; };
- 553742672E9372DF00AB56D0 /* CommonPrefs+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F9C2E9372DF00AB56D0 /* CommonPrefs+Helper.swift */; };
- 553742682E9372DF00AB56D0 /* FilePathTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741672E9372DF00AB56D0 /* FilePathTableCellView.swift */; };
- 553742692E9372DF00AB56D0 /* AttributedMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741372E9372DF00AB56D0 /* AttributedMenuItem.swift */; };
- 5537426A2E9372DF00AB56D0 /* URL+StructuredContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741142E9372DF00AB56D0 /* URL+StructuredContent.swift */; };
- 5537426B2E9372DF00AB56D0 /* SessionPreferencesComparisonPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740B12E9372DF00AB56D0 /* SessionPreferencesComparisonPanel.swift */; };
- 5537426C2E9372DF00AB56D0 /* FolderCompareInfoWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740762E9372DF00AB56D0 /* FolderCompareInfoWindow.swift */; };
- 5537426D2E9372DF00AB56D0 /* NSToolbarItem+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537410D2E9372DF00AB56D0 /* NSToolbarItem+Create.swift */; };
- 5537426E2E9372DF00AB56D0 /* MoveFileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FFF2E9372DF00AB56D0 /* MoveFileOperationExecutor.swift */; };
- 5537426F2E9372DF00AB56D0 /* URL+FileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537410F2E9372DF00AB56D0 /* URL+FileManager.swift */; };
- 553742712E9372DF00AB56D0 /* ConfirmationsDocumentsBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740892E9372DF00AB56D0 /* ConfirmationsDocumentsBox.swift */; };
- 553742722E9372DF00AB56D0 /* ExpressionBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AC2E9372DF00AB56D0 /* ExpressionBox.swift */; };
- 553742732E9372DF00AB56D0 /* CompareItem+LeafPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF02E9372DF00AB56D0 /* CompareItem+LeafPath.swift */; };
- 553742742E9372DF00AB56D0 /* SessionDiff.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FAE2E9372DF00AB56D0 /* SessionDiff.swift */; };
- 553742762E9372DF00AB56D0 /* TimeToleranceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741742E9372DF00AB56D0 /* TimeToleranceView.swift */; };
- 553742782E9372DF00AB56D0 /* FoldersOutlineView+Enumerate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FEA2E9372DF00AB56D0 /* FoldersOutlineView+Enumerate.swift */; };
- 553742792E9372DF00AB56D0 /* HistoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537407A2E9372DF00AB56D0 /* HistoryController.swift */; };
- 5537427A2E9372DF00AB56D0 /* ConsoleToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537414F2E9372DF00AB56D0 /* ConsoleToolbarView.swift */; };
- 5537427B2E9372DF00AB56D0 /* HistorySearchField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537407D2E9372DF00AB56D0 /* HistorySearchField.swift */; };
- 5537427C2E9372DF00AB56D0 /* URL+ResourceFork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741132E9372DF00AB56D0 /* URL+ResourceFork.swift */; };
- 5537427D2E9372DF00AB56D0 /* LinkButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537414C2E9372DF00AB56D0 /* LinkButton.swift */; };
- 5537427E2E9372DF00AB56D0 /* ReplaceInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537400A2E9372DF00AB56D0 /* ReplaceInfoView.swift */; };
- 5537427F2E9372DF00AB56D0 /* NSAlert+DirtyFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC12E9372DF00AB56D0 /* NSAlert+DirtyFiles.swift */; };
- 553742802E9372DF00AB56D0 /* CommonPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F982E9372DF00AB56D0 /* CommonPrefs.swift */; };
- 553742812E9372DF00AB56D0 /* FilesWindowController+LinesDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCD2E9372DF00AB56D0 /* FilesWindowController+LinesDetail.swift */; };
- 553742822E9372DF00AB56D0 /* FileOperationManager+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403E2E9372DF00AB56D0 /* FileOperationManager+Util.swift */; };
- 553742832E9372DF00AB56D0 /* ConsoleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741502E9372DF00AB56D0 /* ConsoleView.swift */; };
- 553742842E9372DF00AB56D0 /* CommonPrefs+DifferenceNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740592E9372DF00AB56D0 /* CommonPrefs+DifferenceNavigator.swift */; };
- 553742852E9372DF00AB56D0 /* FileOperationExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740162E9372DF00AB56D0 /* FileOperationExecutor.swift */; };
- 553742862E9372DF00AB56D0 /* AlignmentPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740A92E9372DF00AB56D0 /* AlignmentPanel.swift */; };
- 553742872E9372DF00AB56D0 /* FoldersOutlineView+ExternalApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FEB2E9372DF00AB56D0 /* FoldersOutlineView+ExternalApp.swift */; };
- 553742882E9372DF00AB56D0 /* PreferencesPanelDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740B92E9372DF00AB56D0 /* PreferencesPanelDataSource.swift */; };
- 553742892E9372DF00AB56D0 /* DiffCountersTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537416A2E9372DF00AB56D0 /* DiffCountersTextFieldCell.swift */; };
- 5537428A2E9372DF00AB56D0 /* FoldersWindowController+FoldersOutlineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740272E9372DF00AB56D0 /* FoldersWindowController+FoldersOutlineView.swift */; };
- 5537428B2E9372DF00AB56D0 /* TableViewCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741422E9372DF00AB56D0 /* TableViewCommon.swift */; };
- 5537428C2E9372DF00AB56D0 /* CompareItem+Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740562E9372DF00AB56D0 /* CompareItem+Path.swift */; };
- 5537428D2E9372DF00AB56D0 /* FolderPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537408F2E9372DF00AB56D0 /* FolderPreferencesPanel.swift */; };
- 5537428E2E9372DF00AB56D0 /* FileOperationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537403C2E9372DF00AB56D0 /* FileOperationManager.swift */; };
- 5537428F2E9372DF00AB56D0 /* StandardUserPreferencesBoxDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740842E9372DF00AB56D0 /* StandardUserPreferencesBoxDataSource.swift */; };
- 553742902E9372DF00AB56D0 /* SecureBookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741262E9372DF00AB56D0 /* SecureBookmark.swift */; };
- 553742912E9372DF00AB56D0 /* FilesScopeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBD2E9372DF00AB56D0 /* FilesScopeBar.swift */; };
- 553742922E9372DF00AB56D0 /* OpenEditorAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537413A2E9372DF00AB56D0 /* OpenEditorAttribute.swift */; };
- 553742932E9372DF00AB56D0 /* WindowCancelOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537415F2E9372DF00AB56D0 /* WindowCancelOperation.swift */; };
- 553742942E9372DF00AB56D0 /* VisibleItem+QLPreviewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740722E9372DF00AB56D0 /* VisibleItem+QLPreviewItem.swift */; };
- 553742952E9372DF00AB56D0 /* FilesWindowController+FilesTableViewContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCB2E9372DF00AB56D0 /* FilesWindowController+FilesTableViewContextMenu.swift */; };
- 553742962E9372DF00AB56D0 /* FolderSelectionInfo+CompareActionValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740692E9372DF00AB56D0 /* FolderSelectionInfo+CompareActionValidator.swift */; };
- 553742972E9372DF00AB56D0 /* MainThreadComparatorDelegateBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF92E9372DF00AB56D0 /* MainThreadComparatorDelegateBridge.swift */; };
- 553742982E9372DF00AB56D0 /* DiffCountersItem+DiffResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FE02E9372DF00AB56D0 /* DiffCountersItem+DiffResult.swift */; };
- 553742992E9372DF00AB56D0 /* FileOperationManagerDelegateImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740082E9372DF00AB56D0 /* FileOperationManagerDelegateImpl.swift */; };
- 5537429A2E9372DF00AB56D0 /* SessionDiff+AlignRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FAF2E9372DF00AB56D0 /* SessionDiff+AlignRule.swift */; };
- 5537429B2E9372DF00AB56D0 /* FoldersWindowController+MenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402A2E9372DF00AB56D0 /* FoldersWindowController+MenuDelegate.swift */; };
- 5537429C2E9372DF00AB56D0 /* MGRecessedPopUpButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740CE2E9372DF00AB56D0 /* MGRecessedPopUpButtonCell.m */; };
- 5537429D2E9372DF00AB56D0 /* FolderSelectionInfo+FilterActionValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537406B2E9372DF00AB56D0 /* FolderSelectionInfo+FilterActionValidator.swift */; };
- 5537429E2E9372DF00AB56D0 /* OpenDiffCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740E22E9372DF00AB56D0 /* OpenDiffCommand.swift */; };
- 5537429F2E9372DF00AB56D0 /* RenameCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740432E9372DF00AB56D0 /* RenameCompareItem.swift */; };
- 553742A02E9372DF00AB56D0 /* DisplayOptions+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537404C2E9372DF00AB56D0 /* DisplayOptions+Helper.swift */; };
- 553742A12E9372DF00AB56D0 /* SessionPreferencesWindow+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740A72E9372DF00AB56D0 /* SessionPreferencesWindow+Data.swift */; };
- 553742A22E9372DF00AB56D0 /* FolderReader+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537405F2E9372DF00AB56D0 /* FolderReader+Log.swift */; };
- 553742A32E9372DF00AB56D0 /* NSArrayController+Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA02E9372DF00AB56D0 /* NSArrayController+Paths.swift */; };
- 553742A42E9372DF00AB56D0 /* NSPredicateEditor+Fix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741012E9372DF00AB56D0 /* NSPredicateEditor+Fix.swift */; };
- 553742A52E9372DF00AB56D0 /* FoldersWindowController+NSToolbarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402C2E9372DF00AB56D0 /* FoldersWindowController+NSToolbarDelegate.swift */; };
- 553742A62E9372DF00AB56D0 /* NSAlert+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740FB2E9372DF00AB56D0 /* NSAlert+Helper.swift */; };
- 553742A72E9372DF00AB56D0 /* FoldersWindowController+NSWindowDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537402D2E9372DF00AB56D0 /* FoldersWindowController+NSWindowDelegate.swift */; };
- 553742A82E9372DF00AB56D0 /* FilesWindowController+FilesScopeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FCA2E9372DF00AB56D0 /* FilesWindowController+FilesScopeBar.swift */; };
- 553742A92E9372DF00AB56D0 /* NSManagedObjectContext+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740EB2E9372DF00AB56D0 /* NSManagedObjectContext+Helpers.swift */; };
- 553742AA2E9372DF00AB56D0 /* String+Path.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741062E9372DF00AB56D0 /* String+Path.swift */; };
- 553742AB2E9372DF00AB56D0 /* TimeInterval+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740ED2E9372DF00AB56D0 /* TimeInterval+Helper.swift */; };
- 553742AC2E9372DF00AB56D0 /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F902E9372DF00AB56D0 /* ColorScheme.swift */; };
- 553742AD2E9372DF00AB56D0 /* FilesWindowController+Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FC82E9372DF00AB56D0 /* FilesWindowController+Document.swift */; };
- 553742AE2E9372DF00AB56D0 /* PathControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741702E9372DF00AB56D0 /* PathControl.swift */; };
- 553742AF2E9372DF00AB56D0 /* TouchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740122E9372DF00AB56D0 /* TouchController.swift */; };
- 553742B02E9372DF00AB56D0 /* CompletionIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740062E9372DF00AB56D0 /* CompletionIndicator.swift */; };
- 553742B12E9372DF00AB56D0 /* FoldersWindowController+UISetup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740332E9372DF00AB56D0 /* FoldersWindowController+UISetup.swift */; };
- 553742B22E9372DF00AB56D0 /* NSTableView+Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741092E9372DF00AB56D0 /* NSTableView+Font.swift */; };
- 553742B32E9372DF00AB56D0 /* ActionBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537414A2E9372DF00AB56D0 /* ActionBarView.swift */; };
- 553742B42E9372DF00AB56D0 /* TouchCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740442E9372DF00AB56D0 /* TouchCompareItem.swift */; };
- 553742B52E9372DF00AB56D0 /* HistoryFetchedResultsControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537407C2E9372DF00AB56D0 /* HistoryFetchedResultsControllerDelegate.swift */; };
- 553742B62E9372DF00AB56D0 /* CommonPrefs+Font.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373F9B2E9372DF00AB56D0 /* CommonPrefs+Font.swift */; };
- 553742B72E9372DF00AB56D0 /* NSWorkspace+Finder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741232E9372DF00AB56D0 /* NSWorkspace+Finder.swift */; };
- 553742B82E9372DF00AB56D0 /* FoldersOutlineViewFindTextDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FEF2E9372DF00AB56D0 /* FoldersOutlineViewFindTextDelegate.swift */; };
- 553742B92E9372DF00AB56D0 /* AlignTestResultBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740AB2E9372DF00AB56D0 /* AlignTestResultBox.swift */; };
- 553742BA2E9372DF00AB56D0 /* VisibleItem+Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740712E9372DF00AB56D0 /* VisibleItem+Log.swift */; };
- 553742BB2E9372DF00AB56D0 /* HistoryTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537407E2E9372DF00AB56D0 /* HistoryTableView.swift */; };
- 553742BC2E9372DF00AB56D0 /* SessionDiff+NSSortDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB12E9372DF00AB56D0 /* SessionDiff+NSSortDescriptor.swift */; };
- 553742BD2E9372DF00AB56D0 /* NSPopUpButton+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537411A2E9372DF00AB56D0 /* NSPopUpButton+Helper.swift */; };
- 553742BE2E9372DF00AB56D0 /* NSColor+Hex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740E92E9372DF00AB56D0 /* NSColor+Hex.swift */; };
- 553742BF2E9372DF00AB56D0 /* FileInfoBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FBA2E9372DF00AB56D0 /* FileInfoBar.swift */; };
- 553742C02E9372DF00AB56D0 /* TitlePredicateEditorRowTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 553740D72E9372DF00AB56D0 /* TitlePredicateEditorRowTemplate.m */; };
- 553742C12E9372DF00AB56D0 /* ErrorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740072E9372DF00AB56D0 /* ErrorsView.swift */; };
- 553742C22E9372DF00AB56D0 /* IconUtils+CompareItemIconUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FF22E9372DF00AB56D0 /* IconUtils+CompareItemIconUtils.swift */; };
- 553742C32E9372DF00AB56D0 /* SessionTypeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FA72E9372DF00AB56D0 /* SessionTypeError.swift */; };
- 553742C42E9372DF00AB56D0 /* FoldersOutlineView+FileCount.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FEC2E9372DF00AB56D0 /* FoldersOutlineView+FileCount.swift */; };
- 553742C52E9372DF00AB56D0 /* SessionPreferencesFiltersPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740B52E9372DF00AB56D0 /* SessionPreferencesFiltersPanel.swift */; };
- 553742C62E9372DF00AB56D0 /* FoldersWindowController+DisplayFiltersScopeBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740232E9372DF00AB56D0 /* FoldersWindowController+DisplayFiltersScopeBarDelegate.swift */; };
- 553742C72E9372DF00AB56D0 /* DiffCountersItem+CompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740372E9372DF00AB56D0 /* DiffCountersItem+CompareItem.swift */; };
- 553742C82E9372DF00AB56D0 /* DisplayFiltersPopUpButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741662E9372DF00AB56D0 /* DisplayFiltersPopUpButtonCell.swift */; };
- 553742C92E9372DF00AB56D0 /* NSEvent+VirtualKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537412A2E9372DF00AB56D0 /* NSEvent+VirtualKeys.swift */; };
- 553742CA2E9372DF00AB56D0 /* DescriptionOutlineNode+FolderCompareInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740752E9372DF00AB56D0 /* DescriptionOutlineNode+FolderCompareInfo.swift */; };
- 553742CB2E9372DF00AB56D0 /* WindowOSD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553741602E9372DF00AB56D0 /* WindowOSD.swift */; };
- 553742CC2E9372DF00AB56D0 /* NSPasteboard+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740FF2E9372DF00AB56D0 /* NSPasteboard+Helper.swift */; };
- 553742CD2E9372DF00AB56D0 /* ConfirmationsPreferencesPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537408C2E9372DF00AB56D0 /* ConfirmationsPreferencesPanel.swift */; };
- 553742CE2E9372DF00AB56D0 /* CompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537404F2E9372DF00AB56D0 /* CompareItem.swift */; };
- 553742CF2E9372DF00AB56D0 /* NSTextField+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537411E2E9372DF00AB56D0 /* NSTextField+Helper.swift */; };
- 553742D02E9372DF00AB56D0 /* FolderViewBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740912E9372DF00AB56D0 /* FolderViewBox.swift */; };
- 553742D12E9372DF00AB56D0 /* SessionDiff+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55373FB32E9372DF00AB56D0 /* SessionDiff+Types.swift */; };
- 553742D22E9372DF00AB56D0 /* FiltersPredicateEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553740B32E9372DF00AB56D0 /* FiltersPredicateEditor.swift */; };
- 553742D32E9372DF00AB56D0 /* HistoryEntityTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5537407B2E9372DF00AB56D0 /* HistoryEntityTableCellView.swift */; };
- 5537434E2E937B7F00AB56D0 /* VDDefaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5537434C2E937B7F00AB56D0 /* VDDefaults.plist */; };
- 5537434F2E937B7F00AB56D0 /* colors.json in Resources */ = {isa = PBXBuildFile; fileRef = 5537434A2E937B7F00AB56D0 /* colors.json */; };
- 553743502E937B7F00AB56D0 /* colorsDark.json in Resources */ = {isa = PBXBuildFile; fileRef = 5537434B2E937B7F00AB56D0 /* colorsDark.json */; };
- 553743512E937B7F00AB56D0 /* VisualDiffer.sdef in Resources */ = {isa = PBXBuildFile; fileRef = 5537434D2E937B7F00AB56D0 /* VisualDiffer.sdef */; };
- 553D10D9163BD0BC008D3F65 /* prefs_confirmations.png in Resources */ = {isa = PBXBuildFile; fileRef = 553D10D8163BD0BC008D3F65 /* prefs_confirmations.png */; };
- 5542D19616317DAC00F801AA /* vd.iconset in Resources */ = {isa = PBXBuildFile; fileRef = 5542D19516317DAC00F801AA /* vd.iconset */; };
- 55450B172ED4790B0048619F /* TextPreferencesPanel+PreferencesBoxDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55450B162ED4790B0048619F /* TextPreferencesPanel+PreferencesBoxDataSource.swift */; };
- 55450B192ED47B700048619F /* FileSessionPreferencesWindow+PreferencesBoxDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55450B182ED47B680048619F /* FileSessionPreferencesWindow+PreferencesBoxDataSource.swift */; };
- 554B4A452E9B7B8F0023AAF0 /* EndOfLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A3A2E9B7B8F0023AAF0 /* EndOfLine.swift */; };
- 554B4A462E9B7B8F0023AAF0 /* DiffSide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A402E9B7B8F0023AAF0 /* DiffSide.swift */; };
- 554B4A472E9B7B8F0023AAF0 /* DiffSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A412E9B7B8F0023AAF0 /* DiffSection.swift */; };
- 554B4A482E9B7B8F0023AAF0 /* DiffResult+Dump.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A3D2E9B7B8F0023AAF0 /* DiffResult+Dump.swift */; };
- 554B4A4A2E9B7B8F0023AAF0 /* DiffResult+Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A3F2E9B7B8F0023AAF0 /* DiffResult+Section.swift */; };
- 554B4A4B2E9B7B8F0023AAF0 /* DiffResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A3B2E9B7B8F0023AAF0 /* DiffResult.swift */; };
- 554B4A4D2E9B7B8F0023AAF0 /* DiffResult+Lines.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A3E2E9B7B8F0023AAF0 /* DiffResult+Lines.swift */; };
- 554B4A4E2E9B7B8F0023AAF0 /* DiffLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 554B4A432E9B7B8F0023AAF0 /* DiffLine.swift */; };
- 554E0EB2163EFD51001418EA /* prefs_confirmations@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 554E0EA0163EFD51001418EA /* prefs_confirmations@2x.png */; };
- 554E0EB3163EFD51001418EA /* prefs_paths@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 554E0EA1163EFD51001418EA /* prefs_paths@2x.png */; };
- 554E0EB4163EFD51001418EA /* prefs_text@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 554E0EA2163EFD51001418EA /* prefs_text@2x.png */; };
- 554E0EBD163EFD6A001418EA /* dropzone@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 554E0EBA163EFD6A001418EA /* dropzone@2x.png */; };
- 554E0EBE163EFD6A001418EA /* rewind@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 554E0EBB163EFD6A001418EA /* rewind@2x.png */; };
- 5550B5931A21CD1F009BC4A4 /* aliasbadge@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5550B5921A21CD1F009BC4A4 /* aliasbadge@2x.png */; };
- 5550B5951A21D2F3009BC4A4 /* empty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5550B5941A21D2F3009BC4A4 /* empty@2x.png */; };
- 555392621889732900D26258 /* deleteRed.png in Resources */ = {isa = PBXBuildFile; fileRef = 555392601889732900D26258 /* deleteRed.png */; };
- 555392631889732900D26258 /* deleteRed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 555392611889732900D26258 /* deleteRed@2x.png */; };
- 5560823F12AD0EF8003DC79D /* folder-999-open.png in Resources */ = {isa = PBXBuildFile; fileRef = 5560823D12AD0EF8003DC79D /* folder-999-open.png */; };
- 5560824012AD0EF8003DC79D /* folder-999.png in Resources */ = {isa = PBXBuildFile; fileRef = 5560823E12AD0EF8003DC79D /* folder-999.png */; };
- 557315B12551307800CF4372 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 557315B02551307800CF4372 /* Images.xcassets */; };
- 55740BF512D710EC004BF6CC /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55740BF412D710EC004BF6CC /* IOKit.framework */; };
- 55740BF912D71103004BF6CC /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55740BF812D71103004BF6CC /* Security.framework */; };
- 557BBB0E2ED1BBB00016CBD4 /* DiffLineComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557BBB0D2ED1BBB00016CBD4 /* DiffLineComponent.swift */; };
- 557C18182E7E6E0100381A3A /* big_file_5000_lines.txt in Resources */ = {isa = PBXBuildFile; fileRef = 557C18162E7E6E0100381A3A /* big_file_5000_lines.txt */; };
- 557C18232E7E8C0D00381A3A /* Signing.local.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 557C18212E7E8C0D00381A3A /* Signing.local.xcconfig */; };
- 557C18242E7E8C0D00381A3A /* Versions.local.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 557C18222E7E8C0D00381A3A /* Versions.local.xcconfig */; };
- 557C18252E7E8C0D00381A3A /* AppConfig.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 557C18202E7E8C0D00381A3A /* AppConfig.xcconfig */; };
- 557EC74212CC7A8700B43F57 /* rewind.png in Resources */ = {isa = PBXBuildFile; fileRef = 557EC74112CC7A8700B43F57 /* rewind.png */; };
- 558DEAC62EA263DE00F05A10 /* CFStringEncoding+StringEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEAC42EA263DE00F05A10 /* CFStringEncoding+StringEncoding.swift */; };
- 558DEACB2EA263F500F05A10 /* EncodingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEAC72EA263F500F05A10 /* EncodingManager.swift */; };
- 558DEACC2EA263F500F05A10 /* SelectEncodingsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEAC92EA263F500F05A10 /* SelectEncodingsPanel.swift */; };
- 558DEACD2EA263F500F05A10 /* EncodingPopUpButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEAC82EA263F500F05A10 /* EncodingPopUpButtonCell.swift */; };
- 558DEAD02EA2642100F05A10 /* NSWindow+Editing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEACE2EA2642100F05A10 /* NSWindow+Editing.swift */; };
- 558DEAD22EA26C5B00F05A10 /* Logger+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 558DEAD12EA26C5800F05A10 /* Logger+App.swift */; };
- 5590B2FF15B0449F00B0E047 /* prefs_paths.png in Resources */ = {isa = PBXBuildFile; fileRef = 5590B2FE15B0449F00B0E047 /* prefs_paths.png */; };
- 55916A102E8A814200ED6629 /* MyDocument.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 55916A092E8A814200ED6629 /* MyDocument.xcdatamodeld */; };
- 55916A112E8A814200ED6629 /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 55916A082E8A814200ED6629 /* History.xcdatamodeld */; };
- 559186412E9B821B00A30620 /* DiffSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559186402E9B821B00A30620 /* DiffSummary.swift */; };
- 5595901D2EABA7FE00B5AB0B /* CompareSummary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5595901C2EABA7FE00B5AB0B /* CompareSummary.swift */; };
- 5595901F2EABA8A100B5AB0B /* CompareChangeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5595901E2EABA8A100B5AB0B /* CompareChangeType.swift */; };
- 559590212EABAFC200B5AB0B /* SessionDiff+ItemComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559590202EABAFC200B5AB0B /* SessionDiff+ItemComparator.swift */; };
- 559590262EABB06100B5AB0B /* ItemComparator+AlignRegularExpression.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559590242EABB06100B5AB0B /* ItemComparator+AlignRegularExpression.swift */; };
- 559590272EABB06100B5AB0B /* ItemComparator+Align.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559590232EABB06100B5AB0B /* ItemComparator+Align.swift */; };
- 559590282EABB06100B5AB0B /* ItemComparator+Compare.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559590252EABB06100B5AB0B /* ItemComparator+Compare.swift */; };
- 559590292EABB06100B5AB0B /* ItemComparator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 559590222EABB06100B5AB0B /* ItemComparator.swift */; };
- 5595902B2EABB15F00B5AB0B /* MockItemComparatorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5595902A2EABB15F00B5AB0B /* MockItemComparatorDelegate.swift */; };
- 559614B114B0471E0075ED34 /* aliasbadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 559614B014B0471E0075ED34 /* aliasbadge.png */; };
- 559E927E1514A63100B76349 /* dropzone.png in Resources */ = {isa = PBXBuildFile; fileRef = 559E927D1514A63100B76349 /* dropzone.png */; };
- 559EA70E14FA1D8F00BC9B82 /* VisualDifferHelp in Resources */ = {isa = PBXBuildFile; fileRef = 559EA70D14FA1D8F00BC9B82 /* VisualDifferHelp */; };
- 55A027D4158242310004583F /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55A027D3158242310004583F /* Quartz.framework */; };
- 55A4DF322E9A49B000ED11BB /* EndOfLineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A4DF312E9A49A700ED11BB /* EndOfLineTests.swift */; };
- 55B1CE2B2E9934E900426FEC /* DateBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B1CE2A2E9934E900426FEC /* DateBuilder.swift */; };
- 55B1CE312E9934F800426FEC /* DiffResultBaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B1CE2E2E9934F800426FEC /* DiffResultBaseTests.swift */; };
- 55B1CE322E9934F800426FEC /* DiffResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B1CE2C2E9934F800426FEC /* DiffResultTests.swift */; };
- 55B6760018956D90000D5A0D /* prefs_keyboard.png in Resources */ = {isa = PBXBuildFile; fileRef = 55B675FE18956D90000D5A0D /* prefs_keyboard.png */; };
- 55B6760118956D90000D5A0D /* prefs_keyboard@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55B675FF18956D90000D5A0D /* prefs_keyboard@2x.png */; };
- 55BC333E2EDAC69C004035A0 /* RowHeightCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BC333D2EDAC69C004035A0 /* RowHeightCalculator.swift */; };
- 55BC33402EDAC96F004035A0 /* TiledImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BC333F2EDAC96F004035A0 /* TiledImageView.swift */; };
- 55BC33432EDACB09004035A0 /* FilesWindowController+RowHeightDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BC33412EDACB09004035A0 /* FilesWindowController+RowHeightDataSource.swift */; };
- 55BC33442EDACB09004035A0 /* FilesWindowController+SplitViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BC33422EDACB09004035A0 /* FilesWindowController+SplitViewDelegate.swift */; };
- 55C165622EE444050082A24C /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 55C165612EE444050082A24C /* Sparkle */; };
- 55C1CBFD2E8BB6AD004FE322 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C1CBF42E8BB6AD004FE322 /* main.swift */; };
- 55C1CC012E8BB755004FE322 /* visdiff in Copy Visdiff to Helpers */ = {isa = PBXBuildFile; fileRef = 55C1CBE22E8BB6A2004FE322 /* visdiff */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
- 55C1CC072E8BBD85004FE322 /* DocumentWaiter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55C1CC062E8BBAD1004FE322 /* DocumentWaiter.swift */; };
- 55C84A712DA93ADB00BA39DA /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55C84A702DA93ADB00BA39DA /* UserNotifications.framework */; };
- 55D352E72EFD0C5B00C944D5 /* FileSystemTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D352E62EFD0C4D00C944D5 /* FileSystemTestHelper.swift */; };
- 55D71FD62EE584B7007E0FA0 /* AppUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55D71FD52EE584B7007E0FA0 /* AppUpdater.swift */; };
- 55DF3DD22E924BB10044CC0C /* BaseTests+FileSystemOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC52E924BB10044CC0C /* BaseTests+FileSystemOperations.swift */; };
- 55DF3DD32E924BB10044CC0C /* FiltersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBF2E924BB10044CC0C /* FiltersTests.swift */; };
- 55DF3DD42E924BB10044CC0C /* LeafPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC82E924BB10044CC0C /* LeafPathTests.swift */; };
- 55DF3DD52E924BB10044CC0C /* DeleteFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBC2E924BB10044CC0C /* DeleteFileTests.swift */; };
- 55DF3DD62E924BB10044CC0C /* TagsCopyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB32E924BB10044CC0C /* TagsCopyTests.swift */; };
- 55DF3DD82E924BB10044CC0C /* CopyFilesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBB2E924BB10044CC0C /* CopyFilesTests.swift */; };
- 55DF3DD92E924BB10044CC0C /* StringUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DCE2E924BB10044CC0C /* StringUtils.swift */; };
- 55DF3DDB2E924BB10044CC0C /* BufferedInputStreamTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB92E924BB10044CC0C /* BufferedInputStreamTests.swift */; };
- 55DF3DDC2E924BB10044CC0C /* TagsMoveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB62E924BB10044CC0C /* TagsMoveTests.swift */; };
- 55DF3DDD2E924BB10044CC0C /* CaseSensitiveBaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC62E924BB10044CC0C /* CaseSensitiveBaseTest.swift */; };
- 55DF3DDE2E924BB10044CC0C /* BaseTests+AssertCompareItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DAA2E924BB10044CC0C /* BaseTests+AssertCompareItem.swift */; };
- 55DF3DDF2E924BB10044CC0C /* AlignmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB82E924BB10044CC0C /* AlignmentTests.swift */; };
- 55DF3DE02E924BB10044CC0C /* RefreshInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DCB2E924BB10044CC0C /* RefreshInfoTests.swift */; };
- 55DF3DE12E924BB10044CC0C /* EmptyFolderColorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBE2E924BB10044CC0C /* EmptyFolderColorTests.swift */; };
- 55DF3DE22E924BB10044CC0C /* BaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DA92E924BB10044CC0C /* BaseTests.swift */; };
- 55DF3DE32E924BB10044CC0C /* FoldersWindowControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DCA2E924BB10044CC0C /* FoldersWindowControllerTests.swift */; };
- 55DF3DE42E924BB10044CC0C /* TagsDeleteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB52E924BB10044CC0C /* TagsDeleteTests.swift */; };
- 55DF3DE52E924BB10044CC0C /* ComparatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBA2E924BB10044CC0C /* ComparatorTests.swift */; };
- 55DF3DE62E924BB10044CC0C /* TouchFilesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC22E924BB10044CC0C /* TouchFilesTests.swift */; };
- 55DF3DE72E924BB10044CC0C /* DisplayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DBD2E924BB10044CC0C /* DisplayTests.swift */; };
- 55DF3DE82E924BB10044CC0C /* BaseTests+AssertFileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC42E924BB10044CC0C /* BaseTests+AssertFileSystem.swift */; };
- 55DF3DE92E924BB10044CC0C /* LabelsCreateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB12E924BB10044CC0C /* LabelsCreateTests.swift */; };
- 55DF3DEA2E924BB10044CC0C /* MockFileOperationManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DAC2E924BB10044CC0C /* MockFileOperationManagerDelegate.swift */; };
- 55DF3DEB2E924BB10044CC0C /* LabelsMoveTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB22E924BB10044CC0C /* LabelsMoveTests.swift */; };
- 55DF3DEC2E924BB10044CC0C /* MoveFilesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC02E924BB10044CC0C /* MoveFilesTests.swift */; };
- 55DF3DED2E924BB10044CC0C /* TagsCreateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB42E924BB10044CC0C /* TagsCreateTests.swift */; };
- 55DF3DEE2E924BB10044CC0C /* LabelsCopyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DB02E924BB10044CC0C /* LabelsCopyTests.swift */; };
- 55DF3DEF2E924BB10044CC0C /* MockFolderReaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DAD2E924BB10044CC0C /* MockFolderReaderDelegate.swift */; };
- 55DF3DF02E924BB10044CC0C /* RenameFilesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55DF3DC12E924BB10044CC0C /* RenameFilesTests.swift */; };
- 55E1029A12C9E17300432C61 /* empty.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E1029912C9E17300432C61 /* empty.png */; };
- 55E31E011BC572F3001ACE4D /* top.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E31DFF1BC572F3001ACE4D /* top.png */; };
- 55E31E021BC572F3001ACE4D /* top@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E31E001BC572F3001ACE4D /* top@2x.png */; };
- 55E31E051BC57373001ACE4D /* bottom.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E31E031BC57373001ACE4D /* bottom.png */; };
- 55E31E061BC57373001ACE4D /* bottom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E31E041BC57373001ACE4D /* bottom@2x.png */; };
- 55E381C12EEFFD0500CB2F00 /* SymbolicLinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E381C02EEFFCF500CB2F00 /* SymbolicLinkTests.swift */; };
- 55E3A5661826552A002A890B /* lockedbadge.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E3A5641826552A002A890B /* lockedbadge.png */; };
- 55E3A5671826552A002A890B /* lockedbadge@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55E3A5651826552A002A890B /* lockedbadge@2x.png */; };
- 55ECD8621476B03400D8BEB4 /* prefs_text.png in Resources */ = {isa = PBXBuildFile; fileRef = 55ECD8611476B03400D8BEB4 /* prefs_text.png */; };
- 55F6B0631AEA93E30096E55E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 55F6B0611AEA93E30096E55E /* Localizable.stringsdict */; };
- 55F6B0661AEA99680096E55E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 55F6B0641AEA99680096E55E /* Localizable.strings */; };
- 55F9E79A2EDD5DBD001218C7 /* DiffResult.Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F9E7992EDD5DAD001218C7 /* DiffResult.Options.swift */; };
- 55F9E79C2EDD6221001218C7 /* WhitespacesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F9E79B2EDD6221001218C7 /* WhitespacesTests.swift */; };
- 55FD7E28180C484500CF473C /* prefs_folder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55FD7E25180C484500CF473C /* prefs_folder@2x.png */; };
- 55FE894A2F054B260003864A /* FlagSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55FE89492F054B260003864A /* FlagSet.swift */; };
- 775DFF38067A968500C5B868 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; };
- 8D15AC2C0486D014006FF6A4 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 2A37F4B9FDCFA73011CA2CEA /* Credits.rtf */; };
- 8D15AC2F0486D014006FF6A4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165FFE840EACC02AAC07 /* InfoPlist.strings */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXContainerItemProxy section */
- 55944CCB2E5C8D9F00FB1F8C /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 2A37F4A9FDCFA73011CA2CEA /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 8D15AC270486D014006FF6A4;
- remoteInfo = VisualDiffer;
- };
- 55C1CBFF2E8BB749004FE322 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 2A37F4A9FDCFA73011CA2CEA /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 55C1CBE12E8BB6A2004FE322;
- remoteInfo = visdiff;
- };
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- 5504B6FF255FCBBA00CDE04A /* Copy Visdiff to Helpers */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = Contents/Helpers;
- dstSubfolderSpec = 1;
- files = (
- 55C1CC012E8BB755004FE322 /* visdiff in Copy Visdiff to Helpers */,
- );
- name = "Copy Visdiff to Helpers";
- runOnlyForDeploymentPostprocessing = 0;
- };
- 55943C852EE43E3800DE513B /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 12;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
- 55C1CBE02E8BB6A2004FE322 /* CopyFiles */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = /usr/share/man/man1/;
- dstSubfolderSpec = 0;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 1;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
- 2A37F4C4FDCFA73011CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
- 2A37F4C5FDCFA73011CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
- 32DBCF750370BD2300C91783 /* VisualDiffer_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisualDiffer_Prefix.pch; sourceTree = ""; };
- 550A2CC113FF973B00981A9B /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
- 55157D6012898F8800826FF8 /* folder-000-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-000-open.png"; sourceTree = ""; };
- 55157D6112898F8800826FF8 /* folder-000.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-000.png"; sourceTree = ""; };
- 55157D6212898F8800826FF8 /* folder-001-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-001-open.png"; sourceTree = ""; };
- 55157D6312898F8800826FF8 /* folder-001.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-001.png"; sourceTree = ""; };
- 55157D6412898F8800826FF8 /* folder-010-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-010-open.png"; sourceTree = ""; };
- 55157D6512898F8800826FF8 /* folder-010.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-010.png"; sourceTree = ""; };
- 55157D6612898F8800826FF8 /* folder-011-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-011-open.png"; sourceTree = ""; };
- 55157D6712898F8800826FF8 /* folder-011.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-011.png"; sourceTree = ""; };
- 55157D6812898F8800826FF8 /* folder-100-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-100-open.png"; sourceTree = ""; };
- 55157D6912898F8800826FF8 /* folder-100.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-100.png"; sourceTree = ""; };
- 55157D6A12898F8800826FF8 /* folder-101-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-101-open.png"; sourceTree = ""; };
- 55157D6B12898F8800826FF8 /* folder-101.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-101.png"; sourceTree = ""; };
- 55157D6C12898F8800826FF8 /* folder-110-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-110-open.png"; sourceTree = ""; };
- 55157D6D12898F8800826FF8 /* folder-110.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-110.png"; sourceTree = ""; };
- 55157D6E12898F8800826FF8 /* folder-111-open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-111-open.png"; sourceTree = ""; };
- 55157D6F12898F8800826FF8 /* folder-111.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-111.png"; sourceTree = ""; };
- 551BF0C81643B91B009CC9D1 /* folder-000-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-000-open@2x.png"; sourceTree = ""; };
- 551BF0C91643B91B009CC9D1 /* folder-000@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-000@2x.png"; sourceTree = ""; };
- 551BF0CA1643B91B009CC9D1 /* folder-001-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-001-open@2x.png"; sourceTree = ""; };
- 551BF0CB1643B91B009CC9D1 /* folder-001@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-001@2x.png"; sourceTree = ""; };
- 551BF0CC1643B91B009CC9D1 /* folder-010-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-010-open@2x.png"; sourceTree = ""; };
- 551BF0CD1643B91B009CC9D1 /* folder-010@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-010@2x.png"; sourceTree = ""; };
- 551BF0CE1643B91B009CC9D1 /* folder-011-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-011-open@2x.png"; sourceTree = ""; };
- 551BF0CF1643B91B009CC9D1 /* folder-011@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-011@2x.png"; sourceTree = ""; };
- 551BF0D01643B91B009CC9D1 /* folder-100-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-100-open@2x.png"; sourceTree = ""; };
- 551BF0D11643B91B009CC9D1 /* folder-100@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-100@2x.png"; sourceTree = ""; };
- 551BF0D21643B91B009CC9D1 /* folder-101-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-101-open@2x.png"; sourceTree = ""; };
- 551BF0D31643B91B009CC9D1 /* folder-101@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-101@2x.png"; sourceTree = ""; };
- 551BF0D41643B91B009CC9D1 /* folder-110-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-110-open@2x.png"; sourceTree = ""; };
- 551BF0D51643B91B009CC9D1 /* folder-110@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-110@2x.png"; sourceTree = ""; };
- 551BF0D61643B91B009CC9D1 /* folder-111-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-111-open@2x.png"; sourceTree = ""; };
- 551BF0D71643B91B009CC9D1 /* folder-111@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-111@2x.png"; sourceTree = ""; };
- 551BF0D81643B91B009CC9D1 /* folder-999-open@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-999-open@2x.png"; sourceTree = ""; };
- 551BF0D91643B91B009CC9D1 /* folder-999@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "folder-999@2x.png"; sourceTree = ""; };
- 551DE39E2ED422820067AB18 /* FilesWindowController+SessionPreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+SessionPreferences.swift"; sourceTree = ""; };
- 551DE3A42ED4237B0067AB18 /* FileSessionPreferencesWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSessionPreferencesWindow.swift; sourceTree = ""; };
- 551DE3A92ED428A50067AB18 /* FilePreferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreferences.swift; sourceTree = ""; };
- 551DE3B32ED42AD00067AB18 /* FilePreferencesComparisonPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreferencesComparisonPanel.swift; sourceTree = ""; };
- 551DE3B52ED42B4E0067AB18 /* FileComparisonBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileComparisonBox.swift; sourceTree = ""; };
- 551DE3B72ED4399B0067AB18 /* PreferencesBoxDataSource+Default.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesBoxDataSource+Default.swift"; sourceTree = ""; };
- 551DEDE0160477CA0014DF88 /* prefs_folder.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = prefs_folder.png; sourceTree = ""; };
- 553033AC2E5DBABF0016F101 /* VisualDiffer.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = VisualDiffer.xctestplan; sourceTree = SOURCE_ROOT; };
- 553251672765F06B0092D65F /* mask-back.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mask-back.png"; sourceTree = ""; };
- 553251682765F06B0092D65F /* mask-full.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mask-full.png"; sourceTree = ""; };
- 553251692765F06B0092D65F /* mask-middle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mask-middle.png"; sourceTree = ""; };
- 5532516A2765F06B0092D65F /* mask-back-white.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mask-back-white.png"; sourceTree = ""; };
- 5532516B2765F06B0092D65F /* mask-front.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mask-front.png"; sourceTree = ""; };
- 5536ADB92EF169820019EFBF /* SessionDiff+ExtraData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff+ExtraData.swift"; sourceTree = ""; };
- 55373F8D2E9372DF00AB56D0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 55373F8F2E9372DF00AB56D0 /* AlignRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlignRule.swift; sourceTree = ""; };
- 55373F902E9372DF00AB56D0 /* ColorScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = ""; };
- 55373F912E9372DF00AB56D0 /* DisplayPositionable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayPositionable.swift; sourceTree = ""; };
- 55373F922E9372DF00AB56D0 /* ImageNames.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageNames.swift; sourceTree = ""; };
- 55373F932E9372DF00AB56D0 /* KeyEquivalent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyEquivalent.swift; sourceTree = ""; };
- 55373F942E9372DF00AB56D0 /* NotificationCenter+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationCenter+Helper.swift"; sourceTree = ""; };
- 55373F952E9372DF00AB56D0 /* NSImage+SymbolCompat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSImage+SymbolCompat.swift"; sourceTree = ""; };
- 55373F962E9372DF00AB56D0 /* ViewLinkable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewLinkable.swift; sourceTree = ""; };
- 55373F982E9372DF00AB56D0 /* CommonPrefs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonPrefs.swift; sourceTree = ""; };
- 55373F992E9372DF00AB56D0 /* CommonPrefs+FileCompare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommonPrefs+FileCompare.swift"; sourceTree = ""; };
- 55373F9A2E9372DF00AB56D0 /* CommonPrefs+FolderCompare.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommonPrefs+FolderCompare.swift"; sourceTree = ""; };
- 55373F9B2E9372DF00AB56D0 /* CommonPrefs+Font.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommonPrefs+Font.swift"; sourceTree = ""; };
- 55373F9C2E9372DF00AB56D0 /* CommonPrefs+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommonPrefs+Helper.swift"; sourceTree = ""; };
- 55373F9D2E9372DF00AB56D0 /* CommonPrefs+Name.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CommonPrefs+Name.swift"; sourceTree = ""; };
- 55373F9F2E9372DF00AB56D0 /* DocumentWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentWindow.swift; sourceTree = ""; };
- 55373FA02E9372DF00AB56D0 /* NSArrayController+Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSArrayController+Paths.swift"; sourceTree = ""; };
- 55373FA12E9372DF00AB56D0 /* PathChooser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PathChooser.swift; sourceTree = ""; };
- 55373FA22E9372DF00AB56D0 /* RecentDocumentPopupMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentDocumentPopupMenu.swift; sourceTree = ""; };
- 55373FA42E9372DF00AB56D0 /* DiffOpenerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffOpenerDelegate.swift; sourceTree = ""; };
- 55373FA52E9372DF00AB56D0 /* DocumentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentError.swift; sourceTree = ""; };
- 55373FA62E9372DF00AB56D0 /* SessionDiff.ItemType+Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff.ItemType+Paths.swift"; sourceTree = ""; };
- 55373FA72E9372DF00AB56D0 /* SessionTypeError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionTypeError.swift; sourceTree = ""; };
- 55373FA82E9372DF00AB56D0 /* VDDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDDocument.swift; sourceTree = ""; };
- 55373FA92E9372DF00AB56D0 /* VDDocumentController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDDocumentController.swift; sourceTree = ""; };
- 55373FAB2E9372DF00AB56D0 /* HistoryEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryEntity.swift; sourceTree = ""; };
- 55373FAC2E9372DF00AB56D0 /* HistorySessionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistorySessionManager.swift; sourceTree = ""; };
- 55373FAE2E9372DF00AB56D0 /* SessionDiff.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDiff.swift; sourceTree = ""; };
- 55373FAF2E9372DF00AB56D0 /* SessionDiff+AlignRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff+AlignRule.swift"; sourceTree = ""; };
- 55373FB12E9372DF00AB56D0 /* SessionDiff+NSSortDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff+NSSortDescriptor.swift"; sourceTree = ""; };
- 55373FB22E9372DF00AB56D0 /* SessionDiff+ResolvePath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff+ResolvePath.swift"; sourceTree = ""; };
- 55373FB32E9372DF00AB56D0 /* SessionDiff+Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionDiff+Types.swift"; sourceTree = ""; };
- 55373FB62E9372DF00AB56D0 /* FilesTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesTableView.swift; sourceTree = ""; };
- 55373FB72E9372DF00AB56D0 /* FilesTableView+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesTableView+Menu.swift"; sourceTree = ""; };
- 55373FB82E9372DF00AB56D0 /* FilesTableViewFindTextDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesTableViewFindTextDelegate.swift; sourceTree = ""; };
- 55373FBA2E9372DF00AB56D0 /* FileInfoBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileInfoBar.swift; sourceTree = ""; };
- 55373FBB2E9372DF00AB56D0 /* FilePanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePanelView.swift; sourceTree = ""; };
- 55373FBC2E9372DF00AB56D0 /* FilePanelView+File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilePanelView+File.swift"; sourceTree = ""; };
- 55373FBD2E9372DF00AB56D0 /* FilesScopeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesScopeBar.swift; sourceTree = ""; };
- 55373FBE2E9372DF00AB56D0 /* FileThumbnailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileThumbnailView.swift; sourceTree = ""; };
- 55373FBF2E9372DF00AB56D0 /* LineNumberTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineNumberTableCellView.swift; sourceTree = ""; };
- 55373FC02E9372DF00AB56D0 /* LineNumberTableRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineNumberTableRowView.swift; sourceTree = ""; };
- 55373FC12E9372DF00AB56D0 /* NSAlert+DirtyFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAlert+DirtyFiles.swift"; sourceTree = ""; };
- 55373FC22E9372DF00AB56D0 /* SaveFileAccessoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveFileAccessoryView.swift; sourceTree = ""; };
- 55373FC32E9372DF00AB56D0 /* TextFieldVerticalCentered.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldVerticalCentered.swift; sourceTree = ""; };
- 55373FC52E9372DF00AB56D0 /* FilesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesWindowController.swift; sourceTree = ""; };
- 55373FC62E9372DF00AB56D0 /* FilesWindowController+Clipboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Clipboard.swift"; sourceTree = ""; };
- 55373FC72E9372DF00AB56D0 /* FilesWindowController+Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Common.swift"; sourceTree = ""; };
- 55373FC82E9372DF00AB56D0 /* FilesWindowController+Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Document.swift"; sourceTree = ""; };
- 55373FC92E9372DF00AB56D0 /* FilesWindowController+FileInfoBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+FileInfoBarDelegate.swift"; sourceTree = ""; };
- 55373FCA2E9372DF00AB56D0 /* FilesWindowController+FilesScopeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+FilesScopeBar.swift"; sourceTree = ""; };
- 55373FCB2E9372DF00AB56D0 /* FilesWindowController+FilesTableViewContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+FilesTableViewContextMenu.swift"; sourceTree = ""; };
- 55373FCC2E9372DF00AB56D0 /* FilesWindowController+JumpLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+JumpLine.swift"; sourceTree = ""; };
- 55373FCD2E9372DF00AB56D0 /* FilesWindowController+LinesDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+LinesDetail.swift"; sourceTree = ""; };
- 55373FCE2E9372DF00AB56D0 /* FilesWindowController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Menu.swift"; sourceTree = ""; };
- 55373FCF2E9372DF00AB56D0 /* FilesWindowController+MenuDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+MenuDelegate.swift"; sourceTree = ""; };
- 55373FD02E9372DF00AB56D0 /* FilesWindowController+Navigate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Navigate.swift"; sourceTree = ""; };
- 55373FD12E9372DF00AB56D0 /* FilesWindowController+NSToolbarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+NSToolbarDelegate.swift"; sourceTree = ""; };
- 55373FD22E9372DF00AB56D0 /* FilesWindowController+NSWindowDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+NSWindowDelegate.swift"; sourceTree = ""; };
- 55373FD32E9372DF00AB56D0 /* FilesWindowController+PathControlDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+PathControlDelegate.swift"; sourceTree = ""; };
- 55373FD42E9372DF00AB56D0 /* FilesWindowController+Read.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Read.swift"; sourceTree = ""; };
- 55373FD52E9372DF00AB56D0 /* FilesWindowController+Save.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Save.swift"; sourceTree = ""; };
- 55373FD62E9372DF00AB56D0 /* FilesWindowController+Slider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+Slider.swift"; sourceTree = ""; };
- 55373FD72E9372DF00AB56D0 /* FilesWindowController+TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+TableView.swift"; sourceTree = ""; };
- 55373FD82E9372DF00AB56D0 /* FilesWindowController+UICreation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+UICreation.swift"; sourceTree = ""; };
- 55373FD92E9372DF00AB56D0 /* FilesWindowController+UISetup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesWindowController+UISetup.swift"; sourceTree = ""; };
- 55373FDB2E9372DF00AB56D0 /* DiffLine+Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiffLine+Color.swift"; sourceTree = ""; };
- 55373FDD2E9372DF00AB56D0 /* DiffChangeType+Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiffChangeType+Color.swift"; sourceTree = ""; };
- 55373FDE2E9372DF00AB56D0 /* DiffChangeType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffChangeType.swift; sourceTree = ""; };
- 55373FE02E9372DF00AB56D0 /* DiffCountersItem+DiffResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DiffCountersItem+DiffResult.swift"; sourceTree = ""; };
- 55373FE12E9372DF00AB56D0 /* FilesTableView+EditorData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FilesTableView+EditorData.swift"; sourceTree = ""; };
- 55373FE32E9372DF00AB56D0 /* JumpToLineWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JumpToLineWindow.swift; sourceTree = ""; };
- 55373FE62E9372DF00AB56D0 /* ColoredFoldersManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColoredFoldersManager.swift; sourceTree = ""; };
- 55373FE72E9372DF00AB56D0 /* FoldersOutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoldersOutlineView.swift; sourceTree = ""; };
- 55373FE82E9372DF00AB56D0 /* FoldersOutlineView+Clipboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+Clipboard.swift"; sourceTree = ""; };
- 55373FE92E9372DF00AB56D0 /* FoldersOutlineView+Columns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+Columns.swift"; sourceTree = ""; };
- 55373FEA2E9372DF00AB56D0 /* FoldersOutlineView+Enumerate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+Enumerate.swift"; sourceTree = ""; };
- 55373FEB2E9372DF00AB56D0 /* FoldersOutlineView+ExternalApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+ExternalApp.swift"; sourceTree = ""; };
- 55373FEC2E9372DF00AB56D0 /* FoldersOutlineView+FileCount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+FileCount.swift"; sourceTree = ""; };
- 55373FED2E9372DF00AB56D0 /* FoldersOutlineView+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+Menu.swift"; sourceTree = ""; };
- 55373FEE2E9372DF00AB56D0 /* FoldersOutlineView+VisibleItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FoldersOutlineView+VisibleItem.swift"; sourceTree = ""; };
- 55373FEF2E9372DF00AB56D0 /* FoldersOutlineViewFindTextDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FoldersOutlineViewFindTextDelegate.swift; sourceTree = ""; };
- 55373FF02E9372DF00AB56D0 /* CompareItem+LeafPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CompareItem+LeafPath.swift"; sourceTree = ""; };
- 55373FF12E9372DF00AB56D0 /* CompareItem+NSTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CompareItem+NSTableCellView.swift"; sourceTree = ""; };
- 55373FF22E9372DF00AB56D0 /* IconUtils+CompareItemIconUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IconUtils+CompareItemIconUtils.swift"; sourceTree = ""; };
- 55373FF42E9372DF00AB56D0 /* DisplayFiltersScopeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayFiltersScopeBar.swift; sourceTree = ""; };
- 55373FF52E9372DF00AB56D0 /* FolderPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderPanelView.swift; sourceTree = ""; };
- 55373FF62E9372DF00AB56D0 /* CompareItemTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompareItemTableCellView.swift; sourceTree = ""; };
- 55373FF72E9372DF00AB56D0 /* CompareItemTableRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompareItemTableRowView.swift; sourceTree = ""; };
- 55373FF92E9372DF00AB56D0 /* MainThreadComparatorDelegateBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainThreadComparatorDelegateBridge.swift; sourceTree = ""; };
- 55373FFB2E9372DF00AB56D0 /* CopyFileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyFileOperationExecutor.swift; sourceTree = ""; };
- 55373FFD2E9372DF00AB56D0 /* DeleteFileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteFileOperationExecutor.swift; sourceTree = ""; };
- 55373FFF2E9372DF00AB56D0 /* MoveFileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoveFileOperationExecutor.swift; sourceTree = ""; };
- 553740012E9372DF00AB56D0 /* ConfirmReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmReplace.swift; sourceTree = ""; };
- 553740022E9372DF00AB56D0 /* NSAlert+ReplaceFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAlert+ReplaceFile.swift"; sourceTree = ""; };
- 553740032E9372DF00AB56D0 /* NSApplication.ModalResponse+ReplaceFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSApplication.ModalResponse+ReplaceFile.swift"; sourceTree = ""; };
- 553740042E9372DF00AB56D0 /* ReplaceFileAttributeKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplaceFileAttributeKey.swift; sourceTree = ""; };
- 553740062E9372DF00AB56D0 /* CompletionIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionIndicator.swift; sourceTree = ""; };
- 553740072E9372DF00AB56D0 /* ErrorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorsView.swift; sourceTree = ""; };
- 553740082E9372DF00AB56D0 /* FileOperationManagerDelegateImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOperationManagerDelegateImpl.swift; sourceTree = ""; };
- 553740092E9372DF00AB56D0 /* ProgressIndicatorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressIndicatorController.swift; sourceTree = ""; };
- 5537400A2E9372DF00AB56D0 /* ReplaceInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplaceInfoView.swift; sourceTree = ""; };
- 5537400C2E9372DF00AB56D0 /* SyncFileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncFileController.swift; sourceTree = ""; };
- 5537400D2E9372DF00AB56D0 /* SyncFileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncFileOperationExecutor.swift; sourceTree = ""; };
- 5537400E2E9372DF00AB56D0 /* SyncItemsInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncItemsInfo.swift; sourceTree = ""; };
- 5537400F2E9372DF00AB56D0 /* SyncOutlineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncOutlineView.swift; sourceTree = ""; };
- 553740112E9372DF00AB56D0 /* DatePickersStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickersStackView.swift; sourceTree = ""; };
- 553740122E9372DF00AB56D0 /* TouchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchController.swift; sourceTree = ""; };
- 553740132E9372DF00AB56D0 /* TouchFileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchFileOperationExecutor.swift; sourceTree = ""; };
- 553740142E9372DF00AB56D0 /* TouchPickersStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchPickersStackView.swift; sourceTree = ""; };
- 553740162E9372DF00AB56D0 /* FileOperationExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOperationExecutor.swift; sourceTree = ""; };
- 553740172E9372DF00AB56D0 /* FileSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSummaryView.swift; sourceTree = ""; };
- 553740182E9372DF00AB56D0 /* FileSystemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSystemController.swift; sourceTree = "