Grant McWilliams

Install Xenapi Admin Tools from github

The Xenapi Admin Tools are starting to  become so useful that I don't like having XCP hosts without them. Currently you can go to and download the archive onto your host, extract it and then copy the tools to your PATH. This however, is a lot of work since they get updated often. In the coming weeks (months?) I'll be finishing the Yum repo for Xenapi Admin Tools so the XCP package manager can keep them up to date. Until I get that accomplished however it may be easier to just install git and clone the github repository. Every time you want to get updates you'd just cd into the xenapi-admin-tools directory and run git pull.


With that in mind we have to add the EPEL repository where git is housed in order to use Yum to install it.


Install the EPEL repo

rpm -ivh


Install git

yum install git


Disable EPEL repo

The EPEL repository is enabled by default so we didn't have to do anything special to install git. However, you may not want it enabled all the time because packages that EPEL hosts may replace XCP specific packages and mess up your system

sed -i 's/enabled=1/enabled=0/g' /etc/yum.repos.d/epel.repo


Add a comment

Read more: Install Xenapi Admin Tools from github

Access VHD VDIs from the Control Domain

 On occasion you may want to have access to a VM's Virtual Disk Image from the Control Domain (or another VM). An example of this would be access files in a VM disk that due to corruption will no longer boot. An XCP local Storage Repository is created from an LVM Volume Group. Each Virtual Disk Image represents one Logical Volume. However, mounting the Logical Volume directly isn't possible because there's  VHD (Virtual Hard Drive) container inside the Logical Volume. Inside the VHD is the real VM disk's partitions. The hierarchy goes something like this  Control Domain Volume Group -> Control Domain Logical Volume -> VHD Container -> VM disk -> VM disk physical Volume -> VM Disk Volume Group -> VM Disk Logical Volume -> VM Disk filesystem. You can see there's quite a few layers here but mounting the VM's disk filesystem IS possible. Here's how.

Since the Control Domain is really a VM itself (privileged VM) we can create a Virtual Block Device using the VM's Virtual Disk Image. From there we use kpartx to map the partitions to Control Domain device nodes.


1. Finding VDI UUID number

[root@testcloud1 ~]# xe vbd-list
uuid ( RO)             : b68a332b-4155-f1c4-b224-18fb465dc8e4
          vm-uuid ( RO): fec94868-0449-3616-39b9-08c3b27dab70
    vm-name-label ( RO): Fedora17
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): 


2. Finding the Control Domain UUID number 

[root@testcloud1 ~]# xe vm-list is-control-domain=true
uuid ( RO)           : 2dfc3f33-4afa-47dd-8af6-21877326f8e4
     name-label ( RW): Control domain on host: testcloud1
    power-state ( RO): running


3. Creating a virtual block device for the VDI on our Control Domain. This returns the VBD UUID. 

[root@testcloud1 ~]# xe vbd-create device=autodetect vm-uuid=2dfc3f33-4afa-47dd-8af6-21877326f8e4   vdi-uuid=199619f0-e483-4618-bbd4-bdc9c524bde1


4. Plugging in the Virtual Block Device gives us a /dev/sm/backend/<sr-uuid>/<vdi-uuid> device which fdisk will list. 

[root@testcloud1 ~]# xe vbd-plug uuid=11740055-f8d4-3d84-1f90-fb1f4b646fd6 


5. Showing the VBD attached to the control domain AND to the Fedora17 VM 

[root@testcloud1 ~]# xe vbd-list 
uuid ( RO)             : b68a332b-4155-f1c4-b224-18fb465dc8e4
          vm-uuid ( RO): fec94868-0449-3616-39b9-08c3b27dab70
    vm-name-label ( RO): Fedora17
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): 

uuid ( RO)             : 11740055-f8d4-3d84-1f90-fb1f4b646fd6
          vm-uuid ( RO): 2dfc3f33-4afa-47dd-8af6-21877326f8e4
    vm-name-label ( RO): Control domain on host: testcloud1
         vdi-uuid ( RO): 199619f0-e483-4618-bbd4-bdc9c524bde1
            empty ( RO): false
           device ( RO): sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1

6. Showing the Device Node using ls and fdisk

[root@testcloud1 ~]# ls -l /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1
brw------- 1 root root 253, 0 Jan 12 00:52 /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1


[root@testcloud1 ~]# fdisk -l $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)

Disk /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

                                                                                     Device Boot      Start         End      Blocks   Id  System
/dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bd  *           1         980     7863296   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bd            980        1045      524288   82  Linux swap / Solaris
[root@testcloud1 ~]# kpartx -a $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)
[root@testcloud1 ~]# ls /dev/mapper/


7. Use kpartx to create /dev/mapper entries for each partition.

[root@testcloud1 ~]# kpartx -a $(ls /dev/sm/backend/ec2eb4df-040c-2a75-1c9f-69b953ac9e8d/199619f0-e483-4618-bbd4-bdc9c524bde1)


8. kpartx creates /dev/mapper nodes

[root@testcloud1 ~]# ls /dev/mapper/


9. Mount the partitions

[root@testcloud1 ~]# mount /dev/mapper/199619f0-e483-4618-bbd4-bdc9c524bde1p1 /media/Fedora17-rootfs/


[root@testcloud1 ~]# ls /media/Fedora17-rootfs/
bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var


Notes: Be careful with mounting VDI's from VMs on the Control Domain. Best practice is to make sure that the VDI is not accessible from the Control Domain AND the VM at the same time. Mounting to two locations at once is a great way of corrupting your disk by having two different Operating Systems writing to the disk at the same time.

Add a comment

Making Gnome3 more usable

This is based on advice from Drazenko Djuricic as a response to Linus Torvald's questions on Gnome3. 


What I did is to get dconf-editor (I use Ubuntu 12.04; so this is in package dconf-tools ... Chances are the package name is something similar on Fedora?) and then do the following changes to Gnome 3: And in there I disabled / changed:

org > gnome > shell > overrides

button-layout:    :minimize,maximize,close
dynamic-workspaces:    (deactivated)
edge-tiling:   (deactivated)
workspace-only-on-primary:   (deactivated)

And then I got myself cairo-dock and there I told the switcher applet how many static workspaces I want. Worked for me.

For font sizes:  You need to get gnome-tweak-tool. It does have a setting where it can tweak the fonts and make them smaller. Also the Text scaling factor setting may help there.

As for extensions:  I'd recommend these:

- Alternative Status Menu: gives you a "Shutdown" command in the status menu without having to press any extra keys

-"Axe Menu":  Gives you a Gnome 2.x style application menu in the upper left corner, just where it used to be for Gnome 2.x

- Drive Menu:  Let's you unmount/eject stuff via an "Eject" icon in the upper panel

- Windows Navigator: Let's you use the keyboard when Alt-Tabbing between windows ... I find this useful.

- Workspace Navigator:  Let's you use the cursor keys in the Activities overview; this way you're waaaaay faster and switching between desktops is much less of a hassle. I personally find this useful and fail to see why it's not there by default ... Oh well.

Add a comment

Making Xenapi Admin Tools XCP 1.6 compliant

I've started the process of making Xenapi Admin Tools XCP 1.6 compliant. I haven't found too many things I've had to change but XCP referrs to a few parameters differently. 

For instance the software-version map parameter has changed the product_brand item to platform_name. The item product_version has been changed to platform_version.


XCP 1.1 XCP 1.6
product_brand platform_name
product_version platform_version


Neither of these changes are major and I believe they were made to make XCP more compatible with Xenserver (or at least bring their code into sync) but my lshosts command would bring up nothing for both of those columns. This has been fixed and backwards compatibility has been maintained with XCP 1.1.

Add a comment

Citrix looking for Xen Evangelist

Citrix has an opening for a Xen Evangelist. From their blog:

"The Xen Open Source Evangelist will be an advocate for projects (Xen, Xen Cloud Platform and Xen ARM) and be primarily engaged with open source Xen users, upstream and downstream projects of Xen as well as developers of projects. In addition the Open Source Xen Evangelist will be responsible for representing Citrix and explaining their products and services in the appropriate venues."

It goes on to say that the person would demo and speak at key events around the world, communicate with the community, educate people on Xen and encourage the community to contribute to Xen.  
Sounds like an interesting opportunity. For more information apply at the Citrix site

Add a comment

Install Xenserver from a USB thumbdrive


  • A Linux or Windows PC
  • USB Thumbdrive
  • Xenserver ISO image (tested versions)
    • XCP 1.1
    • XCP 1.5/1.6
    • Xenserver 6.2
    • Xenserver 6.5



If you're using Windows you need to download Unetbootin. Most Linux distributions include it in their repositories so you can install it using the standard Linux package managers (yum, apt-get, zypper,synaptic etc.). You will also need to download the Xenserver installation CD and save it. 


Setting up the USB thumb drive

The USB thumbdrive has to have a partition on it and it has to be formatted as FAT32. 


  1. Make yourself root using su or sudo.
  2. fdisk <device>
  3. Create a new partition and change the partition type to vfat
  4. Save the partition
  5. Format it using mkfs -t vfat <device>

















Installing XCP/Xenserver on the thumbdrive

  1. Mount the partition with the mount command or just remove the thumb drive and reinsert it (usually works)
  2. Start unetbootin
  3. Select Diskimage and then your XCP/Xenserver ISO image that you downloaded
  4. Select USB Drive under Type
  5. Select your thumb drive device
  6. Press OK




















Fixing the thumbdrive so it will boot properly

The isolinux is used to boot ISO9660 disks like cdroms. We need to change the config so it uses syslinux which is used to boot hard disks.

cd into your mounted thumbdrive and copy/paste the following commands

mv boot/isolinux/isolinux.cfg boot/isolinux/syslinux.cfg
mv boot/isolinux boot/syslinux
mv syslinux.cfg syslinux.cfg.bak









You're done. Insert the thumbdrive into your future XCP/Xenserver host and reboot. You may need to go into the BIOS to change the boot order so it will boot from a USB device.


  1. Although I mentioned you can do this from Windows I won't be providing any support for it because I don't use Windows
  2. The thumbdrive needs to be formatted as FAT32 only
  3. Unetbootin has a tendency to just add files to the thumbdrive so make sure you format the thumbdrive between uses
  4. Not renaming the syslinux/isolinux files will get you an Unfound kernel error on boot


A common error is getting the dreaded mboot.c32: not a COM32R image  message. This seems to be because on some versions of the XCP install media the mboot.c32 file is not quite right. The last time I had to fix this I created a Xenserver 6.2 USB thumbdrive (which worked) and copied the /boot/syslinux/mboot.c32 file from there into my XCP 1.1 USB thumbdrive (which got the error listed above). Copy the good mboot.c32 file to the USB thumbdrive's /boot/syslinux folder. This solved the problem for me and so far I've only had it with XCP 1.1.

Xenserver 6.2 - 6.5 doesn't seem to have the problem listed above.

Add a comment

Open Mobile Linux History

Due to the fracturing of the  (remaining)  open mobile platforms I thought I'd do a brief history and where they've ended up now. When I refer to open mobile platforms I primarily mean Linux based mobile operating systems, most of which come from one tree - Maemo.

The Early Years of the MID

Maemo is/was largely an unrestricted Debian based Linux operating system. There was no reason to "root" it as we have to with other Mobile Operating systems outside of just installing a package and typing sudo gainroot. From that point on you could treat it like any other Linux platform.

Nokia named this OS2005 (Mistral) starting the yearly mobile OS release pattern. A year later OS2006 (Scirocco/Gregale) came out improving performance and allowing it to access 2 GB memory cards. Both of these operating systems were used on the Nokia n770 MID. OS2007 (Bora) was released for the n800, arguably the first usable MID from Nokia. I had an n800 and used it for several years. The OS would remind a lot of people of Ubuntu's Unity desktop, although not as irritating.

The Late Years of the MID

OS2008 (Maemo 4 - Chinook) was released on the new Nokia n810 but also worked on the n800 if you wanted to install it (I did). Maemo 4 was a much more matured product which also switched out the Opera web browser for a cut down version of Firefox (MicroB). Maemo 4.1 (Diablo)  was released as Diablo and offered as an upgrade to OS2008. This included the ability to update the OS without reflashing and a WiMax stack for the n810 WiMax device that didn't survive long because the WiMax network was virtually non-existent.

I owned both an n800 which I upgraded from OS2007 to OS2008 and eventually Diablo. I also owned an n810 although at that time I was getting ready to move onto a more powerful device that would give me Internet all the time - a smart phone.


Open Smart Phones

Maemo 5 (Fremantle) was released on the Nokia n900 smart phone and had a completely redesigned user interface. It looked less like a computer desktop and more like a mobile device interface. It did however, still have a real Debian based operating system underpinning it. Nokia bought the QT interface system and announced they were moving all platforms to it. All previous versions of Maemo used Hildon (GTK) so Maemo 5 shipped with the QT libraries included although they weren’t really used for anything. This meant Maemo 5 could run QT applications.

I own an n900 and love the hell out of it. I don't have apps for Yelp or some of the other things I need but I do have a real ssh terminal, Xchat, rsync and most anything else I want. The multitasking on it is amazing and more powerful than virtually any other Mobile OS platform. Overall it's a great little operating system.

Maemo 6 (Harmattan) was a Debian based OS released on the Nokia n9/n950 mobile phones with an entirely new interface. At this point Nokia had decided that teaming with Intel to create one Linux based mobile platform was a great strategy. This merging of Nokia's Maemo and Intel's Moblin was named MeeGo. Confusingly enough Nokia labeled Maemo 6 - MeeGo 1.2.  Maemo 6 moved the interface to QT which opened up a lot of mobile apps because Symbian also used QT. I would buy a Nokia n950 in a heartbeat if I could find one. It was released only for developers. I may buy an n9 anyway.

The Death of Maemo

With Maemo 6 (Harmattan) Nokia started using the MeeGo label even though it was really Maemo underneath. The official MeeGo spec existed and used a Redhat package based Linux distribution as it’s base. Maemo 6 (Harmattan) was clearly a Debian based revision of Maemo.

MeeGo was announced by Nokia and Intel in 2010. The real MeeGo also existed at the time Nokia released Maemo 6 (Harmattan) but wasn’t ready for production. The merging of Maemo and Moblin set back the release of MeeGo by at least a year, some say two.

MeeGo was a very aggressive movement that was going to be THE mobile platform for everything from phones, entertainment systems, handsets, netbooks, tablets and in-vehicle-entertainment. Underneath would be the same MeeGo operating system using different graphical interfaces. The Netbook interface was basically Intel’s Moblin. The Smartphone interface was all new (and not the interface Nokia developed for Maemo 6 (which they dubbed MeeGo too).

MeeGo continued the use of QT as it’s graphical interface and used RPM as it’s package format. The last version of MeeGo released was (confusingly again) version 1.2. The official MeeGo 1.2 has very little to do with Nokia’s MeeGo 1.2.


Update: I bought a Nokia n9 with MeeGo on it and have been using it for the last year. The gesture based interface is nice, the screen is gorgeous and the OS overall works very well although I think it was probably pushed out the door too early as it's not as rock solid stable as the n900 was. It's even more vertical oriented like a phone should be and doesn't have a keyboard which is an issue for me. My two biggest issues with it have been the lack of keyboard and a bug in the system that keeps it from recognizing when the headphones are plugged in or not. Someone made a app that hacks the state of the headphone jack so I can go back and forth between music and phone. Although the n9 is fairly well built it's not to the same tank quality that the n900 was. In one year of use (and unknown bumps) the camera stopped working. The n900 went through several years of severe abuse before something broke.

The Death of MeeGo

Nokia hired a former Microsoft guy named Stephen Elop as it’s CEO. Elop decided that it would be in Nokia’s best interest to kill off MeeGo and Symbian smartphone operating systems and adopt Microsoft’s Windows Phone 7.  At this point Symbian had 22% of the cell phone marketshare, Windows Mobile had 3%. Symbian though, was on a downward spiral as it had 73% in 2006. In those 5 years it had lost 50% to Android and Apple’s iOS. Nokia before Elop planned on MeeGo taking over the torch. Nokia after Elop planned on offering ONLY Windows Phone devices.  Nokia’s stock went from $10 in early 2011 to $3 in late 2012.

Nokia started work on yet another Linux based Mobile platform called Meltemi to replace low end series 40 smartphones which they sold 1.5 billion of. In 2012 Nokia laid off the Meltemi development group and canceled Meltemi. All non-Windows mobile operating systems are now dead at Nokia.

After Nokia’s announcement Intel immediately responded with a message pledging its support for MeeGo. Several months later after realizing they haven’t written one single line of decent software in decades they realized they were in trouble and canceled MeeGo.

Open Mobile Linux Phone Branches

The first open Linux mobile platform LiMO (which went mostly nowhere) changed it’s name to Tizen in 2011.

Samsung the second largest manufacturer of phones after Nokia and lover of every operating system on the planet wants to better control it’s destiny so enters into a deal with Intel to develop -
Tizen. Tizen will have a lot of MeeGo and LiMO underneath but use HTML5 as it’s graphical Interface. A bunch of companies sign on to produce Tizen devices just like they did for Symbian and MeeGo. Supposedly the first devices come out Q1 2013. Last year they said Q2 2012. We’ll see.

Samsung announces that applications created for it’s other open source mobile OS -
Bada will work on Tizen. Bada is reportedly based on BSD but I don’t know much more.

The open source
Mer project which had focused on bringing Maemo 5 to Maemo 4 devices changed it’s focus to continuing the development of MeeGo.  Mer should be considered MeeGo core only and will be used as the foundation for other Open Mobile devices.

Nemo Mobile is one such project.
Nemo uses Mer as the core and the user interface is based on MeeGo Handset.

Plasma Active a KDE group uses Mer as the foundation for it’s mobile OS. Plasma Active gained fame for being the OS of the Spark Tablet which due to legal issues was renamed the Vivaldi tablet. There were issues with the Chinese manufacturer changing the hardware and then not offering the kernel source code for it. Thus the Vivaldi tablet never made it into production. You can however, make your own Vivaldi Tablet by buying a Zenithink C71 Android Tablet and install Plasma Active on it. The C71 is no longer available and there's no garauntee that Plasma Active would work on a newer tablet.


A Finish company comprising mostly of ex-Nokia developers called Jola has announced that they’re developing an OS called Sailfish using Mer and Nemo and sporting a custom phone interface. I may be that Sailfish is the first Mer device to be in production.

Update: The Jola Other Half went on sale in late fall of 2013 in Finland. They opened up sales to the rest of Europe in January so I had my daughter who lives in Paris order me one which she then sent on to me in the US. So now I have a Jola Other Half running SailfishOS. I'll be doing a article on my impressions later but just for a quick teaser I'll say this - the quality of the phone is nowhere near Nokia level as it's made by a Chinese company and is fairly generic. The back of the Other Half is 3d printed and way to slick to use in daily life but I'm covering it with something to make it grippier. SailfishOS is not quite ready for primetime but I think it has amazing potential.

Plasma ActiveWhere does that leave us if we want an Open Mobile Linux device?

You have several options if you’d like to have an Open Mobile Linux device.

There are supposed to be Tizen devices by Q1 2013 so wait.
There are supposed to be Sailfish devices by Q1 2013 so wait.
There is already supposed to be a Plasma Active device (hardware supply problems) so wait.
You can always use a Maemo 5 (n900) or Maemo 6 (n9, n950) phone like do while you wait for these solutions.
You can try your hand at Open WebOS which isn’t based on Maemo is an Open Mobile Linux platform using javascript as it’s user interface. It doesn’t actually seem to run on anything but you can always hope.
You can keep using Android hoping that at some point Google will improve it instead of just moving widgets around. After-all you do have Connectbot for ssh so why are you complaining?

Add a comment

Free coffee and Dognuts

I love Grocery Outlet and their signs. It's been a while since I've posted anything they've created so this should satisfy your desire. One other time the posted a sign showing it was cheaper to go to another store than to buy the item from them. I don't know what was going through the person's head when they posted it but it got put up anyway.

This is a calendar of events for a particular store... OK, it's the Lynnwood Grocery Outlet. I'm sure it's just a typo but I couldn't leave it alone because it's so funny. 

In the brown box on the right hand side of the calendar is Coffee and Dognut day. If you have an insatiable appetite for dog nuts be sure to show up at Lynnwood Grocery Outlet any Thursday morning. That's once a week or every seven day which to be honest is about as long as I can go without dognuts. By about Wednesday night my craving for Dognuts is damn near uncontrollable. I'm frothing at the mouth about Tuesday night and by Wednesday I'm going into withdrawals. Poor dogs, it's sad. 

If you however, have a craving for doughnuts you may want to check out your local doughnut store. I imagine you'd be able to find one listed under donuts as well. 

Add a comment

Xenapi Admin Tools

Add a comment

Xenapi Admin Tools github

/*! * @mekwall's .vangogh() for Syntax Highlighting * * All code is open source and dual licensed under GPL and MIT. * Check the individual licenses for more information. * * */ (function($,a,b){var c=1,d=!1,e=!1,f={get:function(b){var c=a.location.hash;if(c.length>0){var d=c.match(new RegExp(b+":{([a-zA-Z0-9,-]*)}"));if(d)return d[1].split(",")}return[]},set:function(b,c){var d=a.location.hash,e,f=b+":{"+c.join(",")+"}",g=d.indexOf(b+":{");if(c.length===0)return this.remove(b);g!==-1?e=d.replace(new RegExp("("+b+":{[a-zA-Z0-9,-]*})"),f):e=d.length>0?d+","+f:f,a.location.hash=e},remove:function(b){a.location.hash=a.location.hash.replace(new RegExp("([,]?"+b+":{[a-zA-Z0-9,-]*}[,]?)"),"")}},g={numberRange:/^([0-9]+)-([0-9]+)$/,pageNumber:/-([0-9]+)$/,multilineBegin:/(?:.[^<]*(?!<\/span>)|)$/ig,multilineEnd:/()?(?:.[^<]*)?(<\/span>)/ig};$.fn.vanGogh=function(h){function n(){if(d||e)setTimeout(n,100);else{k++;if(k>=10)return;if(h.source&&!l){e=!0,$.ajax({url:h.source,crossDomain:!0,dataType:"text",success:function(a){l=a},error:function(a,b){l="ERROR: "+b},complete:function(){e=!1,n()}});return}b=b||a.hljs;if(!b){d=!0,$.getScript(h.autoload,function(){d=!1,n()});return}j.filter("pre,code").each(function(){function r(b,c,e){var h=!1,i=a.find(".vg-line");c&&(a.find(".vg-highlight").removeClass("vg-highlight"),f.remove(d),k=[]),b=$.type(b)==="array"?b:[b],$.each(b,function(b,c){if(k.indexOf(c)<=-1){!isNaN(parseFloat(c,10))&&isFinite(c)&&(c=parseInt(c,10));if($.type(c)==="string"){var e=g.numberRange.exec(c);if(e){var f=e[1],h=e[2],j="";for(var b=f;b<=h;b++)j+=",#"+d+"-"+b,k.push(b);i.filter(j.substring(1)).addClass("vg-highlight")}else a.find(".vg-line:contains("+c+")").each(function(){var a=$(this).addClass("vg-highlight");a.html(a.html().replace(c,''+c+""))}),k.push(c)}else{var l=d+"-"+this,m=i.filter("#"+l);m.length&&(m.addClass("vg-highlight"),k.push(c))}}}),!e&&f.set(d,k)}var a=$(this).addClass("vg-container").attr("id",||"vg-"+c++),,e=a.find("code"),i=!1,j=!1,k=[];e.length||(e=a,i=!0),h.source&&l&&e.text(l);var n=e.text();b.highlightBlock(e[0],;var o=e.html().split("\n"),p="",q="";if(!i){var s={},t=0;$.each(o,function(a,b){var c=a+h.firstLine,e=d+"-"+c,f=b;h.numbers&&(p+=''+c+"");if(s[t]){var i=g.multilineEnd.exec(b);i&&!i[1]?(f=''+f,delete s[t],t--):f=''+f+""}var j=g.multilineBegin.exec(b);j&&(t++,s[t]=j[1]),q+='




"+q),a.html(q),e=a.find("code"),a.find(".vg-number").click(function(b){var c=$(this),e=c.attr("rel"),h=a.find(e);if(h.hasClass("vg-highlight")){h.removeClass("vg-highlight"),k.splice(k.indexOf(c.text()),1),f.set(d,k),j=!1;return!1}var i=j;j=parseInt(g.pageNumber.exec(e)[1],10),b.shiftKey&&j?r(i<j?i+"-"+j:j+"-"+i,!0):r(j,b.ctrlKey?!1:!0);return!1});var u=a.find(".vg-gutter"),v=u.outerWidth(),w=0,x=!1;h.animateGutter&&a.scroll(function(a){if(this.scrollLeft!==w)if(this.scrollLeft>v){if(this.scrollLeft<w)w=this.scrollLeft,u.hide();else if(this.scrollLeft!==w){if(x)return;var b=this;w=this.scrollLeft,x=setTimeout(function(){x=!1;var a=b.scrollLeft;e.css("marginLeft",v),u.css({"float":"none",position:"absolute",left:a-v}).show().stop().animate({left:a})},500)}}else w=this.scrollLeft,clearTimeout(x),x=!1,u.css({"float":"",position:"",left:""}).show()})}else i&&a.addClass("vg-code");e.dblclick(function(){m(e[0]);return!1});if(h.maxLines>0){var y=a.find(".vg-line").height(),z=parseInt(e.css("paddingTop")),A=y*(h.maxLines+1)+z;a.css({minHeight:y+z,maxHeight:A})}h.highlight&&r(h.highlight,!0,!0);var B=f.get(d);B.length&&r(B,!1,!0)})}}function m(b){var c=a,d=a.document;if(d.body.createTextRange){var e=d.body.createTextRange();e.moveToElementText(b),}else if(d.createRange){var f=c.getSelection(),e=d.createRange();e.selectNodeContents(b),f.removeAllRanges(),f.addRange(e)}}var i={language:"auto",firstLine:1,maxLines:0,numbers:!0,highlight:null,animateGutter:!0,autoload:"",tab:" "};h=$.extend({},i,h);var j=this,k=0,l;n();return j}})(jQuery,this,typeof this.hljs!="undefined"?this.hljs:!1); /*! * Repo.js * @author Darcy Clarke * * Copyright (c) 2012 Darcy Clarke * Dual licensed under the MIT and GPL licenses. * */ (function($){ // Github repo $.fn.repo = function( options ){ // Context and Base64 methods var _this = this, keyStr64 = "ABCDEFGHIJKLMNOP" + "QRSTUVWXYZabcdef" + "ghijklmnopqrstuv" + "wxyz0123456789+/" + "=", encode64 = function(a){a=escape(a);var b="";var c,d,e="";var f,g,h,i="";var j=0;do{c=a.charCodeAt(j++);d=a.charCodeAt(j++);e=a.charCodeAt(j++);f=c>>2;g=(c&3)<<4|d>>4;h=(d&15)<<2|e>>6;i=e&63;if(isNaN(d)){h=i=64}else if(isNaN(e)){i=64}b=b+keyStr64.charAt(f)+keyStr64.charAt(g)+keyStr64.charAt(h)+keyStr64.charAt(i);c=d=e="";f=g=h=i=""}while(j<a.length);return b}, decode64 = function(a){var b="";var c,d,e="";var f,g,h,i="";var j=0;var k=/[^A-Za-z0-9\+\/\=]/g;if(k.exec(a)){}a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{f=keyStr64.indexOf(a.charAt(j++));g=keyStr64.indexOf(a.charAt(j++));h=keyStr64.indexOf(a.charAt(j++));i=keyStr64.indexOf(a.charAt(j++));c=f<<2|g>>4;d=(g&15)<<4|h>>2;e=(h&3)<<6|i;b=b+String.fromCharCode(c);if(h!=64){b=b+String.fromCharCode(d)}if(i!=64){b=b+String.fromCharCode(e)}c=d=e="";f=g=h=i=""}while(j<a.length);return unescape(b)}, transition = function(el, direction, init){ var opposite = (direction === 'left') ? '' : 'left'; height = el.outerHeight(true) + _this.container.find('h1').outerHeight(true) + parseInt(_this.container.css('padding-top')) + parseInt(_this.container.css('padding-bottom')); if(init){ el.addClass('active'); _this.container.css({'height' : height + 'px'}); } else { _this.container .find('') .css('position','absolute') .addClass(direction) .removeClass('active') .end() .css({'height' : height + 'px'}); el.addClass('active') .removeClass(opposite) .delay(250) .queue(function(){ $(this).css('position','relative').dequeue(); }); } }, getMimeTypeByExtension = function(extension){ var mimeTypes = { // images 'png': 'image/png', 'gif': 'image/gif', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'ico': 'image/x-icon' }; return mimeTypes[extension] ? mimeTypes[extension] : 'text/plain'; }; // Settings _this.settings = $.extend({ user : '', name : '', branch : 'master', css : '@font-face{font-family:"Octicons Regular";src:url("");src:url("") format("embedded-opentype"),url("") format("woff"),url("") format("truetype"),url("") format("svg");font-weight:normal;font-style:normal}.repo,.repo *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}.repo ul *{display:block;font-family:sans-serif;font-size:13px;line-height:18px}.repo{width:100%;margin:0 0 15px 0;position:relative;padding-bottom:1px;color:#555;overflow:hidden;height:300px;-webkit-transition:height .25s;-moz-transition:height .25s;-o-transition:height .25s;-ms-transition:height .25s;transition:height .25s}.repo .page{background:#f8f8f8;border:4px solid rgba(0,0,0,0.08);border-radius:3px;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);opacity:0;left:100%;width:98%;position:absolute;-webkit-transition:all .25s;-moz-transition:all .25s;-o-transition:all .25s;-ms-transition:all .25s;transition:all .25s}.repo{left:1%!important;-ms-filter:"alpha(opacity=100)";filter:alpha(opacity=100);opacity:1;display:block}.repo .page.left{left:-100%}.repo .loader{position:absolute;display:block;width:100%;height:300px;top:0;left:0;background:url( no-repeat center 50%}.repo.loaded .loader{display:none}.repo h1{padding:0 0 0 10px;font-family:sans-serif;font-size:20px;line-height:26px;color:#000;font-weight:normal}.repo h1 a:nth-of-type(1),.repo h1{font-weight:bold}.repo h1,.repo h1,.repo h1,.repo h1{color:#000}.repo h1 a,.repo h1 a:active,.repo h1 a:visited,.repo h1 a:hover{color:#4183c4;text-decoration:none}.repo h1 a:after{content:"/";color:#999;padding:0 5px;font-weight:normal}.repo h1 a:last-child:after{content:""}.repo .page,.repo ul{zoom:1}.repo .page:before,.repo .page:after,.repo ul:before,.repo ul:after{content:"";display:table}.repo .page:after,.repo ul:after{clear:both}.repo ul{border:1px solid rgba(0,0,0,0.25);margin:0;padding:0}.repo li{width:100%;margin:0;padding:0;float:left;border-bottom:1px solid #ccc;position:relative;white-space:nowrap}.repo li.titles{background:-webkit-linear-gradient(#fafafa,#eaeaea);background:-moz-linear-gradient(#fafafa,#eaeaea);background:-o-linear-gradient(#fafafa,#eaeaea);background:-ms-linear-gradient(#fafafa,#eaeaea);background:linear-gradient(#fafafa,#eaeaea);font-weight:bold;padding:10px 10px 8px 36px;text-shadow:0 1px 0 #fff}.repo li:before{content:" ";font-family:"Octicons Regular";position:absolute;top:10px;left:10px;font-size:18px;-webkit-font-smoothing:antialiased}.repo li.dir:before{content:" ";color:#80a6cd}.repo li.titles:before,.repo li.back:before{content:""}.repo li:last-child{border:0;padding-bottom:none;margin:0}.repo li a,.repo li a:visited,.repo li a:active{color:#4183c4;width:100%;padding:10px 10px 8px 36px;display:block;text-decoration:none}.repo li a:hover{text-decoration:underline}.repo li span{display:inline-block}.repo li span:nth-of-type(1){width:30%}.repo li span:nth-of-type(2){width:20%}.repo li span:nth-of-type(3){width:40%}.repo .vg-container{position:relative;overflow:auto;white-space:pre!important;word-wrap:normal!important}.repo .vg-container,.repo .vg-code{border:0;margin:0;overflow:auto}.repo .vg-code .vg-line,.repo .vg-gutter .vg-number{display:block;height:1.5em;line-height:1.5em!important}.repo .vg-gutter{float:left;min-width:20px;width:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.repo .vg-number{cursor:pointer}.repo .vg-container{font-family:"Bitstream Vera Sans Mono","Courier New",monospace;font-size:13px;border:1px solid #ddd}.repo .vg-gutter{background-color:#ececec;border-right:1px solid #ddd;text-align:right;color:#aaa;padding:1em .5em;margin-right:.5em}.repo .vg-code *::-moz-selection,.repo .vg-code *::-webkit-selection,.repo .vg-code *::selection,.repo{background-color:#ffc}.repo .vg-line{color:blue;font-weight:bold;text-decoration:underline}.repo .vg-container .vg-code{display:block;padding:1em .5em;background:#fff}.repo .vg-code{color:#000;background:#f8f8ff;border:0;padding:.4em}.repo .vg-code .comment,.repo .vg-code .template_comment,.repo .vg-code .diff .header,.repo .vg-code .javadoc{color:#998;font-style:italic}.repo .vg-code .keyword,.repo .vg-code .css .rule .keyword,.repo .vg-code .winutils,.repo .vg-code .javascript .title,.repo .vg-code .lisp .title,.repo .vg-code .subst{color:#000;font-weight:bold}.vg-code .number,.vg-code .hexcolor{color:#40a070}.vg-code .string,.repo .vg-code .tag .value,.repo .vg-code .phpdoc,.repo .vg-code .tex .formula{color:#d14}.repo .vg-code .title,.repo .vg-code .id{color:#900;font-weight:bold}.repo .vg-code .javascript .title,.repo .vg-code .lisp .title,.repo .vg-code .subst{font-weight:normal}.repo .vg-code .class .title,.repo .vg-code .haskell .label,.repo .vg-code .tex .command{color:#458;font-weight:bold}.repo .vg-code .tag,.repo .vg-code .tag .title,.repo .vg-code .rules .property,.repo .vg-code .django .tag .keyword{color:#000080;font-weight:normal}.repo .vg-code .attribute,.repo .vg-code .variable,.repo .vg-code .instancevar,.repo .vg-code .lisp .body{color:#008080}.repo .vg-code .regexp{color:#009926}.repo .vg-code .class{color:#458;font-weight:bold}.repo .vg-code .symbol,.repo .vg-code .ruby .symbol .string,.repo .vg-code .ruby .symbol .keyword,.repo .vg-code .ruby .symbol .keymethods,.repo .vg-code .lisp .keyword,.repo .vg-code .tex .special,.repo .vg-code .input_number{color:#990073}.repo .vg-code .builtin,.repo .vg-code .built_in,.repo .vg-code .lisp .title{color:#0086b3}.repo .vg-code .codeprocessor,.repo .vg-code .pi,.repo .vg-code .doctype,.repo .vg-code .shebang,.repo .vg-code .cdata{color:#999;font-weight:bold}.repo .vg-code .deletion{background:#fdd}.repo .vg-code .addition{background:#dfd}.repo .vg-code .diff .change{background:#0086b3}.repo .vg-code .chunk{color:#aaa}.repo .vg-code .tex .formula{-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);opacity:.5}.repo .image{padding:1em .5em;text-align:center}.repo .image .border-wrap{background-color:#fff;border:1px solid #999;line-height:0;display:inline-block}.repo .image img{border:1px solid #fff;background:url(}' }, options); // Extension Hashes _this.extensions = { as : 'actionscript', coffee : 'coffeescript', css : 'css', html : 'html', js : 'javascript', md : 'markdown', php : 'php', py : 'python', rb : 'ruby', }; // Repo _this.repo = { name : 'default', folders : [], files : [] }; // Namespace _this.namespace =; // Insert CSS if(typeof _this.settings.css != 'undefined' && _this.settings.css !== '' && $('#repojs_css').length <= 0) $('body').prepend($('

Add a comment