SushiHangover

PowerShell, Learn it or Perish ;-)

master nix
Gitter

Git - Review a Merge before committing

After you perform a fetch on an upstream or someone’s forked repo, you want to review the changes before committing them.

You can not do a what-if or a dry-run merge but it does not matter as git is your friend in this matter. Just do the merge and review it, BUT, do not let it commit or fast forward during the merge.

git merge --no-commit --no-ff branchname

Without the –no-ff flag, if Git can do a fast-forward then it will do that and commit anyway despite the –no-commit flag.

Setup an alias in your ~/.gitconfig for a simple shortcut

review = merge --no-ff --no-commit

So in looking at upstream changes:

git fetch upstream
git review upstream/master
git status

If you wish to back those changes, just reset that merge:

git reset --merge

Git : Your Github based fork's pull request is rejected, kind-of, now what?

So you have a Github fork of a project and you find a problem. You whip up a fix, commit it in a local branch and push it to your fork you Github. Than you issue a pull request to the upstream repo. Life is good.

But… your pull request is ‘rejected’, kind-of, as the fix is applied differently to their branch. Now your GitHub and local repo are history mismatched to the upstream master. Fetching upstream and merging upstream/master produces conflicts ;-(

First, I do not want to lose the commit that I did do. I want to keep the work/history so a ‘simple’ git hard reset to a prior sha is out of the question.

So lets put your changes on a new branch and reset the master branch back to match the upstream.

Move last commit to a new branch

Note: You will lose uncommitted work, stash first if needed!

git branch newbranch
git reset --hard HEAD~1 # Go back 1 commit or use SHA
git checkout newbranch

Re-sync your Github fork

Now, lets get everything re-sync’d.

git checkout master

Since you already push this branch to your Github fork, you will see the message:

"Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded."

That contains your fix, but you need to merge in the upstream/master changes.

git fetch upstream
git merge upstream/master

And your local master should Fast-forward to match the upstream. All is good, except your repo on Github is not correct as it contains your original commit on the wrong branch.

git push --force

If you want to keep (backup) that new branch to Github than use the following instead:

git push --all --force

Note: You should not be forcing a push if others have already pulled from your repo/fork. That causes bad git mojo and everyone else that pulled your repo will need to be notified that you ‘changed’ history… That is a git fixup story for another day.

Moral of the story:

Create a bugfix branch with your fixes. It should have one commit (rebase if needed) that will fast-forward and issue your pull-request from that branch.

C# - Native Interop Helloworld

The simplest Interop case HelloWorld I can create, give it a try and see what happens:

>cat countbyone.cpp

extern "C" int SomeMethod(int num) {
  return num++;
}

Compile your shared library:

  • Linux: gcc -g -shared -fPIC countbyone.cpp -o libcountbyone.so
  • OS-X: clang -dynamiclib countbyone.cpp -o libcoutbyone.dylib

>cat interop.cs

using System;
using System.Runtime.InteropServices;
namespace InteropDemo
{
    class MainClass
    {
        [DllImport("countbyone")]
        private static extern int SomeMethod(int num);

        public static void Main (string[] args)
        {
            var x = SomeMethod(0);
            Console.WriteLine(x);
        }
    }
}

Compile your .Net/Mono app:

>mcs interop.cs

Run it:

>mono interop.exe
1

Output should be 1 and no errors…

If the shared (native) library is not found, you receive:

XXXXX failed to initialize, the exception is: System.DllNotFoundException

If you have a entry point mismatch you would receive a:

XXXXX failed to initialize, the exception is: System.EntryPointNotFoundException

From my answer on Stackoverflow

Mono - Code Coverage using the new coverage filter

New code coverage filter:

Using the new coverage filter on the mono log profiler, you can get output like this:

Coverage Summary:
    xCorFlags (/Users/administrator/monocov/lib/xCorFlags.exe) 26% covered (42 methods - 11 covered)
        <Module> ?% covered (0 methods - 1 covered)
        CorFlags.CorFlagsSettings 25% covered (4 methods - 1 covered)
        CorFlags.MainClass 50% covered (2 methods - 1 covered)
        CorFlags.CommandLineParser 40% covered (20 methods - 8 covered)

Having a suite of existing unit-tests, you can enable the coverage filter and get some quick answers to your question about how much code you are really exercising and testing.

Background:

Well, it appears that Xamarin has removed the ‘internal’ cov profiler and monocov will not produce any output (besides mono actually loading the shared library, no functions are called) as the api has changed.

They have added a code coverage filter (Apr 7 2015) to the core log profilers and while I could not find any published documentation(?). It is easy enough to enable.

--profile=log:coverage

coverage             enable collection of code coverage data
covfilter=ASSEMBLY   add an assembly to the code coverage filters
                     add a + to include the assembly or a - to exclude it
                     filter=-mscorlib
covfilter-file=FILE  use FILE to generate the list of assemblies to be filtered

Git log info on cov removal and log coverage filter addition:

commit 16570265149730ec6a4760cc0fa34decc1a9d981
Author: Alex Rønne Petersen <alexrp@xamarin.com>
Date:   Tue Apr 7 14:51:27 2015 +0200
        [profiler] Remove old mono-cov profiler.
        We're replacing this with coverage support in the log profiler.

commit e91693fbb87f687a2fdb5a495c945c1872b3066c
Author: iain holmes <iain@xamarin.com>
Date:   Fri Feb 27 10:13:54 2015 +0000
        [cov] Install a coverage filter

If you are still using Mono 3.x, then my other MonoCov post as it would still work:

CursesSharp - 64-bit NCurses on OS-X and Mono

CursesSharp is a C# wrapper for curses library.

I updated this to work for ‘modern’ autotools so allow autoreconf and configure to actual run without throwing errors and then I updated the Makefile.am’s files to allow compiling under OS-X and with Mono 4.0.x. Linux and Windows should still work, but I have not at this time tested those other flavors.

Let me know via Github issues if you have any problems. ;-)

Installing CursesSharp on OS-X

These are the instructions for building CursesSharp on OS-X. The build CursesSharp is a C# wrapper for curses library. process has been tested on 10.10.3 using Apple LLVM version 6.1.0 and a Mono 4.0.1 64-bit build.

0. Prerequisites

  1. Subversion - if you intend to build CursesSharp from SVN repository. If you use the source code package, you don’t need Subversion.
  2. autoconf/automake/libtool - only if you are building from SVN. You don’t need these tools if you use the source code package.
  3. Standard development tools - a C compiler (e.g. GCC) and GNU make (gmake).
  4. Ncurses library and headers (development files) - typically this package is called ncurses-dev.
  5. Mono - the .NET runtime and development framework
  6. pkg-config - typically required by Mono, but make sure it’s installed

1. Getting CursesSharp

You will have to obtain CursesSharp sources. You clone it from the following repository:

https://github.com/sushihangover/CursesSharp.git

Original SVN Repo:

https://curses-sharp.svn.sourceforge.net/svnroot/curses-sharp/trunk

The following section describes the former case. If you downloaded the source code package, extract it and you may skip to step 4.

2. Git clone

Execute the following command:

git clone https://github.com/sushihangover/CursesSharp.git cursessharp

You may substitute the final cursessharp for any other directory of your liking.

3. Bootstrapping

In order to proceed with the build, you will have to create the configure script. Cd into the directory containing CursesSharp sources and execute the following command:

brew link gettext –force
autoreconf -if

4. Configure

In the top source directory execute the command:

LIBS="-lncurses -liconv -lpanel" ./configure

By default CursesSharp is installed in /usr/local. To change the target directory, which you really should do, you can use the “–prefix=” option:

# Following all on one line:    
LIBS="-lncurses -liconv -lpanel" ./configure --prefix=$HOME/cursessharp

You can also use other options. For a complete list execute:

./configure --help

5. Make

After you executed configure, run (in the same directory):

#I am using a locally built/installed 64-bit version of mono, so I add it to the path
export PATH=/Users/administrator/mono/mono-llvm-64/bin:$PATH
make
# remove brew's version of gettext 
brew unlink gettext

To compile the source code.

6. Installation

Execute the command:

make install

This will install CursesSharp. Make sure you have appropriate privileges.

7. Testing

By default CursesSharp will install a few demonstration programs. At this time, these are: FireworkDemo and RainDemo. You can try running the demos to check if CursesSharp works.

Running the demos:

Add your cursessharp’s bin install location to your path, i.e.

export PATH=$HOME/cursessharp/bin:$PATH

And you can run them from anywhere:

RainDemo
FireworksDemo
UnicodeDemo

Have fun ;-)

MonoCov - Building on OS-X

My answer from Stackoverflow on compiling MonoCov on OS-X and Mono 4.0.x

# Clone the MonoCov repo
git clone https://github.com/mono/monocov.git MonoCov
cd MonoCov
# A really old version of cecil and it not available as a nuget
curl http://go-mono.com/archive/cecil/cecil-0.6-bin.zip -o cecil-0.6-bin.zip
unzip cecil-0.6-bin.zip
# Make sure configure can find the Mono.Option source file
export PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/4.0.1/lib:/Library/Frameworks/Mono.framework/Versions/4.0.1/lib/pkgconfig:$PKG_CONFIG_PATH
export 
# Config to install to users home dir
./configure --cecil=$PWD/monocov/cecil-0.6/Mono.Cecil.dll --prefix $HOME/monocov
# Fix Makefile, gmcs no longer exists under Mono 4.x and Makefile is hard coded
sed -i.bak s/gmcs/mcs/g Makefile
# Pass -m32 to make since OS-X Mono framework is still 32-bit
CC="cc -m32" make
# Install does not properly create bin dir, do it before the first install
mkdir $HOME/monocov/bin
# Install..
make install

Compile a test app and test MonoCov:

// Save this to a file named Program.cs
using System;
namespace Foobar
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Console.WriteLine ("Hello MonoCov");
        }
    }
}

Profile a Mono (.Net) application

# Compile a sample app
mcs Program.cs
# Update path to include MonoCov so mono can load it as a profiler
export PATH=$HOME/monocov:$PATH
mono --debug --profile=monocov Program.exe

Launch the MonoCov GUI

# GUI Framework DllNotFoundException fix (if needed)
export DYLD_FALLBACK_LIBRARY_PATH="/Library/Frameworks/Mono.framework/Versions/Current/lib:/usr/local/lib:/usr/lib"
# Update path to include MonoCov
export PATH=$HOME/monocov/bin:$PATH
monocov

Mono Code Coverage Profiler : MonoCov

Mono.Cecil 0.6 05 Oct 2007

Corflags - Release xCorFlags Version 1.0.5643.36015

xCorFlags Version 1.0.5643.36015

Maintenance release of the cross-platform CorFlags Conversion Tool is up on Github.

git log v1.0.5643.30429..v1.0.5643.36015
commit 0125dffeda467b70e869b898d05203aba3669e88
Author: SushiHangover <sushihangover@outlook.com>
Date:   Sun Jun 14 20:06:00 2015 -0700

Fix absolute paths to the assemblies that are passed in

This is a cross-platform version of the Microsoft CorFlags tool that is included in the .Net Framework SDK installations and is a self-contained x86 CIL Image (via ILRepack) that runs on:

  • Windows (xCorFlags)
  • OS-X (mono ./xCorFlags.exe)
  • Linux (mono ./xCorFlags.exe)

For additional information:

Corflags - Release xCorFlags Version 1.0.5643.30429

xCorFlags Version 1.0.5643.30429

The first full release of the cross-platform CorFlags Conversion Tool is up on Github.

This is a cross-platform version of the Microsoft CorFlags tool that is included in the .Net Framework SDK installations and is a self-contained x86 CIL Image (via ILRepack) that runs on:

  • Windows (xCorFlags)
  • OS-X (mono ./xCorFlags.exe)
  • Linux (mono ./xCorFlags.exe)

For additional information:

Git: Set up a fetch-only remote | Disabling push

The PlayScript repo on the PlayScriptRedux Github organization I maintain is a down-stream fork of Mono so I can fetch the changes to their master branch. I also have my own fork of the PlayScript repo so I can code, issue pull-requests and review other people’s pull-requests. But I do not want to screw up and push directly to the Redux based repo from my local repo, only my own fork on GitHub. Also I do not have any push permissions on the Mono repo and want to not even have git try to push to that repo if I screw up on the cmd line.

So after adding my additional remotes my local repo, it looks like this:

git remote -v
origin  https://github.com/sushihangover/playscript.git (fetch)
origin  https://github.com/sushihangover/playscript.git (push)
redux   https://github.com/PlayScriptRedux/playscript.git (fetch)
redux   https://github.com/PlayScriptRedux/playscript.git (push)
upstream    https://github.com/mono/mono.git (fetch)
upstream    https://github.com/mono/mono.git (push)

I want to keep the fetch/pull ability from the redux and upstream remotes and remove the ‘push’ ability to those remotes.

You can not totally clear the push uri as it will be replaced with the fetch uri. So setting the push uri to something nonexistent works, i.e.

 git remote set-url --push upstream DISABLE
 git remote set-url --push redux DISABLE

And to see what that looks like now:

git remote -v
origin  https://github.com/sushihangover/playscript.git (fetch)
origin  https://github.com/sushihangover/playscript.git (push)
redux   https://github.com/PlayScriptRedux/playscript.git (fetch)
redux   DISABLE (push)
upstream    https://github.com/mono/mono.git (fetch)
upstream    DISABLE (push)

Now if you push to the one of the ‘disable’ remotes, you will recieve the following error:

git push redux
fatal: 'DISABLE' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

NOTE: You do not have to use “DISABLE”, any nonsensical URI will do. I like DISABLE as seeing it in the git push error message is a clear indicator of the brain fart that I just typed…

CorFlags Conversion tool - Cross-platform release on Github

I posted the first (alpha) release of a cross-platform version of Microsoft’s CorFlags Conversion tool to Github.

This alpha release is read-only and while accepting argument flags to change the CIL image, you will receive a not implemented exception:

corflags : Error CF0999: Unknown exception: The requested feature is not implemented.

The next release will be feature complete as I just needed to get a backup of the current version to Github for now.

Repo Readme:

xCorFlags.exe (CorFlags Conversion Tool)

Mono and .NET Framework 4.5

The CorFlags Conversion tool allows you to configure the CorFlags section of the header of a portable executable image.

This is a cross-platform version of the Microsoft CorFlags tool that is included in the .Net Framework SDK installations.

This xplat version strives to be argument option and output compatible (using /nologo) with the Microsoft version.

*Note: Platform independent argument prefixes can be used: ‘/’ or ‘-’ *

Usage:

Mono/.NET Framework CorFlags Conversion Tool.  Version  0.9.5643.21314
Copyright (c) SushiHangover.  All rights reserved.

Windows Usage: xCorflags.exe Assembly [options]
 X-Plat Usage: mono xcorflags.exe Assembly [options]

If no options are specified, the flags for the given image are displayed.

     Options: (/ or - prefixed
     /ILONLY+ /ILONLY-       Sets/clears the ILONLY flag
     /32BITREQ+ /32BITREQ-   Sets/clears the bits indicating 32-bit x86 only
     /32BITPREF+ /32BITPREF- Sets/clears the bits indicating 32-bit preferred
     /UpgradeCLRHeader       Upgrade the CLR Header to version 2.5
     /RevertCLRHeader        Revert the CLR Header to version 2.0
     /Force                  Force an assembly update even if the image is
         strong name signed.
         WARNING: Updating a strong name signed assembly
         will require the assembly to be resigned before
         it will execute properly.
     /nologo                 Prevents corflags from displaying logo

Output:

When running with the nologo option, the output should be compatible with Microsoft’s version, a nice to have for those who already are used the output to CorFlags.exe or those that have existing scripts.

mono ./CorFlags.exe /nologo CorFlags.exe
Version   : v4.0.30319
CLR Header: 2.5
PE        : PE32
CorFlags  : 0x3
ILONLY    : 1
32BITREQ  : 1
32BITPREF : 0
Signed    : 0

Without using the nologo argument:

mono ./CorFlags.exe CorFlags.exe SudoKnights.exe
Mono/.NET Framework CorFlags Conversion Tool.  Version  0.9.5643.21314
Copyright (c) SushiHangover.  All rights reserved.

Version   : v4.0.30319
CLR Header: 2.5
PE        : PE32
CorFlags  : 0x20003
ILONLY    : 1
32BITREQ  : 1
32BITPREF : 1
Signed    : 0

versus:

PS> .\CorFlags.exe .\Test\x64\Release\ExeForTesting.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  4.0.30319.17929
Copyright (c) Microsoft Corporation.  All rights reserved.

Version   : v4.0.30319
CLR Header: 2.5
PE        : PE32+
CorFlags  : 0x1
ILONLY    : 1
32BITREQ  : 0
32BITPREF : 0
Signed    : 0

Built and tested using Mono 4.0.1 on:

  • Windows
  • OS-X
  • Linux