diff --git a/.github/workflows/linux-tests.yaml b/.github/workflows/linux-tests.yaml
new file mode 100644
index 0000000..ed428ff
--- /dev/null
+++ b/.github/workflows/linux-tests.yaml
@@ -0,0 +1,28 @@
+on: 
+  pull_request:
+  push:
+    branches:
+    - master
+
+name: Linux Tests
+jobs:
+  test:
+    strategy:
+      matrix:
+        go-version: [1.16.x, 1.17.x, 1.18.x]
+        platform:
+        - ubuntu-latest
+    runs-on: ${{ matrix.platform }}
+    steps:
+    - name: Install Go
+      uses: actions/setup-go@v1
+      with:
+        go-version: ${{ matrix.go-version }}
+    - name: Checkout code
+      uses: actions/checkout@v1
+    - name: Lint
+      run: make lint
+    - name: Install dependencies
+      run: sudo apt install subversion mercurial bzr
+    - name: Test
+      run: make test
diff --git a/.github/workflows/windows-tests.yaml b/.github/workflows/windows-tests.yaml
new file mode 100644
index 0000000..7da86c1
--- /dev/null
+++ b/.github/workflows/windows-tests.yaml
@@ -0,0 +1,33 @@
+on: 
+  pull_request:
+  push:
+    branches:
+    - master
+
+name: Windows Tests
+jobs:
+  test:
+    strategy:
+      matrix:
+        go-version: [1.16.x, 1.17.x, 1.18.x]
+        platform:
+        - windows-latest
+    runs-on: ${{ matrix.platform }}
+    steps:
+    - name: Install Go
+      uses: actions/setup-go@v1
+      with:
+        go-version: ${{ matrix.go-version }}
+    - name: Checkout code
+      uses: actions/checkout@v1
+    - name: Install dependencies
+      run: choco install svn hg
+    - name: Test
+      run: go test -v
+      env:
+        # Skipping bzr tests on Windows as bzr does not install properly there.
+        # bzr development stopped in 2017 (when last change landed). The official
+        # windows installer is still bzr 2.5. The installer does not setup working
+        # cacerts. This needs to be manually modified to get working. Skipping
+        # tests in this environment as there are environment problems.
+        SKIP_BZR: "true"
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..bd2463c
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,24 @@
+linters:
+  disable-all: true
+  enable:
+    - deadcode
+    - dupl
+    - gofmt
+    - goimports
+    - gosimple
+    - govet
+    - ineffassign
+    - nakedret
+    - revive
+    - structcheck
+    - unused
+    - varcheck
+    - staticcheck
+
+linters-settings:
+  gofmt:
+    simplify: true
+  goimports:
+    local-prefixes: helm.sh/helm/v3
+  dupl:
+    threshold: 400
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index f54b68d..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-language: go
-
-go:
-  - 1.6.x
-  - 1.7.x
-  - 1.8.x
-  - 1.9.x
-  - master
-
-before_script:
-  - git version
-  - svn --version
-
-# Setting sudo access to false will let Travis CI use containers rather than
-# VMs to run the tests. For more details see:
-# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
-# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
-sudo: false
-
-script:
-  - make setup
-  - make test
-
-notifications:
-  webhooks:
-    urls:
-      - https://webhooks.gitter.im/e/06e3328629952dabe3e0
-    on_success: change  # options: [always|never|change] default: always
-    on_failure: always  # options: [always|never|change] default: always
-    on_start: never     # options: [always|never|change] default: always
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff0f828..aa79765 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,39 @@
 # Changelog
 
+## 1.13.3 (2022-03-31)
+
+### Fixed
+
+- Case sensitive use of the module name
+
+## 1.13.2 (2022-03-30)
+
+### Fixed
+
+- Fix for CVE-2022-21235
+- #103: Fixed CI testing. This included moving to GitHub Actions, updating the
+  the Git submodule handling, and skipping bzr tests on Windows (bzr has
+  discontinued and the installer now installs a broken environment)
+
+## 1.13.1 (2019-07-09)
+
+### Fixed
+
+- #101: Updated bitbucket API call as previous API was removed
+- #97: Fixed travis ci building
+- #95: Fixed "git clean" invocation for submodule
+
+## 1.13.0 (2019-02-27)
+
+### Changed
+
+- #92: Allow non-200 remote lookup responses for Go style redirects
+
+### Fixed
+
+- #91: For Mercurial/Hg return an error if Version() called and Hg prints to stderr
+- #87 and #93: Fix CI issues
+
 ## 1.12.0 (2017-09-11)
 
 ### Changed
diff --git a/Makefile b/Makefile
index 5d722c2..13123bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,41 +1,19 @@
-.PHONY: setup
-setup:
-	go get -u gopkg.in/alecthomas/gometalinter.v1
-	gometalinter.v1 --install
+GOLANGCI_LINT_VERSION?=1.45.0
+GOLANGCI_LINT_SHA256?=ca06a2b170f41a9e1e34d40ca88b15b8fed2d7e37310f0c08b7fc244c34292a9
+GOLANGCI_LINT=/usr/local/bin/golangci-lint
+
+$(GOLANGCI_LINT):
+	curl -sSLO https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64.tar.gz
+	shasum -a 256 golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64.tar.gz | grep "^${GOLANGCI_LINT_SHA256}  " > /dev/null
+	tar -xf golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64.tar.gz
+	sudo mv golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64/golangci-lint /usr/local/bin/golangci-lint
+	rm -rf golangci-lint-${GOLANGCI_LINT_VERSION}-linux-amd64*
 
 .PHONY: test
-test: validate lint
+test:
 	@echo "==> Running tests"
 	go test -v
 
-.PHONY: validate
-validate:
-# misspell finds the work adresář (used in bzr.go) as a mispelling of
-# address. It finds adres. An issue has been filed at
-# https://github.com/client9/misspell/issues/99. In the meantime adding
-# adres to the ignore list.
-	@echo "==> Running static validations"
-	@gometalinter.v1 \
-	  --disable-all \
-	  --linter "misspell:misspell -i adres -j 1 {path}/*.go:PATH:LINE:COL:MESSAGE" \
-	  --enable deadcode \
-	  --severity deadcode:error \
-	  --enable gofmt \
-	  --enable gosimple \
-	  --enable ineffassign \
-	  --enable misspell \
-	  --enable vet \
-	  --tests \
-	  --vendor \
-	  --deadline 60s \
-	  ./... || exit_code=1
-
 .PHONY: lint
-lint:
-	@echo "==> Running linters"
-	@gometalinter.v1 \
-	  --disable-all \
-	  --enable golint \
-	  --vendor \
-	  --deadline 60s \
-	  ./... || :
+lint: $(GOLANGCI_LINT)
+	@$(GOLANGCI_LINT) run
diff --git a/README.md b/README.md
index a112685..0e41199 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,10 @@
 Manage repos in varying version control systems with ease through a common
 interface.
 
-[![Build Status](https://travis-ci.org/Masterminds/vcs.svg)](https://travis-ci.org/Masterminds/vcs) [![GoDoc](https://godoc.org/github.com/Masterminds/vcs?status.png)](https://godoc.org/github.com/Masterminds/vcs) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/vcs)](https://goreportcard.com/report/github.com/Masterminds/vcs)
-[![Build status](https://ci.appveyor.com/api/projects/status/vg3cjc561q2trobm?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/vcs)
+[![Linux Tests](https://github.com/Masterminds/vcs/actions/workflows/linux-tests.yaml/badge.svg)](https://github.com/Masterminds/vcs/actions/workflows/linux-tests.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/vcs)](https://goreportcard.com/report/github.com/Masterminds/vcs)
+[![Windows Tests](https://github.com/Masterminds/vcs/actions/workflows/windows-tests.yaml/badge.svg)](https://github.com/Masterminds/vcs/actions/workflows/windows-tests.yaml) [![Docs](https://img.shields.io/static/v1?label=docs&message=reference&color=blue)](https://pkg.go.dev/github.com/Masterminds/vcs)
 
+**Note: Module names are case sensitive. Please be sure to use `github.com/Masterminds/vcs` with the capital M.**
 
 ## Quick Usage
 
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index c0c9170..0000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-version: build-{build}.{branch}
-
-clone_folder: C:\gopath\src\github.com\Masterminds\vcs
-shallow_clone: true
-
-environment:
-  GOPATH: C:\gopath
-
-platform:
-  - x64
-
-install:
-  - go version
-  - go env
-  - choco install -y bzr
-  - set PATH=C:\Program Files (x86)\Bazaar;%PATH%
-  - bzr --version
-
-build_script:
-  - go install -v ./...
-
-test_script:
-  - go test -v
-
-deploy: off
diff --git a/bzr.go b/bzr.go
index 8343d3c..9803d20 100644
--- a/bzr.go
+++ b/bzr.go
@@ -80,7 +80,7 @@ func (s *BzrRepo) Get() error {
 		}
 	}
 
-	out, err := s.run("bzr", "branch", s.Remote(), s.LocalPath())
+	out, err := s.run("bzr", "branch", "--", s.Remote(), s.LocalPath())
 	if err != nil {
 		return NewRemoteError("Unable to get repository", err, string(out))
 	}
@@ -90,7 +90,7 @@ func (s *BzrRepo) Get() error {
 
 // Init initializes a bazaar repository at local location.
 func (s *BzrRepo) Init() error {
-	out, err := s.run("bzr", "init", s.LocalPath())
+	out, err := s.run("bzr", "init", "--", s.LocalPath())
 
 	// There are some windows cases where bazaar cannot create the parent
 	// directory if it does not already exist, to the location it's trying
@@ -104,7 +104,7 @@ func (s *BzrRepo) Init() error {
 				return NewLocalError("Unable to initialize repository", err, "")
 			}
 
-			out, err = s.run("bzr", "init", s.LocalPath())
+			out, err = s.run("bzr", "init", "--", s.LocalPath())
 			if err != nil {
 				return NewLocalError("Unable to initialize repository", err, string(out))
 			}
@@ -310,13 +310,13 @@ func (s *BzrRepo) Ping() bool {
 
 	// This is the same command that Go itself uses but it's not fast (or fast
 	// enough by my standards). A faster method would be useful.
-	_, err = s.run("bzr", "info", s.Remote())
+	_, err = s.run("bzr", "info", "--", s.Remote())
 	return err == nil
 }
 
 // ExportDir exports the current revision to the passed in directory.
 func (s *BzrRepo) ExportDir(dir string) error {
-	out, err := s.RunFromDir("bzr", "export", dir)
+	out, err := s.RunFromDir("bzr", "export", "--", dir)
 	s.log(out)
 	if err != nil {
 		return NewLocalError("Unable to export source", err, string(out))
diff --git a/bzr_test.go b/bzr_test.go
index 4b2e50e..c3ad4fb 100644
--- a/bzr_test.go
+++ b/bzr_test.go
@@ -4,6 +4,7 @@ import (
 	"io/ioutil"
 	"path/filepath"
 	"time"
+
 	//"log"
 	"os"
 	"testing"
@@ -17,6 +18,9 @@ var _ Repo = &BzrRepo{}
 // repos these tests are structured to work together.
 
 func TestBzr(t *testing.T) {
+	if os.Getenv("SKIP_BZR") == "true" {
+		t.Skip("Skipping bzr tests")
+	}
 
 	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
 	if err != nil {
@@ -236,6 +240,10 @@ func TestBzr(t *testing.T) {
 }
 
 func TestBzrCheckLocal(t *testing.T) {
+	if os.Getenv("SKIP_BZR") == "true" {
+		t.Skip("Skipping bzr tests")
+	}
+
 	// Verify repo.CheckLocal fails for non-Bzr directories.
 	// TestBzr is already checking on a valid repo
 	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
@@ -263,6 +271,10 @@ func TestBzrCheckLocal(t *testing.T) {
 }
 
 func TestBzrPing(t *testing.T) {
+	if os.Getenv("SKIP_BZR") == "true" {
+		t.Skip("Skipping bzr tests")
+	}
+
 	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
 	if err != nil {
 		t.Error(err)
@@ -296,6 +308,10 @@ func TestBzrPing(t *testing.T) {
 }
 
 func TestBzrInit(t *testing.T) {
+	if os.Getenv("SKIP_BZR") == "true" {
+		t.Skip("Skipping bzr tests")
+	}
+
 	tempDir, err := ioutil.TempDir("", "go-vcs-bzr-tests")
 	repoDir := tempDir + "/repo"
 	if err != nil {
diff --git a/git.go b/git.go
index 4094e0d..2da0274 100644
--- a/git.go
+++ b/git.go
@@ -71,7 +71,7 @@ func (s GitRepo) Vcs() Type {
 
 // Get is used to perform an initial clone of a repository.
 func (s *GitRepo) Get() error {
-	out, err := s.run("git", "clone", "--recursive", s.Remote(), s.LocalPath())
+	out, err := s.run("git", "clone", "--recursive", "--", s.Remote(), s.LocalPath())
 
 	// There are some windows cases where Git cannot create the parent directory,
 	// if it does not already exist, to the location it's trying to create the
@@ -85,7 +85,7 @@ func (s *GitRepo) Get() error {
 				return NewLocalError("Unable to create directory", err, "")
 			}
 
-			out, err = s.run("git", "clone", s.Remote(), s.LocalPath())
+			out, err = s.run("git", "clone", "--recursive", "--", s.Remote(), s.LocalPath())
 			if err != nil {
 				return NewRemoteError("Unable to get repository", err, string(out))
 			}
@@ -101,7 +101,7 @@ func (s *GitRepo) Get() error {
 
 // Init initializes a git repository at local location.
 func (s *GitRepo) Init() error {
-	out, err := s.run("git", "init", s.LocalPath())
+	out, err := s.run("git", "init", "--", s.LocalPath())
 
 	// There are some windows cases where Git cannot create the parent directory,
 	// if it does not already exist, to the location it's trying to create the
@@ -115,7 +115,7 @@ func (s *GitRepo) Init() error {
 				return NewLocalError("Unable to initialize repository", err, "")
 			}
 
-			out, err = s.run("git", "init", s.LocalPath())
+			out, err = s.run("git", "init", "--", s.LocalPath())
 			if err != nil {
 				return NewLocalError("Unable to initialize repository", err, string(out))
 			}
@@ -132,7 +132,7 @@ func (s *GitRepo) Init() error {
 // Update performs an Git fetch and pull to an existing checkout.
 func (s *GitRepo) Update() error {
 	// Perform a fetch to make sure everything is up to date.
-	out, err := s.RunFromDir("git", "fetch", "--tags", s.RemoteLocation)
+	out, err := s.RunFromDir("git", "fetch", "--tags", "--", s.RemoteLocation)
 	if err != nil {
 		return NewRemoteError("Unable to update repository", err, string(out))
 	}
@@ -181,7 +181,7 @@ func (s *GitRepo) defendAgainstSubmodules() error {
 		return NewLocalError("Unexpected error while defensively cleaning up after possible derelict submodule directories", err, string(out))
 	}
 	// Then, repeat just in case there are any nested submodules that went away.
-	out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git", "clean", "-x", "-d", "-f", "-f")
+	out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git clean -x -d -f -f")
 	if err != nil {
 		return NewLocalError("Unexpected error while defensively cleaning up after possible derelict nested submodule directories", err, string(out))
 	}
@@ -366,20 +366,20 @@ func (s *GitRepo) Ping() bool {
 
 // EscapePathSeparator escapes the path separator by replacing it with several.
 // Note: this is harmless on Unix, and needed on Windows.
-func EscapePathSeparator(path string) (string) {
+func EscapePathSeparator(path string) string {
 	switch runtime.GOOS {
 	case `windows`:
 		// On Windows, triple all path separators.
 		// Needed to escape backslash(s) preceding doublequotes,
 		// because of how Windows strings treats backslash+doublequote combo,
 		// and Go seems to be implicitly passing around a doublequoted string on Windows,
-		// so we cannnot use default string instead.
+		// so we cannot use default string instead.
 		// See: https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/
 		// e.g., C:\foo\bar\ -> C:\\\foo\\\bar\\\
 		// used with --prefix, like this: --prefix=C:\foo\bar\ -> --prefix=C:\\\foo\\\bar\\\
 		return strings.Replace(path,
 			string(os.PathSeparator),
-			string(os.PathSeparator) + string(os.PathSeparator) + string(os.PathSeparator),
+			string(os.PathSeparator)+string(os.PathSeparator)+string(os.PathSeparator),
 			-1)
 	default:
 		return path
@@ -404,7 +404,7 @@ func (s *GitRepo) ExportDir(dir string) error {
 		return NewLocalError("Unable to create directory", err, "")
 	}
 
-	path = EscapePathSeparator( dir )
+	path = EscapePathSeparator(dir)
 	out, err := s.RunFromDir("git", "checkout-index", "-f", "-a", "--prefix="+path)
 	s.log(out)
 	if err != nil {
@@ -412,8 +412,8 @@ func (s *GitRepo) ExportDir(dir string) error {
 	}
 
 	// and now, the horror of submodules
-	path = EscapePathSeparator( dir + "$path" + string(os.PathSeparator) )
-	out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git checkout-index -f -a --prefix="+path)
+	handleSubmodules(s, dir)
+
 	s.log(out)
 	if err != nil {
 		return NewLocalError("Error while exporting submodule sources", err, string(out))
diff --git a/git_test.go b/git_test.go
index b58c2c2..919f054 100644
--- a/git_test.go
+++ b/git_test.go
@@ -5,6 +5,7 @@ import (
 	"io/ioutil"
 	"path/filepath"
 	"time"
+
 	//"log"
 	"os"
 	"testing"
@@ -559,7 +560,6 @@ func TestGitSubmoduleHandling2(t *testing.T) {
 		t.Errorf("Current failed to detect Git on tip of master. Got version: %s", v)
 	}
 
-
 	tempDir2, err := ioutil.TempDir("", "go-vcs-git-tests-export")
 	if err != nil {
 		t.Fatalf("Error creating temp directory: %s", err)
@@ -573,6 +573,9 @@ func TestGitSubmoduleHandling2(t *testing.T) {
 
 	exportDir := filepath.Join(tempDir2, "src")
 
+	tl := testLogger(t)
+	repo.Logger = tl
+
 	err = repo.ExportDir(exportDir)
 	if err != nil {
 		t.Errorf("Unable to export Git repo. Err was %s", err)
@@ -583,7 +586,7 @@ func TestGitSubmoduleHandling2(t *testing.T) {
 		t.Errorf("Error checking exported file in Git: %s", err)
 	}
 
-	_, err = os.Stat(filepath.Join( filepath.Join(exportDir, "definitions"), "README.md"))
+	_, err = os.Stat(filepath.Join(filepath.Join(exportDir, "definitions"), "README.md"))
 	if err != nil {
 		t.Errorf("Error checking exported file in Git: %s", err)
 	}
diff --git a/git_unix.go b/git_unix.go
new file mode 100644
index 0000000..16f3801
--- /dev/null
+++ b/git_unix.go
@@ -0,0 +1,13 @@
+//go:build !windows
+// +build !windows
+
+package vcs
+
+import "os"
+
+func handleSubmodules(g *GitRepo, dir string) ([]byte, error) {
+	// Generate path
+	path := EscapePathSeparator(dir + "$path" + string(os.PathSeparator))
+
+	return g.RunFromDir("git", "submodule", "foreach", "--recursive", "git checkout-index -f -a --prefix="+path)
+}
diff --git a/git_windows.go b/git_windows.go
new file mode 100644
index 0000000..2df3684
--- /dev/null
+++ b/git_windows.go
@@ -0,0 +1,47 @@
+//go:build windows
+// +build windows
+
+package vcs
+
+import (
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+func handleSubmodules(g *GitRepo, dir string) ([]byte, error) {
+	// Get the submodule directories
+	out, err := g.RunFromDir("git", "submodule", "foreach", "--quiet", "--recursive", "echo $sm_path")
+	if err != nil {
+		return out, err
+	}
+	cleanOut := strings.TrimSpace(string(out))
+	pths := strings.Split(strings.ReplaceAll(cleanOut, "\r\n", "\n"), "\n")
+
+	// Create the new directories. Directories are sometimes not created under
+	// Windows
+	for _, pth := range pths {
+		fpth := filepath.Join(dir + pth)
+		os.MkdirAll(fpth, 0755)
+	}
+
+	// checkout-index for each submodule. Using $path or $sm_path while iterating
+	// over the submodules does not work in Windows when called from Go.
+	var cOut []byte
+	for _, pth := range pths {
+		// Get the path to the submodule in the exported location
+		fpth := EscapePathSeparator(filepath.Join(dir, pth) + string(os.PathSeparator))
+
+		// Call checkout-index directly in the submodule rather than in the
+		// parent project. This stils git submodule foreach that has trouble
+		// on Windows within Go where $sm_path isn't being handled properly
+		c := g.CmdFromDir("git", "checkout-index", "-f", "-a", "--prefix="+fpth)
+		c.Dir = filepath.Join(c.Dir, pth)
+		out, err := c.CombinedOutput()
+		cOut = append(cOut, out...)
+		if err != nil {
+			return cOut, err
+		}
+	}
+	return cOut, nil
+}
diff --git a/glide.yaml b/glide.yaml
deleted file mode 100644
index b96e0bd..0000000
--- a/glide.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-package: github.com/Masterminds/vcs
-homepage: https://github.com/Masterminds/vcs
-license: MIT
-owners:
-- name: Matt Farina
-  email: matt@mattfarina.com
-  homepage: https://www.mattfarina.com/
-import: []
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..97696ab
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module github.com/Masterminds/vcs
+
+go 1.17
diff --git a/hg.go b/hg.go
index 5000a6d..11e012c 100644
--- a/hg.go
+++ b/hg.go
@@ -1,7 +1,9 @@
 package vcs
 
 import (
+	"bytes"
 	"encoding/xml"
+	"errors"
 	"os"
 	"os/exec"
 	"regexp"
@@ -70,7 +72,7 @@ func (s HgRepo) Vcs() Type {
 
 // Get is used to perform an initial clone of a repository.
 func (s *HgRepo) Get() error {
-	out, err := s.run("hg", "clone", s.Remote(), s.LocalPath())
+	out, err := s.run("hg", "clone", "--", s.Remote(), s.LocalPath())
 	if err != nil {
 		return NewRemoteError("Unable to get repository", err, string(out))
 	}
@@ -79,7 +81,7 @@ func (s *HgRepo) Get() error {
 
 // Init will initialize a mercurial repository at local location.
 func (s *HgRepo) Init() error {
-	out, err := s.run("hg", "init", s.LocalPath())
+	out, err := s.run("hg", "init", "--", s.LocalPath())
 	if err != nil {
 		return NewLocalError("Unable to initialize repository", err, string(out))
 	}
@@ -98,7 +100,7 @@ func (s *HgRepo) UpdateVersion(version string) error {
 		return NewLocalError("Unable to update checked out version", err, string(out))
 	}
 	if len(strings.TrimSpace(version)) > 0 {
-		out, err = s.RunFromDir("hg", "update", version)
+		out, err = s.RunFromDir("hg", "update", "--", version)
 	} else {
 		out, err = s.RunFromDir("hg", "update")
 	}
@@ -110,12 +112,20 @@ func (s *HgRepo) UpdateVersion(version string) error {
 
 // Version retrieves the current version.
 func (s *HgRepo) Version() (string, error) {
-	out, err := s.RunFromDir("hg", "--debug", "identify")
-	if err != nil {
-		return "", NewLocalError("Unable to retrieve checked out version", err, string(out))
-	}
-
-	parts := strings.SplitN(string(out), " ", 2)
+	c := s.CmdFromDir("hg", "--debug", "identify")
+	stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
+	c.Stdout = stdout
+	c.Stderr = stderr
+	if err := c.Run(); err != nil {
+		return "", NewLocalError("Unable to retrieve checked out version", err, stderr.String())
+	}
+	if stderr.Len() > 0 {
+		// "hg --debug identify" can print out errors before it actually prints
+		// the version.
+		// https://github.com/Masterminds/vcs/issues/90
+		return "", NewLocalError("Unable to retrieve checked out version", errors.New("Error output printed before identify"), stderr.String())
+	}
+	parts := strings.SplitN(stdout.String(), " ", 2)
 	sha := parts[0]
 	return strings.TrimSpace(sha), nil
 }
@@ -300,14 +310,14 @@ func (s *HgRepo) TagsFromCommit(id string) ([]string, error) {
 
 // Ping returns if remote location is accessible.
 func (s *HgRepo) Ping() bool {
-	_, err := s.run("hg", "identify", s.Remote())
+	_, err := s.run("hg", "identify", "--", s.Remote())
 	return err == nil
 }
 
 // ExportDir exports the current revision to the passed in directory.
 func (s *HgRepo) ExportDir(dir string) error {
 
-	out, err := s.RunFromDir("hg", "archive", dir)
+	out, err := s.RunFromDir("hg", "archive", "--", dir)
 	s.log(out)
 	if err != nil {
 		return NewLocalError("Unable to export source", err, string(out))
diff --git a/hg_test.go b/hg_test.go
index 6b19f72..131428b 100644
--- a/hg_test.go
+++ b/hg_test.go
@@ -2,12 +2,11 @@ package vcs
 
 import (
 	"io/ioutil"
+	"os"
 	"path/filepath"
 	"strings"
-	"time"
-	//"log"
-	"os"
 	"testing"
+	"time"
 )
 
 // Canary test to ensure HgRepo implements the Repo interface.
@@ -29,7 +28,7 @@ func TestHg(t *testing.T) {
 		}
 	}()
 
-	repo, err := NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo")
+	repo, err := NewHgRepo("http://hg.code.sf.net/p/vcstesthgrepo/code", tempDir+"/testhgrepo")
 	if err != nil {
 		t.Error(err)
 	}
@@ -39,7 +38,7 @@ func TestHg(t *testing.T) {
 	}
 
 	// Check the basic getters.
-	if repo.Remote() != "https://bitbucket.org/mattfarina/testhgrepo" {
+	if repo.Remote() != "http://hg.code.sf.net/p/vcstesthgrepo/code" {
 		t.Error("Remote not set properly")
 	}
 	if repo.LocalPath() != tempDir+"/testhgrepo" {
@@ -70,7 +69,7 @@ func TestHg(t *testing.T) {
 
 	// Test NewRepo on existing checkout. This should simply provide a working
 	// instance without error based on looking at the local directory.
-	nrepo, nrerr := NewRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo")
+	nrepo, nrerr := NewRepo("http://hg.code.sf.net/p/vcstesthgrepo/code", tempDir+"/testhgrepo")
 	if nrerr != nil {
 		t.Error(nrerr)
 	}
@@ -88,14 +87,14 @@ func TestHg(t *testing.T) {
 	}
 
 	// Set the version using the short hash.
-	err = repo.UpdateVersion("a5494ba2177f")
+	err = repo.UpdateVersion("059e82823f3e")
 	if err != nil {
 		t.Errorf("Unable to update Hg repo version. Err was %s", err)
 	}
 
 	// Use Version to verify we are on the right version.
 	v, err = repo.Version()
-	if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" {
+	if v != "059e82823f3ec23fceb532621ee7c15d5624f35f" {
 		t.Errorf("Error checking checked out Hg version: %s", v)
 	}
 	if err != nil {
@@ -106,7 +105,7 @@ func TestHg(t *testing.T) {
 	if err != nil {
 		t.Errorf("Error trying Hg Current for ref: %s", err)
 	}
-	if v != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" {
+	if v != "059e82823f3ec23fceb532621ee7c15d5624f35f" {
 		t.Errorf("Current failed to detect Hg on ref of branch. Got version: %s", v)
 	}
 
@@ -115,7 +114,7 @@ func TestHg(t *testing.T) {
 	if err != nil {
 		t.Error(err)
 	}
-	if d.Format(longForm) != "2015-07-30 16:14:08 -0400" {
+	if d.Format(longForm) != "2022-03-21 15:53:47 -0400" {
 		t.Error("Error checking checked out Hg commit date. Got wrong date:", d)
 	}
 
@@ -126,7 +125,7 @@ func TestHg(t *testing.T) {
 	}
 
 	v, err = repo.Version()
-	if v != "9c6ccbca73e8a1351c834f33f57f1f7a0329ad35" {
+	if v != "c068171728d3cc343fef21ffdff43cdb14e3c716" {
 		t.Errorf("Error checking checked out Hg version: %s", v)
 	}
 	if err != nil {
@@ -141,7 +140,7 @@ func TestHg(t *testing.T) {
 		t.Error("Hg tags is not reporting the correct version")
 	}
 
-	tags, err = repo.TagsFromCommit("a5494ba2177f")
+	tags, err = repo.TagsFromCommit("059e82823f3e")
 	if err != nil {
 		t.Error(err)
 	}
@@ -149,7 +148,7 @@ func TestHg(t *testing.T) {
 		t.Error("Hg is incorrectly returning tags for a commit")
 	}
 
-	tags, err = repo.TagsFromCommit("d680e82228d2")
+	tags, err = repo.TagsFromCommit("96379533a643")
 	if err != nil {
 		t.Error(err)
 	}
@@ -182,21 +181,21 @@ func TestHg(t *testing.T) {
 		t.Error("Hg incorrectly reporting dirty")
 	}
 
-	ci, err := repo.CommitInfo("a5494ba2177f")
+	ci, err := repo.CommitInfo("72a363187366")
 	if err != nil {
 		t.Error(err)
 	}
-	if ci.Commit != "a5494ba2177ff9ef26feb3c155dfecc350b1a8ef" {
+	if ci.Commit != "72a3631873669f4bd4c41e4d9146104e1e55e767" {
 		t.Error("Hg.CommitInfo wrong commit id")
 	}
 	if ci.Author != "Matt Farina <matt@mattfarina.com>" {
 		t.Error("Hg.CommitInfo wrong author")
 	}
-	if ci.Message != "A commit" {
+	if ci.Message != "Removing a" {
 		t.Error("Hg.CommitInfo wrong message")
 	}
 
-	ti := time.Unix(1438287248, 0)
+	ti := time.Unix(1647898961, 0)
 	if !ti.Equal(ci.Date) {
 		t.Error("Hg.CommitInfo wrong date")
 	}
@@ -224,7 +223,7 @@ func TestHg(t *testing.T) {
 		t.Errorf("Unable to export Hg repo. Err was %s", err)
 	}
 
-	_, err = os.Stat(filepath.Join(exportDir, "Readme.md"))
+	_, err = os.Stat(filepath.Join(exportDir, "README.md"))
 	if err != nil {
 		t.Errorf("Error checking exported file in Hg: %s", err)
 	}
@@ -260,7 +259,7 @@ func TestHgCheckLocal(t *testing.T) {
 
 	// Test NewRepo when there's no local. This should simply provide a working
 	// instance without error based on looking at the remote localtion.
-	_, nrerr := NewRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir+"/testhgrepo")
+	_, nrerr := NewRepo("http://hg.code.sf.net/p/vcstesthgrepo/code", tempDir+"/testhgrepo")
 	if nrerr != nil {
 		t.Error(nrerr)
 	}
@@ -278,7 +277,7 @@ func TestHgPing(t *testing.T) {
 		}
 	}()
 
-	repo, err := NewHgRepo("https://bitbucket.org/mattfarina/testhgrepo", tempDir)
+	repo, err := NewHgRepo("http://hg.code.sf.net/p/vcstesthgrepo/code", tempDir)
 	if err != nil {
 		t.Error(err)
 	}
@@ -288,7 +287,7 @@ func TestHgPing(t *testing.T) {
 		t.Error("Hg unable to ping working repo")
 	}
 
-	repo, err = NewHgRepo("https://bitbucket.org/mattfarina/ihopethisneverexistsbecauseitshouldnt", tempDir)
+	repo, err = NewHgRepo("http://bitbucket.org/mattfarina/ihopethisneverexistsbecauseitshouldnt", tempDir)
 	if err != nil {
 		t.Error(err)
 	}
diff --git a/repo_test.go b/repo_test.go
index 8c083b3..a7eab75 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -3,6 +3,7 @@ package vcs
 import (
 	"fmt"
 	"io/ioutil"
+	"log"
 	"os"
 	"testing"
 )
@@ -72,3 +73,16 @@ func TestDepInstalled(t *testing.T) {
 		t.Error("depInstalled finding not installed dep.")
 	}
 }
+
+func testLogger(t *testing.T) *log.Logger {
+	return log.New(testWriter{t}, "test", log.LstdFlags)
+}
+
+type testWriter struct {
+	t *testing.T
+}
+
+func (tw testWriter) Write(p []byte) (n int, err error) {
+	tw.t.Log(string(p))
+	return len(p), nil
+}
diff --git a/svn.go b/svn.go
index 913f90a..0c382c9 100644
--- a/svn.go
+++ b/svn.go
@@ -37,7 +37,7 @@ func NewSvnRepo(remote, local string) (*SvnRepo, error) {
 	if err == nil && r.CheckLocal() {
 		// An SVN repo was found so test that the URL there matches
 		// the repo passed in here.
-		out, err := exec.Command("svn", "info", local).CombinedOutput()
+		out, err := exec.Command("svn", "info", "--", local).CombinedOutput()
 		if err != nil {
 			return nil, NewLocalError("Unable to retrieve local repo information", err, string(out))
 		}
@@ -80,7 +80,7 @@ func (s *SvnRepo) Get() error {
 	} else if runtime.GOOS == "windows" && filepath.VolumeName(remote) != "" {
 		remote = "file:///" + remote
 	}
-	out, err := s.run("svn", "checkout", remote, s.LocalPath())
+	out, err := s.run("svn", "checkout", "--", remote, s.LocalPath())
 	if err != nil {
 		return NewRemoteError("Unable to get repository", err, string(out))
 	}
@@ -341,14 +341,14 @@ func (s *SvnRepo) TagsFromCommit(id string) ([]string, error) {
 
 // Ping returns if remote location is accessible.
 func (s *SvnRepo) Ping() bool {
-	_, err := s.run("svn", "--non-interactive", "info", s.Remote())
+	_, err := s.run("svn", "--non-interactive", "info", "--", s.Remote())
 	return err == nil
 }
 
 // ExportDir exports the current revision to the passed in directory.
 func (s *SvnRepo) ExportDir(dir string) error {
 
-	out, err := s.RunFromDir("svn", "export", ".", dir)
+	out, err := s.RunFromDir("svn", "export", "--", ".", dir)
 	s.log(out)
 	if err != nil {
 		return NewLocalError("Unable to export source", err, string(out))
diff --git a/svn_test.go b/svn_test.go
index 93fc139..6f3ed8e 100644
--- a/svn_test.go
+++ b/svn_test.go
@@ -4,6 +4,7 @@ import (
 	"io/ioutil"
 	"path/filepath"
 	"time"
+
 	//"log"
 	"os"
 	"testing"
diff --git a/vcs_remote_lookup.go b/vcs_remote_lookup.go
index 6689f95..3fc973e 100644
--- a/vcs_remote_lookup.go
+++ b/vcs_remote_lookup.go
@@ -1,7 +1,6 @@
 package vcs
 
 import (
-	"encoding/json"
 	"encoding/xml"
 	"fmt"
 	"io"
@@ -31,9 +30,9 @@ var vcsList = []*vcsInfo{
 		pattern: `^(github\.com[/|:][A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`,
 	},
 	{
-		host:     "bitbucket.org",
-		pattern:  `^(bitbucket\.org/(?P<name>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
-		addCheck: checkBitbucket,
+		host:    "bitbucket.org",
+		pattern: `^(bitbucket\.org/(?P<name>[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`,
+		vcs:     Git,
 	},
 	{
 		host:    "launchpad.net",
@@ -60,6 +59,21 @@ var vcsList = []*vcsInfo{
 		vcs:     Git,
 		pattern: `^(git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)$`,
 	},
+	{
+		host:    "hg.code.sf.net",
+		pattern: `^(hg.code.sf.net/p/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)*$`,
+		vcs:     Hg,
+	},
+	{
+		host:    "git.code.sf.net",
+		pattern: `^(git.code.sf.net/p/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)*$`,
+		vcs:     Git,
+	},
+	{
+		host:    "svn.code.sf.net",
+		pattern: `^(svn.code.sf.net/p/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)*$`,
+		vcs:     Svn,
+	},
 	// If none of the previous detect the type they will fall to this looking for the type in a generic sense
 	// by the extension to the path.
 	{
@@ -109,14 +123,6 @@ func detectVcsFromRemote(vcsURL string) (Type, string, error) {
 		return NoVCS, "", ErrCannotDetectVCS
 	}
 	defer resp.Body.Close()
-	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
-		if resp.StatusCode == 404 {
-			return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Not Found", vcsURL), nil, "")
-		} else if resp.StatusCode == 401 || resp.StatusCode == 403 {
-			return NoVCS, "", NewRemoteError(fmt.Sprintf("%s Access Denied", vcsURL), nil, "")
-		}
-		return NoVCS, "", ErrCannotDetectVCS
-	}
 
 	t, nu, err := parseImportFromBody(u, resp.Body)
 	if err != nil {
@@ -232,40 +238,6 @@ func detectVcsFromURL(vcsURL string) (Type, error) {
 	return "", ErrCannotDetectVCS
 }
 
-// Figure out the type for Bitbucket by the passed in information
-// or via the public API.
-func checkBitbucket(i map[string]string, ul *url.URL) (Type, error) {
-
-	// Fast path for ssh urls where we may not even be able to
-	// anonymously get details from the API.
-	if ul.User != nil {
-		un := ul.User.Username()
-		if un == "git" {
-			return Git, nil
-		} else if un == "hg" {
-			return Hg, nil
-		}
-	}
-
-	// The part of the response we care about.
-	var response struct {
-		SCM Type `json:"scm"`
-	}
-
-	u := expand(i, "https://api.bitbucket.org/1.0/repositories/{name}")
-	data, err := get(u)
-	if err != nil {
-		return "", err
-	}
-
-	if err := json.Unmarshal(data, &response); err != nil {
-		return "", fmt.Errorf("Decoding error %s: %v", u, err)
-	}
-
-	return response.SCM, nil
-
-}
-
 // Expect a type key on i with the exact type detected from the regex.
 func checkURL(i map[string]string, u *url.URL) (Type, error) {
 	return Type(i["type"]), nil
@@ -292,13 +264,6 @@ func get(url string) ([]byte, error) {
 	return b, nil
 }
 
-func expand(match map[string]string, s string) string {
-	for k, v := range match {
-		s = strings.Replace(s, "{"+k+"}", v, -1)
-	}
-	return s
-}
-
 func parseImportFromBody(ur *url.URL, r io.ReadCloser) (tp Type, u string, err error) {
 	d := xml.NewDecoder(r)
 	d.CharsetReader = charsetReader
diff --git a/vcs_remote_lookup_test.go b/vcs_remote_lookup_test.go
index 938cb0e..a027dad 100644
--- a/vcs_remote_lookup_test.go
+++ b/vcs_remote_lookup_test.go
@@ -17,9 +17,7 @@ func TestVCSLookup(t *testing.T) {
 	}{
 		"https://github.com/masterminds":                                   {work: false, t: Git},
 		"https://github.com/Masterminds/VCSTestRepo":                       {work: true, t: Git},
-		"https://bitbucket.org/mattfarina/testhgrepo":                      {work: true, t: Hg},
-		"https://bitbucket.org/mattfarina/repo-does-not-exist":             {work: false, t: Hg},
-		"https://bitbucket.org/mattfarina/private-repo-for-vcs-testing":    {work: false, t: Hg},
+		"https://bitbucket.org/mattfarina/atest":                           {work: true, t: Git},
 		"https://launchpad.net/govcstestbzrrepo/trunk":                     {work: true, t: Bzr},
 		"https://launchpad.net/~mattfarina/+junk/mygovcstestbzrrepo":       {work: true, t: Bzr},
 		"https://launchpad.net/~mattfarina/+junk/mygovcstestbzrrepo/trunk": {work: true, t: Bzr},
@@ -34,11 +32,10 @@ func TestVCSLookup(t *testing.T) {
 		"https://example.com/foo/bar/baz.hg":                               {work: true, t: Hg},
 		"https://gopkg.in/tomb.v1":                                         {work: true, t: Git},
 		"https://golang.org/x/net":                                         {work: true, t: Git},
-		"https://speter.net/go/exp/math/dec/inf":                           {work: true, t: Git},
 		"https://git.openstack.org/foo/bar":                                {work: true, t: Git},
 		"git@github.com:Masterminds/vcs.git":                               {work: true, t: Git},
 		"git@example.com:foo.git":                                          {work: true, t: Git},
-		"ssh://hg@bitbucket.org/mattfarina/testhgrepo":                     {work: true, t: Hg},
+		"ssh://bitbucket.org/mattfarina/testhgrepo":                        {work: true, t: Git},
 		"git@bitbucket.org:mattfarina/glide-bitbucket-example.git":         {work: true, t: Git},
 		"git+ssh://example.com/foo/bar":                                    {work: true, t: Git},
 		"git://example.com/foo/bar":                                        {work: true, t: Git},
@@ -46,6 +43,9 @@ func TestVCSLookup(t *testing.T) {
 		"svn+ssh://example.com/foo/bar":                                    {work: true, t: Svn},
 		"git@example.com:foo/bar":                                          {work: true, t: Git},
 		"hg@example.com:foo/bar":                                           {work: true, t: Hg},
+		"http://hg.code.sf.net/p/masterminds/test":                         {work: true, t: Hg},
+		"http://git.code.sf.net/p/masterminds/test":                        {work: true, t: Git},
+		"http://svn.code.sf.net/p/masterminds/test":                        {work: true, t: Svn},
 	}
 
 	for u, c := range urlList {
@@ -111,27 +111,3 @@ func TestVCSFileLookup(t *testing.T) {
 		t.Errorf("Detected wrong type from file:// path. Found type %v", ty)
 	}
 }
-
-func TestNotFound(t *testing.T) {
-	_, _, err := detectVcsFromRemote("https://mattfarina.com/notfound")
-	if err == nil || !strings.HasSuffix(err.Error(), " Not Found") {
-		t.Errorf("Failed to find not found repo")
-	}
-
-	_, err = NewRepo("https://mattfarina.com/notfound", "")
-	if err == nil || !strings.HasSuffix(err.Error(), " Not Found") {
-		t.Errorf("Failed to find not found repo")
-	}
-}
-
-func TestAccessDenied(t *testing.T) {
-	_, _, err := detectVcsFromRemote("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing")
-	if err == nil || err.Error() != "Access Denied" {
-		t.Errorf("Failed to detect access denied")
-	}
-
-	_, err = NewRepo("https://bitbucket.org/mattfarina/private-repo-for-vcs-testing", "")
-	if err == nil || err.Error() != "Access Denied" {
-		t.Errorf("Failed to detect access denied")
-	}
-}