How can I exclude SVN files from harvesting with heat (WiX)?

jbierling picture jbierling · Jan 5, 2012 · Viewed 7.7k times · Source

I hate to practically duplicate existing questions, but the supplied answers haven't worked:

Here's what my .wxs looks like:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="SDKCONTENTDIR">
<Directory Id="dirE2EC21E8B765C611E918FB22F30721D1" Name=".svn" />
<Directory Id="dir7DC42F44E7FE9E20277B180A353D0263" Name="bin" />
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="sdkContent">
<Component Id="cmp5E86312F0CA2C53B8173AECD6A428747" Directory="dirE2EC21E8B765C611E918FB22F30721D1" Guid="{E87F312D-9DA2-4A68-B6C5-BCE2FF90720C}">
<File Id="filB766A28A7577EB4311FD03CD707BC211" KeyPath="yes" Source="$(var.publishContentDir)\.svn\all-wcprops" />
</Component>
<Component Id="cmp6EF52B3E331F226299060D45F533DC07" Directory="dirE2EC21E8B765C611E918FB22F30721D1" Guid="{5EA6AB2D-20C3-4B07-8E0A-7C28135BE922}">
<File Id="fil83205196F05211A66F9D25A7A5496FBA" KeyPath="yes" Source="$(var.publishContentDir)\.svn\entries" />
</Component>

...

I'm using this .xsl code to exclude:

<xsl:key name="svn-search" match="wix:Component[ancestor::wix:Directory/@Name = '.svn']" use="@Id" />
<xsl:template match="wix:Directory[@Name='.svn']" />
<xsl:template match="wix:Component[key('svn-search', @Id)]" />

But I'm getting many "Error 48 Unresolved reference to symbol" errors as its not removing all child elements.

Ideas?

Answer

Keith Mason picture Keith Mason · Feb 6, 2012

I had the same question, and found your answer. However, I was unhappy with the need to specify the subdirectories of the .svn folder by name. This can break if the .svn directory changes structure in the future, or if I had a directory named tmp on purpose...

When I ran your xsl against my xml, I additionally noticed that there were some directory fragments scattered around. Being OCD and wanting to clean that up, I noticed that heat.exe has an option to "suppress fragments". The actual effect was to make Directory tags actually nest under each other, which makes writing an xsl file much easier.

After deleting .svn directories from the nested tag structure, I still had a problem with ComponentRefs pointing to Component IDs that had been removed along with their containing directories. Being an xsl noob myself, I had to do a little digging, but found that I could use "descendant::" in the use attribute of xsl:key.

In short, here is my solution. Note, I have not actually yet tried to build the MSI with it just yet; that will come in a day or two. But even if it isn't perfect, at least this might help someone else with the same problem...

Use: heat.exe dir source -t excludesvn.xsl -sfrag -o files.wxs

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
  <!-- Copy all attributes and elements to the output. -->
  <xsl:template match="@*|*">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates select="*" />
    </xsl:copy>
  </xsl:template>
  <xsl:output method="xml" indent="yes" />

  <!-- Search directories for the components that will be removed. -->
  <xsl:key name="svn-search" match="wix:Directory[@Name = '.svn']" use="descendant::wix:Component/@Id" />

  <!-- Remove directories. -->
  <xsl:template match="wix:Directory[@Name='.svn']" />

  <!-- Remove componentsrefs referencing components in those directories. -->
  <xsl:template match="wix:ComponentRef[key('svn-search', @Id)]" />
</xsl:stylesheet>