<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[blog.blacksun.cx]]></title><description><![CDATA[Blogging about IT, Tech and things that I'm interested in.]]></description><link>https://blog.blacksun.cx/</link><image><url>https://blog.blacksun.cx/favicon.png</url><title>blog.blacksun.cx</title><link>https://blog.blacksun.cx/</link></image><generator>Ghost 5.42</generator><lastBuildDate>Wed, 25 Mar 2026 15:34:48 GMT</lastBuildDate><atom:link href="https://blog.blacksun.cx/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Ignore a single file in a GIT repository that is checked in but changes a lot (and you don't want to keep those changes)]]></title><description><![CDATA[<h2 id="purpose">Purpose</h2><p>You have a repository in GIT. For some reason, your project produces artifacts that change all the time, for instance </p><ul><li>A filename is injected into them (Stupid Entity Framework EDMX changes) and this filename changes depending on who runs it</li><li>A filename that continually gets injected with different line</li></ul>]]></description><link>https://blog.blacksun.cx/git-ignore-a-single-file-that-is-checked-in-but-changes-a-lot-and-you-dont-want-to-keep-those-change/</link><guid isPermaLink="false">623280b6b12afe0524163a2e</guid><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Sun, 20 Mar 2022 13:30:00 GMT</pubDate><content:encoded><![CDATA[<h2 id="purpose">Purpose</h2><p>You have a repository in GIT. For some reason, your project produces artifacts that change all the time, for instance </p><ul><li>A filename is injected into them (Stupid Entity Framework EDMX changes) and this filename changes depending on who runs it</li><li>A filename that continually gets injected with different line endings</li><li>Any other reason</li></ul><p>If you would just like to ignore it then you can try the following</p><figure class="kg-card kg-code-card"><pre><code>git update-index --skip-worktree .\YourFileToIgnore.txt</code></pre><figcaption>Command line to ignore a file</figcaption></figure><p>And then if you change your mind use</p><figure class="kg-card kg-code-card"><pre><code>git update-index --no-skip-worktree .\YourFileToIgnore.txt</code></pre><figcaption>Command line to stop ignoring a file</figcaption></figure><p>to reverse it.</p>]]></content:encoded></item><item><title><![CDATA[Adapting existing code for Intravenous]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;m using <a href="http://www.royjacobs.org/intravenous/?ref=blog.blacksun.cx">Intravenous</a> more and more to implement the IOC pattern using Node at work. One of the issues with it however is that everything that you use with it either has to be:</p>
<ol>
<li>An ES5 &quot;class&quot; with an <code>$inject</code> property (an array that allows Intravenous</li></ol>]]></description><link>https://blog.blacksun.cx/how-to-adapt-your-code-to-use-intravenous/</link><guid isPermaLink="false">602820ff1e53ae3c62558871</guid><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Sat, 26 Nov 2016 10:13:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;m using <a href="http://www.royjacobs.org/intravenous/?ref=blog.blacksun.cx">Intravenous</a> more and more to implement the IOC pattern using Node at work. One of the issues with it however is that everything that you use with it either has to be:</p>
<ol>
<li>An ES5 &quot;class&quot; with an <code>$inject</code> property (an array that allows Intravenous to reflect on your constructor arguments for the constructor. By the way, Intravenous doesn&apos;t do ES6. Have a look at <a href="https://www.npmjs.com/package/mainliner?ref=blog.blacksun.cx">mainliner</a> it you want to do native ES6.</li>
<li>A plain old JavaScript object.</li>
</ol>
<p>In order to support the normal IOC things like lifetime and constructor injection you need your code to be a ES5 class as per option 1. 9 times out of 10 this is what you so therefore it forces you to write your code exactly like it expects which isn&apos;t really the way things work in the real world. I mean, who on earth is going to publish a module exporting a class with a <code>$inject</code> property and even if they did, you would probably just need to over write it with different identifiers anyway unless you had a very, very controlled environment.</p>
<p>So, my implementation uses a pattern that looks a bit like this:</p>
<pre><code class="language-language-javascript">import Assert from &quot;assert&quot;;
import Bacon from &quot;bacon&quot;;
    
export default class BaconWrapper {
      
  constructor(logger) {

    Assert(logger, &quot;logger is required&quot;);
    this.bacon_ = new Bacon(logger);
  }

  eatBacon(...args) {

    return this.bacon_.eatBacon(...args);
  }
}

BaconWrapper.$inject = [&quot;logger&quot;];
</code></pre>
<p>and after registering BaconWrapper in my container, it works a treat. The problem with this approach of course is that it is:</p>
<ol>
<li>Incredibly manual and tedious.</li>
<li>Every time you change an interface the a wrapper needs to change too!</li>
</ol>
<p>Also, all of this manual code gives you a tonne of new tests you have to write. Yuck.</p>
<p>I figured, especially as this is JavaScript, there must be a better way - and here it is.</p>
<pre><code>function adaptToInjectable(ctrArgNames, ctrArgInjectNames, objectFactory, proxiedKeys) {

  const f = function () {

    // Assert that constructor is new&apos;ed
    Assert(this &amp;&amp; this.constructor === f, &quot;constructor must be called with new&quot;);

    // Assert arguments
    for (let x = 0; x &lt; ctrArgNames.length; x += 1) {
      Assert(arguments[x.toString()], `${ctrArgNames[x]} is required`);
    }

    // Constructor wrapper object
    const args = Array.from(arguments);
    this.wrappedObject_ = objectFactory.apply(null, args);

    // Proxy each key in proxiedKeys
    for (const key of proxiedKeys) {
      const actor = this.wrappedObject_[key];

      // Something is pertty wrong if we are proxying a key with an undefined value
      Assert(typeof actor !== &quot;undefined&quot;, `proxiedKey ${key} does not exist`);

      // If the property is a function then bind it back to the wrappedObject,
      // otherwise just set one to the other
      if (typeof actor === &quot;function&quot;) {
        this[key] = actor.bind(this.wrappedObject_);
      } else {
        this[key] = actor;
      }
    }
  }

  // Add $inject
  f.$inject = ctrArgInjectNames;

  return f;
}
</code></pre>
<p>So, as you can see this adaptor allows you to wrap a piece of arbitrary code (it doesn&apos;t even need to be a class) and with just a small piece of code get it up to a state that is easily injectable into a container.</p>
<p>So, given the following service</p>
<pre><code>class CakeService {

	constructor(logger, cakeType) {

    Assert(logger);
    Assert(cakeType);
    this.logger_ = logger;
    this.cakeType_ = cakeType;
  }

  eat() {

    this.logger_.info(`Nom, nom, nom - I love ${this.cakeType_} cake`);
  }

  get cakeType() {

    return this.cakeType_
  }
}
</code></pre>
<p>We can adapt this using the following code</p>
<pre><code>const sut = adaptToInjectable(
  [&quot;logger&quot;],
  [&quot;myLogger&quot;],
  (logger) =&gt; new CakeService(logger, &quot;chocolate&quot;),
  [&quot;eat&quot;, &quot;cakeType&quot;]
);
</code></pre>
<p>And all of the following assertions should work on the class</p>
<pre><code>  Assert.throws(() =&gt; sut(), /^AssertionError: constructor must be called with new$/,
    &quot;Should assert that ctx called with new&quot;);
  Assert.throws(() =&gt; new sut(), /^AssertionError: logger is required$/, &quot;Logger is a required argument&quot;);
  Assert.deepEqual(sut.$inject, [&quot;myLogger&quot;], &quot;$inject is not set to required arguments&quot;);

  const mockLogger = {
    &quot;info&quot;: Sinon.stub()
  };
  const actual = new sut(mockLogger);

  Assert(actual.cakeType, &quot;.cakeType should be defined&quot;);
  Assert.strictEqual(actual.cakeType, &quot;chocolate&quot;);

  Assert(actual.eat, &quot;.eat should be defined&quot;);
  Assert(typeof actual.eat === &quot;function&quot;, &quot;.eat should be a function&quot;);
  Assert.doesNotThrow(() =&gt; actual.eat(), &quot;.eat should not throw&quot;);
  Sinon.assert.calledWith(mockLogger.info);
  Sinon.assert.calledWithExactly(mockLogger.info, &quot;Nom, nom, nom - I love chocolate cake&quot;);
</code></pre>
<p>I hope that this helps.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[How to stop Kodi from importing Mac resource forks from SMB shares.]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I am using <a href="http://kodi.tv/?ref=blog.blacksun.cx">Kodi</a> (previously XMBC) on one of my <a href="http://www.raspberrypi.org/?ref=blog.blacksun.cx">Raspberry Pi</a> as a small media centre. This is serving videos from my old SAN where I store and share my backed up DVD&apos;s via SMB. This works great except for one small problem. My Mac. Normally Mac&</p>]]></description><link>https://blog.blacksun.cx/kodi-extra-setup/</link><guid isPermaLink="false">602820ff1e53ae3c62558870</guid><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Sun, 22 Feb 2015 01:07:48 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I am using <a href="http://kodi.tv/?ref=blog.blacksun.cx">Kodi</a> (previously XMBC) on one of my <a href="http://www.raspberrypi.org/?ref=blog.blacksun.cx">Raspberry Pi</a> as a small media centre. This is serving videos from my old SAN where I store and share my backed up DVD&apos;s via SMB. This works great except for one small problem. My Mac. Normally Mac&apos;s store a <a href="http://en.wikipedia.org/wiki/Resource_fork?ref=blog.blacksun.cx">resource fork</a> in another section of a file on a Mac filesystem (MFS, HFS and HFS Plus). It uses this to store metadata about the file. As SMB drives don&apos;t support resource forks this is performed using a file that looks like <code>._filename</code> where <code>filename</code> is the name of the original file. By default Kodi picks this file up at scan time and thinks that it is a video file so it adds the TV-Show or Movie twice with only the one file working. This is annoying as you have to manually delete the wrong entry.</p>
<p>To get around this you can use the <a href="http://kodi.wiki/view/Advancedsettings.xml?ref=blog.blacksun.cx"><code>advancedsettings.xml</code></a> file to stop Kodi from picking up these files when it does a scan.</p>
<p>Create or add the <code>advancedsettings.xml</code> with the following:</p>
<pre><code class="language-language-xml">&lt;advancedsettings&gt;
	&lt;video&gt;
		&lt;excludefromscan&gt; &lt;!-- Regular expressions that if evaluated to true won&apos;t be added to library. --&gt;
			&lt;regexp&gt;[-\._ ](sample|trailer)[-\._ ]&lt;/regexp&gt;
			&lt;regexp&gt;[-\._ ](sample|trailer)[-\._ ]&lt;/regexp&gt;
			&lt;regexp&gt;\/\._&lt;/regexp&gt;
		&lt;/excludefromscan&gt;
		&lt;excludetvshowsfromscan&gt;
			&lt;regexp&gt;\/\._&lt;/regexp&gt;
		&lt;/excludetvshowsfromscan&gt;
		&lt;excludefromlisting&gt;
            &lt;!-- Regular expressions that if evaluated to true won&apos;t be displayed in Files View --&gt;
			&lt;regexp&gt;[-\._ ](sample|trailer)[-\._ ]&lt;/regexp&gt;
			&lt;!-- &lt;regexp&gt;/\._&lt;/regexp&gt; --&gt;
		&lt;/excludefromlisting&gt;
	&lt;/video&gt;
&lt;/advancedsettings&gt;
</code></pre>
<p>After this add your libraries. This will stop Kodi from pickup up anything that starts with <code>._</code> and also the word sample or trailer (for good measure).</p>
<p>If you do this after you have added your files to your library then you will still have to delete the entries manually but at least it won&apos;t add any new ones.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Adobe user credential leak]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Just a quick note for readers to check if they&apos;re details were in the recent Adobe leak which saw somewhere between 150 million and 38 million email addresses and encrypted passwords dumped onto the Internet by Hackers. You can check out [this password check page](LastPass adobe password</p>]]></description><link>https://blog.blacksun.cx/adobe-user-credential-leak/</link><guid isPermaLink="false">602820ff1e53ae3c6255886e</guid><category><![CDATA[Security]]></category><category><![CDATA[Breach]]></category><category><![CDATA[Hack]]></category><category><![CDATA[Adobe]]></category><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Tue, 26 Nov 2013 19:46:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Just a quick note for readers to check if they&apos;re details were in the recent Adobe leak which saw somewhere between 150 million and 38 million email addresses and encrypted passwords dumped onto the Internet by Hackers. You can check out [this password check page](LastPass adobe password check) provided by <a href="%5Bhttps://lastpass.com/%5D">LastPass</a> to see if you are affected.</p>
<p>If you are someone who uses the same password, over and over again then you might want to download <a href="%5Bhttps://lastpass.com/%5D">LastPass</a>, get an account and STOP USING A SINGLE PASSWORD!.</p>
<p>I&apos;ve been using a [YubiKey and LastPass premium membership](YubiKey and premium membership) for a couple of years now and I love it. This makes using long, complex and most importantly unique passwords easy.</p>
<p>Thanks for reading,</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Emoticons in the OS-X Terminal]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I found a really neat little feature of the OS-X terminal today. You can display colourful little icons on the terminal by displaying a unicode character. You can enter a unicode character on the terminal with code such as the following (which works in the bash shell).</p>
<pre><code>echo $&apos;\xF0\</code></pre>]]></description><link>https://blog.blacksun.cx/emoticons-in-the-os-x-terminal/</link><guid isPermaLink="false">602820ff1e53ae3c6255886f</guid><category><![CDATA[Mac]]></category><category><![CDATA[Terminal]]></category><category><![CDATA[Emoticon]]></category><category><![CDATA[Unicode]]></category><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Tue, 26 Nov 2013 19:25:17 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I found a really neat little feature of the OS-X terminal today. You can display colourful little icons on the terminal by displaying a unicode character. You can enter a unicode character on the terminal with code such as the following (which works in the bash shell).</p>
<pre><code>echo $&apos;\xF0\x9F\x98\x83&apos;
</code></pre>
<p>this example will display the emoticon of <a href="http://codepoints.net/U+1F603?ref=blog.blacksun.cx">&quot;U+1F603 SMILING FACE WITH OPEN MOUTH&quot;</a>. The codes are the UTF-8 hex values for the character which you can see on the page.</p>
<p>Have a look at some of these pages for some more inspiration:</p>
<ul>
<li><a href="http://codepoints.net/emoticons?ref=blog.blacksun.cx">Emoticons</a></li>
<li><a href="http://codepoints.net/miscellaneous_symbols_and_pictographs?ref=blog.blacksun.cx">Miscellaneous symbols and pictographs</a></li>
</ul>
<p>Find one that you like and replace the UTF-8 codes for the codes for the image you want to see.</p>
<p>Thanks for reading.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[How I write using Markdown]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>As I hinted in my <a href="https://blog.blacksun.cx/zero-to-ghost-blog-hero-in-under-30-minutes/" title="Zero to Ghost blog hero in under 30 minutes">last post</a> I really like Markdown. So much so that when I am writing documentation, letters resumes or anything else, usually I will do anything to avoid having to write them up in Word or any of the many alternatives.</p>
<h2 id="writeupthedocument">Write up the document</h2>
<p><a href="http://bywordapp.com/?ref=blog.blacksun.cx" title="Byword">Byword</a></p>]]></description><link>https://blog.blacksun.cx/how-i-write-using-markdown/</link><guid isPermaLink="false">602820ff1e53ae3c6255886d</guid><category><![CDATA[Markdown]]></category><category><![CDATA[Text Editing]]></category><category><![CDATA[Byword]]></category><category><![CDATA[Content]]></category><category><![CDATA[Pandoc]]></category><category><![CDATA[Vi]]></category><category><![CDATA[Vim]]></category><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Sun, 17 Nov 2013 10:55:43 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>As I hinted in my <a href="https://blog.blacksun.cx/zero-to-ghost-blog-hero-in-under-30-minutes/" title="Zero to Ghost blog hero in under 30 minutes">last post</a> I really like Markdown. So much so that when I am writing documentation, letters resumes or anything else, usually I will do anything to avoid having to write them up in Word or any of the many alternatives.</p>
<h2 id="writeupthedocument">Write up the document</h2>
<p><a href="http://bywordapp.com/?ref=blog.blacksun.cx" title="Byword">Byword 2</a> is great when working on large documents as you can put it in full screen and just see what it is that you are working on. It also has a Markdown preview so can instantly see what you are working on.</p>
<p>I  then usually move to Vim for the last little updates (things like spacing can be a bit tricky in Byword as you can&apos;t turn on visible whitespace which is helpful for doing line breaks. The <a href="https://github.com/plasticboy/vim-markdown?ref=blog.blacksun.cx">vim-markdown</a> plugin is great for</p>
<h2 id="convertthemarkdown">Convert the markdown</h2>
<p>Although you can then export either a PDF or HTML file from the formatted Markdown I prefer to use another application called <a href="http://johnmacfarlane.net/pandoc/?ref=blog.blacksun.cx" title="Pandoc">Pandoc</a>.</p>
<p>Pandoc is a library written in <a href="http://www.haskell.org/haskellwiki/Haskell?ref=blog.blacksun.cx">Haskell</a> which can convert files from one markup language to another. It does this in a nice way in that it converts the input file into it&apos;s own internal format first so that the output filter then only has to know how to convert from one type of file - Pandoc&apos;s internal format, making writing new filter&apos;s easier.</p>
<p>I use it to convert my files into PDF (Using Latex) and DOCX formats usually but you can also convert your files to:</p>
<ul>
<li>HTML and HTML5</li>
<li>OpenDocument XML</li>
<li>ODT</li>
<li>DocBook</li>
<li>MediaWiki markup</li>
<li>RTF</li>
</ul>
<p>and many others. You can even convert them back into Markdown (if you wanted to).</p>
<p>It is a simple matter of calling running it at the command line to generate your files but I have created the following bash script to make creating the PDF and DOCX files even quicker.</p>
<pre><code>#! /bin/bash

# Check for 1 argument
if [ &quot;$#&quot; != &quot;1&quot; ]
	then
		echo &quot;You must include the name of the markdown file to process. Don&apos;t include the .md extension&quot;
		exit 100
fi

# Check the filename argument
extension=&quot;${1##*.}&quot;
filename=&quot;${1%.*}&quot;
if [ &quot;$extension&quot; == &quot;md&quot; ]
	then
		filename=&quot;${1%.*}&quot; 
elif [ -r &quot;$1.md&quot; ]
	then
		filename=&quot;$1&quot; 
else 
		echo &quot;File not found.&quot;
		exit 200
fi

# Generate Word document
if [ -f &quot;$filename.docx&quot; ]
	then
		rm &quot;$filename.docx&quot;
fi
echo Generating docx file
pandoc &quot;$filename.md&quot; -o &quot;$filename.docx&quot; -t docx

# Generate PDF document
if [ -f &quot;$filename.pdf&quot; ]
	then
		rm &quot;$filename.pdf&quot;
fi
echo Generating pdf file
pandoc &quot;$filename.md&quot; -V geometry:margin=1in -o &quot;$filename.pdf&quot; -t latex

# Done
echo Done.
</code></pre>
<p>process-md.sh</p>
<p>for this to work, make sure that the file has execute access and call it with the name of the .md file that you want to convert (it does expect that the files have an extension of md but that could be easily changed).</p>
<p>Thanks for reading.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Zero to Ghost blog hero in under 30 minutes]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;ve been playing around with <a href="http://nodejs.org/?ref=blog.blacksun.cx">Node JS</a> a little bit lately and at the same time had finally decided that I needed a blog to show off and record some stuff that I have been working on in my very meagre spare time.</p>
<p>I then found <a href="http://www.ghost.org/?ref=blog.blacksun.cx">Ghost</a> which</p>]]></description><link>https://blog.blacksun.cx/zero-to-ghost-blog-hero-in-under-30-minutes/</link><guid isPermaLink="false">602820ff1e53ae3c6255886c</guid><dc:creator><![CDATA[Simon Bruce]]></dc:creator><pubDate>Thu, 07 Nov 2013 14:53:41 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>I&apos;ve been playing around with <a href="http://nodejs.org/?ref=blog.blacksun.cx">Node JS</a> a little bit lately and at the same time had finally decided that I needed a blog to show off and record some stuff that I have been working on in my very meagre spare time.</p>
<p>I then found <a href="http://www.ghost.org/?ref=blog.blacksun.cx">Ghost</a> which solved both twitches at the same time. Even better, all of the content is written in <a href="http://daringfireball.net/projects/markdown/?ref=blog.blacksun.cx">Markdown</a> which for me is a total win-win as I think Markdown is fantastic for writing and go to great lengths to enable myself to write things in Markdown when ever possible.</p>
<p>I went ahead and started installing it on my notebook. I already had the basics (node js and npm) installed so it was very easy. I then started looking into installing it on my <a href="http://www.rackspace.com/?ref=blog.blacksun.cx">Rackspace</a> cloud server when I found an article talking about a great new Rackspace feature called deployments. If you want to get a specific product up and running very quickly and don&apos;t want to or need to do it yourself then it is a really quick way to get it up and running straight away. Basically it works like this</p>
<ol>
<li>Log into your Rackspace account.</li>
<li>Click on Deployments.</li>
<li>Type in a name for for the deployment.</li>
<li>Select a region to host the server.</li>
<li>Select the application to be deployed (in my case Ghost).</li>
<li>Type in any additional information required by the application - in the case of Ghost it just requires a URL.</li>
<li>Hit &quot;Next Step&quot; and then select the size of the cloud server to create.</li>
<li>Wait for about 5 minutes.</li>
<li>Once it has finished, the IP address for the new cloud server and use those to create a new DNS record for it pointing at the URL that you used when setting it up.</li>
<li>Once the DNS has propagated then you are done.</li>
</ol>
<p>Although I think that I will eventually redo this, this did save me a good chunk of time which is what really matters in the short term.</p>
<p>Thanks for reading.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>