See the real details of a git commit

The command to see the details of a git commit, specifically the tree attached to it, is:

git cat-file -p HEAD

It produces an output like this:

jason@rise22:~/code/appcove/HKSickler$ git cat-file -p HEAD
tree f388dffd7ac29813d4a61a1cfd9f4a03518c3c56
parent 2752fafb51cb58c288adcd5d0a6f262943416683
parent cd6ce6f905ef61d019fbbd16e157ef0389f809ef
author Jason Garber <> 1669396739 -0500
committer Jason Garber <> 1669396739 -0500

Merge: merge this and that ....
Creo 7 Parametric Assemblies

Creo 7 Parametric Assemblies

A point of confusion when learning Creo 7 (coming from Fusion 360 and previously SolidWorks) was how to mate parts in an assembly. Like many things, once you know it’s pretty simple!

It is at the point you are inserting the part into the assembly that you are able to specify constraints/mates.

You can reopen this area of the application by clicking on a part and then then clicking Edit Definition.

Auto Resize IFRAME Cross Origin

Browser security policies prevent frames from interacting with each other if they are not from the same origin (like domain but even more specific).

However, frames can pass messages to each other.   Here is how you can implement cross-origin iframe auto-resizing based on window.postMessage.

Lets assume we have a parent page that looks like this:

    <title>Parent Page</title>
     [iframe id="frame1" src=""]

(assume [] is <> above, sorry about over protective content escaping in

To enable auto-resizing on this page, add some script to the end of the <head></head> section (or just before </body> if that is where you put them).

This listens for a “message” event and will check to see if it has an action of “resize”.  If so it will update the specified id’s height.

    if('resize') {
      document.getElementById( ='px';

On the embedded frame source, you need an onload event to send a message:

window.onload = function() { 

Note that we need to pass “frame1” which is the ID of the frame on the parent page.

Then the frames should auto-size to their content.

[ERROR] InnoDB: Cannot add field in table because after adding it, the row size is 8572 which is greater than maximum allowed size (8126) for a record on index leaf page.

One day, suddenly, we couldn’t reload a production backup.  Oh no!  It took a bit of digging around but here is the issue, should you find yourself running into it:

Using the InnoDB COMPACT ROW_FORMAT, there are some rules InnoDB uses to decide how much data to put on the first page and how much to put on overflow pages.  While VARCHAR and TEXT type columns are typically stored on overflow pages with no problem, when using the COMPACT row format, up to the first 767 bytes of each field will be stored on the primary page.

This error happens when the amount of actual data exceeds the allows limit for a row size on the main page, which is about 50% of the innodb_page_size variable.

If you have a circumstance with say, 11 TEXT or VARCHAR fields, each with at least 767 bytes of data, and running an innodb_page_size of 16k (which results in 8126 being max row size on main page) …… then 767*11=8437 stored on main page is greater than 8126 which is the “maximum allowed size for a record on index leaf page”, and you will get this error.

The solution is to investigate the use of either DYNAMIC or COMPRESSED row format, depending on your application.


Installing Windows Subsystem for Linux (WSL) on Windows 10

Microsoft has been doing a lot to promote linux  interoperability on windows.  I see this as a great step in the right direction, after decades of a closed and exclusive culture that has been a pain for cross-os users like myself.

Here is a quick and dirty rundown of how (March 2019) to install Ubuntu on Windows 10:

See here for the full rundown:

Install the Windows Subsystem for Linux

Before installing any Linux distros for WSL, you must ensure that the “Windows Subsystem for Linux” optional feature is enabled:

  1. Open PowerShell as Administrator (search for Powershell, right click, run as administrator), and run this command:
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  2. Restart your computer when prompted.

Install your Linux Distribution of Choice

Go to the Microsoft Store and search for Ubuntu.  Install it.

Once you are in Ubuntu, there are a few things to do that will make everything nicer…

Update Ubuntu and setup ssh server
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install openssh-server
sudo service ssh start

Fix character encoding issue (until this is fixed upstream)
sudo gunzip –keep /usr/share/i18n/charmaps/UTF-8.gz
sudo dpkg-reconfigure –frontend=noninteractive locales

Setup SSH under your user
mkdir .ssh
chmod 700 .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
(put your public key in there)
Setup PuTTY
You can then configure PuTTY to connect to port 22 with your username and key (ideally from Pageant)
You can access your c drive under /mnt/c/
You can access your desktop using /mnt/c/Users/YOU/Desktop
This enables you to write convenient scripts in ubuntu that affect windows files on your desktop for example.

Python Mutable vs Immutable

Here is a basic introduction to immutable and immutable types in python.

In python there are two types of data… mutable and immutable. Numbers, strings, boolean, tuples, and other simple types are immutable. Dicts, lists, sets, objects, classes, and other complex types are mutable.

When you say:

a = [1,2,3]
b = a

You’ve created a single mutable list in memory, assigned a to point to it, and then assigned b to point to it. It’s the same thing in memory.

Therefore when you mutate it (modify it):

b[0] = 3

It is a modification (mutation) of the index [0] of the value which b points to at that same memory location.

However, when you replace it:

b = [0,0,0]

It is creating a new mutable list in memory and assigning b to point at it.

Check out the id() function. It will tell you the “address” of any variable. You can see which names are pointing to the same memory location with id(varname).

Bonus: Every value in python is passed by reference… meaning that when you assign it to a variable it simply causes that variable to point to that value where it was in memory. Having immutable types allows python to “reuse” the same memory location for common immutable types.

Consider some common values when the interpreter starts up.  You can see here there are a lot of variables pointing at the memory location held by abc.  cpython, at least, is smart enough to realize that the value `abc` is already stored in memory and because it is immutable, just returns that same memory address.

>>> import sys
>>> sys.getrefcount('abc')
>>> sys.getrefcount(100)
>>> sys.getrefcount(2)

However, a value that is definitely not present would return 2. This has to do with the fact that a couple of references to that value were in-use during the call to sys.getrefcount

>>> sys.getrefcount('nope not me.  I am definitely not here already.')

Notice that an empty tuple has a lot of references:

>>> sys.getrefcount(tuple())

But an empty list has no extra references:

>>> sys.getrefcount(list())

Why is this? Because tuple is immutable so it is fine to share that value across any number of variables. However, lists are mutable so they MUST NOT be shared across arbitrary variables or changes to one would affect the others.

Incidentally, this is also why you must NEVER use mutable types as default argument values to functions. Consider this innocent little function:

>>> def foo(value=[]):
...     value.append(1)
...     print(value)

When you call it you might expect to get [1] printed…

>>> foo()

However, when you call it again, you prob. won’t expect to get [1,1] out… ???

>>> foo()
[1, 1]

And on and on…

>>> foo()
[1, 1, 1]

>>> foo()
[1, 1, 1, 1]

WHY IS THIS? Because default arguments to functions are evaluated once during function definition, and not at function run time. That way if you use a mutable value as a default argument value, then you will be stuck with that one value, mutating in unexpected ways as the function is called multiple times.

The proper way to do it is this:

>>> def foo(value=None):
...     if value is None:
...         value = []
...     value.append(1)
...     print(value)
>>> foo()
>>> foo()
>>> foo()

Stain Dipper Parts

Here is a screenshot of some of the parts we’ve designed for the Stain Dipper.  All of the mechanical parts are in the design and correctly positioned and all the hardware has been ordered…

Here are several of the parts from Fusion 360


Here is a servo motor mount and custom made pulley.

Frame v27

Here is a small piece of Nylon used to connect a 1/16″ cable with a aluminum tube.


How to install a Trusted Certificate Authority on Windows 7

At my company AppCove, we have our own certificate authority that we use with development servers and sites.  This allows us to (at no additional cost) use HTTPS and SSL for all of these alternate domains and subdomains.

The downside is that our certificate is not trusted by any stock browser or operating system.

Therefore, to prevent getting an ugly and scary SSL warning, anyone who needs to visit these (private audience) sites must first “trust” our certificate authority.

A note on security.  If you are telling your computer to trust a certificate authority, then you must really actually “trust” that authority.  If the signing key fell into the wrong hands, then they could create fake certificates for other sites you visit, like, and intercept your data.  At AppCove, we use aggressive security measures to protect the certificate authority key (as we do for customer data and applications).

In this example, I am causing my Windows 7 workstation to trust appcove-ca-cert.pem.crt















— Start of slight detour — 

If you want to verify it was installed, do this.  Otherwise, skip the next 2 screens.



— End of slight detour —



At this point, you should be able to visit any HTTPS site that was signed with this certificate authority and your browser will indicate that it is a secure connection.