ENH: Send all file installations through one path

This creates a single cmFileInstaller method to dispatch installation of
symlinks, directories, and files.  The change removes duplicate tests of
input file type and makes the decision more consistent.
This commit is contained in:
Brad King 2009-04-29 08:47:13 -04:00
parent bc6eec18dc
commit 97263b6cdd
2 changed files with 81 additions and 100 deletions

View File

@ -903,14 +903,10 @@ cmFileCommand::HandleDifferentCommand(std::vector<std::string> const& args)
// File installation helper class. // File installation helper class.
struct cmFileInstaller struct cmFileInstaller
{ {
// Methods to actually install files.
bool InstallFile(const char* fromFile, const char* toFile);
bool InstallDirectory(const char* source, const char* destination);
// All instances need the file command and makefile using them. // All instances need the file command and makefile using them.
cmFileInstaller(cmFileCommand* command): cmFileInstaller(cmFileCommand* command):
FileCommand(command), Makefile(command->GetMakefile()), FileCommand(command), Makefile(command->GetMakefile()),
Always(false), DestDirLength(0), MatchlessFiles(true) Always(false), Optional(false), DestDirLength(0), MatchlessFiles(true)
{ {
// Check whether to copy files always or only if they have changed. // Check whether to copy files always or only if they have changed.
this->Always = this->Always =
@ -932,6 +928,7 @@ private:
bool Always; bool Always;
cmFileTimeComparison FileTimes; cmFileTimeComparison FileTimes;
public: public:
bool Optional;
// The length of the destdir setting. // The length of the destdir setting.
int DestDirLength; int DestDirLength;
@ -964,8 +961,7 @@ public:
std::vector<MatchRule> MatchRules; std::vector<MatchRule> MatchRules;
// Get the properties from rules matching this input file. // Get the properties from rules matching this input file.
MatchProperties CollectMatchProperties(const char* file, MatchProperties CollectMatchProperties(const char* file)
bool isDirectory)
{ {
// Match rules are case-insensitive on some platforms. // Match rules are case-insensitive on some platforms.
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
@ -986,9 +982,9 @@ public:
result.Permissions |= mr->Properties.Permissions; result.Permissions |= mr->Properties.Permissions;
} }
} }
if(!matched && !this->MatchlessFiles && !isDirectory) if(!matched && !this->MatchlessFiles)
{ {
result.Exclude = true; result.Exclude = !cmSystemTools::FileIsDirectory(file);
} }
return result; return result;
} }
@ -1038,8 +1034,61 @@ public:
private: private:
bool InstallSymlink(const char* fromFile, const char* toFile); bool InstallSymlink(const char* fromFile, const char* toFile);
public:
bool InstallFile(const char* fromFile, const char* toFile,
MatchProperties const& match_properties);
bool InstallDirectory(const char* source, const char* destination,
MatchProperties const& match_properties);
bool Install(const char* fromFile, const char* toFile);
}; };
//----------------------------------------------------------------------------
bool cmFileInstaller::Install(const char* fromFile, const char* toFile)
{
if(!*fromFile)
{
cmOStringStream e;
e << "INSTALL encountered an empty string input file name.";
this->FileCommand->SetError(e.str().c_str());
return false;
}
// Collect any properties matching this file name.
MatchProperties match_properties = this->CollectMatchProperties(fromFile);
// Skip the file if it is excluded.
if(match_properties.Exclude)
{
return true;
}
if(cmSystemTools::SameFile(fromFile, toFile))
{
return true;
}
else if(cmSystemTools::FileIsSymlink(fromFile))
{
return this->InstallSymlink(fromFile, toFile);
}
else if(cmSystemTools::FileIsDirectory(fromFile))
{
return this->InstallDirectory(fromFile, toFile, match_properties);
}
else if(cmSystemTools::FileExists(fromFile))
{
return this->InstallFile(fromFile, toFile, match_properties);
}
else if(!this->Optional)
{
// The input file does not exist and installation is not optional.
cmOStringStream e;
e << "INSTALL cannot find file \"" << fromFile << "\" to install.";
this->FileCommand->SetError(e.str().c_str());
return false;
}
return true;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile) bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile)
{ {
@ -1097,24 +1146,9 @@ bool cmFileInstaller::InstallSymlink(const char* fromFile, const char* toFile)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile) bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile,
MatchProperties const& match_properties)
{ {
// Collect any properties matching this file name.
MatchProperties match_properties =
this->CollectMatchProperties(fromFile, false);
// Skip the file if it is excluded.
if(match_properties.Exclude)
{
return true;
}
// Short-circuit for symbolic links.
if(cmSystemTools::FileIsSymlink(fromFile))
{
return this->InstallSymlink(fromFile, toFile);
}
// Determine whether we will copy the file. // Determine whether we will copy the file.
bool copy = true; bool copy = true;
if(!this->Always) if(!this->Always)
@ -1170,24 +1204,9 @@ bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmFileInstaller::InstallDirectory(const char* source, bool cmFileInstaller::InstallDirectory(const char* source,
const char* destination) const char* destination,
MatchProperties const& match_properties)
{ {
// Collect any properties matching this directory name.
MatchProperties match_properties =
this->CollectMatchProperties(source, true);
// Skip the directory if it is excluded.
if(match_properties.Exclude)
{
return true;
}
// Short-circuit for symbolic links.
if(cmSystemTools::FileIsSymlink(source))
{
return this->InstallSymlink(source, destination);
}
// Inform the user about this directory installation. // Inform the user about this directory installation.
std::string message = "Installing: "; std::string message = "Installing: ";
message += destination; message += destination;
@ -1254,28 +1273,14 @@ bool cmFileInstaller::InstallDirectory(const char* source,
cmsys_stl::string fromPath = source; cmsys_stl::string fromPath = source;
fromPath += "/"; fromPath += "/";
fromPath += dir.GetFile(fileNum); fromPath += dir.GetFile(fileNum);
if(cmSystemTools::FileIsDirectory(fromPath.c_str())) std::string toPath = destination;
{ toPath += "/";
cmsys_stl::string toDir = destination; toPath += dir.GetFile(fileNum);
toDir += "/"; if(!this->Install(fromPath.c_str(), toPath.c_str()))
toDir += dir.GetFile(fileNum);
if(!this->InstallDirectory(fromPath.c_str(), toDir.c_str()))
{ {
return false; return false;
} }
} }
else
{
// Install this file.
std::string toFile = destination;
toFile += "/";
toFile += dir.GetFile(fileNum);
if(!this->InstallFile(fromPath.c_str(), toFile.c_str()))
{
return false;
}
}
}
} }
// Set the requested permissions of the destination directory. // Set the requested permissions of the destination directory.
@ -1728,14 +1733,12 @@ bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
std::vector<std::string> files; std::vector<std::string> files;
int itype = cmTarget::INSTALL_FILES; int itype = cmTarget::INSTALL_FILES;
bool optional = false;
bool result = this->ParseInstallArgs(args, installer, bool result = this->ParseInstallArgs(args, installer,
itype, rename, destination, files, itype, rename, destination, files);
optional);
if (result == true) if (result == true)
{ {
result = this->DoInstall(installer, result = this->DoInstall(installer,
itype, rename, destination, files, optional); itype, rename, destination, files);
} }
return result; return result;
} }
@ -1746,8 +1749,7 @@ bool cmFileCommand::ParseInstallArgs(std::vector<std::string> const& args,
int& itype, int& itype,
std::string& rename, std::string& rename,
std::string& destination, std::string& destination,
std::vector<std::string>& files, std::vector<std::string>& files)
bool& optional)
{ {
std::string stype = "FILES"; std::string stype = "FILES";
enum Doing { DoingNone, DoingFiles, enum Doing { DoingNone, DoingFiles,
@ -1795,7 +1797,7 @@ bool cmFileCommand::ParseInstallArgs(std::vector<std::string> const& args,
if ( args[i+1] == "OPTIONAL" ) if ( args[i+1] == "OPTIONAL" )
{ {
i++; i++;
optional = true; installer.Optional = true;
} }
doing = DoingNone; doing = DoingNone;
} }
@ -2030,8 +2032,7 @@ bool cmFileCommand::DoInstall( cmFileInstaller& installer,
const int itype, const int itype,
const std::string& rename, const std::string& rename,
const std::string& destination, const std::string& destination,
const std::vector<std::string>& files, const std::vector<std::string>& files)
const bool optional)
{ {
typedef std::set<cmStdString>::const_iterator iter_type; typedef std::set<cmStdString>::const_iterator iter_type;
@ -2063,37 +2064,19 @@ bool cmFileCommand::DoInstall( cmFileInstaller& installer,
fromFile += fromName; fromFile += fromName;
} }
std::string message; if(itype == cmTarget::INSTALL_DIRECTORY && fromFile.empty())
if(!cmSystemTools::SameFile(fromFile.c_str(), toFile.c_str()))
{ {
if(itype == cmTarget::INSTALL_DIRECTORY && if(!installer.InstallDirectory(fromFile.c_str(), toFile.c_str(),
(fromFile.empty() || cmFileInstaller::MatchProperties()))
cmSystemTools::FileIsDirectory(fromFile.c_str())))
{
// Try installing this directory.
if(!installer.InstallDirectory(fromFile.c_str(), toFile.c_str()))
{ {
return false; return false;
} }
} }
else if(cmSystemTools::FileExists(fromFile.c_str())) else if(!installer.Install(fromFile.c_str(), toFile.c_str()))
{
// Install this file.
if(!installer.InstallFile(fromFile.c_str(), toFile.c_str()))
{ {
return false; return false;
} }
} }
else if(!optional)
{
// The input file does not exist and installation is not optional.
cmOStringStream e;
e << "INSTALL cannot find file \"" << fromFile << "\" to install.";
this->SetError(e.str().c_str());
return false;
}
}
}
return true; return true;
} }

View File

@ -186,15 +186,13 @@ protected:
int& itype, int& itype,
std::string& destination, std::string& destination,
std::string& rename, std::string& rename,
std::vector<std::string>& files, std::vector<std::string>& files
bool& optional
); );
bool DoInstall(cmFileInstaller& installer, bool DoInstall(cmFileInstaller& installer,
const int itype, const int itype,
const std::string& rename, const std::string& rename,
const std::string& destination, const std::string& destination,
const std::vector<std::string>& files, const std::vector<std::string>& files
const bool optional
); );
bool HandleDownloadCommand(std::vector<std::string> const& args); bool HandleDownloadCommand(std::vector<std::string> const& args);
void GetTargetTypeFromString(const std::string& stype, int& itype) const; void GetTargetTypeFromString(const std::string& stype, int& itype) const;