FIX #954: AutoRefresh: symlink issue on MacOS (#959)

This commit is contained in:
rich2014 2023-05-01 18:47:44 +08:00 committed by GitHub
commit 25ee5c367f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -75,6 +75,8 @@ private
function count(): Integer;
function getItem( index:Integer ): TInternalEvent;
procedure adjustSymlinkIfNecessary( index:Integer; watchPath:String; watchRealPath:String );
procedure adjustRenamedEventIfNecessary( index:Integer );
function isRenamed( event:TInternalEvent ): Boolean;
@ -110,6 +112,7 @@ type TDarwinFSWatchCallBack = Procedure( event:TDarwinFSWatchEvent ) of object;
type TDarwinFSWatcher = class
private
_watchPaths: NSMutableArray;
_watchRealPaths: NSMutableArray;
_streamPaths: NSArray;
_watchSubtree: Boolean;
@ -479,10 +482,24 @@ begin
end;
end;
procedure TDarwinFSWatchEventSession.adjustSymlinkIfNecessary( index:Integer; watchPath:String; watchRealPath:String );
var
currentEvent: TInternalEvent;
begin
if watchPath=watchRealPath then exit;
currentEvent:= Items[index];
currentEvent.path:= watchPath + currentEvent.path.Substring(watchRealPath.Length);
if currentEvent.renamedPath.IsEmpty then exit;
if not currentEvent.renamedPath.StartsWith(watchRealPath) then exit;
currentEvent.renamedPath:= watchPath + currentEvent.renamedPath.Substring(watchRealPath.Length);
end;
constructor TDarwinFSWatcher.create( const callback:TDarwinFSWatchCallBack; const watchSubtree:Boolean; const latency:Integer );
begin
Inherited Create;
_watchPaths:= NSMutableArray.alloc.initWithCapacity( 16 );
_watchRealPaths:= NSMutableArray.alloc.initWithCapacity( 16 );
_watchSubtree:= watchSubtree;
_callback:= callback;
@ -502,6 +519,8 @@ begin
FreeAndNil( _pathsSyncObject );
_watchPaths.release;
_watchPaths:= nil;
_watchRealPaths.release;
_watchRealPaths:= nil;
_streamPaths.release;
_streamPaths:= nil;
Inherited;
@ -526,15 +545,23 @@ end;
procedure TDarwinFSWatcher.handleEvents( const originalSession:TDarwinFSWatchEventSession );
var
watchPath: String;
watchRealPath: String;
event: TInternalEvent;
pathIndex: Integer;
i: Integer;
session: TDarwinFSWatchEventSession;
begin
for pathIndex:=0 to _streamPaths.count-1 do
if _watchPaths.count=0 then
begin
watchPath:= NSString(_streamPaths.objectAtIndex(pathIndex)).UTF8String;
if pathIndex=_streamPaths.count-1 then
originalSession.Free;
exit;
end;
for pathIndex:=0 to _watchPaths.count-1 do
begin
watchPath:= NSString(_watchPaths.objectAtIndex(pathIndex)).UTF8String;
watchRealPath:= NSString(_watchRealPaths.objectAtIndex(pathIndex)).UTF8String;
if pathIndex=_watchPaths.count-1 then
session:= originalSession
else
session:= originalSession.deepCopy();
@ -542,9 +569,10 @@ begin
while i < session.count do
begin
event:= session[i];
if isMatchWatchPath(event, watchPath, _watchSubtree) then
if isMatchWatchPath(event, watchRealPath, _watchSubtree) then
begin
session.adjustRenamedEventIfNecessary( i );
session.adjustSymlinkIfNecessary( i, watchPath, watchRealPath );
doCallback( watchPath, event );
end;
inc( i );
@ -646,9 +674,19 @@ begin
notifyPath;
end;
function realpath(__name:Pchar; __resolved:Pchar):Pchar;cdecl;external clib name 'realpath';
function toRealPath( path:String ): String;
var
resolvedPath: array[0..PATH_MAX] of char;
begin
Result:= realpath( pchar(path), resolvedPath );
end;
procedure TDarwinFSWatcher.addPath( path:String );
var
nsPath: NSString;
nsRealPath: NSString;
begin
_lockObject.Acquire;
try
@ -657,6 +695,10 @@ begin
nsPath:= StringToNSString( path );
if _watchPaths.containsObject(nsPath) then exit;
_watchPaths.addObject( nsPath );
nsRealPath:= StringToNSString( toRealPath(path) );
_watchRealPaths.addObject( nsRealPath );
interrupt;
finally
_lockObject.Release;
@ -665,6 +707,7 @@ end;
procedure TDarwinFSWatcher.removePath( path:String );
var
index: NSInteger;
nsPath: NSString;
begin
_lockObject.Acquire;
@ -672,8 +715,12 @@ begin
if path<>PathDelim then
path:= ExcludeTrailingPathDelimiter(path);
nsPath:= StringToNSString( path );
if not _watchPaths.containsObject(nsPath) then exit;
_watchPaths.removeObject( nsPath );
index:= _watchPaths.indexOfObject( nsPath );
if index = NSNotFound then exit;
_watchPaths.removeObjectAtIndex( index );
_watchRealPaths.removeObjectAtIndex( index );
interrupt;
finally
_lockObject.Release;
@ -686,6 +733,7 @@ begin
try
if _watchPaths.count = 0 then exit;
_watchPaths.removeAllObjects;
_watchRealPaths.removeAllObjects;
interrupt;
finally
_lockObject.Release;