Index: src/VCSInfoMenuWzrd.pas ================================================================== --- src/VCSInfoMenuWzrd.pas +++ src/VCSInfoMenuWzrd.pas @@ -3,18 +3,56 @@ interface uses System.Generics.Collections, ToolsAPI; - type + TRepoClient = class; + TRepoClientClass = class of TRepoClient; + TRepoInfo = record Root: string; - IsRepo: Boolean; + Client: TRepoClient; Incoming: Cardinal; Outgoing: Cardinal; LastUpdated: TDateTime; + function IsRepo: Boolean; + end; + + TRepoClient = class abstract + private + FRootPath: string; + public + constructor Create(const Path: string); + property Root: string read FRootPath; + public + class function IsRepo(const Path: string): boolean; virtual; + class function GetRoot(const Path: string): string; virtual; + class function GetIncoming(const Path: string): Cardinal; virtual; + class function GetOutgoing(const Path: string): Cardinal; virtual; + class function GetSummary(const Path: string): Cardinal; virtual; + private + class var FClients: TList; + public + class procedure RegisterClient(const RepoClientClass: TRepoClientClass); + class function CreateClient(const Path: string): TRepoClient; + end; + + THgClient = class(TRepoClient) + class function IsRepo(const Path: string): boolean; override; + class function GetRoot(const Path: string): string; override; + class function GetIncoming(const Path: string): Cardinal; override; + class function GetOutgoing(const Path: string): Cardinal; override; + class function GetSummary(const Path: string): Cardinal; override; + end; + + TFossilClient = class(TRepoClient) + class function IsRepo(const Path: string): boolean; override; + class function GetRoot(const Path: string): string; override; + class function GetIncoming(const Path: string): Cardinal; override; + class function GetOutgoing(const Path: string): Cardinal; override; + class function GetSummary(const Path: string): Cardinal; override; end; // TODO: implement IOTAEditorNotifier and/or IOTAIDENotifier so we know which file is active TVCSInfoWizard = class(TNotifierObject, IOTAWizard, IOTAMenuWizard) private @@ -425,10 +463,11 @@ { ------------------------------------------------------------------------------------------------ } function TVCSInfoWizard.GetRepoInfo(const AFileName: string; const AForceUpdate: Boolean): TRepoInfo; var FilePath, FinalFilePath, RootPath, FinalRootPath: string; + Client: TRepoClient; Lines: TStringList; iRes: Cardinal; begin Result := Default(TRepoInfo); if not Assigned(FRepos) then @@ -435,10 +474,14 @@ FRepos := TDictionary.Create; FilePath := ExtractFileDir(AFileName); FinalFilePath := GetFinalPathName(FilePath); if AForceUpdate or (not FRepos.TryGetValue(FinalFilePath, Result)) or (Now - Result.LastUpdated > 5 / SecsPerDay) then begin + + // TODO: try all registered repo clients to identify whether FilePath is a repo, and get its root + Client := TRepoClient.CreateClient(FilePath); + iRes := ExecuteCmd('hg -yq root', RootPath, False, nil, FilePath); if iRes >= 255 then begin Result.Root := FilePath; Result.LastUpdated := Now; FinalRootPath := FinalFilePath;