Sunday, 28 August 2016

Git Tips and Tricks


Git is a (free) version control system. It allows:
  • saving code snapshots (commits)
  • working with alternative code versions (branches)
  • moving between branches and commits (checkout)
  • easily rolling back to older code snapshots or develop new features without breaking production code

Repository is a bucket which contains a code. 

GitHub is a platform for creating, storing and managing Git repositories in the cloud
  • allows multiple developers to work simultaneously on the centrally stored code base
  • keeps the code safe in case code is lost on dev machines for any reason
  • provides tools for automating code and repository management via GitHub Actions

Switching repositories

Cloning a remote repository:

$ git clone https://github.com/OpenVPN/openvpn-build.git



After cloning desired repository it is always good to run the following command and fetch/clone all its submodules:
$ git submodule update --init

Cloning a remote repository with preserving UNIX-style line endings:

$ git clone https://github.com/OpenVPN/openvpn-build.git --config core.autocrlf=false


Working with Branches



Getting a list of all local branches:

$ git branch



Deleting local branch:

$ git branch -d my_branch
Deleted branch my_branch (was 6d5921868b).



Getting a list of all remote branches:

$ git branch -r



Getting a list of all branches at some specific path (on Windows):

> git branch -r | find "origin/private/bojan"



Example output:

origin/HEAD -> origin/master
origin/master
origin/release/2.3



Deleting remote branch:

git push origin --delete my_branch



To update local list of remote branches:

$ git remote update origin --prune



To list all local and remote branches:

$ git branch -a




Checking out the remote branch (for the first time):

$ git checkout -b branch_name remote_name/branch_name


or shorter (on newer Git versions):

$ git checkout --track remote_name/branch_name



Example:

$ git checkout -b release/2.3 origin/release/2.3
Branch release/2.3 set up to track remote branch release/2.3 from origin.
Switched to a new branch 'release/2.3'



Or:

$ git fetch
...
* [new branch] ModuleA/Project2/JIRA-123 -> origin/ModuleA/Project2/JIRA-123
...

$ git checkout ModuleA/Project2/JIRA-123
Checking out files: 100% (1485/1485), done.
Branch ModuleA/Project2/JIRA-123 set up to track remote branch ModuleA/Project2/JIRA-123 from origin.
Switched to a new branch 'ModuleA/Project2/JIRA-123'


If you get the following error:

$ git checkout ModuleA/Project2/JIRA-123
error: Your local changes to the following files would be overwritten by checkout:
Module2/SomeDir/SomeFile.cpp
Please commit your changes or stash them before you switch branches.
Aborting


...you can force checking out with -f switch:

$ git checkout -f ModuleA/Project2/JIRA-123


To create new local branch:

$ git checkout -b issue-007
Switched to a new branch "issue-007"



The command above is a compact version for a group of these two subsequent git commands:

$ git branch issue-007
$ git checkout issue-007



To create a new branch based on a commit from the current branch:

$ git branch <commit_sha1>

To create a new branch based on a commit from another branch:

$ git branch branch_name <commit_sha1>

To create that branch and check it out:

$ git checkout -b branch_name <commit_sha1>


Bash scripts cheat sheet



Bash is:
  • Unix shell (command-line interpreter, command processor). It can process commands that user types in text window (terminal) or commands written in a file (shell script).
  • command language 
This article contains some my notes about writing shell scripts.

Here are some useful utility functions (source):


yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }
asuser() { sudo su - "$1" -c "${*:2}"; }


  • yell: print the script name and all arguments to stderr
    • $0 is the path to the script
    • $* are all arguments
    • >&2 means > redirect stdout to & pipe 2. pipe 1 would be stdout itself.
  • die does the same as yell, but exits with a non-0 exit status, which means “fail”.
  • try uses the || (boolean OR), which only evaluates the right side if the left one failed.
  • $@ is all arguments again, but different.



set -e 

At the top of the script this will cause it to exit upon any command which errors.

 

set -x

Setting the -x tells Bash to print out the statements as they are being executed. It can be very useful as a logging facility and for debugging when you need to know which statements were execute and in what order. [from Bash set -x to print statements as they are executed]

It is possible to combine two above commands into a single one:

set -ex

Getting the current directory:


$ pwd


To find some executable:


$ where perl
C:\cygwin64\bin\perl.exe



$ which perl
/usr/bin/perl


Viewing the whole content of the file:


$ cat /bin/man2html


Viewing only the first line of the file:

$ head -n 1 file.txt


Viewing only the last line of the file:

$ tail -n 1 file.txt


Editing file:

$ vi /bin/man2html


Initially, vi opens in command mode.

i - to enter edit (insert) mode
ESC - to exit edit mode
:wq - write and quit
:q! - quit without saving changes


Logging



It is a good practice to create a log file for each command/process/script/application that we run. We append both stdout and stderr into file:

my_command >> /tmp/my_command.log 2>&1


----
 

Resources:

 

How to compile OpenVpn for Windows from source code

OpenVpn suggests cross-compilation - compiling Windows executables with Unix build toolchain. This can be accomplished either by using Linux/Unix or Cygwin on Windows.

This article demonstrates compiling OpenVpn with Cygwin on Windows.

The first step is to get build scripts from https://github.com/OpenVPN/openvpn-build.

When cloning OpenVpn repositories to Windows machine, make sure Git client for Windows does not automatically convert Unix-style line endings (LF) in source files into Windows-style line endings (CRLF). If this happens UNIX tools that run in Cygwin will report an error complaining about extra CR characters. So, when cloning, use the following command:


$ git clone https://github.com/OpenVPN/openvpn-build.git --config core.autocrlf=false



Required Cygwin packages are listed here: https://github.com/OpenVPN/openvpn-build/tree/master/generic

Package name Cygwin installer path
diffutils All --> Utils
m4All --> Interpreters
makeAll -> Devel
mingw64-i686-binutilsAll -> Devel
mingw64-i686-gcc-coreAll -> Devel
mingw64-i686-headersAll -> Devel
mingw64-i686-pthreadsAll -> Devel
mingw64-i686-runtimeAll -> Devel
mingw64-x86_64-binutilsAll -> Devel
mingw64-x86_64-gcc-coreAll -> Devel
mingw64-x86_64-headersAll -> Devel
mingw64-x86_64-pthreadsAll -> Devel
mingw64-x86_64-runtimeAll -> Devel
patchAll -> Devel
patchutilsAll -> Devel
perlAll --> Interpreters
unzipAll --> Archive
wgetAll --> Web


Download Perl script man2html and save it as a file with no extensions in /bin directory (C:\cygwin64\bin). Script URL is: http://cpansearch.perl.org/src/EHOOD/man2html3.0.1/man2html. If build is run with no having this script, the following error is reported at the output:


checking for man2html... no
configure: error: man2html is required for win32
FATAL: Configure pkcs11-helper



Make sure that man2html's shebang contains correct path to perl. In order to find perl's path in Cygwin we can do the following:


$ which perl
/usr/bin/perl



In my case shebang

#!/usr/local/bin/perl


has to be replaced with:

#!/usr/bin/perl



In order to build x64 version of OpenVpn go to ../OpenVpn/openvpn-build/generic and execute:

$ IMAGEROOT=`pwd`/image-win64 CHOST=x86_64-w64-mingw32 CBUILD=i686-pc-cygwin ./build




A bit about Cygwin

Checking whether some particular package has been installed (e.g. ca-certificates):

$ cygcheck -c ca-certificates
Cygwin Package Information
Package Version Status
ca-certificates 2.9-1 OK



http://stackoverflow.com/questions/9224298/how-do-i-fix-certificate-errors-when-running-wget-on-an-https-url-in-cygwin

How to create and submit Git patch

Some open-source projects prefer submitting Git patch files to pull requests.

OpenVpn: https://community.openvpn.net/openvpn/wiki/DeveloperDocumentation
Linux kernel: https://www.kernel.org/doc/Documentation/SubmittingPatches

https://shkspr.mobi/blog/2014/04/submitting-trivial-linux-kernel-patches/
https://kernelnewbies.org/FirstKernelPatch
https://www.kernel.org/doc/Documentation/SubmittingPatches
https://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html
https://git-scm.com/docs/git-format-patch

http://who-t.blogspot.co.uk/2009/12/on-commit-messages.html

Tuesday, 23 August 2016

Why is async void bad?

Methods returning void are not awaitable. await operator can be applied only to methods which are returning Task or Task

Let's assume that method Bar is async void. Consequences of  having method Foo calling method Bar are the following:

  • This is a fire and forget model: Foo can't get information when Bar terminates as it can't await on async void method. Foo continues to run before Bar call is completed.
  • If Bar throws an exception, Foo can't catch it as there is no Task object to carry the exception object.
For these reasons async void methods shall be avoided. But this rule has a single exception; top-level events (e.g. GUI events) of void type can be async,

Links:


https://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Tip-1-Async-void-is-for-top-level-event-handlers-only

http://blog.stephencleary.com/2014/02/synchronous-and-asynchronous-delegate.html


http://stackoverflow.com/questions/15522900/how-to-safely-call-an-async-method-in-c-sharp-without-await

http://stackoverflow.com/questions/23285753/how-to-await-on-async-delegate

http://stackoverflow.com/questions/20624667/how-do-you-implement-an-async-action-delegate-method