Basic Makefile, TravisCI support, coveralls support and linters
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6c4a65b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,22 @@
+language: go
+
+go:
+  - 1.7.1
+
+sudo: false
+
+env:
+  global:
+    # Coveralls.io
+    - secure: OGYOsFNXNarEZ5yA4/M6ZdVguD0jL8vXgXrbLzjcpkKcq8ObHSCtNINoUlnNf6l6Z92kPnuV+LSm7jKTojBlov4IwgiY1ACbvg921SdjxYkg1AiwHTRTLR1g/esX8RdaBpJ0TOcXOFFsYMRVvl5sxxtb0tXSuUrT+Ch4SUCY7X8=
+
+install:
+  - make install-dependencies
+  - make install-tools
+  - make install
+
+script:
+  - make lint
+  - make test-with-coverage
+  - gover
+  - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e013f0b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+.PHONY: all clean clean-coverage install install-dependencies install-tools lint test test-verbose test-with-coverage
+
+export ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
+export PKG := github.com/sergi/go-diff
+export ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+
+$(eval $(ARGS):;@:) # turn arguments into do-nothing targets
+export ARGS
+
+ifdef ARGS
+	PKG_TEST := $(ARGS)
+else
+	PKG_TEST := $(PKG)/...
+endif
+
+all: install-tools install-dependencies install lint test
+
+clean:
+	go clean -i $(PKG)/...
+	go clean -i -race $(PKG)/...
+clean-coverage:
+	find $(ROOT_DIR) | grep .coverprofile | xargs rm
+install:
+	go install -v $(PKG)/...
+install-dependencies:
+	go get -t -v $(PKG)/...
+	go build -v $(PKG)/...
+install-tools:
+	# Install linting tools
+	go get -u -v github.com/golang/lint/...
+	go get -u -v github.com/kisielk/errcheck/...
+
+	# Install code coverage tools
+	go get -u -v github.com/onsi/ginkgo/ginkgo/...
+	go get -u -v github.com/modocache/gover/...
+	go get -u -v github.com/mattn/goveralls/...
+lint:
+	$(ROOT_DIR)/scripts/lint.sh
+test:
+	go test -race -test.timeout 120s $(PKG_TEST)
+test-verbose:
+	go test -race -test.timeout 120s -v $(PKG_TEST)
+test-with-coverage:
+	ginkgo -r -cover -race -skipPackage="testdata"
diff --git a/scripts/lint.sh b/scripts/lint.sh
new file mode 100755
index 0000000..1d5821d
--- /dev/null
+++ b/scripts/lint.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ -z ${PKG+x} ]; then echo "PKG is not set"; exit 1; fi
+if [ -z ${ROOT_DIR+x} ]; then echo "ROOT_DIR is not set"; exit 1; fi
+
+echo "gofmt:"
+OUT=$(gofmt -l $ROOT_DIR)
+if [ $(echo -n "$OUT" | wc -l) -ne 0 ]; then echo "$OUT"; PROBLEM=1; fi
+
+echo "errcheck:"
+OUT=$(errcheck $PKG/...)
+if [ $(echo -n "$OUT" | wc -l) -ne 0 ]; then echo "$OUT"; PROBLEM=1; fi
+
+echo "go vet:"
+OUT=$(go tool vet -all=true -v=true $ROOT_DIR 2>&1 | grep --invert-match -P "(Checking file|\%p of wrong type|can't check non-constant format)")
+if [ $(echo -n "$OUT" | wc -l) -ne 0 ]; then echo "$OUT"; PROBLEM=1; fi
+
+echo "golint:"
+OUT=$(golint $PKG/...)
+if [ $(echo -n "$OUT" | wc -l) -ne 0 ]; then echo "$OUT"; PROBLEM=1; fi
+
+if [ -n "$PROBLEM" ]; then exit 1; fi