2015-09-07 19:36:45 +02:00
# include "./mingwbundle.h"
# include "./utilities.h"
# include "./manager.h"
# include "./config.h"
2015-08-19 02:13:28 +02:00
# include <c++utilities/conversion/stringconversion.h>
# include <c++utilities/misc/memory.h>
# include <KTar>
2015-09-04 14:37:01 +02:00
# include <K7Zip>
# include <KZip>
2015-08-19 02:13:28 +02:00
# include <QtConcurrent/QtConcurrent>
2015-09-04 14:37:01 +02:00
# include <QStringBuilder>
# include <QJsonDocument>
# include <QJsonArray>
# include <QFile>
2015-08-19 02:13:28 +02:00
# include <string>
# include <iostream>
using namespace std ;
2016-04-25 22:30:11 +02:00
using namespace ApplicationUtilities ;
2015-08-19 02:13:28 +02:00
2015-09-05 17:25:05 +02:00
namespace RepoIndex {
2015-08-19 02:13:28 +02:00
2015-09-04 14:37:01 +02:00
using namespace Utilities ;
2016-05-26 02:29:56 +02:00
const char * prefix = " mingw-w64- " ;
size_t prefixLen = 10 ;
2015-08-19 02:13:28 +02:00
2016-04-25 22:30:11 +02:00
IncludedPackage : : IncludedPackage ( const Package * package , bool dependencyOnly ) :
package ( package ) ,
dependencyOnly ( dependencyOnly )
{ }
bool IncludedPackage : : operator = = ( const Package * package ) const
{
return this - > package = = package ;
}
2016-05-26 02:29:56 +02:00
MingwBundle : : MingwBundle ( Manager & manager , const std : : vector < const char * > & packages , const std : : vector < const char * > & iconPackages , const std : : vector < const char * > & extraPackages , const std : : vector < const char * > & qtPlugins ) :
2015-09-21 22:16:19 +02:00
m_manager ( manager ) ,
2016-04-25 22:30:11 +02:00
m_extraPackages ( extraPackages ) ,
m_qtPlugins ( qtPlugins )
2015-08-19 02:13:28 +02:00
{
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Resolving dependencies ... " < < endl ;
2015-08-19 02:13:28 +02:00
string missing ;
2015-09-04 14:37:01 +02:00
// add mingw-w64 packages
2016-05-26 02:29:56 +02:00
for ( const char * pkgName : packages ) {
if ( auto * pkg = manager . packageProviding ( Dependency ( QString : : fromLocal8Bit ( strncmp ( pkgName , prefix , prefixLen ) ? pkgName : ( prefix + string ( pkgName ) ) . data ( ) ) ) ) ) {
2015-12-13 21:12:44 +01:00
if ( find ( m_packages . cbegin ( ) , m_packages . cend ( ) , pkg ) = = m_packages . cend ( ) ) {
2016-04-25 22:30:11 +02:00
m_packages . emplace_back ( pkg , false ) ;
2015-08-19 02:13:28 +02:00
addDependencies ( pkg ) ;
}
2015-12-08 18:59:17 +01:00
} else {
2015-08-19 02:13:28 +02:00
missing . push_back ( ' ' ) ;
missing . append ( pkgName ) ;
}
}
2015-09-04 14:37:01 +02:00
// add additional icon packages
for ( const auto & pkgName : iconPackages ) {
2016-05-26 02:29:56 +02:00
if ( auto * pkg = manager . packageProviding ( Dependency ( QString : : fromLocal8Bit ( pkgName ) ) ) ) {
2015-12-13 21:12:44 +01:00
if ( find ( m_packages . cbegin ( ) , m_packages . cend ( ) , pkg ) = = m_packages . cend ( ) ) {
2016-04-25 22:30:11 +02:00
m_packages . emplace_back ( pkg , false ) ;
2015-09-04 14:37:01 +02:00
}
2015-12-08 18:59:17 +01:00
} else {
2015-09-04 14:37:01 +02:00
missing . push_back ( ' ' ) ;
missing . append ( pkgName ) ;
}
}
2015-08-19 02:13:28 +02:00
if ( ! missing . empty ( ) ) {
throw runtime_error ( " The following packages can not be found: " + missing ) ;
} else {
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Adding the following packages: " ;
2016-04-25 22:30:11 +02:00
for ( const IncludedPackage & pkg : m_packages ) {
cerr < < shchar < < ' ' < < pkg . package - > name ( ) . toLocal8Bit ( ) . data ( ) ;
2015-08-19 02:13:28 +02:00
}
2015-09-05 17:25:05 +02:00
cerr < < shchar < < endl ;
2015-08-19 02:13:28 +02:00
}
}
2015-09-04 14:37:01 +02:00
void MingwBundle : : addDependencies ( const Package * pkg )
{
string missing ;
for ( const auto & dep : pkg - > dependencies ( ) ) {
if ( dep . name . startsWith ( QLatin1String ( " mingw-w64- " ) , Qt : : CaseInsensitive ) ) {
2015-12-08 18:59:17 +01:00
if ( auto * pkg = m_manager . packageProviding ( dep ) ) {
2015-12-13 21:12:44 +01:00
if ( find ( m_packages . cbegin ( ) , m_packages . cend ( ) , pkg ) = = m_packages . cend ( ) ) {
2016-04-25 22:30:11 +02:00
m_packages . emplace_back ( pkg , true ) ;
2015-12-08 18:59:17 +01:00
addDependencies ( pkg ) ;
2015-09-04 14:37:01 +02:00
}
2015-12-08 18:59:17 +01:00
} else {
2015-09-04 14:37:01 +02:00
missing . push_back ( ' ' ) ;
2015-12-08 18:59:17 +01:00
missing . append ( dep . name . toLocal8Bit ( ) ) ;
2015-09-04 14:37:01 +02:00
}
}
}
if ( ! missing . empty ( ) ) {
throw runtime_error ( " The following dependencies of the " + string ( pkg - > name ( ) . toLocal8Bit ( ) . data ( ) ) + " package can not be resolved: " + missing ) ;
}
}
2015-08-19 02:13:28 +02:00
enum class RelevantFileType
{
Binary ,
2016-01-03 00:22:48 +01:00
Data ,
2015-09-04 14:37:01 +02:00
Translation ,
QtTranslation ,
QtPlugin ,
2016-01-03 00:22:48 +01:00
Plugin ,
SharedData ,
GLib2Data ,
GLib2Schemas ,
Theme ,
2016-01-06 02:08:24 +01:00
IconTheme
2015-08-19 02:13:28 +02:00
} ;
enum class RelevantFileArch
{
x86_64 ,
2015-09-04 14:37:01 +02:00
i686 ,
Any
2015-08-19 02:13:28 +02:00
} ;
struct RelevantFile
{
2015-09-29 15:44:30 +02:00
RelevantFile ( const KArchiveFile * file , const KArchiveDirectory * containingDir , const RelevantFileType type , const RelevantFileArch arch , const QString & subDir = QString ( ) ) :
2015-09-21 22:16:19 +02:00
name ( file - > name ( ) ) ,
2015-08-19 02:13:28 +02:00
fileType ( type ) ,
2015-09-04 14:37:01 +02:00
arch ( arch ) ,
2015-09-29 15:44:30 +02:00
subDir ( subDir )
{
if ( file - > symLinkTarget ( ) . isEmpty ( ) ) {
data = file - > data ( ) ;
} else if ( const auto * targetEntry = containingDir - > entry ( file - > symLinkTarget ( ) ) ) {
// Windows support for symlinks is not very well
if ( targetEntry - > isFile ( ) ) {
data = static_cast < const KArchiveFile * > ( targetEntry ) - > data ( ) ;
}
}
}
2016-01-03 00:22:48 +01:00
2015-09-21 22:16:19 +02:00
QString name ;
QByteArray data ;
2015-08-19 02:13:28 +02:00
RelevantFileType fileType ;
RelevantFileArch arch ;
2015-09-04 14:37:01 +02:00
QString subDir ;
2015-08-19 02:13:28 +02:00
} ;
struct PkgFileInfo
{
2016-05-26 02:29:56 +02:00
PkgFileInfo ( const QString & name , const QString & path , bool dependencyOnly = false , const vector < const char * > & qtPlugins = vector < const char * > ( ) ) :
2015-09-04 14:37:01 +02:00
name ( name ) ,
path ( path ) ,
2016-04-25 22:30:11 +02:00
dependencyOnly ( dependencyOnly ) ,
qtPlugins ( qtPlugins ) ,
2015-09-04 14:37:01 +02:00
failure ( false )
{ }
2016-01-03 00:22:48 +01:00
2015-09-04 14:37:01 +02:00
QString name ;
2015-08-19 02:13:28 +02:00
QString path ;
unique_ptr < KTar > archive ;
list < RelevantFile > relevantFiles ;
2016-04-25 22:30:11 +02:00
bool dependencyOnly ;
2016-05-26 02:29:56 +02:00
const vector < const char * > & qtPlugins ;
2015-08-19 02:13:28 +02:00
bool failure ;
} ;
2016-01-03 00:22:48 +01:00
void addEntries ( PkgFileInfo & pkgFileInfo , RelevantFileType fileType , const KArchiveDirectory * dir , const QString & relPath = QString ( ) , const QString & ext = QString ( ) , RelevantFileArch relevantArch = RelevantFileArch : : Any )
2015-09-04 14:37:01 +02:00
{
2016-01-03 00:22:48 +01:00
const QString newPath = relPath . isEmpty ( ) ? dir - > name ( ) : relPath % QChar ( ' / ' ) % dir - > name ( ) ;
2015-09-04 14:37:01 +02:00
for ( const auto & entryName : dir - > entries ( ) ) {
if ( auto * entry = dir - > entry ( entryName ) ) {
if ( entry - > isDirectory ( ) ) {
2016-01-03 00:22:48 +01:00
addEntries ( pkgFileInfo , fileType , static_cast < const KArchiveDirectory * > ( entry ) , newPath , ext , relevantArch ) ;
2015-09-04 14:37:01 +02:00
} else if ( entry - > isFile ( ) ) {
2016-01-03 00:22:48 +01:00
if ( ext . isEmpty ( ) | | entry - > name ( ) . endsWith ( ext ) ) {
pkgFileInfo . relevantFiles . emplace_back ( static_cast < const KArchiveFile * > ( entry ) , dir , fileType , relevantArch , newPath ) ;
}
2015-09-04 14:37:01 +02:00
}
}
}
}
2015-08-19 02:13:28 +02:00
void getFiles ( PkgFileInfo & pkgFileInfo )
{
pkgFileInfo . archive = make_unique < KTar > ( pkgFileInfo . path ) ;
if ( pkgFileInfo . archive - > open ( QIODevice : : ReadOnly ) ) {
static const pair < RelevantFileArch , QString > roots [ ] = {
make_pair ( RelevantFileArch : : x86_64 , QStringLiteral ( " /usr/x86_64-w64-mingw32 " ) ) ,
make_pair ( RelevantFileArch : : i686 , QStringLiteral ( " /usr/i686-w64-mingw32 " ) )
} ;
2016-01-03 00:22:48 +01:00
// add files for each architecture separately
2015-08-19 02:13:28 +02:00
for ( const auto & root : roots ) {
2016-01-03 00:22:48 +01:00
// get root entry
2015-08-19 02:13:28 +02:00
const auto * rootEntry = pkgFileInfo . archive - > directory ( ) - > entry ( root . second ) ;
if ( rootEntry & & rootEntry - > isDirectory ( ) ) {
const auto * rootDir = static_cast < const KArchiveDirectory * > ( rootEntry ) ;
2016-01-03 00:22:48 +01:00
// binary directory: *.exe and *.dll files required
2015-08-19 02:13:28 +02:00
const auto * binEntry = rootDir - > entry ( QStringLiteral ( " bin " ) ) ;
if ( binEntry & & binEntry - > isDirectory ( ) ) {
const auto * binDir = static_cast < const KArchiveDirectory * > ( binEntry ) ;
2016-01-06 02:08:24 +01:00
for ( const QString & entryName : binDir - > entries ( ) ) {
2016-04-25 22:30:11 +02:00
if ( ( ! pkgFileInfo . dependencyOnly & & entryName . endsWith ( QLatin1String ( " .exe " ) ) ) | | entryName . indexOf ( QLatin1String ( " .dll " ) ) > 0 ) {
2015-08-19 02:13:28 +02:00
if ( const auto * entry = binDir - > entry ( entryName ) ) {
2016-04-25 22:30:11 +02:00
// do only copy files and no symlinks
if ( entry - > isFile ( ) & & entry - > symLinkTarget ( ) . isEmpty ( ) ) {
2015-09-29 15:44:30 +02:00
pkgFileInfo . relevantFiles . emplace_back ( static_cast < const KArchiveFile * > ( entry ) , binDir , RelevantFileType : : Binary , root . first ) ;
2015-09-04 14:37:01 +02:00
}
}
}
}
}
2016-01-03 00:22:48 +01:00
// library directory: Qt, GTK and application specific libs/plugins required
2015-09-04 14:37:01 +02:00
const auto * libEntry = rootDir - > entry ( QStringLiteral ( " lib " ) ) ;
if ( libEntry & & libEntry - > isDirectory ( ) ) {
2016-01-03 00:22:48 +01:00
// Qt 5 plugins
2015-09-04 14:37:01 +02:00
const auto * libDir = static_cast < const KArchiveDirectory * > ( libEntry ) ;
2016-04-25 22:30:11 +02:00
const auto * qtEntry = libDir - > entry ( QStringLiteral ( " qt " ) ) ;
2015-09-04 14:37:01 +02:00
if ( qtEntry & & qtEntry - > isDirectory ( ) ) {
const auto * qtDir = static_cast < const KArchiveDirectory * > ( qtEntry ) ;
const auto * pluginsEntry = qtDir - > entry ( QStringLiteral ( " plugins " ) ) ;
if ( pluginsEntry & & pluginsEntry - > isDirectory ( ) ) {
const auto * pluginsDir = static_cast < const KArchiveDirectory * > ( pluginsEntry ) ;
for ( const auto & pluginCategory : pluginsDir - > entries ( ) ) {
const auto * categoryEntry = pluginsDir - > entry ( pluginCategory ) ;
if ( categoryEntry & & categoryEntry - > isDirectory ( ) ) {
const auto * categoryDir = static_cast < const KArchiveDirectory * > ( categoryEntry ) ;
2016-04-25 22:30:11 +02:00
for ( const QString & entryName : categoryDir - > entries ( ) ) {
2015-09-04 14:37:01 +02:00
if ( const auto * pluginEntry = categoryDir - > entry ( entryName ) ) {
if ( pluginEntry - > isFile ( ) ) {
2016-04-25 22:30:11 +02:00
if ( entryName . endsWith ( QLatin1String ( " .dll " ) ) ) {
if ( ! pkgFileInfo . qtPlugins . empty ( ) ) {
string pluginName = entryName . toLocal8Bit ( ) . data ( ) ;
pluginName . resize ( pluginName . size ( ) - 4 ) ;
if ( find ( pkgFileInfo . qtPlugins . cbegin ( ) , pkgFileInfo . qtPlugins . cend ( ) , pluginName ) = = pkgFileInfo . qtPlugins . cend ( ) ) {
continue ;
}
}
pkgFileInfo . relevantFiles . emplace_back ( static_cast < const KArchiveFile * > ( pluginEntry ) , categoryDir , RelevantFileType : : QtPlugin , root . first , categoryDir - > name ( ) ) ;
}
2015-09-04 14:37:01 +02:00
}
}
}
}
}
}
}
2016-01-03 00:22:48 +01:00
// Qt 4 plugins
qtEntry = libDir - > entry ( QStringLiteral ( " qt4 " ) ) ;
if ( qtEntry & & qtEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Plugin , static_cast < const KArchiveDirectory * > ( qtEntry ) , QString ( ) , QString ( ) , root . first ) ;
}
// GTK plugins
const auto * gtkEntry = libDir - > entry ( QStringLiteral ( " gtk-2.0 " ) ) ;
if ( gtkEntry & & gtkEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Plugin , static_cast < const KArchiveDirectory * > ( gtkEntry ) , QString ( ) , QStringLiteral ( " .dll " ) , root . first ) ;
}
gtkEntry = libDir - > entry ( QStringLiteral ( " gtk-3.0 " ) ) ;
if ( gtkEntry & & gtkEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Plugin , static_cast < const KArchiveDirectory * > ( gtkEntry ) , QString ( ) , QStringLiteral ( " .dll " ) , root . first ) ;
}
// app specific libs/plugins
const auto * evinceEntry = libDir - > entry ( pkgFileInfo . name ) ;
if ( evinceEntry & & evinceEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Plugin , static_cast < const KArchiveDirectory * > ( evinceEntry ) , QString ( ) , QStringLiteral ( " .dll " ) , root . first ) ;
// required by evince
addEntries ( pkgFileInfo , RelevantFileType : : Plugin , static_cast < const KArchiveDirectory * > ( evinceEntry ) , QString ( ) , QStringLiteral ( " .evince-backend " ) , root . first ) ;
}
2015-09-04 14:37:01 +02:00
}
2016-01-03 00:22:48 +01:00
// data directory: required by geany
const auto * dataEntry = rootDir - > entry ( QStringLiteral ( " data " ) ) ;
if ( dataEntry & & dataEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Data , static_cast < const KArchiveDirectory * > ( dataEntry ) , QString ( ) , QString ( ) , root . first ) ;
}
2016-01-06 02:08:24 +01:00
// share directory: translations, themes, icons, schemas
2015-09-04 14:37:01 +02:00
const auto * shareEntry = rootDir - > entry ( QStringLiteral ( " share " ) ) ;
if ( shareEntry & & shareEntry - > isDirectory ( ) ) {
const auto * shareDir = static_cast < const KArchiveDirectory * > ( shareEntry ) ;
2016-01-06 02:08:24 +01:00
// Qt translations
2015-09-04 14:37:01 +02:00
const auto * qtEntry = shareDir - > entry ( QStringLiteral ( " qt " ) ) ;
if ( qtEntry & & qtEntry - > isDirectory ( ) ) {
const auto * qtDir = static_cast < const KArchiveDirectory * > ( qtEntry ) ;
const auto * trEntry = qtDir - > entry ( QStringLiteral ( " translations " ) ) ;
if ( trEntry & & trEntry - > isDirectory ( ) ) {
const auto trDir = static_cast < const KArchiveDirectory * > ( trEntry ) ;
for ( const auto & entryName : trDir - > entries ( ) ) {
if ( entryName . endsWith ( QLatin1String ( " .qm " ) ) ) {
if ( const auto * qmEntry = trDir - > entry ( entryName ) ) {
if ( qmEntry - > isFile ( ) ) {
2015-09-29 15:44:30 +02:00
pkgFileInfo . relevantFiles . emplace_back ( static_cast < const KArchiveFile * > ( qmEntry ) , trDir , RelevantFileType : : QtTranslation , root . first ) ;
2015-09-04 14:37:01 +02:00
}
}
}
}
}
}
2016-01-03 00:22:48 +01:00
2016-01-06 02:08:24 +01:00
// GTK themes
2016-01-03 00:22:48 +01:00
const auto * themesEntry = shareDir - > entry ( QStringLiteral ( " themes " ) ) ;
if ( themesEntry & & themesEntry - > isDirectory ( ) ) {
const auto * themesDir = static_cast < const KArchiveDirectory * > ( themesEntry ) ;
for ( const auto & themeName : themesDir - > entries ( ) ) {
const auto * themeEntry = themesDir - > entry ( themeName ) ;
if ( themeEntry & & themeEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : Theme , static_cast < const KArchiveDirectory * > ( themeEntry ) , QString ( ) , QString ( ) , root . first ) ;
}
}
}
2016-01-06 02:08:24 +01:00
// icon themes
2015-12-25 01:58:19 +01:00
const auto * iconsEntry = shareDir - > entry ( QStringLiteral ( " icons " ) ) ;
if ( iconsEntry & & iconsEntry - > isDirectory ( ) ) {
const auto * iconsDir = static_cast < const KArchiveDirectory * > ( iconsEntry ) ;
for ( const auto & themeName : iconsDir - > entries ( ) ) {
const auto * themeEntry = iconsDir - > entry ( themeName ) ;
if ( themeEntry & & themeEntry - > isDirectory ( ) ) {
2016-01-03 00:22:48 +01:00
addEntries ( pkgFileInfo , RelevantFileType : : IconTheme , static_cast < const KArchiveDirectory * > ( themeEntry ) , QString ( ) , QString ( ) , root . first ) ;
}
}
}
2016-01-06 02:08:24 +01:00
// glib2 stuff (need to compile glib2 schemes later)
2016-01-03 00:22:48 +01:00
const auto * glib2Entry = shareDir - > entry ( QStringLiteral ( " glib-2.0 " ) ) ;
if ( glib2Entry & & glib2Entry - > isDirectory ( ) ) {
const auto * glib2Dir = static_cast < const KArchiveDirectory * > ( glib2Entry ) ;
for ( const auto & glib2SubEntryName : glib2Dir - > entries ( ) ) {
const auto * glib2SubEntry = glib2Dir - > entry ( glib2SubEntryName ) ;
if ( glib2SubEntry - > isDirectory ( ) ) {
if ( glib2SubEntry - > name ( ) = = QLatin1String ( " schemas " ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : GLib2Schemas , static_cast < const KArchiveDirectory * > ( glib2SubEntry ) , QStringLiteral ( " glib-2.0 " ) , QString ( ) , root . first ) ;
} else {
addEntries ( pkgFileInfo , RelevantFileType : : GLib2Data , static_cast < const KArchiveDirectory * > ( glib2SubEntry ) , QStringLiteral ( " glib-2.0 " ) , QString ( ) , root . first ) ;
}
} else if ( glib2SubEntry - > isFile ( ) ) {
pkgFileInfo . relevantFiles . emplace_back ( static_cast < const KArchiveFile * > ( glib2SubEntry ) , glib2Dir , RelevantFileType : : GLib2Data , root . first , QStringLiteral ( " glib-2.0 " ) ) ;
2015-12-25 01:58:19 +01:00
}
}
}
2016-01-03 00:22:48 +01:00
2016-01-06 02:08:24 +01:00
// application specific stuff (Qt stuff is added separately, so skip Qt here)
2015-09-04 14:37:01 +02:00
if ( pkgFileInfo . name . compare ( QLatin1String ( " qt " ) ) ) {
const auto * appEntry = shareDir - > entry ( pkgFileInfo . name ) ;
if ( appEntry & & appEntry - > isDirectory ( ) ) {
2016-01-06 02:08:24 +01:00
addEntries ( pkgFileInfo , RelevantFileType : : SharedData , static_cast < const KArchiveDirectory * > ( appEntry ) , QString ( ) , QString ( ) , root . first ) ;
2015-08-19 02:13:28 +02:00
}
}
2016-01-03 00:22:48 +01:00
const auto * localeEntry = shareDir - > entry ( QStringLiteral ( " locale " ) ) ;
if ( localeEntry & & localeEntry - > isDirectory ( ) ) {
addEntries ( pkgFileInfo , RelevantFileType : : SharedData , static_cast < const KArchiveDirectory * > ( localeEntry ) , QString ( ) , QString ( ) , root . first ) ;
}
2015-08-19 02:13:28 +02:00
}
}
}
2016-01-03 00:22:48 +01:00
// icons from regular package
2015-09-04 14:37:01 +02:00
const auto * iconsEntry = pkgFileInfo . archive - > directory ( ) - > entry ( QStringLiteral ( " usr/share/icons " ) ) ;
if ( iconsEntry & & iconsEntry - > isDirectory ( ) ) {
const auto * iconsDir = static_cast < const KArchiveDirectory * > ( iconsEntry ) ;
for ( const auto & themeName : iconsDir - > entries ( ) ) {
const auto * themeEntry = iconsDir - > entry ( themeName ) ;
if ( themeEntry & & themeEntry - > isDirectory ( ) ) {
2015-09-21 22:16:19 +02:00
addEntries ( pkgFileInfo , RelevantFileType : : IconTheme , static_cast < const KArchiveDirectory * > ( themeEntry ) ) ;
2015-09-04 14:37:01 +02:00
}
}
}
2015-08-19 02:13:28 +02:00
} else {
2016-05-26 02:29:56 +02:00
if ( pkgFileInfo . archive - > device ( ) ) {
cerr < < shchar < < " Error: Unable to open the archive " < < pkgFileInfo . path . toLocal8Bit ( ) . data ( ) < < " : " < < pkgFileInfo . archive - > device ( ) - > errorString ( ) . toLocal8Bit ( ) . data ( ) < < endl ;
} else {
cerr < < shchar < < " Error: Unable to open the archive " < < pkgFileInfo . path . toLocal8Bit ( ) . data ( ) < < " : Device hasn't been created. " < < endl ;
}
2015-08-19 02:13:28 +02:00
pkgFileInfo . failure = true ;
}
}
2015-09-21 22:16:19 +02:00
void makeArchive ( const list < PkgFileInfo > & pkgFiles , const QByteArray & pkgList , const QByteArray & indexFile , RelevantFileArch arch , const QString & root , const string & targetDir , const string & targetName , const string & targetFormat )
{
2016-01-03 00:22:48 +01:00
// prepare archive
2015-09-21 22:16:19 +02:00
QString targetPath = qstr ( targetDir ) % QChar ( ' / ' ) % root % QChar ( ' - ' ) % qstr ( targetName ) % QChar ( ' . ' ) % qstr ( targetFormat ) ;
cerr < < shchar < < " Making archive \" " < < targetPath . toLocal8Bit ( ) . data ( ) < < " \" ... " < < endl ;
unique_ptr < KArchive > targetArchive ;
if ( targetFormat = = " 7z " ) {
targetArchive = make_unique < K7Zip > ( targetPath ) ;
} else if ( targetFormat = = " zip " ) {
targetArchive = make_unique < KZip > ( targetPath ) ;
} else if ( ConversionUtilities : : startsWith < string > ( targetFormat , " tar " ) ) {
targetArchive = make_unique < KTar > ( targetPath ) ;
} else {
throw runtime_error ( " Specified archive format \" " + targetFormat + " \" is unknown. " ) ;
}
2016-01-03 00:22:48 +01:00
// add files to archive
2015-09-21 22:16:19 +02:00
if ( targetArchive - > open ( QIODevice : : WriteOnly ) ) {
2016-01-03 00:22:48 +01:00
// -> compile glib2 schemas and add
vector < const RelevantFile * > glib2SchemaFiles ;
glib2SchemaFiles . reserve ( 16 ) ;
for ( const auto & pkgFile : pkgFiles ) {
for ( const RelevantFile & relevantFile : pkgFile . relevantFiles ) {
if ( relevantFile . arch = = RelevantFileArch : : Any | | relevantFile . arch = = arch ) {
switch ( relevantFile . fileType ) {
case RelevantFileType : : GLib2Schemas :
glib2SchemaFiles . push_back ( & relevantFile ) ;
break ;
default :
;
}
}
}
}
if ( ! glib2SchemaFiles . empty ( ) ) {
QTemporaryDir tempDir ;
if ( tempDir . isValid ( ) ) {
for ( const RelevantFile * schemaFile : glib2SchemaFiles ) {
QFile file ( tempDir . path ( ) % QChar ( ' / ' ) % schemaFile - > name ) ;
if ( ! file . open ( QFile : : WriteOnly ) | | ! file . write ( schemaFile - > data ) ) {
cerr < < shchar < < " Unable to create glib2 schema file \" " < < schemaFile - > name . toLocal8Bit ( ) . data ( ) < < " \" . " < < endl ;
}
}
QProcess compiler ;
compiler . setProcessChannelMode ( QProcess : : ForwardedChannels ) ;
compiler . start ( QStringLiteral ( " glib-compile-schemas " ) , QStringList ( ) < < tempDir . path ( ) ) ;
compiler . waitForFinished ( ) ;
QFile compiledSchemas ( tempDir . path ( ) + QStringLiteral ( " /gschemas.compiled " ) ) ;
if ( compiledSchemas . open ( QFile : : ReadOnly ) ) {
targetArchive - > writeFile ( root + QStringLiteral ( " /share/glib-2.0/schemas/gschemas.compiled " ) , compiledSchemas . readAll ( ) ) ;
} else {
cerr < < shchar < < " Unable to compile glib2 schemas: Compiled schemas (gschemas.compiled) not found. " < < endl ;
}
} else {
cerr < < shchar < < " Unable to compile glib2 schemas: Can't create temp dir. " < < endl ;
}
}
// -> add note
2015-12-08 00:25:44 +01:00
targetArchive - > writeFile ( root + QStringLiteral ( " /note.txt " ) , QByteArray ( " This archive has been created with Martchus' repository indexing tool. \n "
2016-01-06 02:08:24 +01:00
" List of included packages (name, version, license info and upstream URL): var/lib/repoindex/packages.list \n "
2015-12-08 00:25:44 +01:00
" More info: http://martchus.netai.net/page.php?name=programming " ) ) ;
2016-01-03 00:22:48 +01:00
// -> add package list
2015-09-21 22:16:19 +02:00
if ( ! pkgList . isEmpty ( ) ) {
2015-12-08 00:25:44 +01:00
targetArchive - > writeFile ( root + QStringLiteral ( " /var/lib/repoindex/packages.list " ) , pkgList ) ;
2015-09-21 22:16:19 +02:00
}
2016-01-03 00:22:48 +01:00
// -> set default icon theme
2015-09-21 22:16:19 +02:00
if ( ! indexFile . isEmpty ( ) ) {
2015-12-08 00:25:44 +01:00
targetArchive - > writeFile ( root + QStringLiteral ( " /share/icons/default/index.theme " ) , indexFile ) ;
2015-09-21 22:16:19 +02:00
}
2016-01-03 00:22:48 +01:00
// -> add relevant files from packages
2015-09-21 22:16:19 +02:00
for ( const auto & pkgFile : pkgFiles ) {
for ( const RelevantFile & relevantFile : pkgFile . relevantFiles ) {
if ( relevantFile . arch = = RelevantFileArch : : Any | | relevantFile . arch = = arch ) {
2015-09-27 19:29:45 +02:00
QString path ;
mode_t mode ;
2015-09-21 22:16:19 +02:00
switch ( relevantFile . fileType ) {
case RelevantFileType : : Binary :
2015-09-27 19:29:45 +02:00
path = root % QStringLiteral ( " /bin/ " ) % relevantFile . name ;
mode = 0100755 ;
2015-09-21 22:16:19 +02:00
break ;
2016-01-03 00:22:48 +01:00
case RelevantFileType : : Data :
path = root % QStringLiteral ( " / " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100644 ;
break ;
2015-09-21 22:16:19 +02:00
case RelevantFileType : : Translation :
2015-09-27 19:29:45 +02:00
path = root % QStringLiteral ( " /share/ " ) % pkgFile . name % QStringLiteral ( " /translations/ " ) % relevantFile . name ;
mode = 0100644 ;
2015-09-21 22:16:19 +02:00
break ;
case RelevantFileType : : QtTranslation :
2015-09-27 19:29:45 +02:00
path = root % QStringLiteral ( " /share/qt/translations/ " ) % relevantFile . name ;
mode = 0100644 ;
2015-09-21 22:16:19 +02:00
break ;
case RelevantFileType : : QtPlugin :
2015-09-27 19:29:45 +02:00
path = root % QStringLiteral ( " /bin/ " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100755 ;
2015-09-21 22:16:19 +02:00
break ;
2016-01-03 00:22:48 +01:00
case RelevantFileType : : Plugin :
path = root % QStringLiteral ( " /lib/ " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100755 ;
break ;
case RelevantFileType : : SharedData :
case RelevantFileType : : GLib2Data :
case RelevantFileType : : GLib2Schemas :
path = root % QStringLiteral ( " /share/ " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100644 ;
break ;
case RelevantFileType : : Theme :
path = root % QStringLiteral ( " /share/themes/ " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100644 ;
break ;
2015-09-21 22:16:19 +02:00
case RelevantFileType : : IconTheme :
2015-09-27 19:29:45 +02:00
path = root % QStringLiteral ( " /share/icons/ " ) % relevantFile . subDir % QChar ( ' / ' ) % relevantFile . name ;
mode = 0100644 ;
2015-09-21 22:16:19 +02:00
break ;
}
2016-01-06 02:08:24 +01:00
// write the file
// disable symlinks: there is no decent support for symlinks under Windows
2015-09-29 15:44:30 +02:00
//if(relevantFile.symlinkTarget.isEmpty()) {
2015-09-27 19:29:45 +02:00
targetArchive - > writeFile ( path , relevantFile . data , mode ) ;
2015-09-29 15:44:30 +02:00
//} else {
// targetArchive->writeSymLink(path, relevantFile.symlinkTarget, QString(), QString(), mode);
//}
2015-09-21 22:16:19 +02:00
}
}
}
} else if ( targetArchive - > device ( ) ) {
cerr < < shchar < < " Error: Unable to open target archive: " < < targetArchive - > device ( ) - > errorString ( ) . toLocal8Bit ( ) . data ( ) < < endl ;
} else {
cerr < < shchar < < " Error: Unable to open target archive. " < < endl ;
}
}
void MingwBundle : : createBundle ( const string & targetDir , const string & targetName , const string & targetFormat , const string & defaultIconTheme ) const
2015-08-19 02:13:28 +02:00
{
2015-09-05 17:25:05 +02:00
cerr < < shchar < < " Gathering relevant files ... " < < endl ;
2015-09-04 14:37:01 +02:00
// get package files
2015-08-19 02:13:28 +02:00
list < PkgFileInfo > pkgFiles ;
2016-04-25 22:30:11 +02:00
for ( const IncludedPackage & includedPkg : m_packages ) {
const Package * pkg = includedPkg . package ;
2015-08-19 02:13:28 +02:00
QString pkgFile ;
2015-12-13 21:12:44 +01:00
if ( ! pkg - > repository ( ) - > packagesDirectory ( ) . isEmpty ( ) ) {
pkgFile = pkg - > repository ( ) - > packagesDirectory ( ) % QChar ( ' / ' ) % pkg - > fileName ( ) ;
2015-08-19 02:13:28 +02:00
}
if ( pkgFile . isEmpty ( ) | | ! QFile : : exists ( pkgFile ) ) {
if ( ! m_manager . pacmanCacheDir ( ) . isEmpty ( ) ) {
2015-12-13 21:12:44 +01:00
pkgFile = m_manager . pacmanCacheDir ( ) % QChar ( ' / ' ) % pkg - > fileName ( ) ;
2015-08-19 02:13:28 +02:00
}
if ( pkgFile . isEmpty ( ) | | ! QFile : : exists ( pkgFile ) ) {
2015-12-13 21:12:44 +01:00
throw runtime_error ( " The package file " + string ( pkg - > fileName ( ) . toLocal8Bit ( ) . data ( ) ) + " can't be found. " ) ;
2015-08-19 02:13:28 +02:00
// TODO: download package from mirror
}
}
2016-01-06 02:08:24 +01:00
// strip "mingw-w64-"-prefix and vcs-suffix (if present)
QStringRef pkgName = pkg - > name ( ) . startsWith ( QLatin1String ( " mingw-w64- " ) ) ? pkg - > name ( ) . midRef ( 10 ) : QStringRef ( & pkg - > name ( ) ) ;
if ( pkgName . endsWith ( QLatin1String ( " -svn " ) ) | | pkgName . endsWith ( QLatin1String ( " -git " ) ) ) {
pkgName = pkgName . mid ( 0 , pkgName . length ( ) - 4 ) ;
} else if ( pkgName . endsWith ( QLatin1String ( " -hg " ) ) ) {
pkgName = pkgName . mid ( 0 , pkgName . length ( ) - 3 ) ;
}
2016-04-25 22:30:11 +02:00
pkgFiles . emplace_back ( pkgName . toString ( ) , pkgFile , includedPkg . dependencyOnly , m_qtPlugins ) ;
2015-08-19 02:13:28 +02:00
}
2016-05-26 02:29:56 +02:00
for ( const char * pkgFileRawStr : m_extraPackages ) {
QString pkgFile = QString : : fromLocal8Bit ( pkgFileRawStr ) ;
2015-09-21 22:16:19 +02:00
if ( QFile : : exists ( pkgFile ) ) {
2016-02-14 23:48:43 +01:00
const auto pkg = make_unique < AlpmPackage > ( pkgFile ) ; // do not catch the exception here
2016-04-25 22:30:11 +02:00
pkgFiles . emplace_back ( pkg - > name ( ) . startsWith ( QLatin1String ( " mingw-w64- " ) ) ? pkg - > name ( ) . mid ( 10 ) : pkg - > name ( ) , pkgFile , false , m_qtPlugins ) ;
2015-09-21 22:16:19 +02:00
} else {
2016-05-26 02:29:56 +02:00
throw runtime_error ( " The specified extra package \" " + string ( pkgFileRawStr ) + " \" can't be found. " ) ;
2015-09-21 22:16:19 +02:00
}
}
2015-09-04 14:37:01 +02:00
// get relevant files from packages
2015-08-19 02:13:28 +02:00
QtConcurrent : : blockingMap ( pkgFiles , getFiles ) ;
2015-09-04 14:37:01 +02:00
// check whether all packages could be opened
string failed ;
for ( const auto & pkgFile : pkgFiles ) {
if ( pkgFile . failure ) {
failed . push_back ( ' ' ) ;
failed . append ( pkgFile . path . toLocal8Bit ( ) . data ( ) ) ;
}
}
if ( ! failed . empty ( ) ) {
throw runtime_error ( " Unable to open the following package files: " + failed ) ;
}
// make a list with package info to be included in the target archive
QJsonArray pkgArray ;
2016-04-25 22:30:11 +02:00
for ( const IncludedPackage & pkg : m_packages ) {
pkgArray < < pkg . package - > simpleInfo ( ) ;
2015-09-04 14:37:01 +02:00
}
QJsonDocument pkgList ;
pkgList . setArray ( pkgArray ) ;
2015-12-08 00:25:44 +01:00
const QByteArray pkgListBytes = pkgList . toJson ( ) ;
2015-09-21 22:16:19 +02:00
QByteArray indexFileBytes ;
if ( ! defaultIconTheme . empty ( ) ) {
indexFileBytes . reserve ( 23 + defaultIconTheme . size ( ) ) ;
indexFileBytes . append ( " [Icon Theme] \n Inherits= " ) ;
indexFileBytes . append ( defaultIconTheme . data ( ) ) ;
indexFileBytes . append ( ' \n ' ) ;
2015-08-19 02:13:28 +02:00
}
2015-09-21 22:16:19 +02:00
// make target archive
auto run1 = QtConcurrent : : run ( bind ( makeArchive , ref ( pkgFiles ) , ref ( pkgListBytes ) , ref ( indexFileBytes ) , RelevantFileArch : : x86_64 , QStringLiteral ( " x86_64-w64-mingw32 " ) , ref ( targetDir ) , ref ( targetName ) , ref ( targetFormat ) ) ) ;
auto run2 = QtConcurrent : : run ( bind ( makeArchive , ref ( pkgFiles ) , ref ( pkgListBytes ) , ref ( indexFileBytes ) , RelevantFileArch : : i686 , QStringLiteral ( " i686-w64-mingw32 " ) , ref ( targetDir ) , ref ( targetName ) , ref ( targetFormat ) ) ) ;
run1 . waitForFinished ( ) ;
run2 . waitForFinished ( ) ;
2015-08-19 02:13:28 +02:00
}
} // namespace PackageManagement