Обновлён алгоритм работы с каталогами

This commit is contained in:
Andrei Astafev 2020-06-03 12:20:59 +03:00
parent 395ffb080a
commit b86cf01973
9 changed files with 240 additions and 231 deletions

198
.gitignore vendored
View File

@ -1,8 +1,200 @@
CMakeLists.txt.user*
# Каталог для результатов сборки проекта
_build
# Каталог для тестирования установки
_output
.cmake/
*.autosave
# Файлы настроек, редактируемые во время отладки,
# за исключением шаблонных файлов
files/etc/*.conf
!files/etc/*.example.conf
# Каталоги, в которые разрешена запись данных во время работы программы
files/lib/*
files/log/*
###
### Общие настройки для C, C++, Fortran, Qt, CMake, Ninja, LaTeX и редакторов
###
###
### Временные файлы текстовых редакторов
###
*.bak
*.gho
*.tmp
*.dotdropbak
###
### LyX
###
*.lyx~
*.lyx#
###
### Vim
###
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
###
### C++
###
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.so.*
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
###
### CMake
###
CMakeLists.txt.user*
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
###
### Ninja
###
.ninja_deps
.ninja_log
###
### GCC coverage testing tool files
###
*.gcno
*.gcda
*.gcov
###
### Qt
###
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator local machine specific files for imported projects
*creator.user*
*_qmlcache.qrc
###
### Latex
###
*.acn
*.acr
*.alg
*.aux
*.bbl
*.blg
*.dvi
*.fdb_latexmk
*.glg
*.glo
*.gls
*.idx
*.ilg
*.ind
*.ist
*.lof
*.log
*.lot
*.maf
*.mtc
*.mtc0
*.nav
*.nlo
*.out
*.pdfsync
*.ps
*.snm
*.synctex.gz
*.toc
*.vrb
*.xdy
*.tdo

View File

@ -1,7 +1,6 @@
#include <myx/base/config.hpp>
#include <myx/filesystem/paths.hpp>
#include <myx/filesystem/paths_mt.hpp>
#include <QCoreApplication>
#include <QDebug>
@ -10,26 +9,18 @@
namespace MF = myx::filesystem;
// Переменные для защиты экземпляра класса MF::PathsMT
std::atomic< MF::PathsMT* > MF::PathsMT::sInstance;
std::mutex MF::PathsMT::sMutex;
int main( int argc, char** argv )
{
(void)argc;
(void)argv;
QCoreApplication::setApplicationName( QStringLiteral( CMLIB_PROJECT_NAME ) );
MF::PathsMT& pathsMT = MF::PathsMT::instance();
MF::Paths& paths = MF::Paths::instance();
pathsMT.init( QStringLiteral( CMLIB_PROJECT_NAME ), QStringLiteral( "conf" ) );
pathsMT.findConfigFile( QStringLiteral( "test" ) );
qDebug() << pathsMT.systemLogDirectory();
qDebug() << pathsMT.systemConfigDirectory();
MF::Paths& paths = MF::Paths::instance();
paths.init( QStringLiteral( CMLIB_PROJECT_NAME ), QStringLiteral( "conf" ) );
qDebug() << "prefixDirectory : " << paths.prefixDirectory();
qDebug() << "executableName : " << paths.executableName();
qDebug() << "executableFilePath : " << paths.executableFilePath();
qDebug() << "executableDirectory : " << paths.executableDirectory();

View File

@ -3,16 +3,10 @@ set(TRGT filesystem)
# cmake-format: off
# Список файлов исходных текстов
set(TRGT_cpp
${CMAKE_CURRENT_SOURCE_DIR}/current_executable.cpp
${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp
${CMAKE_CURRENT_SOURCE_DIR}/paths_mt.cpp)
set(TRGT_cpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp)
# Список заголовочных файлов
set(TRGT_hpp
${CMAKE_CURRENT_SOURCE_DIR}/current_executable.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths.hpp
${CMAKE_CURRENT_SOURCE_DIR}/paths_mt.hpp)
set(TRGT_hpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.hpp)
set(TRGT_headers ${TRGT_hpp})
# cmake-format: on

View File

@ -1,41 +0,0 @@
#ifndef MYX_BASE_CURRENT_EXECUTABLE_CPP_
#define MYX_BASE_CURRENT_EXECUTABLE_CPP_
#ifndef MYXLIB_HEADER_ONLY
#include <myx/filesystem/current_executable.hpp>
#else
#pragma once
#endif
#include <myx/base/config.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
#if !defined ( __linux__ )
error "Class CurrentExecutable is supported only in Linux"
#endif
MYXLIB_INLINE CurrentExecutable::CurrentExecutable() :
m_procFilePath( QStringLiteral( "/proc/self/exe" ) )
{
m_canonicalFilePath = m_procFilePath.canonicalFilePath();
}
MYXLIB_INLINE const QFileInfo& CurrentExecutable::canonicalFilePath() const
{
return( m_canonicalFilePath );
}
} // namespace filesystem
} // namespace myx
#endif // MYX_BASE_CURRENT_EXECUTABLE_CPP_

View File

@ -1,51 +0,0 @@
/**
* @file current_executable.hpp
* @brief Параметры исполняемого файла
*/
#ifndef MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_
#define MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <QDir>
#include <QFileInfo>
#include <QString>
namespace myx {
namespace filesystem {
class CurrentExecutable
{
/// @brief Путь к символической ссылке, указывающей на текущий исполняемый файл
QFileInfo m_procFilePath;
/// @brief Канонический путь к текущему исполняемому файлу
QFileInfo m_canonicalFilePath;
friend class Paths;
public:
/**
* @brief Конструктор, собирающий информацию о текущем исполняемом файле.
*/
CurrentExecutable();
/**
* @brief Канонический путь к текущему исполняемому файлу
*/
const QFileInfo& canonicalFilePath() const;
}; // class CurrentExecutable
} // namespace filesystem
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "current_executable.cpp"
#endif
#endif // MYX_FILESYSTEM_CURRENT_EXECUTABLE_HPP_

View File

@ -8,7 +8,6 @@
#endif
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <paths.h>
@ -22,11 +21,22 @@ namespace filesystem {
MYXLIB_INLINE Paths::Paths() = default;
MYXLIB_INLINE void Paths::setupSystemDirectories( const QString& defaultEtcDirectory,
MYXLIB_INLINE void Paths::setupSystemDirectories( const QString& defaultPrefixDirectory,
const QString& defaultEtcDirectory,
const QString& defaultConstDataDirectory,
const QString& defaultVarDataDirectory,
const QString& defaultLogDirectory )
{
QFileInfo prefixDirInfo { defaultPrefixDirectory };
if ( prefixDirInfo.isDir() && prefixDirInfo.isReadable() )
{
m_prefixDirectory = defaultPrefixDirectory;
}
else
{
m_prefixDirectory = ".";
}
QFileInfo etcDirInfo { defaultEtcDirectory };
if ( etcDirInfo.isDir() && etcDirInfo.isReadable() )
{
@ -77,7 +87,8 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
if ( binUnityRegexp.indexIn( binaryDir ) >= 0 )
{
binaryDir.remove( binUnityRegexp );
setupSystemDirectories( binaryDir + "/etc",
setupSystemDirectories( binaryDir,
binaryDir + "/etc",
binaryDir + "/files/data",
binaryDir + "/files/lib",
binaryDir + "/files/log" );
@ -88,6 +99,7 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
QRegExp binRegexp( "/s*bin$" );
if ( binRegexp.indexIn( binaryDir ) == -1 )
{
m_prefixDirectory = m_executableDirectory;
m_systemConstDataDirectory = m_executableDirectory;
m_systemVarDataDirectory = m_executableDirectory;
m_systemConfigDirectory = m_executableDirectory;
@ -100,7 +112,8 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
if ( optRegexp.indexIn( binaryDir ) >= 0 )
{
binaryDir.remove( binRegexp );
setupSystemDirectories( binaryDir + "/etc",
setupSystemDirectories( binaryDir,
binaryDir + "/etc",
binaryDir + "/files/data",
binaryDir + "/files/lib",
binaryDir + "/files/log" );
@ -110,7 +123,8 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
if ( binaryDir.startsWith( QStringLiteral( "/usr/local" ) ) )
{
setupSystemDirectories( "/usr/local/etc/" + m_projectName,
setupSystemDirectories( "/usr/local",
"/usr/local/etc/" + m_projectName,
"/usr/local/share/" + m_projectName,
"/var/lib/" + m_projectName,
"/var/log/" + m_projectName );
@ -120,7 +134,8 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
if ( binaryDir.startsWith( QStringLiteral( "/usr" ) ) )
{
setupSystemDirectories( "/etc/" + m_projectName,
setupSystemDirectories( "/usr",
"/etc/" + m_projectName,
"/usr/share/" + m_projectName,
"/var/lib/" + m_projectName,
"/var/log/" + m_projectName );
@ -131,6 +146,7 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
if ( binaryDir.startsWith( m_homeDirectory + "/.local/bin" ) ||
binaryDir.startsWith( m_homeDirectory + "/bin" ) )
{
m_prefixDirectory = m_homeDirectory;
m_systemConfigDirectory = m_userConfigDirectory;
m_systemConstDataDirectory = m_userConstDataDirectory;
m_systemVarDataDirectory = m_userVarDataDirectory;
@ -140,7 +156,8 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
}
binaryDir.remove( binRegexp );
setupSystemDirectories( binaryDir + "/etc",
setupSystemDirectories( binaryDir,
binaryDir + "/etc",
binaryDir + "/files/data",
binaryDir + "/files/lib",
binaryDir + "/files/log" );
@ -151,10 +168,11 @@ MYXLIB_INLINE Paths::HierarchyType Paths::getHierarchyType()
MYXLIB_INLINE bool Paths::init( const QString& projectDir, const QString& configFileExtension )
{
CurrentExecutable exe;
m_executableName = exe.m_canonicalFilePath.fileName();
m_executableFilePath = exe.m_canonicalFilePath.absoluteFilePath();
m_executableDirectory = exe.m_canonicalFilePath.absolutePath();
QFileInfo procSelfExe( QStringLiteral( "/proc/self/exe" ) );
QFileInfo currentExecutable = procSelfExe.canonicalFilePath();
m_executableName = currentExecutable.fileName();
m_executableFilePath = currentExecutable.absoluteFilePath();
m_executableDirectory = currentExecutable.absolutePath();
m_projectName = projectDir.isEmpty() ? m_executableName
: projectDir;
@ -334,6 +352,12 @@ MYXLIB_INLINE const QString& Paths::executableDirectory() const
return( m_executableDirectory );
}
MYXLIB_INLINE const QString& Paths::prefixDirectory() const
{
return( m_prefixDirectory );
}
} // namespace filesystem
} // namespace myx

View File

@ -9,7 +9,6 @@
#pragma once
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <QDir>
#include <QFileInfo>
@ -53,6 +52,9 @@ class Paths
QString m_executableFilePath;
QString m_executableDirectory;
/// @brief Общий префикс для файлов проекта
QString m_prefixDirectory;
/// @brief Путь к каталогу с временными файлами
QString m_tempDirectory;
/// @brief Путь к домашнему каталогу текущего пользователя
@ -85,7 +87,8 @@ class Paths
/// @brief Расширение для файла настройки
QString m_configFileExtension;
void setupSystemDirectories( const QString& defaultEtcDirectory,
void setupSystemDirectories( const QString& defaultPrefixDirectory,
const QString& defaultEtcDirectory,
const QString& defaultConstDataDirectory,
const QString& defaultVarDataDirectory,
const QString& defaultLogDirectory );

View File

@ -1,44 +0,0 @@
#ifndef MYX_BASE_PATHS_MT_CPP_
#define MYX_BASE_PATHS_MT_CPP_
#ifndef MYXLIB_HEADER_ONLY
#include <myx/filesystem/paths_mt.hpp>
#else
#pragma once
#endif
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <paths.h>
#include <QCoreApplication>
#include <QString>
namespace myx {
namespace filesystem {
MYXLIB_INLINE PathsMT::PathsMT() = default;
MYXLIB_INLINE PathsMT& PathsMT::instance()
{
volatile PathsMT* localInstance = sInstance.load( std::memory_order_acquire );
if ( localInstance == nullptr )
{
std::lock_guard< std::mutex > myLock( sMutex );
localInstance = sInstance.load( std::memory_order_relaxed );
if ( localInstance == nullptr ) // -V1036
{
localInstance = new PathsMT();
sInstance.store( const_cast< PathsMT* >( localInstance ), std::memory_order_release ); // NOLINT
}
}
return( const_cast< PathsMT& >( *localInstance ) ); // NOLINT
}
} // namespace filesystem
} // namespace myx
#endif // MYX_BASE_PATHS_MT_CPP_

View File

@ -1,59 +0,0 @@
/**
* @file paths.hpp
* @brief Стандартные пути к каталогам и файлам
*/
#ifndef MYX_FILESYSTEM_PATHS_MT_HPP_
#define MYX_FILESYSTEM_PATHS_MT_HPP_
#pragma once
#include <myx/base/config.hpp>
#include <myx/filesystem/current_executable.hpp>
#include <myx/filesystem/paths.hpp>
#include <QDir>
#include <QFileInfo>
#include <QString>
#include <atomic>
#include <future>
#include <mutex>
#include <thread>
namespace myx {
namespace filesystem {
/// @brief Потокобезопасная версия класса myx::filesystem::Paths
class PathsMT : public Paths
{
PathsMT();
~PathsMT() = default;
static std::atomic< PathsMT* > sInstance;
static std::mutex sMutex;
public:
PathsMT( const PathsMT& ) = delete;
PathsMT& operator=( const PathsMT& ) = delete;
PathsMT( PathsMT&& ) = delete;
PathsMT& operator=( PathsMT&& ) = delete;
/**
* @brief getInstance
* @return Уникальный экземпляр класса PathsMT
*/
static PathsMT& instance();
}; // class PathsMT
} // namespace filesystem
} // namespace myx
#ifdef MYXLIB_HEADER_ONLY
#include "paths_mt.cpp"
#endif
#endif // MYX_FILESYSTEM_PATHS_MT_HPP_