[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[tyndur-devel] [PATCH 7/9] lpt: Pakete deinstallieren



+ lpt: Pakete deinstallieren

Signed-off-by: Antoine Kaufmann <toni@xxxxxxxxxx>
---
 src/modules/pas/lpt/lang/lang_en.c |   15 ++++-
 src/modules/pas/lpt/lang/resstr.h  |    3 +
 src/modules/pas/lpt/lpt.pas        |  151 +++++++++++++++++++++++++++++++++++-
 3 files changed, 167 insertions(+), 2 deletions(-)

diff --git a/src/modules/pas/lpt/lang/lang_en.c b/src/modules/pas/lpt/lang/lang_en.c
index 74d7c1d..dd3b228 100644
--- a/src/modules/pas/lpt/lang/lang_en.c
+++ b/src/modules/pas/lpt/lang/lang_en.c
@@ -62,7 +62,8 @@ static const struct tms_strings dict[] = {
     "  list:    List all available packages\n"
     "  get:     Install a package\n"
     "  install: Install a package from a local file\n"
-    "           (speficy file name as last parameter)",
+    "           (speficy file name as last parameter)\n"
+    "  remove:  Remove a package",
 
     // Herunterladen und Entpacken von %s
     &RESSTR_P$LPT_RSDOWNLOADANDEXTRACT,
@@ -76,6 +77,10 @@ static const struct tms_strings dict[] = {
     &RESSTR_P$LPT_RSCONFIGURING,
     "Configuring %s",
 
+    // Entferne %s
+    &RESSTR_P$LPT_RSREMOVING,
+    "Removing %s",
+
     // Fehler:
     &RESSTR_P$LPT_RSERROR,
     "Error:",
@@ -92,6 +97,10 @@ static const struct tms_strings dict[] = {
     &RESSTR_P$LPT_RSALREADYINSTALLED,
     "Package is already installed:",
 
+    // Paket ist nicht installiert
+    &RESSTR_P$LPT_RSNOTINSTALLED,
+    "Package is not installed",
+
     // Kann die Paketlisten nicht einlesen:
     &RESSTR_P$LPT_RSCANNOTREADPKGLISTS,
     "Cannot read package lists:",
@@ -112,6 +121,10 @@ static const struct tms_strings dict[] = {
     &RESSTR_P$LPT_RSINVALIDACTION,
     "Invalid action:",
 
+    // Kann Paket nicht deinstallieren, da die pkgcontent-Datei fehlt.
+    &RESSTR_P$LPT_RSNOPKGCONTENTFILE,
+    "Could not remove package, pkgcontent file is missing.",
+
     // Paket %s fehlt
     &RESSTR_PACKAGES_RSPACKAGEMISSING,
     "Package %s is not available",
diff --git a/src/modules/pas/lpt/lang/resstr.h b/src/modules/pas/lpt/lang/resstr.h
index 7b9b3ca..10f95e7 100644
--- a/src/modules/pas/lpt/lang/resstr.h
+++ b/src/modules/pas/lpt/lang/resstr.h
@@ -38,15 +38,18 @@ extern void* RESSTR_P$LPT_RSUSAGE;
 extern void* RESSTR_P$LPT_RSDOWNLOADANDEXTRACT;
 extern void* RESSTR_P$LPT_RSSEARCHING;
 extern void* RESSTR_P$LPT_RSCONFIGURING;
+extern void* RESSTR_P$LPT_RSREMOVING;
 extern void* RESSTR_P$LPT_RSERROR;
 extern void* RESSTR_P$LPT_RSCANTLOADREPOLIST;
 extern void* RESSTR_P$LPT_RSFAILDOWNLOADREPOLIST;
 extern void* RESSTR_P$LPT_RSALREADYINSTALLED;
+extern void* RESSTR_P$LPT_RSNOTINSTALLED;
 extern void* RESSTR_P$LPT_RSCANNOTREADPKGLISTS;
 extern void* RESSTR_P$LPT_RSCANNOTFINDPACKAGE;
 extern void* RESSTR_P$LPT_RSCANNOTRESOLVEDEP;
 extern void* RESSTR_P$LPT_RSWRONGPARAMCOUNT;
 extern void* RESSTR_P$LPT_RSINVALIDACTION;
+extern void* RESSTR_P$LPT_RSNOPKGCONTENTFILE;
 extern void* RESSTR_PACKAGES_RSPACKAGEMISSING;
 extern void* RESSTR_REPOSITORIES_RSUNKNOWNREPOTYPE;
 extern void* RESSTR_REPOSITORIES_RSINVALIDPKGSRC;
diff --git a/src/modules/pas/lpt/lpt.pas b/src/modules/pas/lpt/lpt.pas
index 5fda323..cef2d56 100644
--- a/src/modules/pas/lpt/lpt.pas
+++ b/src/modules/pas/lpt/lpt.pas
@@ -12,21 +12,27 @@ resourcestring
         '  list: Zeigt alle verfügbaren Pakete an'#10 +
         '  get:  Installiert das angegebene Paket'#10 +
         '  install: Installiert das angegebene Paket aus lokaler Datei'#10 +
-        '           Achtung, Datei als letzten Parameter angeben!';
+        '           Achtung, Datei als letzten Parameter angeben!'#10 +
+        '  remove: Paket deinstallieren';
+
 
     rsDownloadAndExtract = 'Herunterladen und Entpacken von %s';
     rsSearching = 'Suche %s';
     rsConfiguring = 'Richte %s ein';
+    rsRemoving = 'Entferne %s';
 
     rsError = 'Fehler:';
     rsCantLoadRepoList = 'Kann Repository-Liste nicht laden:';
     rsFailDownloadRepoList = 'Download der Paketliste für %s fehlgeschlagen:';
     rsAlreadyInstalled = 'Paket ist bereits installiert:';
+    rsNotInstalled = 'Paket ist nicht installiert';
     rsCannotReadPkglists = 'Kann die Paketlisten nicht einlesen:';
     rsCannotFindPackage = 'Konnte keine Version von %s finden';
     rsCannotResolveDep = 'Konnte die Abhängigkeiten des Pakets nicht auflösen:';
     rsWrongParamCount = 'Falsche Parameterzahl';
     rsInvalidAction = 'Ungütige Aktion:';
+    rsNoPkgcontentFile = 'Kann Paket nicht deinstallieren, da die pkgcontent-' +
+        'Datei fehlt.';
 
 
 procedure PrintUsage;
@@ -312,6 +318,142 @@ begin
     end;
 end;
 
+(**
+ * Bestimmte Version eines Pakets deinstallieren
+ *
+ * @param version Zu deinstalliernde Version
+ *
+ * @return True bei Erfolg, False sonst
+ *)
+function RemoveVersion(version: TPackageVersion): Boolean;
+
+    (**
+     * Pre-Remove-Skript der angegebenen Version ausfuehren ausfuehren
+     *)
+    procedure ExecutePreremoveScript(version: TPackageVersion);
+    var
+        filename: String;
+    begin
+        filename := 'file:/packages/' + version.pkg.name + '/' +
+            version.version + '/preremove-' + version.section.section;
+
+        WriteLn(Format(rsSearching, [filename]));
+        if FileExists(filename) then begin
+            exec(filename, '');
+        end;
+    end;
+
+    (**
+     * Die angegebene Datei/das angegebene Verzeichnis loeschen, und falls das
+     * Elternverzeichnis dadurch leer wird, dieses auch entfernen.
+     *
+     * @param path Zu loeschender Pfad
+     *
+     * @result True wenn die Datei erfolgreich geloescht wurde, false sonst.
+     *)
+    function RemoveWithParent(path: String): Boolean;
+    var
+        f: Text;
+        dir, fn, ext: String;
+        rec: Searchrec;
+    begin
+        if not DeleteFile(path) then begin
+            Exit(False);
+        end;
+
+        (* Wenn das Verzeichnis leer ist, machen wir rekursiv weiter *)
+        dos.FSplit(path, dir, fn, ext);
+        DosError := 0;
+        dos.FindFirst(dir + '/*', 0, rec);
+        while DosError = 0 do begin
+            if (rec.name <> '.') and (rec.name <> '..') then begin
+                dos.FindClose(rec);
+                Exit(True);
+            end;
+            dos.FindNext(rec);
+        end;
+        dos.FindClose(rec);
+
+        RemoveWithParent(Copy(dir, 1, Length(dir) - 1));
+        Exit(True);
+    end;
+
+    (**
+     * Alle installierten Dateien dieser Version entfernen
+     *
+     * @param version Zu entfernende Version
+     *)
+    procedure RemoveVersionFiles(version: TPackageVersion);
+    var
+        filename: String;
+        contents: Text;
+        path: String;
+    begin
+        filename := 'file:/packages/' + version.pkg.name + '/' + version.version
+            + '/pkgcontent-' +  version.section.section;
+
+        Assign(contents, filename);
+        Reset(contents);
+        if IOResult <> 0 then begin
+            WriteLn(rsNoPkgcontentFile);
+            Exit;
+        end;
+
+        repeat
+            ReadLn(contents, path);
+            RemoveWithParent(path);
+        until Eof(contents);
+
+        Close(contents);
+
+        (* Die Paketliste koennen wir erst loeschen wenn sie geschlossen ist *)
+        RemoveWithParent(filename);
+    end;
+
+begin
+    WriteLn(Format(rsRemoving, [version.pkg.name + '-' + version.version + '/' +
+        version.section.section]));
+
+    ExecutePreremoveScript(version);
+    RemoveVersionFiles(version);
+    Exit(True);
+end;
+
+(**
+ * Paket entfernen
+ *
+ * @param pkgname Name des zu entfernenden Pakets
+ *)
+procedure Remove(pkgname: String);
+var
+    installed: TPackageSet;
+    version: TPackageVersion;
+    section: String;
+    i: Integer;
+begin
+    installed := TPackageSet.create;
+    FindInstalledPackages(installed);
+
+    // Parameter hat die Form Paketname/Section. Wenn keine Section angegeben
+    // ist, wird bin als Default benutzt.
+    // FIXME: Hier will man wohl auch die Version angeben koennen
+    i := Pos('/', pkgname);
+    if i > 0 then begin
+        section := Copy(pkgname, i + 1, Length(pkgname));
+        pkgname := Copy(pkgname, 1, i - 1);
+    end else begin
+        section := 'bin';
+    end;
+
+    version := installed.GetCurrentVersion(pkgname, section);
+    if version = nil then begin
+        WriteLn(rsNotInstalled);
+        Exit;
+    end;
+
+    RemoveVersion(version);
+end;
+
 function c_lostio_create_link(target, link: PChar; hard: boolean): integer; cdecl; external name 'io_create_link';
 
 procedure CfgAddbin(path, pubname: String);
@@ -404,6 +546,13 @@ begin
             WriteLn(rsWrongParamCount);
             PrintUsage;
         end;
+    end else if system.ParamStr(1) = 'remove' then begin
+        if system.ParamCount = 2 then begin
+            Remove(system.ParamStr(2));
+        end else begin
+            WriteLn(rsWrongParamCount);
+            PrintUsage;
+        end;
     end else if system.ParamStr(1) = 'cfg-addbin' then begin
         if system.ParamCount = 3 then begin
             CfgAddbin(system.ParamStr(2), system.ParamStr(3));
-- 
1.6.3.3