From: Jon Turney Date: Tue, 25 Apr 2017 22:44:08 +0000 (+0100) Subject: Hoist uninstall up to Installer::uninstallOne() X-Git-Tag: release_2.883~5 X-Git-Url: https://cygwin.com/git/?a=commitdiff_plain;h=70191308aa651b7b564eddb7e89622c15406dbbd;p=cygwin-apps%2Fsetup.git Hoist uninstall up to Installer::uninstallOne() This calls packagemeta, which applies to packageversion (which delegates through packageversion_ to cygpackage) to return lines from the .lst.gz file (pretending that we know it contains a file list for that specific version) and to remove the .lst.gz file when done. Move this all up into Installer::uninstallOne(), where it's all in the same place as the operation it is reversing, Installer::installOne(). --- diff --git a/cygpackage.cc b/cygpackage.cc index 56c1da8e..32b94038 100644 --- a/cygpackage.cc +++ b/cygpackage.cc @@ -36,12 +36,8 @@ packagev (), canonical (), sdesc (), ldesc (), -type (package_binary), -listdata (), -listfile () +type (package_binary) { - memset( getfilenamebuffer, '\0', CYG_PATH_MAX); - /* FIXME: query the install database for the currently installed * version details */ @@ -103,46 +99,6 @@ cygpackage::~cygpackage () { } -const std::string -cygpackage::getfirstfile () -{ - if (listdata) - delete listdata; - listfile = - io_stream::open ("cygfile:///etc/setup/" + name + ".lst.gz", "rb", 0); - listdata = compress::decompress (listfile); - if (!listdata) - return std::string(); - /* std::string(NULL) will crash, so be careful to test for that. */ - const char *result = listdata->gets (getfilenamebuffer, sizeof (getfilenamebuffer)); - if (result == NULL) - Log (LOG_PLAIN) << "Corrupt package listing for " << name << ", can't uninstall old files." << endLog; - return std::string (result ? result : ""); -} - -const std::string -cygpackage::getnextfile () -{ - if (listdata) - { - /* std::string(NULL) will crash, so be careful to test for that. */ - const char *sz = listdata->gets (getfilenamebuffer, - sizeof (getfilenamebuffer)); - if (sz) - return std::string(sz); - } - return std::string(); -} - -void -cygpackage::uninstall () -{ - if (listdata) - delete listdata; - listdata = 0; - io_stream::remove ("cygfile:///etc/setup/" + name + ".lst.gz"); -} - const std::string cygpackage::Name () { diff --git a/cygpackage.h b/cygpackage.h index 40224725..c6d06573 100644 --- a/cygpackage.h +++ b/cygpackage.h @@ -20,9 +20,6 @@ * arbitrate acceess to cygwin binary packages amd cygwin source packages */ -/* for MAX_PATH */ -#include "win32.h" - #include "package_version.h" class io_stream; @@ -48,19 +45,11 @@ public: { return ldesc; }; - virtual void uninstall (); - /* pass the name of the package when constructing */ void setCanonicalVersion (const std::string& ); - virtual ~ cygpackage (); - /* TODO: we should probably return a metaclass - file name & path & size & type - - ie doc/script/binary - */ - virtual const std::string getfirstfile (); - virtual const std::string getnextfile (); /* pass the name of the package when constructing */ static packageversion createInstance (const std::string& pkgname, @@ -77,12 +66,9 @@ private: std::string packagev; std::string canonical; std::string sdesc, ldesc; - char getfilenamebuffer[CYG_PATH_MAX]; // package_stability_t stability; package_type_t type; - - io_stream *listdata, *listfile; }; #endif /* SETUP_CYGPACKAGE_H */ diff --git a/install.cc b/install.cc index f9496ebd..85051993 100644 --- a/install.cc +++ b/install.cc @@ -165,10 +165,81 @@ Installer::preremoveOne (packagemeta & pkg) void Installer::uninstallOne (packagemeta & pkg) { + if (!pkg.installed) + return; + Progress.SetText1 ("Uninstalling..."); Progress.SetText2 (pkg.name.c_str()); Log (LOG_PLAIN) << "Uninstalling " << pkg.name << endLog; - pkg.uninstall (); + + std::set dirs; + + io_stream *listfile = io_stream::open ("cygfile:///etc/setup/" + pkg.name + ".lst.gz", "rb", 0); + io_stream *listdata = compress::decompress (listfile); + + while (listdata) + { + char getfilenamebuffer[CYG_PATH_MAX]; + const char *sz = listdata->gets (getfilenamebuffer, sizeof (getfilenamebuffer)); + if (sz == NULL) + break; + + std::string line(sz); + + /* Insert the paths of all parent directories of line into dirs. */ + size_t idx = line.length(); + while ((idx = line.find_last_of('/', idx-1)) != string::npos) + { + std::string dir_path = line.substr(0, idx); + bool was_new = dirs.insert(dir_path).second; + /* If the path was already present in dirs, then all parent paths + * must necessarily be present also, so don't do any further work. + * */ + if (!was_new) break; + } + + std::string d = cygpath ("/" + line); + WCHAR wname[d.size () + 11]; /* Prefix + ".lnk". */ + mklongpath (wname, d.c_str (), d.size () + 11); + DWORD dw = GetFileAttributesW (wname); + if (dw != INVALID_FILE_ATTRIBUTES + && !(dw & FILE_ATTRIBUTE_DIRECTORY)) + { + Log (LOG_BABBLE) << "unlink " << d << endLog; + SetFileAttributesW (wname, dw & ~FILE_ATTRIBUTE_READONLY); + DeleteFileW (wname); + } + /* Check for Windows shortcut of same name. */ + d += ".lnk"; + wcscat (wname, L".lnk"); + dw = GetFileAttributesW (wname); + if (dw != INVALID_FILE_ATTRIBUTES + && !(dw & FILE_ATTRIBUTE_DIRECTORY)) + { + Log (LOG_BABBLE) << "unlink " << d << endLog; + SetFileAttributesW (wname, dw & ~FILE_ATTRIBUTE_READONLY); + DeleteFileW (wname); + } + } + + /* Remove the listing file */ + delete listdata; + io_stream::remove ("cygfile:///etc/setup/" + pkg.name + ".lst.gz"); + + /* An STL set maintains itself in sorted order. Thus, iterating over it + * in reverse order will ensure we process directories depth-first. */ + set::const_iterator it = dirs.end(); + while (it != dirs.begin()) + { + it--; + std::string d = cygpath("/" + *it); + WCHAR wname[d.size () + 11]; + mklongpath (wname, d.c_str (), d.size () + 11); + if (RemoveDirectoryW (wname)) + Log (LOG_BABBLE) << "rmdir " << d << endLog; + } + + pkg.installed = packageversion(); num_uninstalls++; } diff --git a/package_meta.cc b/package_meta.cc index 9d0e9c3f..83018b44 100644 --- a/package_meta.cc +++ b/package_meta.cc @@ -140,76 +140,6 @@ packagemeta::set_installed (packageversion & thepkg) installed = thepkg; } -/* uninstall a package if it's installed */ -void -packagemeta::uninstall () -{ - if (installed) - { - /* this will need to be pushed down to the version, or even the source level - * to allow differences between formats to be seamlessly managed - * but for now: here is ok - */ - set dirs; - string line = installed.getfirstfile (); - - while (line.size()) - { - /* Insert the paths of all parent directories of line into dirs. */ - size_t idx = line.length(); - while ((idx = line.find_last_of('/', idx-1)) != string::npos) - { - string dir_path = line.substr(0, idx); - bool was_new = dirs.insert(dir_path).second; - /* If the path was already present in dirs, then all parent paths - * must necessarily be present also, so don't do any further work. - * */ - if (!was_new) break; - } - - std::string d = cygpath ("/" + line); - WCHAR wname[d.size () + 11]; /* Prefix + ".lnk". */ - mklongpath (wname, d.c_str (), d.size () + 11); - DWORD dw = GetFileAttributesW (wname); - if (dw != INVALID_FILE_ATTRIBUTES - && !(dw & FILE_ATTRIBUTE_DIRECTORY)) - { - Log (LOG_BABBLE) << "unlink " << d << endLog; - SetFileAttributesW (wname, dw & ~FILE_ATTRIBUTE_READONLY); - DeleteFileW (wname); - } - /* Check for Windows shortcut of same name. */ - d += ".lnk"; - wcscat (wname, L".lnk"); - dw = GetFileAttributesW (wname); - if (dw != INVALID_FILE_ATTRIBUTES - && !(dw & FILE_ATTRIBUTE_DIRECTORY)) - { - Log (LOG_BABBLE) << "unlink " << d << endLog; - SetFileAttributesW (wname, dw & ~FILE_ATTRIBUTE_READONLY); - DeleteFileW (wname); - } - line = installed.getnextfile (); - } - installed.uninstall (); - - /* An STL set maintains itself in sorted order. Thus, iterating over it - * in reverse order will ensure we process directories depth-first. */ - set::const_iterator it = dirs.end(); - while (it != dirs.begin()) - { - it--; - std::string d = cygpath("/" + *it); - WCHAR wname[d.size () + 11]; - mklongpath (wname, d.c_str (), d.size () + 11); - if (RemoveDirectoryW (wname)) - Log (LOG_BABBLE) << "rmdir " << d << endLog; - } - } - installed = packageversion(); -} - - void packagemeta::add_category (const std::string& cat) { diff --git a/package_meta.h b/package_meta.h index dbd8eb98..529b2a24 100644 --- a/package_meta.h +++ b/package_meta.h @@ -71,7 +71,6 @@ public: static const _actions Uninstall_action; void set_action (trusts const t); void set_action (_actions, packageversion const & default_version); - void uninstall (); void set_message (const std::string& message_id, const std::string& message_string) { diff --git a/package_version.cc b/package_version.cc index cb884307..5e9271bc 100644 --- a/package_version.cc +++ b/package_version.cc @@ -46,13 +46,10 @@ public: const std::string Canonical_version() {return std::string();} void setCanonicalVersion (const std::string& ) {} package_type_t Type () {return package_binary;} - const std::string getfirstfile () {return std::string();} - const std::string getnextfile () {return std::string();} const std::string SDesc () {return std::string();} void set_sdesc (const std::string& ) {} const std::string LDesc () {return std::string();} void set_ldesc (const std::string& ) {} - void uninstall (){} }; static _defaultversion defaultversion; @@ -169,18 +166,6 @@ packageversion::Type () const return data->Type (); } -const std::string -packageversion::getfirstfile () -{ - return data->getfirstfile (); -} - -const std::string -packageversion::getnextfile () -{ - return data->getnextfile (); -} - const std::string packageversion::SDesc () const { @@ -235,12 +220,6 @@ packageversion::depends() const return &data->depends; } -void -packageversion::uninstall () -{ - data->uninstall (); -} - packagesource * packageversion::source () const { diff --git a/package_version.h b/package_version.h index 2fc733f4..4689330c 100644 --- a/package_version.h +++ b/package_version.h @@ -98,8 +98,6 @@ public: const std::string Canonical_version () const; void setCanonicalVersion (const std::string& ); package_type_t Type () const; - const std::string getfirstfile (); - const std::string getnextfile (); const std::string SDesc () const; void set_sdesc (const std::string& ); const std::string LDesc () const; @@ -112,7 +110,6 @@ public: PackageDepends *depends(); const PackageDepends *depends() const; - void uninstall (); /* invariant: never null */ packagesource *source() const; /* where can we source the file from */ @@ -146,11 +143,6 @@ public: virtual void setCanonicalVersion (const std::string& ) = 0; // virtual package_stability_t Stability () = 0; virtual package_type_t Type () = 0; - /* TODO: we should probably return a metaclass - file name & path & size & type - - ie doc/script/binary - */ - virtual const std::string getfirstfile () = 0; - virtual const std::string getnextfile () = 0; virtual const std::string SDesc () = 0; virtual void set_sdesc (const std::string& ) = 0; virtual const std::string LDesc () = 0; @@ -166,7 +158,6 @@ public: PackageDepends depends; - virtual void uninstall () = 0; packagesource source; /* where can we source the file from */ virtual bool accessible () const;