[msitools: 1/2] Support DefaultVersion and CompanionFile in File element




commit d282ca012ac4bd18d859d69d9de882cc84abc2a2
Author: Ygor Mutti <ygormutti gmail com>
Date:   Fri Aug 13 21:44:30 2021 -0300

    Support DefaultVersion and CompanionFile in File element

 tools/wixl/builder.vala | 38 +++++++++++++++++++++++++++++++++++++-
 tools/wixl/msi.vala     | 13 +++++++------
 tools/wixl/wix.vala     |  2 ++
 3 files changed, 46 insertions(+), 7 deletions(-)
---
diff --git a/tools/wixl/builder.vala b/tools/wixl/builder.vala
index 9e24905..064d377 100644
--- a/tools/wixl/builder.vala
+++ b/tools/wixl/builder.vala
@@ -203,6 +203,10 @@ namespace Wixl {
         private void hash_files () throws GLib.Error {
             foreach (var rec in db.table_file.records) {
                 var f = rec.get_data<WixFile> ("wixfile");
+                if (f.CompanionFile != null || f.DefaultVersion != null)
+                    // versioned/companion files don't need rows in hash table
+                    continue;
+                
                 var component = f.parent as WixComponent;
                 if (component.in_feature.length () == 0)
                     continue;
@@ -211,6 +215,36 @@ namespace Wixl {
             }
         }
 
+        /*
+         * CompanionFile attribute makes a file a companion child of another file, so referenced
+         * file must exist and the companion child must not be the key path of its component
+         * 
+         * See: https://docs.microsoft.com/en-us/windows/win32/msi/companion-files
+         */
+        private void validate_companion_files () throws GLib.Error {
+            var companionByFile = new HashTable<string, string?>(str_hash, str_equal);
+
+            foreach (var rec in db.table_file.records) {
+                var f = rec.get_data<WixFile> ("wixfile");
+                companionByFile.insert (f.Id, f.CompanionFile);
+                if (f.CompanionFile == null)
+                    continue;
+
+                var component = f.parent as WixComponent;
+                if (component.key != f)
+                    continue;
+
+                throw new Wixl.Error.FAILED ("companion file %s is key of its component".printf (f.Id));
+            }
+            
+            foreach (var companion in companionByFile.get_values ()) {
+                if (companion == null || companionByFile.contains (companion))
+                    continue;
+
+                throw new Wixl.Error.FAILED ("file %s referenced by CompanionFile does not exist".printf 
(companion));
+            }
+        }
+
         private void build_cabinet () throws GLib.Error {
             var sequence = 0;
 
@@ -276,6 +310,7 @@ namespace Wixl {
             shortcut_target ();
             sequence_actions ();
             hash_files ();
+            validate_companion_files ();
             build_cabinet ();
 
             return db;
@@ -689,8 +724,9 @@ namespace Wixl {
             FileInfo info;
             file.file = find_file (source, out info);
             var attr = FileAttribute.VITAL;
+            var version = file.CompanionFile ?? file.DefaultVersion;
 
-            var rec = db.table_file.add (file.Id, comp.Id, name, (int)info.get_size (), attr);
+            var rec = db.table_file.add (file.Id, comp.Id, name, (int)info.get_size (), attr, version);
             rec.set_data<WixFile> ("wixfile", file);
 
             visit_key_element (file);
diff --git a/tools/wixl/msi.vala b/tools/wixl/msi.vala
index 0778481..c23739f 100644
--- a/tools/wixl/msi.vala
+++ b/tools/wixl/msi.vala
@@ -283,18 +283,19 @@ namespace Wixl {
         static construct {
             name = "File";
             sql_create = "CREATE TABLE `File` (`File` CHAR(72) NOT NULL, `Component_` CHAR(72) NOT NULL, 
`FileName` CHAR(255) NOT NULL LOCALIZABLE, `FileSize` LONG NOT NULL, `Version` CHAR(72), `Language` CHAR(20), 
`Attributes` INT, `Sequence` LONG NOT NULL PRIMARY KEY `File`)";
-            sql_insert = "INSERT INTO `File` (`File`, `Component_`, `FileName`, `FileSize`, `Attributes`, 
`Sequence`) VALUES (?, ?, ?, ?, ?, ?)";
+            sql_insert = "INSERT INTO `File` (`File`, `Component_`, `FileName`, `FileSize`, `Version`, 
`Attributes`, `Sequence`) VALUES (?, ?, ?, ?, ?, ?, ?)";
         }
 
-        public Libmsi.Record add (string File, string Component, string FileName, int FileSize, int 
Attributes, int Sequence = 1) throws GLib.Error {
-            var rec = new Libmsi.Record (6);
+        public Libmsi.Record add (string File, string Component, string FileName, int FileSize, int 
Attributes, string? Version = null, int Sequence = 1) throws GLib.Error {
+            var rec = new Libmsi.Record (7);
 
             if (!rec.set_string (1, File) ||
                 !rec.set_string (2, Component) ||
                 !rec.set_string (3, FileName) ||
                 !rec.set_int (4, FileSize) ||
-                !rec.set_int (5, Attributes) ||
-                !rec.set_int (6, Sequence))
+                (Version != null && !rec.set_string (5, Version)) ||
+                !rec.set_int (6, Attributes) ||
+                !rec.set_int (7, Sequence))
                 throw new Wixl.Error.FAILED ("failed to add record");
 
             records.append (rec);
@@ -303,7 +304,7 @@ namespace Wixl {
         }
 
         public static bool set_sequence (Libmsi.Record rec, int Sequence) {
-            return rec.set_int (6, Sequence);
+            return rec.set_int (7, Sequence);
         }
     }
 
diff --git a/tools/wixl/wix.vala b/tools/wixl/wix.vala
index 396c93a..41a7963 100644
--- a/tools/wixl/wix.vala
+++ b/tools/wixl/wix.vala
@@ -418,6 +418,8 @@ namespace Wixl {
         public string DiskId { get; set; }
         public string Source { get; set; }
         public string Name { get; set; }
+        public string DefaultVersion { get; set; }
+        public string CompanionFile { get; set; }
 
         public File file;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]