diff options
-rw-r--r-- | src/builder.vala | 41 | ||||
-rw-r--r-- | src/msi.vala | 48 | ||||
-rw-r--r-- | src/util.vala | 8 | ||||
-rw-r--r-- | src/wix.vala | 75 |
4 files changed, 168 insertions, 4 deletions
diff --git a/src/builder.vala b/src/builder.vala index 699be29..a7a5cf0 100644 --- a/src/builder.vala +++ b/src/builder.vala @@ -41,6 +41,8 @@ namespace Wixl { add ("CostFinalize", 1000); add ("InstallValidate", 1400); add ("InstallInitialize", 1500); + if (db.table_shortcut.records.length () > 0) + add ("CreateShortcuts", 4500); add ("PublishFeatures", 6300); add ("PublishProduct", 6400); add ("InstallFinalize", 6600); @@ -60,10 +62,14 @@ namespace Wixl { add ("RemoveRegistryValues", 2600); add ("WriteRegistryValues", 2600); } + if (db.table_shortcut.records.length () > 0) + add ("RemoveShortcuts", 3200); if (db.table_remove_file.records.length () > 0) add ("RemoveFiles", 3500); if (db.table_file.records.length () > 0) add ("InstallFiles", 4000); + if (db.table_shortcut.records.length () > 0) + add ("CreateShortcuts", 4500); add ("RegisterUser", 6000); add ("RegisterProduct", 6100); add ("PublishFeatures", 6300); @@ -108,10 +114,21 @@ namespace Wixl { } } + public void shortcut_target () throws GLib.Error { + var shortcuts = root.get_elements<WixShortcut> (); + + foreach (var sc in shortcuts) { + var component = sc.get_component (); + var feature = component.in_feature.first ().data; + MsiTableShortcut.set_target (sc.record, feature.Id); + } + } + public MsiDatabase build () throws GLib.Error { db = new MsiDatabase (); root.accept (this); + shortcut_target (); sequence_actions (); build_cabinet (); @@ -204,8 +221,11 @@ namespace Wixl { public override void visit_component_ref (WixComponentRef ref) throws GLib.Error { if (ref.parent is WixFeature) { - var parent = ref.parent as WixFeature; - db.table_feature_components.add (parent.Id, @ref.Id); + var feature = ref.parent as WixFeature; + + var component = root.find_element (typeof (WixComponent), @ref.Id) as WixComponent; + component.in_feature.append (feature); + db.table_feature_components.add (feature.Id, @ref.Id); } else warning ("unhandled parent type %s", @ref.parent.name); } @@ -299,6 +319,23 @@ namespace Wixl { visit_key_element (file); } + + public override void visit_shortcut (WixShortcut shortcut) throws GLib.Error { + if (!parse_yesno (shortcut.Advertise)) + throw new Wixl.Error.FIXME ("unimplemented"); + + var component = shortcut.get_component (); + var rec = db.table_shortcut.add (shortcut.Id, shortcut.Directory, shortcut.Name, component.Id); + shortcut.record = rec; + + if (shortcut.Icon != null) + MsiTableShortcut.set_icon (rec, shortcut.Icon, int.parse (shortcut.IconIndex)); + if (shortcut.WorkingDirectory != null) + MsiTableShortcut.set_working_dir (rec, shortcut.WorkingDirectory); + } + + public override void visit_create_folder (WixCreateFolder folder) throws GLib.Error { + } } } // Wixl diff --git a/src/msi.vala b/src/msi.vala index 027f44f..a85eecd 100644 --- a/src/msi.vala +++ b/src/msi.vala @@ -362,6 +362,51 @@ namespace Wixl { } } + class MsiTableShortcut: MsiTable { + construct { + name = "Shortcut"; + } + + public Libmsi.Record add (string Shortcut, string Directory, string Name, string Component) throws GLib.Error { + var rec = new Libmsi.Record (8); + + if (!rec.set_string (1, Shortcut) || + !rec.set_string (2, Directory) || + !rec.set_string (3, Name) || + !rec.set_string (4, Component)) + throw new Wixl.Error.FAILED ("failed to add record"); + + records.append (rec); + + return rec; + } + + public static void set_target (Libmsi.Record rec, string Target) throws GLib.Error { + if (!rec.set_string (5, Target)) + throw new Wixl.Error.FAILED ("failed to set record"); + } + + public static void set_icon (Libmsi.Record rec, string Icon, int IconIndex) throws GLib.Error { + if (!rec.set_string (6, Icon) || + !rec.set_int (7, IconIndex)) + throw new Wixl.Error.FAILED ("failed to set record"); + } + + public static void set_working_dir (Libmsi.Record rec, string WkDir) throws GLib.Error { + if (!rec.set_string (8, WkDir)) + throw new Wixl.Error.FAILED ("failed to set record"); + } + + public override void create (Libmsi.Database db) throws GLib.Error { + var query = new Libmsi.Query (db, "CREATE TABLE `Shortcut` (`Shortcut` CHAR(72) NOT NULL, `Directory_` CHAR(72) NOT NULL, `Name` CHAR(128) NOT NULL LOCALIZABLE, `Component_` CHAR(72) NOT NULL, `Target` CHAR(72) NOT NULL, `Arguments` CHAR(255), `Description` CHAR(255) LOCALIZABLE, `Hotkey` INT, `Icon_` CHAR(72), `IconIndex` INT, `ShowCmd` INT, `WkDir` CHAR(72), `DisplayResourceDLL` CHAR(255), `DisplayResourceId` INT, `DescriptionResourceDLL` CHAR(255), `DescriptionResourceId` INT PRIMARY KEY `Shortcut`)"); + query.execute (null); + + query = new Libmsi.Query (db, "INSERT INTO `Shortcut` (`Shortcut`, `Directory_`, `Name`, `Component_`, `Target`, `Icon_`, `IconIndex`, `WkDir`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + foreach (var r in records) + query.execute (r); + } + } + class MsiTableRemoveFile: MsiTable { construct { name = "RemoveFile"; @@ -513,6 +558,7 @@ namespace Wixl { public MsiTableInstallExecuteSequence table_install_execute_sequence; public MsiTableInstallUISequence table_install_ui_sequence; public MsiTableStreams table_streams; + public MsiTableShortcut table_shortcut; HashTable<string, MsiTable> tables; @@ -551,6 +597,7 @@ namespace Wixl { table_install_execute_sequence = new MsiTableInstallExecuteSequence (); table_install_ui_sequence = new MsiTableInstallUISequence (); table_streams = new MsiTableStreams (); + table_shortcut = new MsiTableShortcut (); foreach (var t in new MsiTable[] { table_admin_execute_sequence, @@ -569,6 +616,7 @@ namespace Wixl { table_registry, table_file, table_streams, + table_shortcut, new MsiTableError (), new MsiTableValidation () }) { diff --git a/src/util.vala b/src/util.vala index 00ae957..a5514a3 100644 --- a/src/util.vala +++ b/src/util.vala @@ -1,7 +1,8 @@ namespace Wixl { public errordomain Error { - FAILED + FAILED, + FIXME, } namespace UUID { @@ -85,7 +86,10 @@ namespace Wixl { return str; } - bool parse_yesno (string str) { + bool parse_yesno (string? str) { + if (str == null) + return false; + return (str[0] == 'Y' || str[0] == 'y'); } } // Wixl diff --git a/src/wix.vala b/src/wix.vala index 33291fd..2b25f18 100644 --- a/src/wix.vala +++ b/src/wix.vala @@ -14,6 +14,7 @@ namespace Wixl { public abstract void visit_registry_value (WixRegistryValue reg) throws GLib.Error; public abstract void visit_file (WixFile reg) throws GLib.Error; public abstract void visit_shortcut (WixShortcut shortcut) throws GLib.Error; + public abstract void visit_create_folder (WixCreateFolder folder) throws GLib.Error; } public abstract class WixElement: Object { @@ -44,6 +45,37 @@ namespace Wixl { children.append (e); } + private G[] add_elements<G> (owned G[] a) { + // jeez, vala, took me a while to workaround generics & array issues.. + var array = a; + var type = typeof (G); + + if (this.get_type () == type) + array += this; + + foreach (var c in children) + array = c.add_elements<G> (array); + + return array; + } + + public G[] get_elements<G> () { + return add_elements<G> ({}); + } + + public WixElement? find_element (Type type, string Id) { + if (this.Id == Id && this.get_type () == type) + return this; + + foreach (var c in children) { + var e = c.find_element (type, Id); + if (e != null) + return e; + } + + return null; + } + public virtual void load (Xml.Node *node) throws Wixl.Error { if (node->name != name) throw new Error.FAILED ("%s: invalid node %s".printf (name, node->name)); @@ -152,6 +184,18 @@ namespace Wixl { } } + public class WixCreateFolder: WixElement { + static construct { + name = "CreateFolder"; + } + + public string Directory { get; set; } + + public override void accept (WixElementVisitor visitor) throws GLib.Error { + visitor.visit_create_folder (this); + } + } + public class WixIcon: WixElement { static construct { name = "Icon"; @@ -164,6 +208,32 @@ namespace Wixl { } } + public class WixShortcut: WixElement { + static construct { + name = "Shortcut"; + } + + public string Directory { get; set; } + public string Name { get; set; } + public string IconIndex { get; set; } + public string WorkingDirectory { get; set; } + public string Icon { get; set; } + public string Advertise { get; set; } + + public Libmsi.Record record; + + public WixComponent? get_component () { + if (parent is WixFile || parent is WixCreateFolder) + return parent.parent as WixComponent; + else + return parent as WixComponent; + } + + public override void accept (WixElementVisitor visitor) throws GLib.Error { + visitor.visit_shortcut (this); + } + } + public abstract class WixKeyElement: WixElement { public string KeyPath { get; set; } } @@ -171,6 +241,8 @@ namespace Wixl { public class WixFile: WixKeyElement { static construct { name = "File"; + + add_child_types (child_types, { typeof (WixShortcut) }); } public string DiskId { get; set; } @@ -180,6 +252,7 @@ namespace Wixl { public Libmsi.Record record; public override void accept (WixElementVisitor visitor) throws GLib.Error { + base.accept (visitor); visitor.visit_file (this); } } @@ -297,6 +370,8 @@ namespace Wixl { public string Guid { get; set; } public WixKeyElement? key; + public List<WixFeature> in_feature; + public override void accept (WixElementVisitor visitor) throws GLib.Error { base.accept (visitor); visitor.visit_component (this); |