Browse Source

Use architecture-specific suffixes to disambiguate colliding files

pull/108/head
Daniel Scharrer 7 years ago
parent
commit
2065fee5a8
  1. 1
      CHANGELOG
  2. 10
      doc/innoextract.1.in
  3. 18
      src/cli/extract.cpp

1
CHANGELOG

@ -10,6 +10,7 @@ innoextract 1.8 (WIP)
- Added support for using boost_{zlib,bzip2} when statically linking Boost
- Added support for automatically reading external setup.0 files
- Implemented parsing of GOG Galaxy architecture constraints
- The architecture-specific suffixes @32bit and @64bit are now used to disambiguate colliding files
- Fixed extracting files from slices larger than 2 GiB with 32-bit builds
- Fixed output path for files with absolute paths (canonicalization now strips all unsafe characters)
- Fixed output directory being created even when not extracting files

10
doc/innoextract.1.in

@ -94,10 +94,10 @@ Inno Setup installers can contain duplicate files with the same name. This optio
Extract only one of the colliding files. The choice is done similar to how Inno Setup overwrites files during installation. This is the default.
.TP
"\fBrename\fP"
Rename files that would be overwritten using the "\fBoverwrite\fP" action by appending a suffix comprised of the file's language, the component it belongs to and/or a number to make the filename unique. The language suffix (if applicable) is also appended to the \fIdefault\fP file that would have been extracted with the "\fBoverwrite\fP" action.
Rename files that would be overwritten using the "\fBoverwrite\fP" action by appending a suffix comprised of the file's language, it's architecture, the component it belongs to and/or a number to make the filename unique. The language suffix (if applicable) is also appended to the \fIdefault\fP file that would have been extracted with the "\fBoverwrite\fP" action.
.TP
"\fBrename-all\fP"
Rename all colliding files by appending a suffix comprised of the file's language, the component it belongs to and/or a number to make the filename unique. The complete suffix is appended to both files that would have been overwritten using the "\fBoverwrite\fP" action and to those that would have overwritten other files.
Rename all colliding files by appending a suffix comprised of the file's language, it's architecture, the component it belongs to and/or a number to make the filename unique. The complete suffix is appended to both files that would have been overwritten using the "\fBoverwrite\fP" action and to those that would have overwritten other files.
.TP
"\fBerror\fP"
Exit when a collision is detected.
@ -107,9 +107,11 @@ Exit when a collision is detected.
1. If the \fBcomponent\fP is not the same for all files in the collision set (all files with the same filename), "\fB#\fP" (without quotes) followed by the component id is appended to all files that are specific to a single component.
2. If the \fBlanguage\fP is not the same for all files in the collision set, "\fB@\fP" (without quotes) followed by the language id is appended to all files that are specific to a single component unless that language matches the default language specified by the \fB--default-language\fP. While the suffix is omitted for the default language, no numbered suffix is added in it's place unless needed to make the filename unique.
2. If the \fBlanguage\fP is not the same for all files in the collision set, "\fB@\fP" (without quotes) followed by the language id is appended to all files that are specific to a single language unless that language matches the default language specified by the \fB--default-language\fP. While the suffix is omitted for the default language, no numbered suffix is added in it's place unless needed to make the filename unique.
3. If no suffix was added by the previous steps, or if the filename is not yet unique, "\fB$\fP" (without quotes) followed by the lowest integer (starting at 0) to make the filename unique is appended.
3. If the \fBarchitecture\fP is not the same for all files in the collision set, "\fB@32bit\fP" or "\fB@64bit\fP" (without quotes) is appended to all files that are specific to a single architecture.
4. If no suffix was added by the previous steps, or if the filename is not yet unique, "\fB$\fP" (without quotes) followed by the lowest integer (starting at 0) to make the filename unique is appended.
With the "\fBrename\fP" action, steps 1 and 3 are only applied to files that would have been overwritten by the "\fBoverwrite\fP" action while "\fBrename-all\fP" applies them to all files in the collision set.
.TP

18
src/cli/extract.cpp

@ -482,12 +482,14 @@ bool insert_dirs(DirectoriesMap & processed_directories, const path_filter & inc
}
bool rename_collision(const extract_options & o, FilesMap & processed_files, const std::string & path,
const processed_file & other, bool common_component, bool common_language, bool first) {
const processed_file & other, bool common_component, bool common_language,
bool common_arch, bool first) {
const setup::file_entry & file = other.entry();
bool require_number_suffix = !first || (o.collisions == RenameAllCollisions);
std::ostringstream oss;
const setup::file_entry::flags arch_flags = setup::file_entry::Bits32 | setup::file_entry::Bits64;
if(!common_component && !file.components.empty()) {
if(setup::is_simple_expression(file.components)) {
@ -503,6 +505,13 @@ bool rename_collision(const extract_options & o, FilesMap & processed_files, con
}
}
}
if(!common_arch && (file.options & arch_flags) == setup::file_entry::Bits32) {
require_number_suffix = false;
oss << "@32bit";
} else if(!common_arch && (file.options & arch_flags) == setup::file_entry::Bits64) {
require_number_suffix = false;
oss << "@64bit";
}
size_t i = 0;
std::string suffix = oss.str();
@ -536,23 +545,26 @@ void rename_collisions(const extract_options & o, FilesMap & processed_files,
const processed_file & base = processed_files.find(path)->second;
const setup::file_entry & file = base.entry();
const setup::file_entry::flags arch_flags = setup::file_entry::Bits32 | setup::file_entry::Bits64;
bool common_component = true;
bool common_language = true;
bool common_arch = true;
BOOST_FOREACH(const processed_file & other, collision.second) {
common_component = common_component && other.entry().components == file.components;
common_language = common_language && other.entry().languages == file.languages;
common_arch = common_arch && (other.entry().options & arch_flags) == (file.options & arch_flags);
}
bool ignore_component = common_component || o.collisions != RenameAllCollisions;
if(rename_collision(o, processed_files, path, base,
ignore_component, common_language, true)) {
ignore_component, common_language, common_arch, true)) {
processed_files.erase(path);
}
BOOST_FOREACH(const processed_file & other, collision.second) {
rename_collision(o, processed_files, path, other,
common_component, common_language, false);
common_component, common_language, common_arch, false);
}
}

Loading…
Cancel
Save