Программа находит свой каталог через символьную ссылку

Ссылка в ~/.local/bin и ярлык в меню запускают программу не по её
настоящему пути. ExtractFilePath(ParamStr(0)) при этом указывал на
каталог ссылки, и рядом с ней оказались бы и журнал, и файл
зависимостей, и поиск ffmpeg «рядом с программой».

Появился ProgramDir в uAppTypes: он раскрывает ссылки, пока они не
кончатся, с ограничением на случай закольцованных. Под Windows ссылок
такого рода нет, и путь берётся как есть.

Заменены все четыре места, где каталог программы вычислялся вручную:
журнал, поиск инструментов, каталог зависимостей и путь заготовки в
проекте.

Проверено: запуск через ~/.local/bin/nlve из домашнего каталога кладёт
журнал в каталог программы, а не рядом со ссылкой.
This commit is contained in:
4aiman 2026-08-22 13:41:07 +03:00
commit e4a77d1a72
5 changed files with 44 additions and 6 deletions

View file

@ -11,7 +11,8 @@ unit uAppTypes;
interface
uses
SysUtils;
SysUtils
{$IFDEF UNIX}, BaseUnix{$ENDIF};
type
{ Чем заполнен сегмент готового ряда.
@ -119,6 +120,16 @@ function Plural(ACount: Integer; const AOne, AFew, AMany: string): string;
Назад полоска не идёт никогда. }
function AdvanceProgress(AShown, AReal, ANext, AStepShare: Double): Double;
{ Каталог, в котором лежит сама программа.
Не ExtractFilePath(ParamStr(0)): если программу запустили через
символьную ссылку — а так она и попадает в PATH и в меню, — то путь
укажет на ссылку, и рядом с ней окажутся и журнал, и файл зависимостей,
и поиск ffmpeg. Ссылки раскрываются, пока не кончатся.
Под Windows ссылок такого рода нет, и путь берётся как есть. }
function ProgramDir: string;
implementation
var
@ -182,4 +193,31 @@ begin
Result := 0.999;
end;
function ProgramDir: string;
var
Path, Target: string;
{$IFDEF UNIX}
Guard: Integer;
{$ENDIF}
begin
Path := ExpandFileName(ParamStr(0));
{$IFDEF UNIX}
{ Ограничение на число переходов — от закольцованных ссылок. }
Guard := 0;
while Guard < 16 do
begin
Target := fpReadLink(Path);
if Target = '' then
Break;
{ Ссылка может указывать и относительным путём — считаем его от
каталога самой ссылки. }
if (Length(Target) > 0) and (Target[1] <> '/') then
Target := ExpandFileName(ExtractFilePath(Path) + Target);
Path := Target;
Inc(Guard);
end;
{$ENDIF}
Result := ExtractFilePath(Path);
end;
end.

View file

@ -24,7 +24,7 @@ unit uDeps;
interface
uses
Classes, SysUtils;
Classes, SysUtils, uAppTypes;
type
TStringArray = array of string;
@ -89,7 +89,7 @@ uses
function DepTargetDir: string;
begin
Result := ExtractFilePath(ExpandFileName(ParamStr(0)));
Result := ProgramDir;
end;
function DepsConfigPath: string;

View file

@ -362,7 +362,7 @@ function LocateTool(const AName: string): string;
var
Own: string;
begin
Own := ExtractFilePath(ExpandFileName(ParamStr(0))) + AName
Own := ProgramDir + AName
{$IFDEF WINDOWS} + '.exe'{$ENDIF};
if FileExists(Own) then
Exit(Own);

View file

@ -350,7 +350,7 @@ begin
pnlVideo.Color := clBlack;
memoLog.Clear;
FLogFilePath := ExtractFilePath(ExpandFileName(ParamStr(0))) + 'nlve.log';
FLogFilePath := ProgramDir + 'nlve.log';
FPlayer := TMpvPlayer.Create(pnlVideo);
FPlayer.OnLog := @PlayerLog;

View file

@ -912,7 +912,7 @@ begin
if FFileName = '' then
{ Проект ещё не сохранён — держим кэш рядом с программой, чтобы не
разбрасывать файлы по системным каталогам. }
Result := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) +
Result := ProgramDir +
'unsaved.nlve-cache' + PathDelim
else
Result := IncludeTrailingPathDelimiter(ExtractFilePath(FFileName)) +